diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index f0a03a1e3f30a6019d6b16ce657d8b38f8c9e3b9..176105b9a46fa98673feecd8d2cdea911fbd810d 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -87,6 +87,7 @@ D_FRONTEND_OBJS = \
 	d/ast_node.o \
 	d/astcodegen.o \
 	d/astenums.o \
+	d/basicmangle.o \
 	d/blockexit.o \
 	d/builtin.o \
 	d/canthrow.o \
@@ -122,6 +123,7 @@ D_FRONTEND_OBJS = \
 	d/dtoh.o \
 	d/dversion.o \
 	d/entity.o \
+	d/enumsem.o \
 	d/errors.o \
 	d/errorsink.o \
 	d/escape.o \
@@ -130,6 +132,7 @@ D_FRONTEND_OBJS = \
 	d/file_manager.o \
 	d/foreachvar.o \
 	d/func.o \
+	d/funcsem.o \
 	d/globals.o \
 	d/gluelayer.o \
 	d/hdrgen.o \
@@ -192,6 +195,7 @@ D_FRONTEND_OBJS = \
 	d/stmtstate.o \
 	d/target.o \
 	d/templateparamsem.o \
+	d/templatesem.o \
 	d/tokens.o \
 	d/traits.o \
 	d/transitivevisitor.o \
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 9d604974f85ea2cb620cd94914fcafeed955ab73..1b5b3bea8ca7d6c41444a42786593e4528be3d10 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -240,7 +240,7 @@ build_frontend_type (tree type)
       sdecl->sizeok = Sizeok::done;
       sdecl->type = (TypeStruct::create (sdecl))->addMod (mod);
       sdecl->type->ctype = type;
-      sdecl->type->merge2 ();
+      merge2 (sdecl->type);
 
       /* Add both named and anonymous fields as members of the struct.
 	 Anonymous fields still need a name in D, so call them "__pad%u".  */
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 22005a45fca7af1214faac44cc76cf7fc7389677..af938ddc04aa5ccfbb01cbef118e3b8ecab4d048 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -150,7 +150,7 @@ declaration_type (Declaration *decl)
       TypeFunction *tf = TypeFunction::create (NULL, decl->type,
 					       VARARGnone, LINK::d);
       TypeDelegate *t = TypeDelegate::create (tf);
-      return build_ctype (t->merge2 ());
+      return build_ctype (merge2 (t));
     }
 
   /* Static array va_list have array->pointer conversions applied.  */
@@ -200,7 +200,7 @@ parameter_type (Parameter *arg)
       TypeFunction *tf = TypeFunction::create (NULL, arg->type,
 					       VARARGnone, LINK::d);
       TypeDelegate *t = TypeDelegate::create (tf);
-      return build_ctype (t->merge2 ());
+      return build_ctype (merge2 (t));
     }
 
   /* Static array va_list have array->pointer conversions applied.  */
diff --git a/gcc/d/d-incpath.cc b/gcc/d/d-incpath.cc
index e505f4ec6be2a001d793ce65707cf42dff4055e7..32ab0b71efad27fe51b2121459498d97ff91dc3d 100644
--- a/gcc/d/d-incpath.cc
+++ b/gcc/d/d-incpath.cc
@@ -71,9 +71,6 @@ add_globalpaths (Strings *paths)
 {
   if (paths)
     {
-      if (!global.path)
-	global.path = d_gc_malloc<Strings> ();
-
       for (size_t i = 0; i < paths->length; i++)
 	{
 	  const char *path = (*paths)[i];
@@ -86,7 +83,7 @@ add_globalpaths (Strings *paths)
 	      continue;
 	    }
 
-	  global.path->push (target);
+	  global.path.push (target);
 	}
     }
 }
@@ -98,9 +95,6 @@ add_filepaths (Strings *paths)
 {
   if (paths)
     {
-      if (!global.filePath)
-	global.filePath = d_gc_malloc<Strings> ();
-
       for (size_t i = 0; i < paths->length; i++)
 	{
 	  const char *path = (*paths)[i];
@@ -112,7 +106,7 @@ add_filepaths (Strings *paths)
 	      continue;
 	    }
 
-	  global.filePath->push (target);
+	  global.filePath.push (target);
 	}
     }
 }
@@ -143,9 +137,9 @@ add_import_paths (const char *iprefix, const char *imultilib, bool stdinc)
 
 	  /* Ignore duplicate entries.  */
 	  bool found = false;
-	  for (size_t i = 0; i < global.params.imppath->length; i++)
+	  for (size_t i = 0; i < global.params.imppath.length; i++)
 	    {
-	      if (strcmp (path, (*global.params.imppath)[i]) == 0)
+	      if (strcmp (path, global.params.imppath[i]) == 0)
 		{
 		  found = true;
 		  break;
@@ -162,33 +156,26 @@ add_import_paths (const char *iprefix, const char *imultilib, bool stdinc)
 	  if (imultilib)
 	    {
 	      char *target_path = concat (path, "/", imultilib, NULL);
-	      global.params.imppath->shift (target_path);
+	      global.params.imppath.shift (target_path);
 	    }
 
-	  global.params.imppath->shift (path);
+	  global.params.imppath.shift (path);
 	}
     }
 
   /* Add import search paths.  */
-  if (global.params.imppath)
+  for (size_t i = 0; i < global.params.imppath.length; i++)
     {
-      for (size_t i = 0; i < global.params.imppath->length; i++)
-	{
-	  const char *path = (*global.params.imppath)[i];
-	  if (path)
-	    add_globalpaths (FileName::splitPath (path));
-	}
+      const char *path = global.params.imppath[i];
+      if (path)
+	add_globalpaths (FileName::splitPath (path));
     }
 
   /* Add string import search paths.  */
-  if (global.params.fileImppath)
+  for (size_t i = 0; i < global.params.fileImppath.length; i++)
     {
-      for (size_t i = 0; i < global.params.fileImppath->length; i++)
-	{
-	  const char *path = (*global.params.fileImppath)[i];
-	  if (path)
-	    add_filepaths (FileName::splitPath (path));
-	}
+      const char *path = global.params.fileImppath[i];
+      if (path)
+	add_filepaths (FileName::splitPath (path));
     }
 }
-
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index aabe1ad43cba3419edbd2d990f0b200123c913c3..138a7f9d0f98c59b782055ba2a8fd21db4cfc939 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -306,9 +306,6 @@ d_init_options (unsigned int, cl_decoded_option *decoded_options)
   global.params.v.errorLimit = flag_max_errors;
   global.params.v.messageStyle = MessageStyle::gnu;
 
-  global.params.imppath = d_gc_malloc<Strings> ();
-  global.params.fileImppath = d_gc_malloc<Strings> ();
-
   /* Extra GDC-specific options.  */
   d_option.fonly = NULL;
   d_option.multilib = NULL;
@@ -724,11 +721,11 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       break;
 
     case OPT_I:
-      global.params.imppath->push (arg);
+      global.params.imppath.push (arg);
       break;
 
     case OPT_J:
-      global.params.fileImppath->push (arg);
+      global.params.fileImppath.push (arg);
       break;
 
     case OPT_MM:
@@ -1045,25 +1042,24 @@ d_parse_file (void)
 {
   if (global.params.v.verbose)
     {
+      /* Dump information about the D compiler and language version.  */
       message ("binary    %s", global.params.argv0.ptr);
       message ("version   %s", global.versionChars ());
 
-      if (global.versionids)
+      /* Dump all predefined version identifiers.  */
+      obstack buffer;
+      gcc_obstack_init (&buffer);
+      obstack_grow (&buffer, "predefs  ", 9);
+      for (size_t i = 0; i < global.versionids.length; i++)
 	{
-	  obstack buffer;
-	  gcc_obstack_init (&buffer);
-	  obstack_grow (&buffer, "predefs  ", 9);
-	  for (size_t i = 0; i < global.versionids->length; i++)
-	    {
-	      Identifier *id = (*global.versionids)[i];
-	      const char *str = id->toChars ();
-	      obstack_1grow (&buffer, ' ');
-	      obstack_grow (&buffer, str, strlen (str));
-	    }
-
-	  obstack_1grow (&buffer, '\0');
-	  message ("%s", (char *) obstack_finish (&buffer));
+	  Identifier *id = global.versionids[i];
+	  const char *str = id->toChars ();
+	  obstack_1grow (&buffer, ' ');
+	  obstack_grow (&buffer, str, strlen (str));
 	}
+
+      obstack_1grow (&buffer, '\0');
+      message ("%s", (char *) obstack_finish (&buffer));
     }
 
   /* Start the main input file, if the debug writer wants it.  */
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 4ca85bb970d6edade34275321d0b5193935d7127..d2e84d3ba619504f769d8765a9fe746b19579615 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -539,7 +539,7 @@ public:
 	  continue;
 
 	/* Ensure function has a return value.  */
-	if (!fd->functionSemantic ())
+	if (!functionSemantic (fd))
 	  has_errors = true;
 
 	/* No name hiding to check for.  */
@@ -563,20 +563,23 @@ public:
 	    if (fd2->isFuture ())
 	      continue;
 
-	    if (fd->leastAsSpecialized (fd2, NULL) != MATCH::nomatch
-		|| fd2->leastAsSpecialized (fd, NULL) != MATCH::nomatch)
-	      {
-		error_at (make_location_t (fd->loc), "use of %qs",
-			  fd->toPrettyChars ());
-		inform (make_location_t (fd2->loc), "is hidden by %qs",
-			fd2->toPrettyChars ());
-		inform (make_location_t (d->loc),
-			"use %<alias %s = %s.%s;%> to introduce base class "
-			"overload set", fd->toChars (),
-			fd->parent->toChars (), fd->toChars ());
-		has_errors = true;
-		break;
-	      }
+	    if (FuncDeclaration::leastAsSpecialized (fd, fd2, NULL)
+		    == MATCH::nomatch
+		&& FuncDeclaration::leastAsSpecialized (fd2, fd, NULL)
+		    == MATCH::nomatch)
+	      continue;
+
+	    /* Hiding detected; same name, overlapping specializations.  */
+	    error_at (make_location_t (fd->loc), "use of %qs",
+		      fd->toPrettyChars ());
+	    inform (make_location_t (fd2->loc), "is hidden by %qs",
+		    fd2->toPrettyChars ());
+	    inform (make_location_t (d->loc),
+		    "use %<alias %s = %s.%s;%> to introduce base class "
+		    "overload set", fd->toChars (),
+		    fd->parent->toChars (), fd->toChars ());
+	    has_errors = true;
+	    break;
 	  }
       }
 
@@ -943,7 +946,7 @@ public:
 	gcc_assert (!doing_semantic_analysis_p);
 
 	doing_semantic_analysis_p = true;
-	d->functionSemantic3 ();
+	functionSemantic3 (d);
 	Module::runDeferredSemantic3 ();
 	doing_semantic_analysis_p = false;
       }
@@ -1231,7 +1234,7 @@ get_symbol_decl (Declaration *decl)
   if (fd)
     {
       /* Run full semantic on functions we need to know about.  */
-      if (!fd->functionSemantic ())
+      if (!functionSemantic (fd))
 	{
 	  decl->csym = error_mark_node;
 	  return decl->csym;
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 138b0b6fa7c0ba978651e4122b0c435391885321..9217c654225b3ca5910e645498e1b6a72b51954b 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-bce5c1f7b521d22dcf1ea4e2bc3f76d9d28274fa
+e7709452775d374c1e2dfb67566668ada3dec5fc
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/README.md b/gcc/d/dmd/README.md
index f8ac00117ebc1acb59360b100d22974d1ceb226c..23f3333198d8829892686d7d61efd0d8eb3469e6 100644
--- a/gcc/d/dmd/README.md
+++ b/gcc/d/dmd/README.md
@@ -110,6 +110,8 @@ Note that these groups have no strict meaning, the category assignments are a bi
 | File                                                                                      | Purpose                                                           |
 |-------------------------------------------------------------------------------------------|-------------------------------------------------------------------|
 | [dsymbolsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dsymbolsem.d)             | Do semantic 1 pass (symbol identifiers/types)                     |
+| [enumsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/enumsem.d)                   | Enum semantics                                                    |
+| [funcsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/funcsem.d)                   | Function semantics                                                |
 | [semantic2.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/semantic2.d)               | Do semantic 2 pass (symbol initializers)                          |
 | [semantic3.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/semantic3.d)               | Do semantic 3 pass (function bodies)                              |
 | [inline.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/inline.d)                     | Do inline pass (optimization pass that dmd does in the front-end) |
@@ -117,6 +119,7 @@ Note that these groups have no strict meaning, the category assignments are a bi
 | [expressionsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/expressionsem.d)       | Do semantic analysis for expressions                              |
 | [statementsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/statementsem.d)         | Do semantic analysis for statements                               |
 | [initsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/initsem.d)                   | Do semantic analysis for initializers                             |
+| [templatesem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/templatesem.d)           | Do semantic analysis for templates                                |
 | [templateparamsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/templateparamsem.d) | Do semantic analysis for template parameters                      |
 | [typesem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/typesem.d)                   | Do semantic analysis for types                                    |
 
@@ -230,6 +233,7 @@ Note that these groups have no strict meaning, the category assignments are a bi
 |-----------------------------------------------------------------------------------|------------------------------------------------------------------|
 | [cppmangle.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cppmangle.d)       | C++ name mangling                                                |
 | [cppmanglewin.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cppmanglewin.d) | C++ name mangling for Windows                                    |
+| [basicmangle.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/basicmangle.d)   | D name mangling for basic types                                  |
 | [dmangle.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dmangle.d)           | D [name mangling](https://dlang.org/spec/abi.html#name_mangling) |
 
 ### Linking
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index 9abdd094b3f21561565ce931043caaa5a40f3c03..f466ba6174061d93d022978c3a3d084ee3b5e9d6 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -234,7 +234,8 @@ struct ClassFlags
         hasTypeInfo = 0x20,
         isAbstract = 0x40,
         isCPPclass = 0x80,
-        hasDtor = 0x100
+        hasDtor = 0x100,
+        hasNameSig = 0x200,
     };
 };
 
diff --git a/gcc/d/dmd/basicmangle.d b/gcc/d/dmd/basicmangle.d
new file mode 100644
index 0000000000000000000000000000000000000000..52534fa3526bad4038b7c6b7560832b611f3fd46
--- /dev/null
+++ b/gcc/d/dmd/basicmangle.d
@@ -0,0 +1,109 @@
+/**
+ * Defines the building blocks for creating the mangled names for basic types.
+ *
+ * Copyright:   Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
+ * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/basicmangle.d, _basicmangle.d)
+ * Documentation:  https://dlang.org/phobos/dmd_basicmangle.html
+ * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/basicmangle.d
+ */
+module dmd.basicmangle;
+
+import dmd.astenums;
+import dmd.common.outbuffer : OutBuffer;
+
+/// Type mangling mapping for basic, derived and user defined types
+immutable char[TMAX] mangleChar =
+[
+    Tchar        : 'a',
+    Tbool        : 'b',
+    Tcomplex80   : 'c',
+    Tfloat64     : 'd',
+    Tfloat80     : 'e',
+    Tfloat32     : 'f',
+    Tint8        : 'g',
+    Tuns8        : 'h',
+    Tint32       : 'i',
+    Timaginary80 : 'j',
+    Tuns32       : 'k',
+    Tint64       : 'l',
+    Tuns64       : 'm',
+    Tnull        : 'n',
+    Timaginary32 : 'o',
+    Timaginary64 : 'p',
+    Tcomplex32   : 'q',
+    Tcomplex64   : 'r',
+    Tint16       : 's',
+    Tuns16       : 't',
+    Twchar       : 'u',
+    Tvoid        : 'v',
+    Tdchar       : 'w',
+    //              x   // const
+    //              y   // immutable
+    Tint128      : 'z', // zi
+    Tuns128      : 'z', // zk
+
+    Tarray       : 'A',
+    Ttuple       : 'B',
+    Tclass       : 'C',
+    Tdelegate    : 'D',
+    Tenum        : 'E',
+    Tfunction    : 'F', // D function
+    Tsarray      : 'G',
+    Taarray      : 'H',
+    //              I   // in
+    //              J   // out
+    //              K   // ref
+    //              L   // lazy
+    //              M   // has this, or scope
+    //              N   // Nh:vector Ng:wild Nn:noreturn
+    //              O   // shared
+    Tpointer     : 'P',
+    //              Q   // Type/symbol/identifier backward reference
+    Treference   : 'R',
+    Tstruct      : 'S',
+    //              T   // Ttypedef
+    //              U   // C function
+    //              W   // Windows function
+    //              X   // variadic T t...)
+    //              Y   // variadic T t,...)
+    //              Z   // not variadic, end of parameters
+
+    // '@' shouldn't appear anywhere in the deco'd names
+    Tnone        : '@',
+    Tident       : '@',
+    Tinstance    : '@',
+    Terror       : '@',
+    Ttypeof      : '@',
+    Tslice       : '@',
+    Treturn      : '@',
+    Tvector      : '@',
+    Ttraits      : '@',
+    Tmixin       : '@',
+    Ttag         : '@',
+    Tnoreturn    : '@',         // becomes 'Nn'
+];
+
+unittest
+{
+    foreach (i, mangle; mangleChar)
+    {
+        if (mangle == char.init)
+        {
+            import core.stdc.stdio;
+            fprintf(stderr, "ty = %u\n", cast(uint)i);
+            assert(0);
+        }
+    }
+}
+
+/***********************
+ * Mangle basic type ty to buf.
+ */
+void tyToDecoBuffer(ref OutBuffer buf, int ty) @safe
+{
+    const c = mangleChar[ty];
+    buf.writeByte(c);
+    if (c == 'z')
+        buf.writeByte(ty == Tint128 ? 'i' : 'k');
+}
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index 6fbf8e284deb47ed671ee7d3c4478a7421ecce10..46470ee9e3725582e2e32a996abfbec45a718eea 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -27,6 +27,7 @@ import dmd.errors;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
+import dmd.funcsem;
 import dmd.globals;
 import dmd.id;
 import dmd.identifier;
@@ -905,7 +906,7 @@ void buildDtors(AggregateDeclaration ad, Scope* sc)
                 a.addMember(sc, ad); // temporarily add to symbol table
             }
 
-            sdv.dtor.functionSemantic();
+            functionSemantic(sdv.dtor);
 
             stc = mergeFuncAttrs(stc, sdv.dtor);
             if (stc & STC.disable)
@@ -1154,7 +1155,7 @@ private DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
     ad.members.push(func);
     func.addMember(sc2, ad);
     func.dsymbolSemantic(sc2);
-    func.functionSemantic(); // to infer attributes
+    functionSemantic(func); // to infer attributes
 
     sc2.pop();
     return func;
@@ -1336,7 +1337,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
         // perform semantic on the member postblit in order to
         // be able to aggregate it later on with the rest of the
         // postblits
-        sdv.postblit.functionSemantic();
+        functionSemantic(sdv.postblit);
 
         stc = mergeFuncAttrs(stc, sdv.postblit);
         stc = mergeFuncAttrs(stc, sdv.dtor);
@@ -1401,7 +1402,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
          */
         if (sdv.dtor)
         {
-            sdv.dtor.functionSemantic();
+            functionSemantic(sdv.dtor);
 
             // keep a list of fields that need to be destroyed in case
             // of a future postblit failure
diff --git a/gcc/d/dmd/common/outbuffer.d b/gcc/d/dmd/common/outbuffer.d
index cff08ec5d435670996bc0dbd8a0f76a5039dcf88..cb2439ff746d859eb9b2339b694ef2341e93810a 100644
--- a/gcc/d/dmd/common/outbuffer.d
+++ b/gcc/d/dmd/common/outbuffer.d
@@ -755,6 +755,25 @@ struct OutBuffer
         } while (value);
     }
 
+    /**
+     * Write an array as a string of hexadecimal digits
+     * Params:
+     *     data = bytes to write
+     *     upperCase = whether to upper case hex digits A-F
+     */
+    void writeHexString(scope const(ubyte)[] data, bool upperCase) pure nothrow @safe
+    {
+        auto slice = this.allocate(2 * data.length);
+        const a = upperCase ? 'A' : 'a';
+        foreach (i, c; data)
+        {
+            char hi = (c >> 4) & 0xF;
+            slice[i * 2] = cast(char)(hi < 10 ? hi + '0' : hi - 10 + a);
+            char lo = c & 0xF;
+            slice[i * 2 + 1] = cast(char)(lo < 10 ? lo + '0' : lo - 10 + a);
+        }
+    }
+
     /**
     Destructively saves the contents of `this` to `filename`. As an
     optimization, if the file already has identical contents with the buffer,
@@ -943,3 +962,11 @@ unittest
     else
         assert(buf[] == "\nabc\n\n");
 }
+
+unittest
+{
+    OutBuffer buf;
+    buf.writeHexString([0xAA, 0xBB], false);
+    buf.writeHexString([0xCC], true);
+    assert(buf[] == "aabbCC");
+}
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index 1b32ff774c87248dcb6c52a00c47bceb455ceb2c..e194664383e9a91dccfa9be33c18ad64fddd2597 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -548,8 +548,6 @@ extern (C++) final class DebugCondition : DVCondition
     /// Ditto
     extern(D) static void addGlobalIdent(const(char)[] ident)
     {
-        if (!global.debugids)
-            global.debugids = new Identifiers();
         global.debugids.push(Identifier.idPool(ident));
     }
 
@@ -579,7 +577,7 @@ extern (C++) final class DebugCondition : DVCondition
             bool definedInModule = false;
             if (ident)
             {
-                if (findCondition(mod.debugids, ident))
+                if (mod.debugids && findCondition(*mod.debugids, ident))
                 {
                     inc = Include.yes;
                     definedInModule = true;
@@ -830,8 +828,6 @@ extern (C++) final class VersionCondition : DVCondition
     /// Ditto
     extern(D) static void addPredefinedGlobalIdent(const(char)[] ident)
     {
-        if (!global.versionids)
-            global.versionids = new Identifiers();
         global.versionids.push(Identifier.idPool(ident));
     }
 
@@ -861,7 +857,7 @@ extern (C++) final class VersionCondition : DVCondition
             bool definedInModule = false;
             if (ident)
             {
-                if (findCondition(mod.versionids, ident))
+                if (mod.versionids && findCondition(*mod.versionids, ident))
                 {
                     inc = Include.yes;
                     definedInModule = true;
@@ -983,15 +979,12 @@ extern (C++) final class StaticIfCondition : Condition
  * Returns:
  *      true if found
  */
-bool findCondition(Identifiers* ids, Identifier ident) @safe nothrow pure
+bool findCondition(ref Identifiers ids, Identifier ident) @safe nothrow pure
 {
-    if (ids)
+    foreach (id; ids)
     {
-        foreach (id; *ids)
-        {
-            if (id == ident)
-                return true;
-        }
+        if (id == ident)
+            return true;
     }
     return false;
 }
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index cee1f6364bc1537620c9c4fc53fc6298984f265a..41fed9cae49678284496c00563b0c757f544f5e6 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -711,7 +711,7 @@ UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e
             cmp = 1; // if dim1 winds up being 0
             foreach (i; 0 .. dim1)
             {
-                uinteger_t c = es1.getCodeUnit(i);
+                uinteger_t c = es1.getIndex(i);
                 auto ee2 = es2[i];
                 if (ee2.isConst() != 1)
                 {
@@ -1119,7 +1119,7 @@ UnionExp Index(Type type, Expression e1, Expression e2, bool indexIsInBounds)
         }
         else
         {
-            emplaceExp!(IntegerExp)(&ue, loc, es1.getCodeUnit(cast(size_t) i), type);
+            emplaceExp!(IntegerExp)(&ue, loc, es1.getIndex(cast(size_t) i), type);
         }
     }
     else if (e1.type.toBasetype().ty == Tsarray && e2.op == EXP.int64)
@@ -1282,7 +1282,7 @@ void sliceAssignArrayLiteralFromString(ArrayLiteralExp existingAE, const StringE
     Type elemType = existingAE.type.nextOf();
     foreach (j; 0 .. len)
     {
-        const val = newval.getCodeUnit(j);
+        const val = newval.getIndex(j);
         (*existingAE.elements)[j + firstIndex] = new IntegerExp(newval.loc, val, elemType);
     }
 }
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index 5fe1e7dccb01043b0263ff245898928c154beccd..af83aad554548fc2e5c848bed1779bd4596f7934 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -568,6 +568,9 @@ StringExp createBlockDuplicatedStringLiteral(UnionExp* pue, const ref Loc loc, T
         case 4:
             (cast(dchar*)s)[elemi] = value;
             break;
+        case 8:
+            (cast(ulong*)s)[elemi] = value;
+            break;
         default:
             assert(0);
         }
@@ -1494,7 +1497,7 @@ Expression ctfeIndex(UnionExp* pue, const ref Loc loc, Type type, Expression e1,
             error(loc, "string index %llu is out of bounds `[0 .. %llu]`", indx, cast(ulong)es1.len);
             return CTFEExp.cantexp;
         }
-        emplaceExp!IntegerExp(pue, loc, es1.getCodeUnit(cast(size_t) indx), type);
+        emplaceExp!IntegerExp(pue, loc, es1.getIndex(cast(size_t) indx), type);
         return pue.exp();
     }
 
@@ -1704,7 +1707,7 @@ Expression changeArrayLiteralLength(UnionExp* pue, const ref Loc loc, TypeArray
         void* s = mem.xcalloc(newlen + 1, oldse.sz);
         const data = oldse.peekData();
         memcpy(s, data.ptr, copylen * oldse.sz);
-        const defaultValue = cast(uint)defaultElem.toInteger();
+        const defaultValue = cast(ulong)defaultElem.toInteger();
         foreach (size_t elemi; copylen .. newlen)
         {
             switch (oldse.sz)
@@ -1718,6 +1721,9 @@ Expression changeArrayLiteralLength(UnionExp* pue, const ref Loc loc, TypeArray
             case 4:
                 (cast(dchar*)s)[cast(size_t)(indxlo + elemi)] = cast(dchar)defaultValue;
                 break;
+            case 8:
+                (cast(ulong*)s)[cast(size_t)(indxlo + elemi)] = cast(ulong)defaultValue;
+                break;
             default:
                 assert(0);
             }
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index 405e8170b2c825819a6c6f468e0c24deda270cbf..7e5e7e44178909d77138d74a5cc01e3a5ccd3fea 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -123,6 +123,7 @@ extern (C++) struct BaseClass
     }
 }
 
+// These must match the values in druntime/src/object.d
 enum ClassFlags : uint
 {
     none          = 0x0,
@@ -135,6 +136,7 @@ enum ClassFlags : uint
     isAbstract    = 0x40,
     isCPPclass    = 0x80,
     hasDtor       = 0x100,
+    hasNameSig    = 0x200,
 }
 
 /***********************************************************
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 0e327bedfbd23415c97e990e008ed6d83de02cfb..e4efbbcc91bed812e03234e2b12dc796fa1a8152 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -30,6 +30,9 @@ class StructDeclaration;
 struct IntRange;
 struct AttributeViolation;
 
+bool functionSemantic(FuncDeclaration* fd);
+bool functionSemantic3(FuncDeclaration* fd);
+
 //enum STC : ulong from astenums.d:
 
     #define STCundefined          0ULL
@@ -698,14 +701,12 @@ public:
     FuncDeclaration *fdensure(FuncDeclaration *fde);
     Expressions *fdrequireParams(Expressions *fdrp);
     Expressions *fdensureParams(Expressions *fdep);
-    bool functionSemantic();
-    bool functionSemantic3();
     bool equals(const RootObject * const o) const override final;
 
     int findVtblIndex(Dsymbols *vtbl, int dim);
     bool overloadInsert(Dsymbol *s) override;
     bool inUnittest();
-    MATCH leastAsSpecialized(FuncDeclaration *g, Identifiers *names);
+    static MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, Identifiers *names);
     LabelDsymbol *searchLabel(Identifier *ident, const Loc &loc);
     const char *toPrettyChars(bool QualifyTypes = false) override;
     const char *toFullSignature();  // for diagnostics, e.g. 'int foo(int x, int y) pure'
diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index 5464ff99f58ce2945be1ce55cc0911145550dc70..9abdebd6adcfebdd7dd7782b315b7367e04b363c 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/dmd/denum.d
@@ -122,91 +122,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
         return isSpecialEnumIdent(ident) && memtype;
     }
 
-    Expression getDefaultValue(const ref Loc loc)
-    {
-        Expression handleErrors(){
-            defaultval = ErrorExp.get();
-            return defaultval;
-        }
-        //printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars());
-        // https://issues.dlang.org/show_bug.cgi?id=23904
-        // Return defaultval only if it is not ErrorExp.
-        // A speculative context may set defaultval to ErrorExp;
-        // subsequent non-speculative contexts need to be able
-        // to print the error.
-        if (defaultval && !defaultval.isErrorExp())
-            return defaultval;
-
-        if (isCsymbol())
-            return memtype.defaultInit(loc, true);
-
-        if (_scope)
-            dsymbolSemantic(this, _scope);
-        if (errors)
-            return handleErrors();
-        if (!members)
-        {
-            if (isSpecial())
-            {
-                /* Allow these special enums to not need a member list
-                 */
-                return defaultval = memtype.defaultInit(loc);
-            }
-
-            error(loc, "%s `%s` is opaque and has no default initializer", kind, toPrettyChars);
-            return handleErrors();
-        }
-
-        foreach (const i; 0 .. members.length)
-        {
-            EnumMember em = (*members)[i].isEnumMember();
-            if (em)
-            {
-                if (em.semanticRun < PASS.semanticdone)
-                {
-                    error(loc, "%s `%s` forward reference of `%s.init`", kind, toPrettyChars, toChars());
-                    return handleErrors();
-                }
-
-                defaultval = em.value;
-                return defaultval;
-            }
-        }
-        return handleErrors();
-    }
-
-    Type getMemtype(const ref Loc loc)
-    {
-        if (_scope)
-        {
-            /* Enum is forward referenced. We don't need to resolve the whole thing,
-             * just the base type
-             */
-            if (memtype)
-            {
-                Loc locx = loc.isValid() ? loc : this.loc;
-                memtype = memtype.typeSemantic(locx, _scope);
-            }
-            else
-            {
-                // Run semantic to get the type from a possible first member value
-                dsymbolSemantic(this, _scope);
-            }
-        }
-        if (!memtype)
-        {
-            if (!isAnonymous() && (members || semanticRun >= PASS.semanticdone))
-                memtype = Type.tint32;
-            else
-            {
-                Loc locx = loc.isValid() ? loc : this.loc;
-                error(locx, "is forward referenced looking for base type");
-                return Type.terror;
-            }
-        }
-        return memtype;
-    }
-
     override inout(EnumDeclaration) isEnumDeclaration() inout
     {
         return this;
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index a3b38d9fee3e43098f4a41e9f7921c2698b1f1c7..d8069c63a56bfd8ff34f90039da5c744ece52eb3 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -33,6 +33,7 @@ import dmd.errors;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
+import dmd.funcsem;
 import dmd.globals;
 import dmd.hdrgen;
 import dmd.id;
@@ -440,7 +441,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
         fdError("circular dependency. Functions cannot be interpreted while being compiled");
         return CTFEExp.cantexp;
     }
-    if (!fd.functionSemantic3())
+    if (!functionSemantic3(fd))
         return CTFEExp.cantexp;
     if (fd.semanticRun < PASS.semantic3done)
     {
@@ -6097,11 +6098,35 @@ public:
             result.type = e.to;
             return;
         }
+
         // Disallow array type painting, except for conversions between built-in
         // types of identical size.
         if ((e.to.ty == Tsarray || e.to.ty == Tarray) && (e1.type.ty == Tsarray || e1.type.ty == Tarray) && !isSafePointerCast(e1.type.nextOf(), e.to.nextOf()))
         {
+            auto se = e1.isStringExp();
+            // Allow casting a hex string literal to short[], int[] or long[]
+            if (se && se.hexString && se.postfix == StringExp.NoPostfix)
+            {
+                const sz = cast(size_t) e.to.nextOf().size;
+                if ((se.len % sz) != 0)
+                {
+                    error(e.loc, "hex string length %d must be a multiple of %d to cast to `%s`",
+                        cast(int) se.len, cast(int) sz, e.to.toChars());
+                    result = CTFEExp.cantexp;
+                    return;
+                }
+
+                auto str = arrayCastBigEndian((cast(const ubyte[]) se.peekString()), sz);
+                emplaceExp!(StringExp)(pue, e1.loc, str, se.len / sz, cast(ubyte) sz);
+                result = pue.exp();
+                result.type = e.to;
+                return;
+            }
             error(e.loc, "array cast from `%s` to `%s` is not supported at compile time", e1.type.toChars(), e.to.toChars());
+            if (se && se.hexString && se.postfix != StringExp.NoPostfix)
+                errorSupplemental(e.loc, "perhaps remove postfix `%s` from hex string",
+                    (cast(char) se.postfix ~ "\0").ptr);
+
             result = CTFEExp.cantexp;
             return;
         }
@@ -7719,3 +7744,44 @@ private void removeHookTraceImpl(ref CallExp ce, ref FuncDeclaration fd)
     if (global.params.v.verbose)
         message("strip     %s =>\n          %s", oldCE.toChars(), ce.toChars());
 }
+
+/**
+ * Cast a `ubyte[]` to an array of larger integers as if we are on a big endian architecture
+ * Params:
+ *   data = array with big endian data
+ *   size = 1 for ubyte[], 2 for ushort[], 4 for uint[], 8 for ulong[]
+ * Returns: copy of `data`, with bytes shuffled if compiled for `version(LittleEndian)`
+ */
+ubyte[] arrayCastBigEndian(const ubyte[] data, size_t size)
+{
+    ubyte[] impl(T)()
+    {
+        auto result = new T[](data.length / T.sizeof);
+        foreach (i; 0 .. result.length)
+        {
+            result[i] = 0;
+            foreach (j; 0 .. T.sizeof)
+            {
+                result[i] |= T(data[i * T.sizeof + j]) << ((T.sizeof - 1 - j) * 8);
+            }
+        }
+        return cast(ubyte[]) result;
+    }
+    switch (size)
+    {
+        case 1: return data.dup;
+        case 2: return impl!ushort;
+        case 4: return impl!uint;
+        case 8: return impl!ulong;
+        default: assert(0);
+    }
+}
+
+unittest
+{
+    ubyte[] data = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22];
+    assert(cast(ulong[]) arrayCastBigEndian(data, 8) == [0xAABBCCDDEEFF1122]);
+    assert(cast(uint[]) arrayCastBigEndian(data, 4) == [0xAABBCCDD, 0xEEFF1122]);
+    assert(cast(ushort[]) arrayCastBigEndian(data, 2) == [0xAABB, 0xCCDD, 0xEEFF, 0x1122]);
+    assert(cast(ubyte[]) arrayCastBigEndian(data, 1) == data);
+}
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index 15b77eaac4c8a4918d02794a88e59e9bf065a65f..5bd1379d17053dec994a1e0ba99f9bae1bd7dbe6 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -137,6 +137,7 @@ import core.stdc.string;
 import dmd.aggregate;
 import dmd.arraytypes;
 import dmd.astenums;
+import dmd.basicmangle;
 import dmd.dclass;
 import dmd.declaration;
 import dmd.dinterpret;
@@ -161,89 +162,6 @@ import dmd.target;
 import dmd.tokens;
 import dmd.visitor;
 
-private immutable char[TMAX] mangleChar =
-[
-    Tchar        : 'a',
-    Tbool        : 'b',
-    Tcomplex80   : 'c',
-    Tfloat64     : 'd',
-    Tfloat80     : 'e',
-    Tfloat32     : 'f',
-    Tint8        : 'g',
-    Tuns8        : 'h',
-    Tint32       : 'i',
-    Timaginary80 : 'j',
-    Tuns32       : 'k',
-    Tint64       : 'l',
-    Tuns64       : 'm',
-    Tnull        : 'n',
-    Timaginary32 : 'o',
-    Timaginary64 : 'p',
-    Tcomplex32   : 'q',
-    Tcomplex64   : 'r',
-    Tint16       : 's',
-    Tuns16       : 't',
-    Twchar       : 'u',
-    Tvoid        : 'v',
-    Tdchar       : 'w',
-    //              x   // const
-    //              y   // immutable
-    Tint128      : 'z', // zi
-    Tuns128      : 'z', // zk
-
-    Tarray       : 'A',
-    Ttuple       : 'B',
-    Tclass       : 'C',
-    Tdelegate    : 'D',
-    Tenum        : 'E',
-    Tfunction    : 'F', // D function
-    Tsarray      : 'G',
-    Taarray      : 'H',
-    //              I   // in
-    //              J   // out
-    //              K   // ref
-    //              L   // lazy
-    //              M   // has this, or scope
-    //              N   // Nh:vector Ng:wild Nn:noreturn
-    //              O   // shared
-    Tpointer     : 'P',
-    //              Q   // Type/symbol/identifier backward reference
-    Treference   : 'R',
-    Tstruct      : 'S',
-    //              T   // Ttypedef
-    //              U   // C function
-    //              W   // Windows function
-    //              X   // variadic T t...)
-    //              Y   // variadic T t,...)
-    //              Z   // not variadic, end of parameters
-
-    // '@' shouldn't appear anywhere in the deco'd names
-    Tnone        : '@',
-    Tident       : '@',
-    Tinstance    : '@',
-    Terror       : '@',
-    Ttypeof      : '@',
-    Tslice       : '@',
-    Treturn      : '@',
-    Tvector      : '@',
-    Ttraits      : '@',
-    Tmixin       : '@',
-    Ttag         : '@',
-    Tnoreturn    : '@',         // becomes 'Nn'
-];
-
-unittest
-{
-    foreach (i, mangle; mangleChar)
-    {
-        if (mangle == char.init)
-        {
-            fprintf(stderr, "ty = %u\n", cast(uint)i);
-            assert(0);
-        }
-    }
-}
-
 /************************************************
  * Append the mangling of type `t` to `buf`.
  * Params:
@@ -584,6 +502,20 @@ public:
             toBuffer(*buf, id.toString(), s);
     }
 
+    void mangleInteger(dinteger_t v)
+    {
+        if (cast(sinteger_t) v < 0)
+        {
+            buf.writeByte('N');
+            buf.print(-v);
+        }
+        else
+        {
+            buf.writeByte('i');
+            buf.print(v);
+        }
+    }
+
     ////////////////////////////////////////////////////////////////////////////
     void mangleDecl(Declaration sthis)
     {
@@ -991,17 +923,7 @@ public:
 
     override void visit(IntegerExp e)
     {
-        const v = e.toInteger();
-        if (cast(sinteger_t)v < 0)
-        {
-            buf.writeByte('N');
-            buf.print(-v);
-        }
-        else
-        {
-            buf.writeByte('i');
-            buf.print(v);
-        }
+        mangleInteger(e.toInteger());
     }
 
     override void visit(RealExp e)
@@ -1028,6 +950,7 @@ public:
         char m;
         OutBuffer tmp;
         const(char)[] q;
+
         /* Write string in UTF-8 format
          */
         switch (e.sz)
@@ -1065,7 +988,15 @@ public:
             q = tmp[];
             break;
         }
-
+        case 8:
+            // String of size 8 has to be hexstring cast to long[], mangle as array literal
+            buf.writeByte('A');
+            buf.print(e.len);
+            foreach (i; 0 .. e.len)
+            {
+                mangleInteger(e.getIndex(i));
+            }
+            return;
         default:
             assert(0);
         }
@@ -1073,14 +1004,7 @@ public:
         buf.writeByte(m);
         buf.print(q.length);
         buf.writeByte('_');    // nbytes <= 11
-        auto slice = buf.allocate(2 * q.length);
-        foreach (i, c; q)
-        {
-            char hi = (c >> 4) & 0xF;
-            slice[i * 2] = cast(char)(hi < 10 ? hi + '0' : hi - 10 + 'a');
-            char lo = c & 0xF;
-            slice[i * 2 + 1] = cast(char)(lo < 10 ? lo + '0' : lo - 10 + 'a');
-        }
+        buf.writeHexString(cast(const(ubyte)[]) q, false);
     }
 
     override void visit(ArrayLiteralExp e)
@@ -1168,6 +1092,7 @@ private struct Backref
         {
             if (t.isFunction_Delegate_PtrToFunction())
             {
+                import dmd.typesem : merge2;
                 t = t.merge2();
             }
         }
@@ -1213,19 +1138,6 @@ private struct Backref
     AssocArray!(Identifier, size_t) idents; /// Identifier => (offset+1) in buf
 }
 
-
-/***********************
- * Mangle basic type ty to buf.
- */
-
-private void tyToDecoBuffer(ref OutBuffer buf, int ty) @safe
-{
-    const c = mangleChar[ty];
-    buf.writeByte(c);
-    if (c == 'z')
-        buf.writeByte(ty == Tint128 ? 'i' : 'k');
-}
-
 /*********************************
  * Mangling for mod.
  */
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 59d40655253be61e3cd39ba17ae924c1df6ade15..6167e2a748668b9a8ddce58153570f3eab500dc1 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -490,7 +490,7 @@ extern (C++) final class Module : Package
 
     extern (D) static const(char)[] find(const(char)[] filename)
     {
-        return global.fileManager.lookForSourceFile(filename, global.path ? (*global.path)[] : null);
+        return global.fileManager.lookForSourceFile(filename, global.path[]);
     }
 
     extern (C++) static Module load(const ref Loc loc, Identifiers* packages, Identifier ident)
@@ -644,9 +644,9 @@ extern (C++) final class Module : Package
         {
             /* Print path
              */
-            if (global.path)
+            if (global.path.length)
             {
-                foreach (i, p; *global.path)
+                foreach (i, p; global.path[])
                     fprintf(stderr, "import path[%llu] = %s\n", cast(ulong)i, p);
             }
             else
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index ec3cc91409b9a4b93a4789c1f778f11337acd931..bcf358cb5e9dbec3dced2a41861f2f74425471b3 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -5204,6 +5204,7 @@ void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset)
             highlight = "$(D_COMMENT ";
             break;
         case TOK.string_:
+        case TOK.interpolated:
             highlight = "$(D_STRING ";
             break;
         default:
@@ -5216,7 +5217,7 @@ void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t offset)
             res.writestring(highlight);
             size_t o = res.length;
             highlightCode3(sc, res, tok.ptr, lex.p);
-            if (tok.value == TOK.comment || tok.value == TOK.string_)
+            if (tok.value == TOK.comment || tok.value == TOK.string_ || tok.value == TOK.interpolated)
                 /* https://issues.dlang.org/show_bug.cgi?id=7656
                  * https://issues.dlang.org/show_bug.cgi?id=7715
                  * https://issues.dlang.org/show_bug.cgi?id=10519
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index 5683d5fb1d575572e643219e46d3949608b6c0ce..7546fb6146b421799003cbb17ce134eb5bb4caa8 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -616,7 +616,7 @@ bool _isZeroInit(Expression exp)
 
             foreach (i; 0 .. se.len)
             {
-                if (se.getCodeUnit(i))
+                if (se.getIndex(i) != 0)
                     return false;
             }
             return true;
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index e9cdb945b5771996f8d97d367f59094fdc9f2d41..658beafdf839c148b951ec7305a9f76e5c24ad6f 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -38,11 +38,13 @@ import dmd.dstruct;
 import dmd.dsymbol;
 import dmd.dtemplate;
 import dmd.dversion;
+import dmd.enumsem;
 import dmd.errors;
 import dmd.escape;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
+import dmd.funcsem;
 import dmd.globals;
 import dmd.id;
 import dmd.identifier;
@@ -440,6 +442,15 @@ private bool checkDeprecatedAliasThis(AliasThis at, const ref Loc loc, Scope* sc
     return false;
 }
 
+// Save the scope and defer semantic analysis on the Dsymbol.
+void deferDsymbolSemantic(Scope* sc, Dsymbol s, Scope *scx)
+{
+    s._scope = scx ? scx : sc.copy();
+    s._scope.setNoFree();
+    Module.addDeferredSemantic(s);
+}
+
+
 private extern(C++) final class DsymbolSemanticVisitor : Visitor
 {
     alias visit = Visitor.visit;
@@ -450,14 +461,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         this.sc = sc;
     }
 
-    // Save the scope and defer semantic analysis on the Dsymbol.
-    private void deferDsymbolSemantic(Dsymbol s, Scope *scx)
-    {
-        s._scope = scx ? scx : sc.copy();
-        s._scope.setNoFree();
-        Module.addDeferredSemantic(s);
-    }
-
     override void visit(Dsymbol dsym)
     {
         .error(dsym.loc, "%s `%s` %p has no semantic routine", dsym.kind, dsym.toPrettyChars, dsym);
@@ -2301,543 +2304,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
     override void visit(EnumDeclaration ed)
     {
-        //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc.scopesym, sc.scopesym.toChars(), ed.toChars());
-        //printf("EnumDeclaration::semantic() %p %s\n", ed, ed.toChars());
-        if (ed.semanticRun >= PASS.semanticdone)
-            return; // semantic() already completed
-        if (ed.semanticRun == PASS.semantic)
-        {
-            assert(ed.memtype);
-            error(ed.loc, "circular reference to enum base type `%s`", ed.memtype.toChars());
-            ed.errors = true;
-            ed.semanticRun = PASS.semanticdone;
-            return;
-        }
-        Scope* scx = null;
-        if (ed._scope)
-        {
-            sc = ed._scope;
-            scx = ed._scope; // save so we don't make redundant copies
-            ed._scope = null;
-        }
-
-        if (!sc)
-            return;
-
-        ed.parent = sc.parent;
-        ed.type = ed.type.typeSemantic(ed.loc, sc);
-
-        ed.visibility = sc.visibility;
-        if (sc.stc & STC.deprecated_)
-            ed.isdeprecated = true;
-        ed.userAttribDecl = sc.userAttribDecl;
-        ed.cppnamespace = sc.namespace;
-
-        ed.semanticRun = PASS.semantic;
-        UserAttributeDeclaration.checkGNUABITag(ed, sc.linkage);
-        checkMustUseReserved(ed);
-
-        if (!ed.members && !ed.memtype) // enum ident;
-        {
-            ed.semanticRun = PASS.semanticdone;
-            return;
-        }
-
-        if (!ed.symtab)
-            ed.symtab = new DsymbolTable();
-
-        /* The separate, and distinct, cases are:
-         *  1. enum { ... }
-         *  2. enum : memtype { ... }
-         *  3. enum ident { ... }
-         *  4. enum ident : memtype { ... }
-         *  5. enum ident : memtype;
-         *  6. enum ident;
-         */
-
-        if (ed.memtype)
-        {
-            ed.memtype = ed.memtype.typeSemantic(ed.loc, sc);
-
-            /* Check to see if memtype is forward referenced
-             */
-            if (auto te = ed.memtype.isTypeEnum())
-            {
-                auto sym = te.toDsymbol(sc).isEnumDeclaration();
-                // Special enums like __c_[u]long[long] are fine to forward reference
-                // see https://issues.dlang.org/show_bug.cgi?id=20599
-                if (!sym.isSpecial() && (!sym.memtype ||  !sym.members || !sym.symtab || sym._scope))
-                {
-                    // memtype is forward referenced, so try again later
-                    deferDsymbolSemantic(ed, scx);
-                    //printf("\tdeferring %s\n", toChars());
-                    ed.semanticRun = PASS.initial;
-                    return;
-                }
-                else
-                    // Ensure that semantic is run to detect. e.g. invalid forward references
-                    sym.dsymbolSemantic(sc);
-            }
-            if (ed.memtype.ty == Tvoid)
-            {
-                .error(ed.loc, "%s `%s` base type must not be `void`", ed.kind, ed.toPrettyChars);
-                ed.memtype = Type.terror;
-            }
-            if (ed.memtype.ty == Terror)
-            {
-                ed.errors = true;
-                // poison all the members
-                ed.members.foreachDsymbol( (s) { s.errors = true; } );
-                ed.semanticRun = PASS.semanticdone;
-                return;
-            }
-        }
-
-        if (!ed.members) // enum ident : memtype;
-        {
-            ed.semanticRun = PASS.semanticdone;
-            return;
-        }
-
-        if (ed.members.length == 0)
-        {
-            .error(ed.loc, "%s `%s enum `%s` must have at least one member", ed.kind, ed.toPrettyChars, ed.toChars());
-            ed.errors = true;
-            ed.semanticRun = PASS.semanticdone;
-            return;
-        }
-
-        if (!(sc.flags & SCOPE.Cfile))  // C enum remains incomplete until members are done
-            ed.semanticRun = PASS.semanticdone;
-
-        version (none)
-        {
-            // @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
-            // Deprecated in 2.100
-            // Make an error in 2.110
-            if (sc.stc & STC.scope_)
-                deprecation(ed.loc, "`scope` as a type constraint is deprecated.  Use `scope` at the usage site.");
-        }
-
-        Scope* sce;
-        if (ed.isAnonymous())
-            sce = sc;
-        else
-        {
-            sce = sc.push(ed);
-            sce.parent = ed;
-        }
-        sce = sce.startCTFE();
-        sce.setNoFree(); // needed for getMaxMinValue()
-
-        /* Each enum member gets the sce scope
-         */
-        ed.members.foreachDsymbol( (s)
-        {
-            EnumMember em = s.isEnumMember();
-            if (em)
-                em._scope = sce;
-        });
-
-        /* addMember() is not called when the EnumDeclaration appears as a function statement,
-         * so we have to do what addMember() does and install the enum members in the right symbol
-         * table
-         */
-        addEnumMembersToSymtab(ed, sc, sc.getScopesym());
-
-        if (sc.flags & SCOPE.Cfile)
-        {
-            /* C11 6.7.2.2
-             */
-            Type commonType = ed.memtype;
-            if (!commonType)
-                commonType = Type.tint32;
-            ulong nextValue = 0;        // C11 6.7.2.2-3 first member value defaults to 0
-
-            // C11 6.7.2.2-2 value must be representable as an int.
-            // The sizemask represents all values that int will fit into,
-            // from 0..uint.max.  We want to cover int.min..uint.max.
-            IntRange ir = IntRange.fromType(commonType);
-
-            void emSemantic(EnumMember em, ref ulong nextValue)
-            {
-                static void errorReturn(EnumMember em)
-                {
-                    em.value = ErrorExp.get();
-                    em.errors = true;
-                    em.semanticRun = PASS.semanticdone;
-                }
-
-                em.semanticRun = PASS.semantic;
-                em.type = commonType;
-                em._linkage = LINK.c;
-                em.storage_class |= STC.manifest;
-                if (em.value)
-                {
-                    Expression e = em.value;
-                    assert(e.dyncast() == DYNCAST.expression);
-
-                    /* To merge the type of e with commonType, add 0 of type commonType
-                     */
-                    if (!ed.memtype)
-                        e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType));
-
-                    e = e.expressionSemantic(sc);
-                    e = resolveProperties(sc, e);
-                    e = e.integralPromotions(sc);
-                    e = e.ctfeInterpret();
-                    if (e.op == EXP.error)
-                        return errorReturn(em);
-                    auto ie = e.isIntegerExp();
-                    if (!ie)
-                    {
-                        // C11 6.7.2.2-2
-                        .error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars());
-                        return errorReturn(em);
-                    }
-                    if (ed.memtype && !ir.contains(getIntRange(ie)))
-                    {
-                        // C11 6.7.2.2-2
-                        .error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
-                        return errorReturn(em);
-                    }
-                    nextValue = ie.toInteger();
-                    if (!ed.memtype)
-                        commonType = e.type;
-                    em.value = new IntegerExp(em.loc, nextValue, commonType);
-                }
-                else
-                {
-                    // C11 6.7.2.2-3 add 1 to value of previous enumeration constant
-                    bool first = (em == (*em.ed.members)[0]);
-                    if (!first)
-                    {
-                        Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
-                        if (nextValue == max.toInteger())
-                        {
-                            .error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
-                            return errorReturn(em);
-                        }
-                        nextValue += 1;
-                    }
-                    em.value = new IntegerExp(em.loc, nextValue, commonType);
-                }
-                em.type = commonType;
-                em.semanticRun = PASS.semanticdone;
-            }
-
-            ed.members.foreachDsymbol( (s)
-            {
-                if (EnumMember em = s.isEnumMember())
-                    emSemantic(em, nextValue);
-            });
-
-            if (!ed.memtype)
-            {
-                // cast all members to commonType
-                ed.members.foreachDsymbol( (s)
-                {
-                    if (EnumMember em = s.isEnumMember())
-                    {
-                        em.type = commonType;
-                        em.value = em.value.castTo(sc, commonType);
-                    }
-                });
-            }
-
-            ed.memtype = commonType;
-            ed.semanticRun = PASS.semanticdone;
-            return;
-        }
-
-        ed.members.foreachDsymbol( (s)
-        {
-            if (EnumMember em = s.isEnumMember())
-                em.dsymbolSemantic(em._scope);
-        });
-        //printf("defaultval = %lld\n", defaultval);
-
-        //if (defaultval) printf("defaultval: %s %s\n", defaultval.toChars(), defaultval.type.toChars());
-        //printf("members = %s\n", members.toChars());
+        enumSemantic(sc, ed);
     }
 
     override void visit(EnumMember em)
     {
-        //printf("EnumMember::semantic() %s\n", em.toChars());
-
-        void errorReturn()
-        {
-            em.errors = true;
-            em.semanticRun = PASS.semanticdone;
-        }
-
-        if (em.errors || em.semanticRun >= PASS.semanticdone)
-            return;
-        if (em.semanticRun == PASS.semantic)
-        {
-            .error(em.loc, "%s `%s` circular reference to `enum` member", em.kind, em.toPrettyChars);
-            return errorReturn();
-        }
-        assert(em.ed);
-
-        em.ed.dsymbolSemantic(sc);
-        if (em.ed.errors)
-            return errorReturn();
-        if (em.errors || em.semanticRun >= PASS.semanticdone)
-            return;
-
-        if (em._scope)
-            sc = em._scope;
-        if (!sc)
-            return;
-
-        em.semanticRun = PASS.semantic;
-
-        em.visibility = em.ed.isAnonymous() ? em.ed.visibility : Visibility(Visibility.Kind.public_);
-        em._linkage = LINK.d;
-        em.storage_class |= STC.manifest;
-
-        // https://issues.dlang.org/show_bug.cgi?id=9701
-        if (em.ed.isAnonymous())
-        {
-            if (em.userAttribDecl)
-                em.userAttribDecl.userAttribDecl = em.ed.userAttribDecl;
-            else
-                em.userAttribDecl = em.ed.userAttribDecl;
-        }
-
-        // Eval UDA in this same scope. Issues 19344, 20835, 21122
-        if (em.userAttribDecl)
-        {
-            // Set scope but avoid extra sc.uda attachment inside setScope()
-            auto inneruda = em.userAttribDecl.userAttribDecl;
-            em.userAttribDecl.setScope(sc);
-            em.userAttribDecl.userAttribDecl = inneruda;
-            em.userAttribDecl.dsymbolSemantic(sc);
-        }
-
-        // The first enum member is special
-        bool first = (em == (*em.ed.members)[0]);
-
-        if (em.origType)
-        {
-            em.origType = em.origType.typeSemantic(em.loc, sc);
-            em.type = em.origType;
-            assert(em.value); // "type id;" is not a valid enum member declaration
-        }
-
-        if (em.value)
-        {
-            Expression e = em.value;
-            assert(e.dyncast() == DYNCAST.expression);
-            e = e.expressionSemantic(sc);
-            e = resolveProperties(sc, e);
-            e = e.ctfeInterpret();
-            if (e.op == EXP.error)
-                return errorReturn();
-            if (first && !em.ed.memtype && !em.ed.isAnonymous())
-            {
-                em.ed.memtype = e.type;
-                if (em.ed.memtype.ty == Terror)
-                {
-                    em.ed.errors = true;
-                    return errorReturn();
-                }
-                if (em.ed.memtype.ty != Terror)
-                {
-                    /* https://issues.dlang.org/show_bug.cgi?id=11746
-                     * All of named enum members should have same type
-                     * with the first member. If the following members were referenced
-                     * during the first member semantic, their types should be unified.
-                     */
-                    em.ed.members.foreachDsymbol( (s)
-                    {
-                        EnumMember enm = s.isEnumMember();
-                        if (!enm || enm == em || enm.semanticRun < PASS.semanticdone || enm.origType)
-                            return;
-
-                        //printf("[%d] em = %s, em.semanticRun = %d\n", i, toChars(), em.semanticRun);
-                        Expression ev = enm.value;
-                        ev = ev.implicitCastTo(sc, em.ed.memtype);
-                        ev = ev.ctfeInterpret();
-                        ev = ev.castTo(sc, em.ed.type);
-                        if (ev.op == EXP.error)
-                            em.ed.errors = true;
-                        enm.value = ev;
-                    });
-
-                    if (em.ed.errors)
-                    {
-                        em.ed.memtype = Type.terror;
-                        return errorReturn();
-                    }
-                }
-            }
-
-            if (em.ed.memtype && !em.origType)
-            {
-                e = e.implicitCastTo(sc, em.ed.memtype);
-                e = e.ctfeInterpret();
-
-                // save origValue for better json output
-                em.origValue = e;
-
-                if (!em.ed.isAnonymous())
-                {
-                    e = e.castTo(sc, em.ed.type.addMod(e.type.mod)); // https://issues.dlang.org/show_bug.cgi?id=12385
-                    e = e.ctfeInterpret();
-                }
-            }
-            else if (em.origType)
-            {
-                e = e.implicitCastTo(sc, em.origType);
-                e = e.ctfeInterpret();
-                assert(em.ed.isAnonymous());
-
-                // save origValue for better json output
-                em.origValue = e;
-            }
-            em.value = e;
-        }
-        else if (first)
-        {
-            Type t;
-            if (em.ed.memtype)
-                t = em.ed.memtype;
-            else
-            {
-                t = Type.tint32;
-                if (!em.ed.isAnonymous())
-                    em.ed.memtype = t;
-            }
-            const errors = global.startGagging();
-            Expression e = new IntegerExp(em.loc, 0, t);
-            e = e.ctfeInterpret();
-            if (global.endGagging(errors))
-            {
-                error(em.loc, "cannot generate 0 value of type `%s` for `%s`",
-                    t.toChars(), em.toChars());
-            }
-            // save origValue for better json output
-            em.origValue = e;
-
-            if (!em.ed.isAnonymous())
-            {
-                e = e.castTo(sc, em.ed.type);
-                e = e.ctfeInterpret();
-            }
-            em.value = e;
-        }
-        else
-        {
-            /* Find the previous enum member,
-             * and set this to be the previous value + 1
-             */
-            EnumMember emprev = null;
-            em.ed.members.foreachDsymbol( (s)
-            {
-                if (auto enm = s.isEnumMember())
-                {
-                    if (enm == em)
-                        return 1;       // found
-                    emprev = enm;
-                }
-                return 0;       // continue
-            });
-
-            assert(emprev);
-            if (emprev.semanticRun < PASS.semanticdone) // if forward reference
-                emprev.dsymbolSemantic(emprev._scope); // resolve it
-            if (emprev.errors)
-                return errorReturn();
-
-            auto errors = global.startGagging();
-            Expression eprev = emprev.value;
-            assert(eprev);
-            // .toHeadMutable() due to https://issues.dlang.org/show_bug.cgi?id=18645
-            Type tprev = eprev.type.toHeadMutable().equals(em.ed.type.toHeadMutable())
-                ? em.ed.memtype
-                : eprev.type;
-            /*
-                https://issues.dlang.org/show_bug.cgi?id=20777
-                Previously this used getProperty, which doesn't consider anything user defined,
-                this construct does do that and thus fixes the bug.
-            */
-            Expression emax = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
-            emax = emax.expressionSemantic(sc);
-            emax = emax.ctfeInterpret();
-
-            // check that (eprev != emax)
-            Expression e = new EqualExp(EXP.equal, em.loc, eprev, emax);
-            e = e.expressionSemantic(sc);
-            e = e.ctfeInterpret();
-            if (global.endGagging(errors))
-            {
-                // display an introductory error before showing what actually failed
-                error(em.loc, "cannot check `%s` value for overflow", em.toPrettyChars());
-                // rerun to show errors
-                Expression e2 = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
-                e2 = e2.expressionSemantic(sc);
-                e2 = e2.ctfeInterpret();
-                e2 = new EqualExp(EXP.equal, em.loc, eprev, e2);
-                e2 = e2.expressionSemantic(sc);
-                e2 = e2.ctfeInterpret();
-            }
-            // now any errors are for generating a value
-            if (e.toInteger())
-            {
-                auto mt = em.ed.memtype;
-                if (!mt)
-                    mt = eprev.type;
-                .error(em.loc, "%s `%s` initialization with `%s.%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars,
-                    emprev.ed.toChars(), emprev.toChars(), mt.toChars());
-                return errorReturn();
-            }
-            errors = global.startGagging();
-            // Now set e to (eprev + 1)
-            e = new AddExp(em.loc, eprev, IntegerExp.literal!1);
-            e = e.expressionSemantic(sc);
-            e = e.castTo(sc, eprev.type);
-            e = e.ctfeInterpret();
-            if (global.endGagging(errors))
-            {
-                error(em.loc, "cannot generate value for `%s`", em.toPrettyChars());
-                // rerun to show errors
-                Expression e2 = new AddExp(em.loc, eprev, IntegerExp.literal!1);
-                e2 = e2.expressionSemantic(sc);
-                e2 = e2.castTo(sc, eprev.type);
-                e2 = e2.ctfeInterpret();
-            }
-            // save origValue (without cast) for better json output
-            if (e.op != EXP.error) // avoid duplicate diagnostics
-            {
-                assert(emprev.origValue);
-                em.origValue = new AddExp(em.loc, emprev.origValue, IntegerExp.literal!1);
-                em.origValue = em.origValue.expressionSemantic(sc);
-                em.origValue = em.origValue.ctfeInterpret();
-            }
-
-            if (e.op == EXP.error)
-                return errorReturn();
-            if (e.type.isfloating())
-            {
-                // Check that e != eprev (not always true for floats)
-                Expression etest = new EqualExp(EXP.equal, em.loc, e, eprev);
-                etest = etest.expressionSemantic(sc);
-                etest = etest.ctfeInterpret();
-                if (etest.toInteger())
-                {
-                    .error(em.loc, "%s `%s` has inexact value due to loss of precision", em.kind, em.toPrettyChars);
-                    return errorReturn();
-                }
-            }
-            em.value = e;
-        }
-        if (!em.origType)
-            em.type = em.value.type;
-
-        assert(em.origValue);
-        em.semanticRun = PASS.semanticdone;
+        enumMemberSemantic(sc, em);
     }
 
     override void visit(TemplateDeclaration tempdecl)
@@ -3026,7 +2498,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             if (tm.semanticRun == PASS.initial) // forward reference had occurred
             {
                 //printf("forward reference - deferring\n");
-                return deferDsymbolSemantic(tm, scx);
+                return deferDsymbolSemantic(sc, tm, scx);
             }
 
             tm.inst = tm;
@@ -3740,7 +3212,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                         continue;
                     if (cbd.parent && cbd.parent.isTemplateInstance())
                     {
-                        if (!f2.functionSemantic())
+                        if (!functionSemantic(f2))
                             goto Ldone;
                     }
                     may_override = true;
@@ -4945,7 +4417,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             sc2.pop();
 
             if (log) printf("\tdeferring %s\n", sd.toChars());
-            return deferDsymbolSemantic(sd, scx);
+            return deferDsymbolSemantic(sc, sd, scx);
         }
 
         /* Look for special member functions.
@@ -5336,7 +4808,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             {
                 // Forward referencee of one or more bases, try again later
                 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
-                return deferDsymbolSemantic(cldec, scx);
+                return deferDsymbolSemantic(sc, cldec, scx);
             }
             cldec.baseok = Baseok.done;
 
@@ -5446,7 +4918,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 if (tc.sym._scope)
                     Module.addDeferredSemantic(tc.sym);
                 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
-                return deferDsymbolSemantic(cldec, scx);
+                return deferDsymbolSemantic(sc, cldec, scx);
             }
         }
 
@@ -5563,7 +5035,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             sc2.pop();
 
             //printf("\tdeferring %s\n", toChars());
-            return deferDsymbolSemantic(cldec, scx);
+            return deferDsymbolSemantic(sc, cldec, scx);
         }
 
         /* Look for special member functions.
@@ -5905,7 +5377,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             if (idec.baseok == Baseok.none)
             {
                 // Forward referencee of one or more bases, try again later
-                return deferDsymbolSemantic(idec, scx);
+                return deferDsymbolSemantic(sc, idec, scx);
             }
             idec.baseok = Baseok.done;
 
@@ -5942,7 +5414,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 // Forward referencee of one or more bases, try again later
                 if (tc.sym._scope)
                     Module.addDeferredSemantic(tc.sym);
-                return deferDsymbolSemantic(idec, scx);
+                return deferDsymbolSemantic(sc, idec, scx);
             }
         }
 
@@ -6281,7 +5753,7 @@ private extern(C++) class AddMemberVisitor : Visitor
             }
             else
             {
-                if (findCondition(m.debugidsNot, ds.ident))
+                if (m.debugidsNot && findCondition(*m.debugidsNot, ds.ident))
                 {
                     .error(ds.loc, "%s `%s` defined after use", ds.kind, ds.toPrettyChars);
                     ds.errors = true;
@@ -6319,7 +5791,7 @@ private extern(C++) class AddMemberVisitor : Visitor
             }
             else
             {
-                if (findCondition(m.versionidsNot, vs.ident))
+                if (m.versionidsNot && findCondition(*m.versionidsNot, vs.ident))
                 {
                     .error(vs.loc, "%s `%s` defined after use", vs.kind, vs.toPrettyChars);
                     vs.errors = true;
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 13cc32f73e01617de80cd377307bdf77203bc4eb..465ae7453cdcf271213080ccf98a2f32775d4e66 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -60,6 +60,7 @@ import dmd.errorsink;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
+import dmd.funcsem;
 import dmd.globals;
 import dmd.hdrgen;
 import dmd.id;
@@ -76,6 +77,7 @@ import dmd.common.outbuffer;
 import dmd.rootobject;
 import dmd.semantic2;
 import dmd.semantic3;
+import dmd.templatesem;
 import dmd.tokens;
 import dmd.typesem;
 import dmd.visitor;
@@ -373,7 +375,7 @@ Lnomatch:
 /************************************
  * Match an array of them.
  */
-private bool arrayObjectMatch(ref Objects oa1, ref Objects oa2)
+bool arrayObjectMatch(ref Objects oa1, ref Objects oa2)
 {
     if (&oa1 == &oa2)
         return true;
@@ -586,9 +588,9 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
     // threaded list of previous instantiation attempts on stack
     TemplatePrevious* previous;
 
-    private Expression lastConstraint; /// the constraint after the last failed evaluation
-    private Array!Expression lastConstraintNegs; /// its negative parts
-    private Objects* lastConstraintTiargs; /// template instance arguments for `lastConstraint`
+    Expression lastConstraint; /// the constraint after the last failed evaluation
+    Array!Expression lastConstraintNegs; /// its negative parts
+    Objects* lastConstraintTiargs; /// template instance arguments for `lastConstraint`
 
     extern (D) this(const ref Loc loc, Identifier ident, TemplateParameters* parameters, Expression constraint, Dsymbols* decldefs, bool ismixin = false, bool literal = false)
     {
@@ -743,1545 +745,75 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
 
     override const(char)* toChars() const
     {
-        return toCharsMaybeConstraints(true);
-    }
-
-    /****************************
-     * Similar to `toChars`, but does not print the template constraints
-     */
-    const(char)* toCharsNoConstraints() const
-    {
-        return toCharsMaybeConstraints(false);
-    }
-
-    // Note: this function is not actually `const`, because iterating the
-    // function parameter list may run dsymbolsemantic on enum types
-    const(char)* toCharsMaybeConstraints(bool includeConstraints) const
-    {
-        OutBuffer buf;
-        HdrGenState hgs;
-
-        buf.writestring(ident == Id.ctor ? "this" : ident.toString());
-        buf.writeByte('(');
-        foreach (i, const tp; *parameters)
-        {
-            if (i)
-                buf.writestring(", ");
-            toCBuffer(tp, buf, hgs);
-        }
-        buf.writeByte(')');
-
-        if (onemember)
-        {
-            if (const fd = onemember.isFuncDeclaration())
-            {
-                if (TypeFunction tf = cast(TypeFunction)fd.type.isTypeFunction())
-                {
-                    // !! Casted away const
-                    buf.writestring(parametersTypeToChars(tf.parameterList));
-                    if (tf.mod)
-                    {
-                        buf.writeByte(' ');
-                        buf.MODtoBuffer(tf.mod);
-                    }
-                }
-            }
-        }
-
-        if (includeConstraints &&
-            constraint)
-        {
-            buf.writestring(" if (");
-            toCBuffer(constraint, buf, hgs);
-            buf.writeByte(')');
-        }
-
-        return buf.extractChars();
-    }
-
-    override Visibility visible() pure nothrow @nogc @safe
-    {
-        return visibility;
-    }
-
-    /****************************
-     * Check to see if constraint is satisfied.
-     */
-    private bool evaluateConstraint(TemplateInstance ti, Scope* sc, Scope* paramscope, Objects* dedargs, FuncDeclaration fd)
-    {
-        /* Detect recursive attempts to instantiate this template declaration,
-         * https://issues.dlang.org/show_bug.cgi?id=4072
-         *  void foo(T)(T x) if (is(typeof(foo(x)))) { }
-         *  static assert(!is(typeof(foo(7))));
-         * Recursive attempts are regarded as a constraint failure.
-         */
-        /* There's a chicken-and-egg problem here. We don't know yet if this template
-         * instantiation will be a local one (enclosing is set), and we won't know until
-         * after selecting the correct template. Thus, function we're nesting inside
-         * is not on the sc scope chain, and this can cause errors in FuncDeclaration.getLevel().
-         * Workaround the problem by setting a flag to relax the checking on frame errors.
-         */
-
-        for (TemplatePrevious* p = previous; p; p = p.prev)
-        {
-            if (!arrayObjectMatch(*p.dedargs, *dedargs))
-                continue;
-            //printf("recursive, no match p.sc=%p %p %s\n", p.sc, this, this.toChars());
-            /* It must be a subscope of p.sc, other scope chains are not recursive
-             * instantiations.
-             * the chain of enclosing scopes is broken by paramscope (its enclosing
-             * scope is _scope, but paramscope.callsc is the instantiating scope). So
-             * it's good enough to check the chain of callsc
-             */
-            for (Scope* scx = paramscope.callsc; scx; scx = scx.callsc)
-            {
-                // The first scx might be identical for nested eponymeous templates, e.g.
-                // template foo() { void foo()() {...} }
-                if (scx == p.sc && scx !is paramscope.callsc)
-                    return false;
-            }
-            /* BUG: should also check for ref param differences
-             */
-        }
-
-        TemplatePrevious pr;
-        pr.prev = previous;
-        pr.sc = paramscope.callsc;
-        pr.dedargs = dedargs;
-        previous = &pr; // add this to threaded list
-
-        Scope* scx = paramscope.push(ti);
-        scx.parent = ti;
-        scx.tinst = null;
-        scx.minst = null;
-        // Set SCOPE.constraint before declaring function parameters for the static condition
-        // (previously, this was immediately before calling evalStaticCondition), so the
-        // semantic pass knows not to issue deprecation warnings for these throw-away decls.
-        // https://issues.dlang.org/show_bug.cgi?id=21831
-        scx.flags |= SCOPE.constraint;
-
-        assert(!ti.symtab);
-        if (fd)
-        {
-            /* Declare all the function parameters as variables and add them to the scope
-             * Making parameters is similar to FuncDeclaration.semantic3
-             */
-            auto tf = fd.type.isTypeFunction();
-
-            scx.parent = fd;
-
-            Parameters* fparameters = tf.parameterList.parameters;
-            const nfparams = tf.parameterList.length;
-            foreach (i, fparam; tf.parameterList)
-            {
-                fparam.storageClass &= (STC.IOR | STC.lazy_ | STC.final_ | STC.TYPECTOR | STC.nodtor);
-                fparam.storageClass |= STC.parameter;
-                if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nfparams)
-                {
-                    fparam.storageClass |= STC.variadic;
-                    /* Don't need to set STC.scope_ because this will only
-                     * be evaluated at compile time
-                     */
-                }
-            }
-            foreach (fparam; *fparameters)
-            {
-                if (!fparam.ident)
-                    continue;
-                // don't add it, if it has no name
-                auto v = new VarDeclaration(fparam.loc, fparam.type, fparam.ident, null);
-                fparam.storageClass |= STC.parameter;
-                v.storage_class = fparam.storageClass;
-                v.dsymbolSemantic(scx);
-                if (!ti.symtab)
-                    ti.symtab = new DsymbolTable();
-                if (!scx.insert(v))
-                    .error(loc, "%s `%s` parameter `%s.%s` is already defined", kind, toPrettyChars, toChars(), v.toChars());
-                else
-                    v.parent = fd;
-            }
-            if (isstatic)
-                fd.storage_class |= STC.static_;
-            fd.declareThis(scx);
-        }
-
-        lastConstraint = constraint.syntaxCopy();
-        lastConstraintTiargs = ti.tiargs;
-        lastConstraintNegs.setDim(0);
-
-        import dmd.staticcond;
-
-        assert(ti.inst is null);
-        ti.inst = ti; // temporary instantiation to enable genIdent()
-        bool errors;
-        const bool result = evalStaticCondition(scx, constraint, lastConstraint, errors, &lastConstraintNegs);
-        if (result || errors)
-        {
-            lastConstraint = null;
-            lastConstraintTiargs = null;
-            lastConstraintNegs.setDim(0);
-        }
-        ti.inst = null;
-        ti.symtab = null;
-        scx = scx.pop();
-        previous = pr.prev; // unlink from threaded list
-        if (errors)
-            return false;
-        return result;
-    }
-
-    /****************************
-     * Destructively get the error message from the last constraint evaluation
-     * Params:
-     *      tip = tip to show after printing all overloads
-     */
-    const(char)* getConstraintEvalError(ref const(char)* tip)
-    {
-        import dmd.staticcond;
-
-        // there will be a full tree view in verbose mode, and more compact list in the usual
-        const full = global.params.v.verbose;
-        uint count;
-        const msg = visualizeStaticCondition(constraint, lastConstraint, lastConstraintNegs[], full, count);
-        scope (exit)
-        {
-            lastConstraint = null;
-            lastConstraintTiargs = null;
-            lastConstraintNegs.setDim(0);
-        }
-        if (!msg)
-            return null;
-
-        OutBuffer buf;
-
-        assert(parameters && lastConstraintTiargs);
-        if (parameters.length > 0)
-        {
-            formatParamsWithTiargs(*lastConstraintTiargs, buf);
-            buf.writenl();
-        }
-        if (!full)
-        {
-            // choosing singular/plural
-            const s = (count == 1) ?
-                "  must satisfy the following constraint:" :
-                "  must satisfy one of the following constraints:";
-            buf.writestring(s);
-            buf.writenl();
-            // the constraints
-            buf.writeByte('`');
-            buf.writestring(msg);
-            buf.writeByte('`');
-        }
-        else
-        {
-            buf.writestring("  whose parameters have the following constraints:");
-            buf.writenl();
-            const sep = "  `~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`";
-            buf.writestring(sep);
-            buf.writenl();
-            // the constraints
-            buf.writeByte('`');
-            buf.writestring(msg);
-            buf.writeByte('`');
-            buf.writestring(sep);
-            tip = "not satisfied constraints are marked with `>`";
-        }
-        return buf.extractChars();
-    }
-
-    private void formatParamsWithTiargs(ref Objects tiargs, ref OutBuffer buf)
-    {
-        buf.writestring("  with `");
-
-        // write usual arguments line-by-line
-        // skips trailing default ones - they are not present in `tiargs`
-        const bool variadic = isVariadic() !is null;
-        const end = cast(int)parameters.length - (variadic ? 1 : 0);
-        uint i;
-        for (; i < tiargs.length && i < end; i++)
-        {
-            if (i > 0)
-            {
-                buf.writeByte(',');
-                buf.writenl();
-                buf.writestring("       ");
-            }
-            write(buf, (*parameters)[i]);
-            buf.writestring(" = ");
-            write(buf, tiargs[i]);
-        }
-        // write remaining variadic arguments on the last line
-        if (variadic)
-        {
-            if (i > 0)
-            {
-                buf.writeByte(',');
-                buf.writenl();
-                buf.writestring("       ");
-            }
-            write(buf, (*parameters)[end]);
-            buf.writestring(" = ");
-            buf.writeByte('(');
-            if (cast(int)tiargs.length - end > 0)
-            {
-                write(buf, tiargs[end]);
-                foreach (j; parameters.length .. tiargs.length)
-                {
-                    buf.writestring(", ");
-                    write(buf, tiargs[j]);
-                }
-            }
-            buf.writeByte(')');
-        }
-        buf.writeByte('`');
-    }
-
-    /******************************
-     * Create a scope for the parameters of the TemplateInstance
-     * `ti` in the parent scope sc from the ScopeDsymbol paramsym.
-     *
-     * If paramsym is null a new ScopeDsymbol is used in place of
-     * paramsym.
-     * Params:
-     *      ti = the TemplateInstance whose parameters to generate the scope for.
-     *      sc = the parent scope of ti
-     * Returns:
-     *      a scope for the parameters of ti
-     */
-    Scope* scopeForTemplateParameters(TemplateInstance ti, Scope* sc)
-    {
-        ScopeDsymbol paramsym = new ScopeDsymbol();
-        paramsym.parent = _scope.parent;
-        Scope* paramscope = _scope.push(paramsym);
-        paramscope.tinst = ti;
-        paramscope.minst = sc.minst;
-        paramscope.callsc = sc;
-        paramscope.stc = 0;
-        return paramscope;
-    }
-
-    /***************************************
-     * Given that ti is an instance of this TemplateDeclaration,
-     * deduce the types of the parameters to this, and store
-     * those deduced types in dedtypes[].
-     * Input:
-     *      flag    1: don't do semantic() because of dummy types
-     *              2: don't change types in matchArg()
-     * Output:
-     *      dedtypes        deduced arguments
-     * Return match level.
-     */
-    private MATCH matchWithInstance(Scope* sc, TemplateInstance ti, ref Objects dedtypes, ArgumentList argumentList, int flag)
-    {
-        enum LOGM = 0;
-        static if (LOGM)
-        {
-            printf("\n+TemplateDeclaration.matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti.toChars(), flag);
-        }
-        version (none)
-        {
-            printf("dedtypes.length = %d, parameters.length = %d\n", dedtypes.length, parameters.length);
-            if (ti.tiargs.length)
-                printf("ti.tiargs.length = %d, [0] = %p\n", ti.tiargs.length, (*ti.tiargs)[0]);
-        }
-        MATCH nomatch()
-        {
-            static if (LOGM)
-            {
-                printf(" no match\n");
-            }
-            return MATCH.nomatch;
-        }
-        MATCH m;
-        size_t dedtypes_dim = dedtypes.length;
-
-        dedtypes.zero();
-
-        if (errors)
-            return MATCH.nomatch;
-
-        size_t parameters_dim = parameters.length;
-        int variadic = isVariadic() !is null;
-
-        // If more arguments than parameters, no match
-        if (ti.tiargs.length > parameters_dim && !variadic)
-        {
-            static if (LOGM)
-            {
-                printf(" no match: more arguments than parameters\n");
-            }
-            return MATCH.nomatch;
-        }
-
-        assert(dedtypes_dim == parameters_dim);
-        assert(dedtypes_dim >= ti.tiargs.length || variadic);
-
-        assert(_scope);
-
-        // Set up scope for template parameters
-        Scope* paramscope = scopeForTemplateParameters(ti,sc);
-
-        // Attempt type deduction
-        m = MATCH.exact;
-        for (size_t i = 0; i < dedtypes_dim; i++)
-        {
-            MATCH m2;
-            TemplateParameter tp = (*parameters)[i];
-            Declaration sparam;
-
-            //printf("\targument [%d]\n", i);
-            static if (LOGM)
-            {
-                //printf("\targument [%d] is %s\n", i, oarg ? oarg.toChars() : "null");
-                TemplateTypeParameter ttp = tp.isTemplateTypeParameter();
-                if (ttp)
-                    printf("\tparameter[%d] is %s : %s\n", i, tp.ident.toChars(), ttp.specType ? ttp.specType.toChars() : "");
-            }
-
-            m2 = tp.matchArg(ti.loc, paramscope, ti.tiargs, i, parameters, dedtypes, &sparam);
-            //printf("\tm2 = %d\n", m2);
-            if (m2 == MATCH.nomatch)
-            {
-                version (none)
-                {
-                    printf("\tmatchArg() for parameter %i failed\n", i);
-                }
-                return nomatch();
-            }
-
-            if (m2 < m)
-                m = m2;
-
-            if (!flag)
-                sparam.dsymbolSemantic(paramscope);
-            if (!paramscope.insert(sparam)) // TODO: This check can make more early
-            {
-                // in TemplateDeclaration.semantic, and
-                // then we don't need to make sparam if flags == 0
-                return nomatch();
-            }
-        }
-
-        if (!flag)
-        {
-            /* Any parameter left without a type gets the type of
-             * its corresponding arg
-             */
-            foreach (i, ref dedtype; dedtypes)
-            {
-                if (!dedtype)
-                {
-                    assert(i < ti.tiargs.length);
-                    dedtype = cast(Type)(*ti.tiargs)[i];
-                }
-            }
-        }
-
-        if (m > MATCH.nomatch && constraint && !flag)
-        {
-            if (ti.hasNestedArgs(ti.tiargs, this.isstatic)) // TODO: should gag error
-                ti.parent = ti.enclosing;
-            else
-                ti.parent = this.parent;
-
-            // Similar to doHeaderInstantiation
-            FuncDeclaration fd = onemember ? onemember.isFuncDeclaration() : null;
-            if (fd)
-            {
-                TypeFunction tf = fd.type.isTypeFunction().syntaxCopy();
-                if (argumentList.hasNames)
-                    return nomatch();
-                Expressions* fargs = argumentList.arguments;
-                // TODO: Expressions* fargs = tf.resolveNamedArgs(argumentList, null);
-                // if (!fargs)
-                //     return nomatch();
-
-                fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, tf);
-                fd.parent = ti;
-                fd.inferRetType = true;
-
-                // Shouldn't run semantic on default arguments and return type.
-                foreach (ref param; *tf.parameterList.parameters)
-                    param.defaultArg = null;
-
-                tf.next = null;
-                tf.incomplete = true;
-
-                // Resolve parameter types and 'auto ref's.
-                tf.fargs = fargs;
-                uint olderrors = global.startGagging();
-                fd.type = tf.typeSemantic(loc, paramscope);
-                global.endGagging(olderrors);
-                if (fd.type.ty != Tfunction)
-                    return nomatch();
-                fd.originalType = fd.type; // for mangling
-            }
-
-            // TODO: dedtypes => ti.tiargs ?
-            if (!evaluateConstraint(ti, sc, paramscope, &dedtypes, fd))
-                return nomatch();
-        }
-
-        static if (LOGM)
-        {
-            // Print out the results
-            printf("--------------------------\n");
-            printf("template %s\n", toChars());
-            printf("instance %s\n", ti.toChars());
-            if (m > MATCH.nomatch)
-            {
-                for (size_t i = 0; i < dedtypes_dim; i++)
-                {
-                    TemplateParameter tp = (*parameters)[i];
-                    RootObject oarg;
-                    printf(" [%d]", i);
-                    if (i < ti.tiargs.length)
-                        oarg = (*ti.tiargs)[i];
-                    else
-                        oarg = null;
-                    tp.print(oarg, (*dedtypes)[i]);
-                }
-            }
-            else
-                return nomatch();
-        }
-        static if (LOGM)
-        {
-            printf(" match = %d\n", m);
-        }
-
-        paramscope.pop();
-        static if (LOGM)
-        {
-            printf("-TemplateDeclaration.matchWithInstance(this = %s, ti = %s) = %d\n", toChars(), ti.toChars(), m);
-        }
-        return m;
-    }
-
-    /********************************************
-     * Determine partial specialization order of 'this' vs td2.
-     * Returns:
-     *      match   this is at least as specialized as td2
-     *      0       td2 is more specialized than this
-     */
-    extern (D) MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration td2, ArgumentList argumentList)
-    {
-        enum LOG_LEASTAS = 0;
-        static if (LOG_LEASTAS)
-        {
-            printf("%s.leastAsSpecialized(%s)\n", toChars(), td2.toChars());
-        }
-
-        /* This works by taking the template parameters to this template
-         * declaration and feeding them to td2 as if it were a template
-         * instance.
-         * If it works, then this template is at least as specialized
-         * as td2.
-         */
-
-        // Set type arguments to dummy template instance to be types
-        // generated from the parameters to this template declaration
-        auto tiargs = new Objects();
-        tiargs.reserve(parameters.length);
-        foreach (tp; *parameters)
-        {
-            if (tp.dependent)
-                break;
-            RootObject p = tp.dummyArg();
-            if (!p) //TemplateTupleParameter
-                break;
-
-            tiargs.push(p);
-        }
-        scope TemplateInstance ti = new TemplateInstance(Loc.initial, ident, tiargs); // create dummy template instance
-
-        // Temporary Array to hold deduced types
-        Objects dedtypes = Objects(td2.parameters.length);
-
-        // Attempt a type deduction
-        MATCH m = td2.matchWithInstance(sc, ti, dedtypes, argumentList, 1);
-        if (m > MATCH.nomatch)
-        {
-            /* A non-variadic template is more specialized than a
-             * variadic one.
-             */
-            TemplateTupleParameter tp = isVariadic();
-            if (tp && !tp.dependent && !td2.isVariadic())
-                goto L1;
-
-            static if (LOG_LEASTAS)
-            {
-                printf("  matches %d, so is least as specialized\n", m);
-            }
-            return m;
-        }
-    L1:
-        static if (LOG_LEASTAS)
-        {
-            printf("  doesn't match, so is not as specialized\n");
-        }
-        return MATCH.nomatch;
-    }
-
-    /*************************************************
-     * Match function arguments against a specific template function.
-     *
-     * Params:
-     *     ti = template instance. `ti.tdtypes` will be set to Expression/Type deduced template arguments
-     *     sc = instantiation scope
-     *     fd = Partially instantiated function declaration, which is set to an instantiated function declaration
-     *     tthis = 'this' argument if !NULL
-     *     argumentList = arguments to function
-     *
-     * Returns:
-     *      match pair of initial and inferred template arguments
-     */
-    extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateInstance ti, Scope* sc, ref FuncDeclaration fd, Type tthis, ArgumentList argumentList)
-    {
-        version (none)
-        {
-            printf("\nTemplateDeclaration.deduceFunctionTemplateMatch() %s\n", toChars());
-            for (size_t i = 0; i < (fargs ? fargs.length : 0); i++)
-            {
-                Expression e = (*fargs)[i];
-                printf("\tfarg[%d] is %s, type is %s\n", cast(int) i, e.toChars(), e.type.toChars());
-            }
-            printf("fd = %s\n", fd.toChars());
-            printf("fd.type = %s\n", fd.type.toChars());
-            if (tthis)
-                printf("tthis = %s\n", tthis.toChars());
-        }
-
-        assert(_scope);
-
-        auto dedargs = new Objects(parameters.length);
-        dedargs.zero();
-
-        Objects* dedtypes = &ti.tdtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
-        dedtypes.setDim(parameters.length);
-        dedtypes.zero();
-
-        if (errors || fd.errors)
-            return MATCHpair(MATCH.nomatch, MATCH.nomatch);
-
-        // Set up scope for parameters
-        Scope* paramscope = scopeForTemplateParameters(ti,sc);
-
-        MATCHpair nomatch()
-        {
-            paramscope.pop();
-            //printf("\tnomatch\n");
-            return MATCHpair(MATCH.nomatch, MATCH.nomatch);
-        }
-
-        MATCHpair matcherror()
-        {
-            // todo: for the future improvement
-            paramscope.pop();
-            //printf("\terror\n");
-            return MATCHpair(MATCH.nomatch, MATCH.nomatch);
-        }
-        // Mark the parameter scope as deprecated if the templated
-        // function is deprecated (since paramscope.enclosing is the
-        // calling scope already)
-        paramscope.stc |= fd.storage_class & STC.deprecated_;
-
-        TemplateTupleParameter tp = isVariadic();
-        Tuple declaredTuple = null;
-
-        version (none)
-        {
-            for (size_t i = 0; i < dedargs.length; i++)
-            {
-                printf("\tdedarg[%d] = ", i);
-                RootObject oarg = (*dedargs)[i];
-                if (oarg)
-                    printf("%s", oarg.toChars());
-                printf("\n");
-            }
-        }
-
-        size_t ntargs = 0; // array size of tiargs
-        size_t inferStart = 0; // index of first parameter to infer
-        const Loc instLoc = ti.loc;
-        MATCH matchTiargs = MATCH.exact;
-
-        if (auto tiargs = ti.tiargs)
-        {
-            // Set initial template arguments
-            ntargs = tiargs.length;
-            size_t n = parameters.length;
-            if (tp)
-                n--;
-            if (ntargs > n)
-            {
-                if (!tp)
-                    return nomatch();
-
-                /* The extra initial template arguments
-                 * now form the tuple argument.
-                 */
-                auto t = new Tuple(ntargs - n);
-                assert(parameters.length);
-                (*dedargs)[parameters.length - 1] = t;
-
-                for (size_t i = 0; i < t.objects.length; i++)
-                {
-                    t.objects[i] = (*tiargs)[n + i];
-                }
-                declareParameter(paramscope, tp, t);
-                declaredTuple = t;
-            }
-            else
-                n = ntargs;
-
-            memcpy(dedargs.tdata(), tiargs.tdata(), n * (*dedargs.tdata()).sizeof);
-
-            for (size_t i = 0; i < n; i++)
-            {
-                assert(i < parameters.length);
-                Declaration sparam = null;
-                MATCH m = (*parameters)[i].matchArg(instLoc, paramscope, dedargs, i, parameters, *dedtypes, &sparam);
-                //printf("\tdeduceType m = %d\n", m);
-                if (m == MATCH.nomatch)
-                    return nomatch();
-                if (m < matchTiargs)
-                    matchTiargs = m;
-
-                sparam.dsymbolSemantic(paramscope);
-                if (!paramscope.insert(sparam))
-                    return nomatch();
-            }
-            if (n < parameters.length && !declaredTuple)
-            {
-                inferStart = n;
-            }
-            else
-                inferStart = parameters.length;
-            //printf("tiargs matchTiargs = %d\n", matchTiargs);
-        }
-        version (none)
-        {
-            for (size_t i = 0; i < dedargs.length; i++)
-            {
-                printf("\tdedarg[%d] = ", i);
-                RootObject oarg = (*dedargs)[i];
-                if (oarg)
-                    printf("%s", oarg.toChars());
-                printf("\n");
-            }
-        }
-
-        ParameterList fparameters = fd.getParameterList(); // function parameter list
-        const nfparams = fparameters.length; // number of function parameters
-        if (argumentList.hasNames)
-            return matcherror(); // TODO: resolve named args
-        Expression[] fargs = argumentList.arguments ? (*argumentList.arguments)[] : null;
-
-        /* Check for match of function arguments with variadic template
-         * parameter, such as:
-         *
-         * void foo(T, A...)(T t, A a);
-         * void main() { foo(1,2,3); }
-         */
-        size_t fptupindex = IDX_NOTFOUND;
-        if (tp) // if variadic
-        {
-            // TemplateTupleParameter always makes most lesser matching.
-            matchTiargs = MATCH.convert;
-
-            if (nfparams == 0 && argumentList.length != 0) // if no function parameters
-            {
-                if (!declaredTuple)
-                {
-                    auto t = new Tuple();
-                    //printf("t = %p\n", t);
-                    (*dedargs)[parameters.length - 1] = t;
-                    declareParameter(paramscope, tp, t);
-                    declaredTuple = t;
-                }
-            }
-            else
-            {
-                /* Figure out which of the function parameters matches
-                 * the tuple template parameter. Do this by matching
-                 * type identifiers.
-                 * Set the index of this function parameter to fptupindex.
-                 */
-                for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
-                {
-                    auto fparam = (*fparameters.parameters)[fptupindex]; // fparameters[fptupindex] ?
-                    if (fparam.type.ty != Tident)
-                        continue;
-                    TypeIdentifier tid = fparam.type.isTypeIdentifier();
-                    if (!tp.ident.equals(tid.ident) || tid.idents.length)
-                        continue;
-
-                    if (fparameters.varargs != VarArg.none) // variadic function doesn't
-                        return nomatch(); // go with variadic template
-
-                    goto L1;
-                }
-                fptupindex = IDX_NOTFOUND;
-            L1:
-            }
-        }
-
-        MATCH match = MATCH.exact;
-        if (toParent().isModule())
-            tthis = null;
-        if (tthis)
-        {
-            bool hasttp = false;
-
-            // Match 'tthis' to any TemplateThisParameter's
-            foreach (param; *parameters)
-            {
-                if (auto ttp = param.isTemplateThisParameter())
-                {
-                    hasttp = true;
-
-                    Type t = new TypeIdentifier(Loc.initial, ttp.ident);
-                    MATCH m = deduceType(tthis, paramscope, t, *parameters, *dedtypes);
-                    if (m == MATCH.nomatch)
-                        return nomatch();
-                    if (m < match)
-                        match = m; // pick worst match
-                }
-            }
-
-            // Match attributes of tthis against attributes of fd
-            if (fd.type && !fd.isCtorDeclaration() && !(_scope.stc & STC.static_))
-            {
-                StorageClass stc = _scope.stc | fd.storage_class2;
-                // Propagate parent storage class, https://issues.dlang.org/show_bug.cgi?id=5504
-                Dsymbol p = parent;
-                while (p.isTemplateDeclaration() || p.isTemplateInstance())
-                    p = p.parent;
-                AggregateDeclaration ad = p.isAggregateDeclaration();
-                if (ad)
-                    stc |= ad.storage_class;
-
-                ubyte mod = fd.type.mod;
-                if (stc & STC.immutable_)
-                    mod = MODFlags.immutable_;
-                else
-                {
-                    if (stc & (STC.shared_ | STC.synchronized_))
-                        mod |= MODFlags.shared_;
-                    if (stc & STC.const_)
-                        mod |= MODFlags.const_;
-                    if (stc & STC.wild)
-                        mod |= MODFlags.wild;
-                }
-
-                ubyte thismod = tthis.mod;
-                if (hasttp)
-                    mod = MODmerge(thismod, mod);
-                MATCH m = MODmethodConv(thismod, mod);
-                if (m == MATCH.nomatch)
-                    return nomatch();
-                if (m < match)
-                    match = m;
-            }
-        }
-
-        // Loop through the function parameters
-        {
-            //printf("%s\n\tnfargs = %d, nfparams = %d, tuple_dim = %d\n", toChars(), nfargs, nfparams, declaredTuple ? declaredTuple.objects.length : 0);
-            //printf("\ttp = %p, fptupindex = %d, found = %d, declaredTuple = %s\n", tp, fptupindex, fptupindex != IDX_NOTFOUND, declaredTuple ? declaredTuple.toChars() : NULL);
-            size_t argi = 0;
-            size_t nfargs2 = fargs.length; // nfargs + supplied defaultArgs
-            uint inoutMatch = 0; // for debugging only
-            for (size_t parami = 0; parami < nfparams; parami++)
-            {
-                Parameter fparam = fparameters[parami];
-
-                // Apply function parameter storage classes to parameter types
-                Type prmtype = fparam.type.addStorageClass(fparam.storageClass);
-
-                Expression farg;
-
-                /* See function parameters which wound up
-                 * as part of a template tuple parameter.
-                 */
-                if (fptupindex != IDX_NOTFOUND && parami == fptupindex)
-                {
-                    TypeIdentifier tid = prmtype.isTypeIdentifier();
-                    assert(tid);
-                    if (!declaredTuple)
-                    {
-                        /* The types of the function arguments
-                         * now form the tuple argument.
-                         */
-                        declaredTuple = new Tuple();
-                        (*dedargs)[parameters.length - 1] = declaredTuple;
-
-                        /* Count function parameters with no defaults following a tuple parameter.
-                         * void foo(U, T...)(int y, T, U, double, int bar = 0) {}  // rem == 2 (U, double)
-                         */
-                        size_t rem = 0;
-                        foreach (j; parami + 1 .. nfparams)
-                        {
-                            Parameter p = fparameters[j];
-                            if (p.defaultArg)
-                            {
-                               break;
-                            }
-                            if (!reliesOnTemplateParameters(p.type, (*parameters)[inferStart .. parameters.length]))
-                            {
-                                Type pt = p.type.syntaxCopy().typeSemantic(fd.loc, paramscope);
-                                if (auto ptt = pt.isTypeTuple())
-                                    rem += ptt.arguments.length;
-                                else
-                                    rem += 1;
-                            }
-                            else
-                            {
-                                ++rem;
-                            }
-                        }
-
-                        if (nfargs2 - argi < rem)
-                            return nomatch();
-                        declaredTuple.objects.setDim(nfargs2 - argi - rem);
-                        foreach (i; 0 .. declaredTuple.objects.length)
-                        {
-                            farg = fargs[argi + i];
-
-                            // Check invalid arguments to detect errors early.
-                            if (farg.op == EXP.error || farg.type.ty == Terror)
-                                return nomatch();
-
-                            if (!fparam.isLazy() && farg.type.ty == Tvoid)
-                                return nomatch();
-
-                            Type tt;
-                            MATCH m;
-                            if (ubyte wm = deduceWildHelper(farg.type, &tt, tid))
-                            {
-                                inoutMatch |= wm;
-                                m = MATCH.constant;
-                            }
-                            else
-                            {
-                                m = deduceTypeHelper(farg.type, tt, tid);
-                            }
-                            if (m == MATCH.nomatch)
-                                return nomatch();
-                            if (m < match)
-                                match = m;
-
-                            /* Remove top const for dynamic array types and pointer types
-                             */
-                            if ((tt.ty == Tarray || tt.ty == Tpointer) && !tt.isMutable() && (!(fparam.storageClass & STC.ref_) || (fparam.storageClass & STC.auto_) && !farg.isLvalue()))
-                            {
-                                tt = tt.mutableOf();
-                            }
-                            declaredTuple.objects[i] = tt;
-                        }
-                        declareParameter(paramscope, tp, declaredTuple);
-                    }
-                    else
-                    {
-                        // https://issues.dlang.org/show_bug.cgi?id=6810
-                        // If declared tuple is not a type tuple,
-                        // it cannot be function parameter types.
-                        for (size_t i = 0; i < declaredTuple.objects.length; i++)
-                        {
-                            if (!isType(declaredTuple.objects[i]))
-                                return nomatch();
-                        }
-                    }
-                    assert(declaredTuple);
-                    argi += declaredTuple.objects.length;
-                    continue;
-                }
-
-                // If parameter type doesn't depend on inferred template parameters,
-                // semantic it to get actual type.
-                if (!reliesOnTemplateParameters(prmtype, (*parameters)[inferStart .. parameters.length]))
-                {
-                    // should copy prmtype to avoid affecting semantic result
-                    prmtype = prmtype.syntaxCopy().typeSemantic(fd.loc, paramscope);
-
-                    if (TypeTuple tt = prmtype.isTypeTuple())
-                    {
-                        const tt_dim = tt.arguments.length;
-                        for (size_t j = 0; j < tt_dim; j++, ++argi)
-                        {
-                            Parameter p = (*tt.arguments)[j];
-                            if (j == tt_dim - 1 && fparameters.varargs == VarArg.typesafe &&
-                                parami + 1 == nfparams && argi < fargs.length)
-                            {
-                                prmtype = p.type;
-                                goto Lvarargs;
-                            }
-                            if (argi >= fargs.length)
-                            {
-                                if (p.defaultArg)
-                                    continue;
-
-                                // https://issues.dlang.org/show_bug.cgi?id=19888
-                                if (fparam.defaultArg)
-                                    break;
-
-                                return nomatch();
-                            }
-                            farg = fargs[argi];
-                            if (!farg.implicitConvTo(p.type))
-                                return nomatch();
-                        }
-                        continue;
-                    }
-                }
-
-                if (argi >= fargs.length) // if not enough arguments
-                {
-                    if (!fparam.defaultArg)
-                        goto Lvarargs;
-
-                    /* https://issues.dlang.org/show_bug.cgi?id=2803
-                     * Before the starting of type deduction from the function
-                     * default arguments, set the already deduced parameters into paramscope.
-                     * It's necessary to avoid breaking existing acceptable code. Cases:
-                     *
-                     * 1. Already deduced template parameters can appear in fparam.defaultArg:
-                     *  auto foo(A, B)(A a, B b = A.stringof);
-                     *  foo(1);
-                     *  // at fparam == 'B b = A.string', A is equivalent with the deduced type 'int'
-                     *
-                     * 2. If prmtype depends on default-specified template parameter, the
-                     * default type should be preferred.
-                     *  auto foo(N = size_t, R)(R r, N start = 0)
-                     *  foo([1,2,3]);
-                     *  // at fparam `N start = 0`, N should be 'size_t' before
-                     *  // the deduction result from fparam.defaultArg.
-                     */
-                    if (argi == fargs.length)
-                    {
-                        foreach (ref dedtype; *dedtypes)
-                        {
-                            Type at = isType(dedtype);
-                            if (at && at.ty == Tnone)
-                            {
-                                TypeDeduced xt = cast(TypeDeduced)at;
-                                dedtype = xt.tded; // 'unbox'
-                            }
-                        }
-                        for (size_t i = ntargs; i < dedargs.length; i++)
-                        {
-                            TemplateParameter tparam = (*parameters)[i];
-
-                            RootObject oarg = (*dedargs)[i];
-                            RootObject oded = (*dedtypes)[i];
-                            if (oarg)
-                                continue;
-
-                            if (oded)
-                            {
-                                if (tparam.specialization() || !tparam.isTemplateTypeParameter())
-                                {
-                                    /* The specialization can work as long as afterwards
-                                     * the oded == oarg
-                                     */
-                                    (*dedargs)[i] = oded;
-                                    MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, *dedtypes, null);
-                                    //printf("m2 = %d\n", m2);
-                                    if (m2 == MATCH.nomatch)
-                                        return nomatch();
-                                    if (m2 < matchTiargs)
-                                        matchTiargs = m2; // pick worst match
-                                    if (!(*dedtypes)[i].equals(oded))
-                                        .error(loc, "%s `%s` specialization not allowed for deduced parameter `%s`", kind, toPrettyChars, kind, toPrettyChars, tparam.ident.toChars());
-                                }
-                                else
-                                {
-                                    if (MATCH.convert < matchTiargs)
-                                        matchTiargs = MATCH.convert;
-                                }
-                                (*dedargs)[i] = declareParameter(paramscope, tparam, oded);
-                            }
-                            else
-                            {
-                                oded = tparam.defaultArg(instLoc, paramscope);
-                                if (oded)
-                                    (*dedargs)[i] = declareParameter(paramscope, tparam, oded);
-                            }
-                        }
-                    }
-                    nfargs2 = argi + 1;
-
-                    /* If prmtype does not depend on any template parameters:
-                     *
-                     *  auto foo(T)(T v, double x = 0);
-                     *  foo("str");
-                     *  // at fparam == 'double x = 0'
-                     *
-                     * or, if all template parameters in the prmtype are already deduced:
-                     *
-                     *  auto foo(R)(R range, ElementType!R sum = 0);
-                     *  foo([1,2,3]);
-                     *  // at fparam == 'ElementType!R sum = 0'
-                     *
-                     * Deducing prmtype from fparam.defaultArg is not necessary.
-                     */
-                    if (prmtype.deco || prmtype.syntaxCopy().trySemantic(loc, paramscope))
-                    {
-                        ++argi;
-                        continue;
-                    }
-
-                    // Deduce prmtype from the defaultArg.
-                    farg = fparam.defaultArg.syntaxCopy();
-                    farg = farg.expressionSemantic(paramscope);
-                    farg = resolveProperties(paramscope, farg);
-                }
-                else
-                {
-                    farg = fargs[argi];
-                }
-                {
-                    // Check invalid arguments to detect errors early.
-                    if (farg.op == EXP.error || farg.type.ty == Terror)
-                        return nomatch();
-
-                    Type att = null;
-                Lretry:
-                    version (none)
-                    {
-                        printf("\tfarg.type   = %s\n", farg.type.toChars());
-                        printf("\tfparam.type = %s\n", prmtype.toChars());
-                    }
-                    Type argtype = farg.type;
-
-                    if (!fparam.isLazy() && argtype.ty == Tvoid && farg.op != EXP.function_)
-                        return nomatch();
-
-                    // https://issues.dlang.org/show_bug.cgi?id=12876
-                    // Optimize argument to allow CT-known length matching
-                    farg = farg.optimize(WANTvalue, fparam.isReference());
-                    //printf("farg = %s %s\n", farg.type.toChars(), farg.toChars());
-
-                    RootObject oarg = farg;
-                    if ((fparam.storageClass & STC.ref_) && (!(fparam.storageClass & STC.auto_) || farg.isLvalue()))
-                    {
-                        /* Allow expressions that have CT-known boundaries and type [] to match with [dim]
-                         */
-                        bool inferIndexType = (argtype.ty == Tarray) && (prmtype.ty == Tsarray || prmtype.ty == Taarray);
-                        if (auto aaType = prmtype.isTypeAArray())
-                        {
-                            if (auto indexType = aaType.index.isTypeIdentifier())
-                            {
-                                inferIndexType = indexType.idents.length == 0;
-                            }
-                        }
-                        if (inferIndexType)
-                        {
-                            if (StringExp se = farg.isStringExp())
-                            {
-                                argtype = se.type.nextOf().sarrayOf(se.len);
-                            }
-                            else if (ArrayLiteralExp ae = farg.isArrayLiteralExp())
-                            {
-                                argtype = ae.type.nextOf().sarrayOf(ae.elements.length);
-                            }
-                            else if (SliceExp se = farg.isSliceExp())
-                            {
-                                if (Type tsa = toStaticArrayType(se))
-                                    argtype = tsa;
-                            }
-                        }
-
-                        oarg = argtype;
-                    }
-                    else if ((fparam.storageClass & STC.out_) == 0 && (argtype.ty == Tarray || argtype.ty == Tpointer) && templateParameterLookup(prmtype, parameters) != IDX_NOTFOUND && prmtype.isTypeIdentifier().idents.length == 0)
-                    {
-                        /* The farg passing to the prmtype always make a copy. Therefore,
-                         * we can shrink the set of the deduced type arguments for prmtype
-                         * by adjusting top-qualifier of the argtype.
-                         *
-                         *  prmtype         argtype     ta
-                         *  T            <- const(E)[]  const(E)[]
-                         *  T            <- const(E[])  const(E)[]
-                         *  qualifier(T) <- const(E)[]  const(E[])
-                         *  qualifier(T) <- const(E[])  const(E[])
-                         */
-                        Type ta = argtype.castMod(prmtype.mod ? argtype.nextOf().mod : 0);
-                        if (ta != argtype)
-                        {
-                            Expression ea = farg.copy();
-                            ea.type = ta;
-                            oarg = ea;
-                        }
-                    }
-
-                    if (fparameters.varargs == VarArg.typesafe && parami + 1 == nfparams && argi + 1 < fargs.length)
-                        goto Lvarargs;
-
-                    uint im = 0;
-                    MATCH m = deduceType(oarg, paramscope, prmtype, *parameters, *dedtypes, &im, inferStart);
-                    //printf("\tL%d deduceType m = %d, im = x%x, inoutMatch = x%x\n", __LINE__, m, im, inoutMatch);
-                    inoutMatch |= im;
-
-                    /* If no match, see if the argument can be matched by using
-                     * implicit conversions.
-                     */
-                    if (m == MATCH.nomatch && prmtype.deco)
-                        m = farg.implicitConvTo(prmtype);
-
-                    if (m == MATCH.nomatch)
-                    {
-                        AggregateDeclaration ad = isAggregate(farg.type);
-                        if (ad && ad.aliasthis && !isRecursiveAliasThis(att, argtype))
-                        {
-                            // https://issues.dlang.org/show_bug.cgi?id=12537
-                            // The isRecursiveAliasThis() call above
-
-                            /* If a semantic error occurs while doing alias this,
-                             * eg purity(https://issues.dlang.org/show_bug.cgi?id=7295),
-                             * just regard it as not a match.
-                             *
-                             * We also save/restore sc.func.flags to avoid messing up
-                             * attribute inference in the evaluation.
-                            */
-                            const oldflags = sc.func ? sc.func.flags : 0;
-                            auto e = resolveAliasThis(sc, farg, true);
-                            if (sc.func)
-                                sc.func.flags = oldflags;
-                            if (e)
-                            {
-                                farg = e;
-                                goto Lretry;
-                            }
-                        }
-                    }
-
-                    if (m > MATCH.nomatch && (fparam.storageClass & (STC.ref_ | STC.auto_)) == STC.ref_)
-                    {
-                        if (!farg.isLvalue())
-                        {
-                            if ((farg.op == EXP.string_ || farg.op == EXP.slice) && (prmtype.ty == Tsarray || prmtype.ty == Taarray))
-                            {
-                                // Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
-                            }
-                            else if (global.params.rvalueRefParam == FeatureState.enabled)
-                            {
-                                // Allow implicit conversion to ref
-                            }
-                            else
-                                return nomatch();
-                        }
-                    }
-                    if (m > MATCH.nomatch && (fparam.storageClass & STC.out_))
-                    {
-                        if (!farg.isLvalue())
-                            return nomatch();
-                        if (!farg.type.isMutable()) // https://issues.dlang.org/show_bug.cgi?id=11916
-                            return nomatch();
-                    }
-                    if (m == MATCH.nomatch && fparam.isLazy() && prmtype.ty == Tvoid && farg.type.ty != Tvoid)
-                        m = MATCH.convert;
-                    if (m != MATCH.nomatch)
-                    {
-                        if (m < match)
-                            match = m; // pick worst match
-                        argi++;
-                        continue;
-                    }
-                }
-
-            Lvarargs:
-                /* The following code for variadic arguments closely
-                 * matches TypeFunction.callMatch()
-                 */
-                if (!(fparameters.varargs == VarArg.typesafe && parami + 1 == nfparams))
-                    return nomatch();
-
-                /* Check for match with function parameter T...
-                 */
-                Type tb = prmtype.toBasetype();
-                switch (tb.ty)
-                {
-                    // 6764 fix - TypeAArray may be TypeSArray have not yet run semantic().
-                case Tsarray:
-                case Taarray:
-                    {
-                        // Perhaps we can do better with this, see TypeFunction.callMatch()
-                        if (TypeSArray tsa = tb.isTypeSArray())
-                        {
-                            dinteger_t sz = tsa.dim.toInteger();
-                            if (sz != fargs.length - argi)
-                                return nomatch();
-                        }
-                        else if (TypeAArray taa = tb.isTypeAArray())
-                        {
-                            Expression dim = new IntegerExp(instLoc, fargs.length - argi, Type.tsize_t);
-
-                            size_t i = templateParameterLookup(taa.index, parameters);
-                            if (i == IDX_NOTFOUND)
-                            {
-                                Expression e;
-                                Type t;
-                                Dsymbol s;
-                                Scope *sco;
-
-                                uint errors = global.startGagging();
-                                /* ref: https://issues.dlang.org/show_bug.cgi?id=11118
-                                 * The parameter isn't part of the template
-                                 * ones, let's try to find it in the
-                                 * instantiation scope 'sc' and the one
-                                 * belonging to the template itself. */
-                                sco = sc;
-                                taa.index.resolve(instLoc, sco, e, t, s);
-                                if (!e)
-                                {
-                                    sco = paramscope;
-                                    taa.index.resolve(instLoc, sco, e, t, s);
-                                }
-                                global.endGagging(errors);
-
-                                if (!e)
-                                    return nomatch();
-
-                                e = e.ctfeInterpret();
-                                e = e.implicitCastTo(sco, Type.tsize_t);
-                                e = e.optimize(WANTvalue);
-                                if (!dim.equals(e))
-                                    return nomatch();
-                            }
-                            else
-                            {
-                                // This code matches code in TypeInstance.deduceType()
-                                TemplateParameter tprm = (*parameters)[i];
-                                TemplateValueParameter tvp = tprm.isTemplateValueParameter();
-                                if (!tvp)
-                                    return nomatch();
-                                Expression e = cast(Expression)(*dedtypes)[i];
-                                if (e)
-                                {
-                                    if (!dim.equals(e))
-                                        return nomatch();
-                                }
-                                else
-                                {
-                                    Type vt = tvp.valType.typeSemantic(Loc.initial, sc);
-                                    MATCH m = dim.implicitConvTo(vt);
-                                    if (m == MATCH.nomatch)
-                                        return nomatch();
-                                    (*dedtypes)[i] = dim;
-                                }
-                            }
-                        }
-                        goto case Tarray;
-                    }
-                case Tarray:
-                    {
-                        TypeArray ta = cast(TypeArray)tb;
-                        Type tret = fparam.isLazyArray();
-                        for (; argi < fargs.length; argi++)
-                        {
-                            Expression arg = fargs[argi];
-                            assert(arg);
+        HdrGenState hgs;
+        OutBuffer buf;
+        toCharsMaybeConstraints(this, buf, hgs);
+        return buf.extractChars();
+    }
 
-                            MATCH m;
-                            /* If lazy array of delegates,
-                             * convert arg(s) to delegate(s)
-                             */
-                            if (tret)
-                            {
-                                if (ta.next.equals(arg.type))
-                                {
-                                    m = MATCH.exact;
-                                }
-                                else
-                                {
-                                    m = arg.implicitConvTo(tret);
-                                    if (m == MATCH.nomatch)
-                                    {
-                                        if (tret.toBasetype().ty == Tvoid)
-                                            m = MATCH.convert;
-                                    }
-                                }
-                            }
-                            else
-                            {
-                                uint wm = 0;
-                                m = deduceType(arg, paramscope, ta.next, *parameters, *dedtypes, &wm, inferStart);
-                                inoutMatch |= wm;
-                            }
-                            if (m == MATCH.nomatch)
-                                return nomatch();
-                            if (m < match)
-                                match = m;
-                        }
-                        goto Lmatch;
-                    }
-                case Tclass:
-                case Tident:
-                    goto Lmatch;
+    override Visibility visible() pure nothrow @nogc @safe
+    {
+        return visibility;
+    }
 
-                default:
-                    return nomatch();
-                }
-                assert(0);
-            }
-            //printf(". argi = %d, nfargs = %d, nfargs2 = %d\n", argi, nfargs, nfargs2);
-            if (argi != nfargs2 && fparameters.varargs == VarArg.none)
-                return nomatch();
-        }
+    /****************************
+     * Destructively get the error message from the last constraint evaluation
+     * Params:
+     *      tip = tip to show after printing all overloads
+     */
+    const(char)* getConstraintEvalError(ref const(char)* tip)
+    {
+        import dmd.staticcond;
 
-    Lmatch:
-        foreach (ref dedtype; *dedtypes)
-        {
-            if (Type at = isType(dedtype))
-            {
-                if (at.ty == Tnone)
-                {
-                    TypeDeduced xt = cast(TypeDeduced)at;
-                    at = xt.tded; // 'unbox'
-                }
-                dedtype = at.merge2();
-            }
-        }
-        for (size_t i = ntargs; i < dedargs.length; i++)
+        // there will be a full tree view in verbose mode, and more compact list in the usual
+        const full = global.params.v.verbose;
+        uint count;
+        const msg = visualizeStaticCondition(constraint, lastConstraint, lastConstraintNegs[], full, count);
+        scope (exit)
         {
-            TemplateParameter tparam = (*parameters)[i];
-            //printf("tparam[%d] = %s\n", i, tparam.ident.toChars());
-
-            /* For T:T*, the dedargs is the T*, dedtypes is the T
-             * But for function templates, we really need them to match
-             */
-            RootObject oarg = (*dedargs)[i];
-            RootObject oded = (*dedtypes)[i];
-            //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
-            //if (oarg) printf("oarg: %s\n", oarg.toChars());
-            //if (oded) printf("oded: %s\n", oded.toChars());
-            if (oarg)
-                continue;
-
-            if (oded)
-            {
-                if (tparam.specialization() || !tparam.isTemplateTypeParameter())
-                {
-                    /* The specialization can work as long as afterwards
-                     * the oded == oarg
-                     */
-                    (*dedargs)[i] = oded;
-                    MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, *dedtypes, null);
-                    //printf("m2 = %d\n", m2);
-                    if (m2 == MATCH.nomatch)
-                        return nomatch();
-                    if (m2 < matchTiargs)
-                        matchTiargs = m2; // pick worst match
-                    if (!(*dedtypes)[i].equals(oded))
-                        .error(loc, "%s `%s` specialization not allowed for deduced parameter `%s`", kind, toPrettyChars, tparam.ident.toChars());
-                }
-                else
-                {
-                    // Discussion: https://issues.dlang.org/show_bug.cgi?id=16484
-                    if (MATCH.convert < matchTiargs)
-                        matchTiargs = MATCH.convert;
-                }
-            }
-            else
-            {
-                oded = tparam.defaultArg(instLoc, paramscope);
-                if (!oded)
-                {
-                    // if tuple parameter and
-                    // tuple parameter was not in function parameter list and
-                    // we're one or more arguments short (i.e. no tuple argument)
-                    if (tparam == tp &&
-                        fptupindex == IDX_NOTFOUND &&
-                        ntargs <= dedargs.length - 1)
-                    {
-                        // make tuple argument an empty tuple
-                        oded = new Tuple();
-                    }
-                    else
-                        return nomatch();
-                }
-                if (isError(oded))
-                    return matcherror();
-                ntargs++;
-
-                /* At the template parameter T, the picked default template argument
-                 * X!int should be matched to T in order to deduce dependent
-                 * template parameter A.
-                 *  auto foo(T : X!A = X!int, A...)() { ... }
-                 *  foo();  // T <-- X!int, A <-- (int)
-                 */
-                if (tparam.specialization())
-                {
-                    (*dedargs)[i] = oded;
-                    MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, *dedtypes, null);
-                    //printf("m2 = %d\n", m2);
-                    if (m2 == MATCH.nomatch)
-                        return nomatch();
-                    if (m2 < matchTiargs)
-                        matchTiargs = m2; // pick worst match
-                    if (!(*dedtypes)[i].equals(oded))
-                        .error(loc, "%s `%s` specialization not allowed for deduced parameter `%s`", kind, toPrettyChars, tparam.ident.toChars());
-                }
-            }
-            oded = declareParameter(paramscope, tparam, oded);
-            (*dedargs)[i] = oded;
+            lastConstraint = null;
+            lastConstraintTiargs = null;
+            lastConstraintNegs.setDim(0);
         }
+        if (!msg)
+            return null;
 
-        /* https://issues.dlang.org/show_bug.cgi?id=7469
-         * As same as the code for 7469 in findBestMatch,
-         * expand a Tuple in dedargs to normalize template arguments.
-         */
-        if (auto d = dedargs.length)
-        {
-            if (auto va = isTuple((*dedargs)[d - 1]))
-            {
-                dedargs.setDim(d - 1);
-                dedargs.insert(d - 1, &va.objects);
-            }
-        }
-        ti.tiargs = dedargs; // update to the normalized template arguments.
+        OutBuffer buf;
 
-        // Partially instantiate function for constraint and fd.leastAsSpecialized()
+        assert(parameters && lastConstraintTiargs);
+        if (parameters.length > 0)
         {
-            assert(paramscope.scopesym);
-            Scope* sc2 = _scope;
-            sc2 = sc2.push(paramscope.scopesym);
-            sc2 = sc2.push(ti);
-            sc2.parent = ti;
-            sc2.tinst = ti;
-            sc2.minst = sc.minst;
-            sc2.stc |= fd.storage_class & STC.deprecated_;
-
-            fd = doHeaderInstantiation(ti, sc2, fd, tthis, argumentList.arguments);
-
-            sc2 = sc2.pop();
-            sc2 = sc2.pop();
-
-            if (!fd)
-                return nomatch();
+            formatParamsWithTiargs(*parameters, *lastConstraintTiargs, isVariadic() !is null, buf);
+            buf.writenl();
         }
-
-        if (constraint)
+        if (!full)
         {
-            if (!evaluateConstraint(ti, sc, paramscope, dedargs, fd))
-                return nomatch();
+            // choosing singular/plural
+            const s = (count == 1) ?
+                "  must satisfy the following constraint:" :
+                "  must satisfy one of the following constraints:";
+            buf.writestring(s);
+            buf.writenl();
+            // the constraints
+            buf.writeByte('`');
+            buf.writestring(msg);
+            buf.writeByte('`');
         }
-
-        version (none)
+        else
         {
-            for (size_t i = 0; i < dedargs.length; i++)
-            {
-                RootObject o = (*dedargs)[i];
-                printf("\tdedargs[%d] = %d, %s\n", i, o.dyncast(), o.toChars());
-            }
+            buf.writestring("  whose parameters have the following constraints:");
+            buf.writenl();
+            const sep = "  `~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`";
+            buf.writestring(sep);
+            buf.writenl();
+            // the constraints
+            buf.writeByte('`');
+            buf.writestring(msg);
+            buf.writeByte('`');
+            buf.writestring(sep);
+            tip = "not satisfied constraints are marked with `>`";
         }
-
-        paramscope.pop();
-        //printf("\tmatch %d\n", match);
-        return MATCHpair(matchTiargs, match);
+        return buf.extractChars();
     }
 
     /**************************************************
@@ -2770,8 +1302,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
          * This is because f() is "more specialized."
          */
         {
-            MATCH c1 = fd.leastAsSpecialized(m.lastf, argumentList.names);
-            MATCH c2 = m.lastf.leastAsSpecialized(fd, argumentList.names);
+            MATCH c1 = FuncDeclaration.leastAsSpecialized(fd, m.lastf, argumentList.names);
+            MATCH c2 = FuncDeclaration.leastAsSpecialized(m.lastf, fd, argumentList.names);
             //printf("c1 = %d, c2 = %d\n", c1, c2);
             if (c1 > c2) return firstIsBetter();
             if (c1 < c2) return 0;
@@ -2876,7 +1408,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
             auto ti = new TemplateInstance(loc, td, tiargs);
             Objects dedtypes = Objects(td.parameters.length);
             assert(td.semanticRun != PASS.initial);
-            MATCH mta = td.matchWithInstance(sc, ti, dedtypes, argumentList, 0);
+            MATCH mta = matchWithInstance(sc, td, ti, dedtypes, argumentList, 0);
             //printf("matchWithInstance = %d\n", mta);
             if (mta == MATCH.nomatch || mta < ta_last)   // no match or less match
                 return 0;
@@ -3036,8 +1568,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
             if (td_best)
             {
                 // Disambiguate by picking the most specialized TemplateDeclaration
-                MATCH c1 = td.leastAsSpecialized(sc, td_best, argumentList);
-                MATCH c2 = td_best.leastAsSpecialized(sc, td, argumentList);
+                MATCH c1 = leastAsSpecialized(sc, td, td_best, argumentList);
+                MATCH c2 = leastAsSpecialized(sc, td_best, td, argumentList);
                 //printf("1: c1 = %d, c2 = %d\n", c1, c2);
                 if (c1 > c2) goto Ltd;
                 if (c1 < c2) goto Ltd_best;
@@ -3055,8 +1587,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
             }
             {
                 // Disambiguate by picking the most specialized FunctionDeclaration
-                MATCH c1 = fd.leastAsSpecialized(m.lastf, argumentList.names);
-                MATCH c2 = m.lastf.leastAsSpecialized(fd, argumentList.names);
+                MATCH c1 = FuncDeclaration.leastAsSpecialized(fd, m.lastf, argumentList.names);
+                MATCH c2 = FuncDeclaration.leastAsSpecialized(m.lastf, fd, argumentList.names);
                 //printf("3: c1 = %d, c2 = %d\n", c1, c2);
                 if (c1 > c2) goto Ltd;
                 if (c1 < c2) goto Ltd_best;
@@ -3199,7 +1731,7 @@ private size_t templateIdentifierLookup(Identifier id, TemplateParameters* param
     return IDX_NOTFOUND;
 }
 
-private size_t templateParameterLookup(Type tparam, TemplateParameters* parameters)
+size_t templateParameterLookup(Type tparam, TemplateParameters* parameters)
 {
     if (TypeIdentifier tident = tparam.isTypeIdentifier())
     {
@@ -3209,7 +1741,7 @@ private size_t templateParameterLookup(Type tparam, TemplateParameters* paramete
     return IDX_NOTFOUND;
 }
 
-private ubyte deduceWildHelper(Type t, Type* at, Type tparam)
+ubyte deduceWildHelper(Type t, Type* at, Type tparam)
 {
     if ((tparam.mod & MODFlags.wild) == 0)
         return 0;
@@ -3292,7 +1824,7 @@ private Type rawTypeMerge(Type t1, Type t2)
     return null;
 }
 
-private MATCH deduceTypeHelper(Type t, out Type at, Type tparam)
+MATCH deduceTypeHelper(Type t, out Type at, Type tparam)
 {
     // 9*9 == 81 cases
 
@@ -5000,7 +3532,7 @@ bool reliesOnTident(Type t, TemplateParameters* tparams, size_t iStart = 0)
  *      t           = Tested type, if null, returns false.
  *      tparams     = Template parameters.
  */
-private bool reliesOnTemplateParameters(Type t, TemplateParameter[] tparams)
+bool reliesOnTemplateParameters(Type t, TemplateParameter[] tparams)
 {
     bool visitVector(TypeVector t)
     {
@@ -6930,7 +5462,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
                 }
                 FuncDeclaration fd = sa.isFuncDeclaration();
                 if (fd)
-                    fd.functionSemantic();
+                    functionSemantic(fd);
             }
             else if (isParameter(o))
             {
@@ -7001,7 +5533,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
             assert(tempdecl._scope);
             // Deduce tdtypes
             tdtypes.setDim(tempdecl.parameters.length);
-            if (!tempdecl.matchWithInstance(sc, this, tdtypes, argumentList, 2))
+            if (!matchWithInstance(sc, tempdecl, this, tdtypes, argumentList, 2))
             {
                 .error(loc, "%s `%s` incompatible arguments for template instantiation", kind, toPrettyChars);
                 return false;
@@ -7051,7 +5583,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
                 dedtypes.zero();
                 assert(td.semanticRun != PASS.initial);
 
-                MATCH m = td.matchWithInstance(sc, this, dedtypes, argumentList, 0);
+                MATCH m = matchWithInstance(sc, td, this, dedtypes, argumentList, 0);
                 //printf("matchWithInstance = %d\n", m);
                 if (m == MATCH.nomatch) // no match at all
                     return 0;
@@ -7060,8 +5592,8 @@ extern (C++) class TemplateInstance : ScopeDsymbol
 
                 // Disambiguate by picking the most specialized TemplateDeclaration
                 {
-                MATCH c1 = td.leastAsSpecialized(sc, td_best, argumentList);
-                MATCH c2 = td_best.leastAsSpecialized(sc, td, argumentList);
+                MATCH c1 = leastAsSpecialized(sc, td, td_best, argumentList);
+                MATCH c2 = leastAsSpecialized(sc, td_best, td, argumentList);
                 //printf("c1 = %d, c2 = %d\n", c1, c2);
                 if (c1 > c2) goto Ltd;
                 if (c1 < c2) goto Ltd_best;
@@ -7159,7 +5691,11 @@ extern (C++) class TemplateInstance : ScopeDsymbol
                 // Only one template, so we can give better error message
                 const(char)* msg = "does not match template declaration";
                 const(char)* tip;
-                const tmsg = tdecl.toCharsNoConstraints();
+                OutBuffer buf;
+                HdrGenState hgs;
+                hgs.skipConstraints = true;
+                toCharsMaybeConstraints(tdecl, buf, hgs);
+                const tmsg = buf.peekChars();
                 const cmsg = tdecl.getConstraintEvalError(tip);
                 if (cmsg)
                 {
@@ -7327,7 +5863,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
                             return 1;
                         }
                     }
-                    MATCH m = td.matchWithInstance(sc, this, dedtypes, ArgumentList(), 0);
+                    MATCH m = matchWithInstance(sc, td, this, dedtypes, ArgumentList(), 0);
                     if (m == MATCH.nomatch)
                         return 0;
                 }
@@ -8562,15 +7098,21 @@ extern (C++) void printTemplateStats(bool listInstances, ErrorSink eSink)
 
     sortedStats.sort!(TemplateDeclarationStats.compare);
 
+    OutBuffer buf;
     foreach (const ref ss; sortedStats[])
     {
+        buf.reset();
+        HdrGenState hgs;
+        hgs.skipConstraints = true;
+        toCharsMaybeConstraints(ss.td, buf, hgs);
+        const tchars = buf.peekChars();
         if (listInstances && ss.ts.allInstances)
         {
             eSink.message(ss.td.loc,
                     "vtemplate: %u (%u distinct) instantiation(s) of template `%s` found, they are:",
                     ss.ts.numInstantiations,
                     ss.ts.uniqueInstantiations,
-                    ss.td.toCharsNoConstraints());
+                    tchars);
             foreach (const ti; (*ss.ts.allInstances)[])
             {
                 if (ti.tinst)   // if has enclosing instance
@@ -8585,13 +7127,13 @@ extern (C++) void printTemplateStats(bool listInstances, ErrorSink eSink)
                     "vtemplate: %u (%u distinct) instantiation(s) of template `%s` found",
                     ss.ts.numInstantiations,
                     ss.ts.uniqueInstantiations,
-                    ss.td.toCharsNoConstraints());
+                    tchars);
         }
     }
 }
 
 /// Pair of MATCHes
-private struct MATCHpair
+struct MATCHpair
 {
     MATCH mta;  /// match template parameters by initial template arguments
     MATCH mfa;  /// match template parameters by inferred template arguments
@@ -8605,7 +7147,7 @@ private struct MATCHpair
     }
 }
 
-private void write(ref OutBuffer buf, RootObject obj)
+void write(ref OutBuffer buf, RootObject obj)
 {
     if (obj)
     {
diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h
index a4bb588cac63feed151ea14845a7af8ec8ba7142..650bf3e2c7cdac7319b21bd22a478037ca103fb1 100644
--- a/gcc/d/dmd/enum.h
+++ b/gcc/d/dmd/enum.h
@@ -52,8 +52,6 @@ public:
     bool isDeprecated() const override;       // is Dsymbol deprecated?
     Visibility visible() override;
     bool isSpecial() const;
-    Expression *getDefaultValue(const Loc &loc);
-    Type *getMemtype(const Loc &loc);
 
     EnumDeclaration *isEnumDeclaration() override { return this; }
 
diff --git a/gcc/d/dmd/enumsem.d b/gcc/d/dmd/enumsem.d
new file mode 100644
index 0000000000000000000000000000000000000000..060396026e90a6e4b6b5857818a0143cf33a62d0
--- /dev/null
+++ b/gcc/d/dmd/enumsem.d
@@ -0,0 +1,714 @@
+/**
+ * Does the semantic passes on enums.
+ *
+ * Copyright:   Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
+ * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
+ * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/enumsem.d, _enumsem.d)
+ * Documentation:  https://dlang.org/phobos/dmd_enumsem.html
+ * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/enumsem.d
+ */
+
+module dmd.enumsem;
+
+import core.stdc.stdio;
+import core.stdc.string;
+
+import dmd.aggregate;
+import dmd.aliasthis;
+import dmd.arraytypes;
+import dmd.astcodegen;
+import dmd.astenums;
+import dmd.attrib;
+import dmd.blockexit;
+import dmd.clone;
+import dmd.cond;
+import dmd.compiler;
+import dmd.dcast;
+import dmd.dclass;
+import dmd.declaration;
+import dmd.denum;
+import dmd.dimport;
+import dmd.dinterpret;
+import dmd.dmangle;
+import dmd.dmodule;
+import dmd.dscope;
+import dmd.dstruct;
+import dmd.dsymbol;
+import dmd.dsymbolsem;
+import dmd.dtemplate;
+import dmd.dversion;
+import dmd.errors;
+import dmd.escape;
+import dmd.expression;
+import dmd.expressionsem;
+import dmd.func;
+import dmd.funcsem;
+import dmd.globals;
+import dmd.id;
+import dmd.identifier;
+import dmd.importc;
+import dmd.init;
+import dmd.initsem;
+import dmd.intrange;
+import dmd.hdrgen;
+import dmd.location;
+import dmd.mtype;
+import dmd.mustuse;
+import dmd.nogc;
+import dmd.nspace;
+import dmd.objc;
+import dmd.opover;
+import dmd.optimize;
+import dmd.parse;
+import dmd.root.array;
+import dmd.root.filename;
+import dmd.common.outbuffer;
+import dmd.root.rmem;
+import dmd.rootobject;
+import dmd.root.utf;
+import dmd.semantic2;
+import dmd.semantic3;
+import dmd.sideeffect;
+import dmd.statementsem;
+import dmd.staticassert;
+import dmd.tokens;
+import dmd.utils;
+import dmd.statement;
+import dmd.target;
+import dmd.templateparamsem;
+import dmd.typesem;
+import dmd.visitor;
+
+
+/*********************************
+ * Perform semantic analysis on enum declaration `em`
+ */
+void enumSemantic(Scope* sc, EnumDeclaration ed)
+{
+    //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc.scopesym, sc.scopesym.toChars(), ed.toChars());
+    //printf("EnumDeclaration::semantic() %p %s\n", ed, ed.toChars());
+    if (ed.semanticRun >= PASS.semanticdone)
+        return; // semantic() already completed
+    if (ed.semanticRun == PASS.semantic)
+    {
+        assert(ed.memtype);
+        error(ed.loc, "circular reference to enum base type `%s`", ed.memtype.toChars());
+        ed.errors = true;
+        ed.semanticRun = PASS.semanticdone;
+        return;
+    }
+    Scope* scx = null;
+    if (ed._scope)
+    {
+        sc = ed._scope;
+        scx = ed._scope; // save so we don't make redundant copies
+        ed._scope = null;
+    }
+
+    if (!sc)
+        return;
+
+    ed.parent = sc.parent;
+    ed.type = ed.type.typeSemantic(ed.loc, sc);
+
+    ed.visibility = sc.visibility;
+    if (sc.stc & STC.deprecated_)
+        ed.isdeprecated = true;
+    ed.userAttribDecl = sc.userAttribDecl;
+    ed.cppnamespace = sc.namespace;
+
+    ed.semanticRun = PASS.semantic;
+    UserAttributeDeclaration.checkGNUABITag(ed, sc.linkage);
+    checkMustUseReserved(ed);
+
+    if (!ed.members && !ed.memtype) // enum ident;
+    {
+        ed.semanticRun = PASS.semanticdone;
+        return;
+    }
+
+    if (!ed.symtab)
+        ed.symtab = new DsymbolTable();
+
+    /* The separate, and distinct, cases are:
+     *  1. enum { ... }
+     *  2. enum : memtype { ... }
+     *  3. enum ident { ... }
+     *  4. enum ident : memtype { ... }
+     *  5. enum ident : memtype;
+     *  6. enum ident;
+     */
+
+    if (ed.memtype)
+    {
+        ed.memtype = ed.memtype.typeSemantic(ed.loc, sc);
+
+        /* Check to see if memtype is forward referenced
+         */
+        if (auto te = ed.memtype.isTypeEnum())
+        {
+            auto sym = te.toDsymbol(sc).isEnumDeclaration();
+            // Special enums like __c_[u]long[long] are fine to forward reference
+            // see https://issues.dlang.org/show_bug.cgi?id=20599
+            if (!sym.isSpecial() && (!sym.memtype ||  !sym.members || !sym.symtab || sym._scope))
+            {
+                // memtype is forward referenced, so try again later
+                deferDsymbolSemantic(sc, ed, scx);
+                //printf("\tdeferring %s\n", toChars());
+                ed.semanticRun = PASS.initial;
+                return;
+            }
+            else
+                // Ensure that semantic is run to detect. e.g. invalid forward references
+                sym.dsymbolSemantic(sc);
+        }
+        if (ed.memtype.ty == Tvoid)
+        {
+            .error(ed.loc, "%s `%s` base type must not be `void`", ed.kind, ed.toPrettyChars);
+            ed.memtype = Type.terror;
+        }
+        if (ed.memtype.ty == Terror)
+        {
+            ed.errors = true;
+            // poison all the members
+            ed.members.foreachDsymbol( (s) { s.errors = true; } );
+            ed.semanticRun = PASS.semanticdone;
+            return;
+        }
+    }
+
+    if (!ed.members) // enum ident : memtype;
+    {
+        ed.semanticRun = PASS.semanticdone;
+        return;
+    }
+
+    if (ed.members.length == 0)
+    {
+        .error(ed.loc, "%s `%s enum `%s` must have at least one member", ed.kind, ed.toPrettyChars, ed.toChars());
+        ed.errors = true;
+        ed.semanticRun = PASS.semanticdone;
+        return;
+    }
+
+    if (!(sc.flags & SCOPE.Cfile))  // C enum remains incomplete until members are done
+        ed.semanticRun = PASS.semanticdone;
+
+    version (none)
+    {
+        // @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
+        // Deprecated in 2.100
+        // Make an error in 2.110
+        if (sc.stc & STC.scope_)
+            deprecation(ed.loc, "`scope` as a type constraint is deprecated.  Use `scope` at the usage site.");
+    }
+
+    Scope* sce;
+    if (ed.isAnonymous())
+        sce = sc;
+    else
+    {
+        sce = sc.push(ed);
+        sce.parent = ed;
+    }
+    sce = sce.startCTFE();
+    sce.setNoFree(); // needed for getMaxMinValue()
+
+    /* Each enum member gets the sce scope
+     */
+    ed.members.foreachDsymbol( (s)
+    {
+        EnumMember em = s.isEnumMember();
+        if (em)
+            em._scope = sce;
+    });
+
+    /* addMember() is not called when the EnumDeclaration appears as a function statement,
+     * so we have to do what addMember() does and install the enum members in the right symbol
+     * table
+     */
+    addEnumMembersToSymtab(ed, sc, sc.getScopesym());
+
+    if (sc.flags & SCOPE.Cfile)
+    {
+        /* C11 6.7.2.2
+         */
+        Type commonType = ed.memtype;
+        if (!commonType)
+            commonType = Type.tint32;
+        ulong nextValue = 0;        // C11 6.7.2.2-3 first member value defaults to 0
+
+        // C11 6.7.2.2-2 value must be representable as an int.
+        // The sizemask represents all values that int will fit into,
+        // from 0..uint.max.  We want to cover int.min..uint.max.
+        IntRange ir = IntRange.fromType(commonType);
+
+        void emSemantic(EnumMember em, ref ulong nextValue)
+        {
+            static void errorReturn(EnumMember em)
+            {
+                em.value = ErrorExp.get();
+                em.errors = true;
+                em.semanticRun = PASS.semanticdone;
+            }
+
+            em.semanticRun = PASS.semantic;
+            em.type = commonType;
+            em._linkage = LINK.c;
+            em.storage_class |= STC.manifest;
+            if (em.value)
+            {
+                Expression e = em.value;
+                assert(e.dyncast() == DYNCAST.expression);
+
+                /* To merge the type of e with commonType, add 0 of type commonType
+                 */
+                if (!ed.memtype)
+                    e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType));
+
+                e = e.expressionSemantic(sc);
+                e = resolveProperties(sc, e);
+                e = e.integralPromotions(sc);
+                e = e.ctfeInterpret();
+                if (e.op == EXP.error)
+                    return errorReturn(em);
+                auto ie = e.isIntegerExp();
+                if (!ie)
+                {
+                    // C11 6.7.2.2-2
+                    .error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars());
+                    return errorReturn(em);
+                }
+                if (ed.memtype && !ir.contains(getIntRange(ie)))
+                {
+                    // C11 6.7.2.2-2
+                    .error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars());
+                    return errorReturn(em);
+                }
+                nextValue = ie.toInteger();
+                if (!ed.memtype)
+                    commonType = e.type;
+                em.value = new IntegerExp(em.loc, nextValue, commonType);
+            }
+            else
+            {
+                // C11 6.7.2.2-3 add 1 to value of previous enumeration constant
+                bool first = (em == (*em.ed.members)[0]);
+                if (!first)
+                {
+                    Expression max = getProperty(commonType, null, em.loc, Id.max, 0);
+                    if (nextValue == max.toInteger())
+                    {
+                        .error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars());
+                        return errorReturn(em);
+                    }
+                    nextValue += 1;
+                }
+                em.value = new IntegerExp(em.loc, nextValue, commonType);
+            }
+            em.type = commonType;
+            em.semanticRun = PASS.semanticdone;
+        }
+
+        ed.members.foreachDsymbol( (s)
+        {
+            if (EnumMember em = s.isEnumMember())
+                emSemantic(em, nextValue);
+        });
+
+        if (!ed.memtype)
+        {
+            // cast all members to commonType
+            ed.members.foreachDsymbol( (s)
+            {
+                if (EnumMember em = s.isEnumMember())
+                {
+                    em.type = commonType;
+                    em.value = em.value.castTo(sc, commonType);
+                }
+            });
+        }
+
+        ed.memtype = commonType;
+        ed.semanticRun = PASS.semanticdone;
+        return;
+    }
+
+    ed.members.foreachDsymbol( (s)
+    {
+        if (EnumMember em = s.isEnumMember())
+            em.dsymbolSemantic(em._scope);
+    });
+    //printf("ed.defaultval = %lld\n", ed.defaultval);
+
+    //if (ed.defaultval) printf("ed.defaultval: %s %s\n", ed.defaultval.toChars(), ed.defaultval.type.toChars());
+    //printf("members = %s\n", members.toChars());
+}
+
+Expression getDefaultValue(EnumDeclaration ed, const ref Loc loc)
+{
+    Expression handleErrors(){
+        ed.defaultval = ErrorExp.get();
+        return ed.defaultval;
+    }
+    //printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars());
+    // https://issues.dlang.org/show_bug.cgi?id=23904
+    // Return ed.defaultval only if it is not ErrorExp.
+    // A speculative context may set ed.defaultval to ErrorExp;
+    // subsequent non-speculative contexts need to be able
+    // to print the error.
+    if (ed.defaultval && !ed.defaultval.isErrorExp())
+        return ed.defaultval;
+
+    if (ed.isCsymbol())
+        return ed.memtype.defaultInit(loc, true);
+
+    if (ed._scope)
+        dsymbolSemantic(ed, ed._scope);
+    if (ed.errors)
+        return handleErrors();
+    if (!ed.members)
+    {
+        if (ed.isSpecial())
+        {
+            /* Allow these special enums to not need a member list
+             */
+            return ed.defaultval = ed.memtype.defaultInit(loc);
+        }
+
+        error(loc, "%s `%s` is opaque and has no default initializer", ed.kind, ed.toPrettyChars);
+        return handleErrors();
+    }
+
+    foreach (const i; 0 .. ed.members.length)
+    {
+        EnumMember em = (*ed.members)[i].isEnumMember();
+        if (em)
+        {
+            if (em.semanticRun < PASS.semanticdone)
+            {
+                error(loc, "%s `%s` forward reference of `%s.init`", ed.kind, ed.toPrettyChars, ed.toChars());
+                return handleErrors();
+            }
+
+            ed.defaultval = em.value;
+            return ed.defaultval;
+        }
+    }
+    return handleErrors();
+}
+
+Type getMemtype(EnumDeclaration ed, const ref Loc loc)
+{
+    if (ed._scope)
+    {
+        /* Enum is forward referenced. We don't need to resolve the whole thing,
+         * just the base type
+         */
+        if (ed.memtype)
+        {
+            Loc locx = loc.isValid() ? loc : ed.loc;
+            ed.memtype = ed.memtype.typeSemantic(locx, ed._scope);
+        }
+        else
+        {
+            // Run semantic to get the type from a possible first member value
+            dsymbolSemantic(ed, ed._scope);
+        }
+    }
+    if (!ed.memtype)
+    {
+        if (!ed.isAnonymous() && (ed.members || ed.semanticRun >= PASS.semanticdone))
+            ed.memtype = Type.tint32;
+        else
+        {
+            Loc locx = loc.isValid() ? loc : ed.loc;
+            error(locx, "is forward referenced looking for base type");
+            return Type.terror;
+        }
+    }
+    return ed.memtype;
+}
+
+/*********************************
+ * Perform semantic analysis on enum member `em`
+ */
+void enumMemberSemantic(Scope* sc, EnumMember em)
+{
+    //printf("EnumMember::semantic() %s\n", em.toChars());
+
+    void errorReturn()
+    {
+        em.errors = true;
+        em.semanticRun = PASS.semanticdone;
+    }
+
+    if (em.errors || em.semanticRun >= PASS.semanticdone)
+        return;
+    if (em.semanticRun == PASS.semantic)
+    {
+        .error(em.loc, "%s `%s` circular reference to `enum` member", em.kind, em.toPrettyChars);
+        return errorReturn();
+    }
+    assert(em.ed);
+
+    em.ed.dsymbolSemantic(sc);
+    if (em.ed.errors)
+        return errorReturn();
+    if (em.errors || em.semanticRun >= PASS.semanticdone)
+        return;
+
+    if (em._scope)
+        sc = em._scope;
+    if (!sc)
+        return;
+
+    em.semanticRun = PASS.semantic;
+
+    em.visibility = em.ed.isAnonymous() ? em.ed.visibility : Visibility(Visibility.Kind.public_);
+    em._linkage = LINK.d;
+    em.storage_class |= STC.manifest;
+
+    // https://issues.dlang.org/show_bug.cgi?id=9701
+    if (em.ed.isAnonymous())
+    {
+        if (em.userAttribDecl)
+            em.userAttribDecl.userAttribDecl = em.ed.userAttribDecl;
+        else
+            em.userAttribDecl = em.ed.userAttribDecl;
+    }
+
+    // Eval UDA in this same scope. Issues 19344, 20835, 21122
+    if (em.userAttribDecl)
+    {
+        // Set scope but avoid extra sc.uda attachment inside setScope()
+        auto inneruda = em.userAttribDecl.userAttribDecl;
+        em.userAttribDecl.setScope(sc);
+        em.userAttribDecl.userAttribDecl = inneruda;
+        em.userAttribDecl.dsymbolSemantic(sc);
+    }
+
+    // The first enum member is special
+    bool first = (em == (*em.ed.members)[0]);
+
+    if (em.origType)
+    {
+        em.origType = em.origType.typeSemantic(em.loc, sc);
+        em.type = em.origType;
+        assert(em.value); // "type id;" is not a valid enum member declaration
+    }
+
+    if (em.value)
+    {
+        Expression e = em.value;
+        assert(e.dyncast() == DYNCAST.expression);
+        e = e.expressionSemantic(sc);
+        e = resolveProperties(sc, e);
+        e = e.ctfeInterpret();
+        if (e.op == EXP.error)
+            return errorReturn();
+        if (first && !em.ed.memtype && !em.ed.isAnonymous())
+        {
+            em.ed.memtype = e.type;
+            if (em.ed.memtype.ty == Terror)
+            {
+                em.ed.errors = true;
+                return errorReturn();
+            }
+            if (em.ed.memtype.ty != Terror)
+            {
+                /* https://issues.dlang.org/show_bug.cgi?id=11746
+                 * All of named enum members should have same type
+                 * with the first member. If the following members were referenced
+                 * during the first member semantic, their types should be unified.
+                 */
+                em.ed.members.foreachDsymbol( (s)
+                {
+                    EnumMember enm = s.isEnumMember();
+                    if (!enm || enm == em || enm.semanticRun < PASS.semanticdone || enm.origType)
+                        return;
+
+                    //printf("[%d] em = %s, em.semanticRun = %d\n", i, toChars(), em.semanticRun);
+                    Expression ev = enm.value;
+                    ev = ev.implicitCastTo(sc, em.ed.memtype);
+                    ev = ev.ctfeInterpret();
+                    ev = ev.castTo(sc, em.ed.type);
+                    if (ev.op == EXP.error)
+                        em.ed.errors = true;
+                    enm.value = ev;
+                });
+
+                if (em.ed.errors)
+                {
+                    em.ed.memtype = Type.terror;
+                    return errorReturn();
+                }
+            }
+        }
+
+        if (em.ed.memtype && !em.origType)
+        {
+            e = e.implicitCastTo(sc, em.ed.memtype);
+            e = e.ctfeInterpret();
+
+            // save origValue for better json output
+            em.origValue = e;
+
+            if (!em.ed.isAnonymous())
+            {
+                e = e.castTo(sc, em.ed.type.addMod(e.type.mod)); // https://issues.dlang.org/show_bug.cgi?id=12385
+                e = e.ctfeInterpret();
+            }
+        }
+        else if (em.origType)
+        {
+            e = e.implicitCastTo(sc, em.origType);
+            e = e.ctfeInterpret();
+            assert(em.ed.isAnonymous());
+
+            // save origValue for better json output
+            em.origValue = e;
+        }
+        em.value = e;
+    }
+    else if (first)
+    {
+        Type t;
+        if (em.ed.memtype)
+            t = em.ed.memtype;
+        else
+        {
+            t = Type.tint32;
+            if (!em.ed.isAnonymous())
+                em.ed.memtype = t;
+        }
+        const errors = global.startGagging();
+        Expression e = new IntegerExp(em.loc, 0, t);
+        e = e.ctfeInterpret();
+        if (global.endGagging(errors))
+        {
+            error(em.loc, "cannot generate 0 value of type `%s` for `%s`",
+                t.toChars(), em.toChars());
+        }
+        // save origValue for better json output
+        em.origValue = e;
+
+        if (!em.ed.isAnonymous())
+        {
+            e = e.castTo(sc, em.ed.type);
+            e = e.ctfeInterpret();
+        }
+        em.value = e;
+    }
+    else
+    {
+        /* Find the previous enum member,
+         * and set this to be the previous value + 1
+         */
+        EnumMember emprev = null;
+        em.ed.members.foreachDsymbol( (s)
+        {
+            if (auto enm = s.isEnumMember())
+            {
+                if (enm == em)
+                    return 1;       // found
+                emprev = enm;
+            }
+            return 0;       // continue
+        });
+
+        assert(emprev);
+        if (emprev.semanticRun < PASS.semanticdone) // if forward reference
+            emprev.dsymbolSemantic(emprev._scope); // resolve it
+        if (emprev.errors)
+            return errorReturn();
+
+        auto errors = global.startGagging();
+        Expression eprev = emprev.value;
+        assert(eprev);
+        // .toHeadMutable() due to https://issues.dlang.org/show_bug.cgi?id=18645
+        Type tprev = eprev.type.toHeadMutable().equals(em.ed.type.toHeadMutable())
+            ? em.ed.memtype
+            : eprev.type;
+        /*
+            https://issues.dlang.org/show_bug.cgi?id=20777
+            Previously this used getProperty, which doesn't consider anything user defined,
+            this construct does do that and thus fixes the bug.
+        */
+        Expression emax = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
+        emax = emax.expressionSemantic(sc);
+        emax = emax.ctfeInterpret();
+
+        // check that (eprev != emax)
+        Expression e = new EqualExp(EXP.equal, em.loc, eprev, emax);
+        e = e.expressionSemantic(sc);
+        e = e.ctfeInterpret();
+        if (global.endGagging(errors))
+        {
+            // display an introductory error before showing what actually failed
+            error(em.loc, "cannot check `%s` value for overflow", em.toPrettyChars());
+            // rerun to show errors
+            Expression e2 = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
+            e2 = e2.expressionSemantic(sc);
+            e2 = e2.ctfeInterpret();
+            e2 = new EqualExp(EXP.equal, em.loc, eprev, e2);
+            e2 = e2.expressionSemantic(sc);
+            e2 = e2.ctfeInterpret();
+        }
+        // now any errors are for generating a value
+        if (e.toInteger())
+        {
+            auto mt = em.ed.memtype;
+            if (!mt)
+                mt = eprev.type;
+            .error(em.loc, "%s `%s` initialization with `%s.%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars,
+                emprev.ed.toChars(), emprev.toChars(), mt.toChars());
+            return errorReturn();
+        }
+        errors = global.startGagging();
+        // Now set e to (eprev + 1)
+        e = new AddExp(em.loc, eprev, IntegerExp.literal!1);
+        e = e.expressionSemantic(sc);
+        e = e.castTo(sc, eprev.type);
+        e = e.ctfeInterpret();
+        if (global.endGagging(errors))
+        {
+            error(em.loc, "cannot generate value for `%s`", em.toPrettyChars());
+            // rerun to show errors
+            Expression e2 = new AddExp(em.loc, eprev, IntegerExp.literal!1);
+            e2 = e2.expressionSemantic(sc);
+            e2 = e2.castTo(sc, eprev.type);
+            e2 = e2.ctfeInterpret();
+        }
+        // save origValue (without cast) for better json output
+        if (e.op != EXP.error) // avoid duplicate diagnostics
+        {
+            assert(emprev.origValue);
+            em.origValue = new AddExp(em.loc, emprev.origValue, IntegerExp.literal!1);
+            em.origValue = em.origValue.expressionSemantic(sc);
+            em.origValue = em.origValue.ctfeInterpret();
+        }
+
+        if (e.op == EXP.error)
+            return errorReturn();
+        if (e.type.isfloating())
+        {
+            // Check that e != eprev (not always true for floats)
+            Expression etest = new EqualExp(EXP.equal, em.loc, e, eprev);
+            etest = etest.expressionSemantic(sc);
+            etest = etest.ctfeInterpret();
+            if (etest.toInteger())
+            {
+                .error(em.loc, "%s `%s` has inexact value due to loss of precision", em.kind, em.toPrettyChars);
+                return errorReturn();
+            }
+        }
+        em.value = e;
+    }
+    if (!em.origType)
+        em.type = em.value.type;
+
+    assert(em.origValue);
+    em.semanticRun = PASS.semanticdone;
+}
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index cbf01186f98dbc6e0658dbed324ee6a60f29bfbd..1603f2bbb5350421a8777abe6c39b12c46069373 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -721,6 +721,7 @@ extern (C++) abstract class Expression : ASTNode
         inout(SuperExp)     isSuperExp() { return op == EXP.super_ ? cast(typeof(return))this : null; }
         inout(NullExp)      isNullExp() { return op == EXP.null_ ? cast(typeof(return))this : null; }
         inout(StringExp)    isStringExp() { return op == EXP.string_ ? cast(typeof(return))this : null; }
+        inout(InterpExp)    isInterpExp() { return op == EXP.interpolated ? cast(typeof(return))this : null; }
         inout(TupleExp)     isTupleExp() { return op == EXP.tuple ? cast(typeof(return))this : null; }
         inout(ArrayLiteralExp) isArrayLiteralExp() { return op == EXP.arrayLiteral ? cast(typeof(return))this : null; }
         inout(AssocArrayLiteralExp) isAssocArrayLiteralExp() { return op == EXP.assocArrayLiteral ? cast(typeof(return))this : null; }
@@ -1499,6 +1500,7 @@ extern (C++) final class StringExp : Expression
         char* string;   // if sz == 1
         wchar* wstring; // if sz == 2
         dchar* dstring; // if sz == 4
+        ulong* lstring; // if sz == 8
     }                   // (const if ownedByCtfe == OwnedBy.code)
     size_t len;         // number of code units
     ubyte sz = 1;       // 1: char, 2: wchar, 4: dchar
@@ -1661,6 +1663,13 @@ extern (C++) final class StringExp : Expression
      *  code unit at index i
      */
     dchar getCodeUnit(size_t i) const pure
+    {
+        assert(this.sz <= dchar.sizeof);
+        return cast(dchar) getIndex(i);
+    }
+
+    /// Returns: integer at index `i`
+    dinteger_t getIndex(size_t i) const pure
     {
         assert(i < len);
         final switch (sz)
@@ -1671,6 +1680,8 @@ extern (C++) final class StringExp : Expression
             return wstring[i];
         case 4:
             return dstring[i];
+        case 8:
+            return lstring[i];
         }
     }
 
@@ -1681,6 +1692,11 @@ extern (C++) final class StringExp : Expression
      *  c = code unit to set it to
      */
     extern (D) void setCodeUnit(size_t i, dchar c)
+    {
+        return setIndex(i, c);
+    }
+
+    extern (D) void setIndex(size_t i, long c)
     {
         assert(i < len);
         final switch (sz)
@@ -1692,7 +1708,10 @@ extern (C++) final class StringExp : Expression
             wstring[i] = cast(wchar)c;
             break;
         case 4:
-            dstring[i] = c;
+            dstring[i] = cast(dchar) c;
+            break;
+        case 8:
+            lstring[i] = c;
             break;
         }
     }
@@ -1847,6 +1866,28 @@ extern (C++) final class StringExp : Expression
     }
 }
 
+extern (C++) final class InterpExp : Expression
+{
+    char postfix = NoPostfix;   // 'c', 'w', 'd'
+    OwnedBy ownedByCtfe = OwnedBy.code;
+    InterpolatedSet* interpolatedSet;
+
+    enum char NoPostfix = 0;
+
+    extern (D) this(const ref Loc loc, InterpolatedSet* set, char postfix = NoPostfix) scope
+    {
+        super(loc, EXP.interpolated);
+        this.interpolatedSet = set;
+        this.postfix = postfix;
+    }
+
+    override void accept(Visitor v)
+    {
+        v.visit(this);
+    }
+}
+
+
 /***********************************************************
  * A sequence of expressions
  *
@@ -5494,6 +5535,7 @@ private immutable ubyte[EXP.max+1] expSize = [
     EXP.preMinusMinus: __traits(classInstanceSize, PreExp),
     EXP.identifier: __traits(classInstanceSize, IdentifierExp),
     EXP.string_: __traits(classInstanceSize, StringExp),
+    EXP.interpolated: __traits(classInstanceSize, InterpExp),
     EXP.this_: __traits(classInstanceSize, ThisExp),
     EXP.super_: __traits(classInstanceSize, SuperExp),
     EXP.halt: __traits(classInstanceSize, HaltExp),
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index f57f6a402957fbf7a41f78175ec1bad756a6cab2..d53cc3e85cc58df27303b1f63ff33e9aca3fb876 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -38,6 +38,7 @@ class TemplateDeclaration;
 class ClassDeclaration;
 class OverloadSet;
 class StringExp;
+class InterpExp;
 class LoweredAssignExp;
 #ifdef IN_GCC
 typedef union tree_node Symbol;
@@ -129,6 +130,7 @@ public:
     SuperExp* isSuperExp();
     NullExp* isNullExp();
     StringExp* isStringExp();
+    InterpExp* isInterpExp();
     TupleExp* isTupleExp();
     ArrayLiteralExp* isArrayLiteralExp();
     AssocArrayLiteralExp* isAssocArrayLiteralExp();
@@ -352,7 +354,7 @@ class StringExp final : public Expression
 public:
     utf8_t postfix;      // 'c', 'w', 'd'
     OwnedBy ownedByCtfe;
-    void *string;       // char, wchar, or dchar data
+    void *string;       // char, wchar, dchar, or long data
     size_t len;         // number of chars, wchars, or dchars
     unsigned char sz;   // 1: char, 2: wchar, 4: dchar
     d_bool committed;   // if type is committed
@@ -362,6 +364,7 @@ public:
     static StringExp *create(const Loc &loc, const void *s, d_size_t len);
     bool equals(const RootObject * const o) const override;
     char32_t getCodeUnit(d_size_t i) const;
+    dinteger_t getIndex(d_size_t i) const;
     StringExp *toStringExp() override;
     Optional<bool> toBool() override;
     bool isLvalue() override;
@@ -370,6 +373,16 @@ public:
     void writeTo(void* dest, bool zero, int tyto = 0) const;
 };
 
+class InterpExp final : public Expression
+{
+public:
+    utf8_t postfix;   // 'c', 'w', 'd'
+    OwnedBy ownedByCtfe;
+    void* interpolatedSet;
+
+    void accept(Visitor* v) override { v->visit(this); }
+};
+
 // Tuple
 
 class TupleExp final : public Expression
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index d46457481771a50402fbc33aec0f07165554e2f5..f2133037a2307af33f08d536606aebdb463f9882 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -42,10 +42,12 @@ import dmd.dsymbolsem;
 import dmd.dtemplate;
 import dmd.errors;
 import dmd.errorsink;
+import dmd.enumsem;
 import dmd.escape;
 import dmd.expression;
 import dmd.file_manager;
 import dmd.func;
+import dmd.funcsem;
 import dmd.globals;
 import dmd.hdrgen;
 import dmd.id;
@@ -1579,7 +1581,7 @@ Lagain:
     if (auto f = s.isFuncDeclaration())
     {
         f = f.toAliasFunc();
-        if (!f.functionSemantic())
+        if (!functionSemantic(f))
             return ErrorExp.get();
 
         if (!hasOverloads && f.checkForwardRef(loc))
@@ -2866,7 +2868,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
     // If inferring return type, and semantic3() needs to be run if not already run
     if (!tf.next && fd.inferRetType)
     {
-        fd.functionSemantic();
+        functionSemantic(fd);
     }
     else if (fd && fd.parent)
     {
@@ -4145,6 +4147,84 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         result = e;
     }
 
+    override void visit(InterpExp e)
+    {
+        // the lexer breaks up into an odd/even array of literals and expression code
+        // we need to turn that into:
+        /+
+            tuple(
+                .object.imported!"core.interpolation".InterpolationHeader(),
+                ...
+                .object.imported!"core.interpolation".InterpolationFooter()
+            )
+
+            There the ... loops through them all, making the even ones
+                .object.imported!"core.interpolation".InterpolatedLiteral!str()
+            and making the odd ones
+                .object.imported!"core.interpolation".InterpolatedExpression!str(),
+                the code represented by str
+
+            Empty string literals are skipped as they provide no additional information.
+        +/
+
+        if (e.postfix)
+            error(e.loc, "String postfixes on interpolated expression sequences are not allowed.");
+
+        Expression makeNonTemplateItem(Identifier which) {
+            Expression id = new IdentifierExp(e.loc, Id.empty);
+            id = new DotIdExp(e.loc, id, Id.object);
+            auto moduleNameArgs = new Objects();
+            moduleNameArgs.push(new StringExp(e.loc, "core.interpolation"));
+            id = new DotTemplateInstanceExp(e.loc, id, Id.imported, moduleNameArgs);
+            id = new DotIdExp(e.loc, id, which);
+            id = new CallExp(e.loc, id, new Expressions());
+            return id;
+        }
+
+        Expression makeTemplateItem(Identifier which, string arg) {
+            Expression id = new IdentifierExp(e.loc, Id.empty);
+            id = new DotIdExp(e.loc, id, Id.object);
+            auto moduleNameArgs = new Objects();
+            moduleNameArgs.push(new StringExp(e.loc, "core.interpolation"));
+            id = new DotTemplateInstanceExp(e.loc, id, Id.imported, moduleNameArgs);
+            auto tiargs = new Objects();
+            auto templateStringArg = new StringExp(e.loc, arg);
+            // banning those instead of forwarding them
+            // templateStringArg.postfix = e.postfix; // forward the postfix to these literals
+            tiargs.push(templateStringArg);
+            id = new DotTemplateInstanceExp(e.loc, id, which, tiargs);
+            id = new CallExp(e.loc, id, new Expressions());
+            return id;
+        }
+
+        auto arguments = new Expressions();
+        arguments.push(makeNonTemplateItem(Id.InterpolationHeader));
+
+        foreach (idx, str; e.interpolatedSet.parts)
+        {
+            if (idx % 2 == 0)
+            {
+                if (str.length > 0)
+                    arguments.push(makeTemplateItem(Id.InterpolatedLiteral, str));
+            }
+            else
+            {
+                arguments.push(makeTemplateItem(Id.InterpolatedExpression, str));
+                Expressions* mix = new Expressions();
+                mix.push(new StringExp(e.loc, str));
+                // FIXME: i'd rather not use MixinExp but idk how to do it lol
+                arguments.push(new MixinExp(e.loc, mix));
+            }
+        }
+
+        arguments.push(makeNonTemplateItem(Id.InterpolationFooter));
+
+        auto loweredTo = new TupleExp(e.loc, arguments);
+        visit(loweredTo);
+
+        result = loweredTo;
+    }
+
     override void visit(StringExp e)
     {
         static if (LOGSEMANTIC)
@@ -5366,7 +5446,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (fd)
         {
             //printf("L%d fd = %s\n", __LINE__, f.toChars());
-            if (!fd.functionSemantic())
+            if (!functionSemantic(fd))
                 return setError();
         }
 
@@ -6564,10 +6644,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                         .errorSupplemental(exp.loc, "the following error occured while looking for a UFCS match");
                     }
 
-                    .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
-                        exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
+                    .error(exp.loc, "%s `%s` is not callable using argument types `%s`",
+                        exp.f.kind(), exp.f.toChars(), buf.peekChars());
                     if (failMessage)
                         errorSupplemental(exp.loc, "%s", failMessage);
+                    .errorSupplemental(exp.f.loc, "`%s%s` declared here", exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList));
                     exp.f = null;
                 }
 
@@ -7549,7 +7630,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         se = se.toUTF8(sc);
 
         auto namez = se.toStringz();
-        if (!global.filePath)
+        if (!global.filePath.length)
         {
             error(e.loc, "need `-J` switch to import text file `%s`", namez.ptr);
             return setError();
@@ -7580,12 +7661,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return setError();
         }
 
-        auto resolvedNamez = FileName.searchPath(global.filePath, namez, false);
+        auto resolvedNamez = FileName.searchPath(global.filePath[], namez, false);
         if (!resolvedNamez)
         {
             error(e.loc, "file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
             errorSupplemental(e.loc, "Path(s) searched (as provided by `-J`):");
-            foreach (idx, path; *global.filePath)
+            foreach (idx, path; global.filePath[])
             {
                 const attr = FileName.exists(path);
                 const(char)* err = attr == 2 ? "" :
@@ -8170,7 +8251,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (FuncDeclaration fd = exp.var.isFuncDeclaration())
         {
             // for functions, do checks after overload resolution
-            if (!fd.functionSemantic())
+            if (!functionSemantic(fd))
                 return setError();
 
             /* https://issues.dlang.org/show_bug.cgi?id=13843
@@ -8937,7 +9018,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         bool err = false;
         if (cd.dtor)
         {
-            err |= !cd.dtor.functionSemantic();
+            err |= !functionSemantic(cd.dtor);
             err |= cd.dtor.checkPurity(exp.loc, sc);
             err |= cd.dtor.checkSafety(exp.loc, sc);
             err |= cd.dtor.checkNogc(exp.loc, sc);
@@ -14356,7 +14437,7 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag)
             if (auto f = s.isFuncDeclaration())
             {
                 //printf("it's a function\n");
-                if (!f.functionSemantic())
+                if (!functionSemantic(f))
                     return ErrorExp.get();
                 Expression e;
                 if (f.needThis())
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 370da6f0ee6d81e93542e27d81044d498f2c0557..adfecc83a1789925eeb2d3951d1fa10ed9bcfb32 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -39,6 +39,7 @@ import dmd.dtemplate;
 import dmd.errors;
 import dmd.escape;
 import dmd.expression;
+import dmd.funcsem;
 import dmd.globals;
 import dmd.hdrgen;
 import dmd.id;
@@ -466,103 +467,13 @@ extern (C++) class FuncDeclaration : Declaration
         return f;
     }
 
-    /****************************************************
-     * Resolve forward reference of function signature -
-     * parameter types, return type, and attributes.
-     * Returns:
-     *  false if any errors exist in the signature.
-     */
-    final bool functionSemantic()
-    {
-        //printf("functionSemantic() %p %s\n", this, toChars());
-        if (!_scope)
-            return !errors;
-
-        this.cppnamespace = _scope.namespace;
-
-        if (!originalType) // semantic not yet run
-        {
-            TemplateInstance spec = isSpeculative();
-            uint olderrs = global.errors;
-            uint oldgag = global.gag;
-            if (global.gag && !spec)
-                global.gag = 0;
-            dsymbolSemantic(this, _scope);
-            global.gag = oldgag;
-            if (spec && global.errors != olderrs)
-                spec.errors = (global.errors - olderrs != 0);
-            if (olderrs != global.errors) // if errors compiling this function
-                return false;
-        }
-
-        // if inferring return type, sematic3 needs to be run
-        // - When the function body contains any errors, we cannot assume
-        //   the inferred return type is valid.
-        //   So, the body errors should become the function signature error.
-        if (inferRetType && type && !type.nextOf())
-            return functionSemantic3();
-
-        TemplateInstance ti;
-        if (isInstantiated() && !isVirtualMethod() &&
-            ((ti = parent.isTemplateInstance()) is null || ti.isTemplateMixin() || ti.tempdecl.ident == ident))
-        {
-            AggregateDeclaration ad = isMemberLocal();
-            if (ad && ad.sizeok != Sizeok.done)
-            {
-                /* Currently dmd cannot resolve forward references per methods,
-                 * then setting SIZOKfwd is too conservative and would break existing code.
-                 * So, just stop method attributes inference until ad.dsymbolSemantic() done.
-                 */
-                //ad.sizeok = Sizeok.fwd;
-            }
-            else
-                return functionSemantic3() || !errors;
-        }
-
-        if (storage_class & STC.inference)
-            return functionSemantic3() || !errors;
-
-        return !errors;
-    }
-
-    /****************************************************
-     * Resolve forward reference of function body.
-     * Returns false if any errors exist in the body.
-     */
-    final bool functionSemantic3()
-    {
-        if (semanticRun < PASS.semantic3 && _scope)
-        {
-            /* Forward reference - we need to run semantic3 on this function.
-             * If errors are gagged, and it's not part of a template instance,
-             * we need to temporarily ungag errors.
-             */
-            TemplateInstance spec = isSpeculative();
-            uint olderrs = global.errors;
-            uint oldgag = global.gag;
-            if (global.gag && !spec)
-                global.gag = 0;
-            semantic3(this, _scope);
-            global.gag = oldgag;
-
-            // If it is a speculatively-instantiated template, and errors occur,
-            // we need to mark the template as having errors.
-            if (spec && global.errors != olderrs)
-                spec.errors = (global.errors - olderrs != 0);
-            if (olderrs != global.errors) // if errors compiling this function
-                return false;
-        }
-
-        return !errors && !this.hasSemantic3Errors();
-    }
-
     /****************************************************
      * Check that this function type is properly resolved.
      * If not, report "forward reference error" and return true.
      */
     extern (D) final bool checkForwardRef(const ref Loc loc)
     {
-        if (!functionSemantic())
+        if (!functionSemantic(this))
             return true;
 
         /* No deco means the functionSemantic() call could not resolve
@@ -579,72 +490,6 @@ extern (C++) class FuncDeclaration : Declaration
         return false;
     }
 
-    // called from semantic3
-    /**
-     * Creates and returns the hidden parameters for this function declaration.
-     *
-     * Hidden parameters include the `this` parameter of a class, struct or
-     * nested function and the selector parameter for Objective-C methods.
-     */
-    extern (D) final void declareThis(Scope* sc)
-    {
-        const bool dualCtx = (toParent2() != toParentLocal());
-        if (dualCtx)
-            this.hasDualContext = true;
-        auto ad = isThis();
-        if (!dualCtx && !ad && !isNested())
-        {
-            vthis = null;
-            objc.selectorParameter = null;
-            return;
-        }
-
-        Type addModStc(Type t)
-        {
-            return t.addMod(type.mod).addStorageClass(storage_class);
-        }
-
-        if (dualCtx || isNested())
-        {
-            /* The 'this' for a nested function is the link to the
-             * enclosing function's stack frame.
-             * Note that nested functions and member functions are disjoint.
-             */
-            Type tthis = addModStc(dualCtx ?
-                                   Type.tvoidptr.sarrayOf(2).pointerTo() :
-                                   Type.tvoid.pointerTo());
-            vthis = new VarDeclaration(loc, tthis, dualCtx ? Id.this2 : Id.capture, null);
-            vthis.storage_class |= STC.parameter | STC.nodtor;
-        }
-        else if (ad)
-        {
-            Type thandle = addModStc(ad.handleType());
-            vthis = new ThisDeclaration(loc, thandle);
-            vthis.storage_class |= STC.parameter;
-            if (thandle.ty == Tstruct)
-            {
-                vthis.storage_class |= STC.ref_;
-            }
-        }
-
-        if (auto tf = type.isTypeFunction())
-        {
-            if (tf.isreturn)
-                vthis.storage_class |= STC.return_;
-            if (tf.isScopeQual)
-                vthis.storage_class |= STC.scope_;
-            if (tf.isreturnscope)
-                vthis.storage_class |= STC.returnScope;
-        }
-
-        vthis.dsymbolSemantic(sc);
-        if (!sc.insert(vthis))
-            assert(0);
-        vthis.parent = this;
-        if (ad)
-            objc.selectorParameter = .objc.createSelectorParameter(this, sc);
-    }
-
     override final bool equals(const RootObject o) const
     {
         if (this == o)
@@ -1104,20 +949,24 @@ extern (C++) class FuncDeclaration : Declaration
     }
 
     /*************************************
-     * Determine partial specialization order of 'this' vs g.
+     * Determine partial specialization order of functions `f` vs `g`.
      * This is very similar to TemplateDeclaration::leastAsSpecialized().
+     * Params:
+     *  f = first function
+     *  g = second function
+     *  names = names of parameters
      * Returns:
      *      match   'this' is at least as specialized as g
      *      0       g is more specialized than 'this'
      */
-    final MATCH leastAsSpecialized(FuncDeclaration g, Identifiers* names)
+    static MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* names)
     {
         enum LOG_LEASTAS = 0;
         static if (LOG_LEASTAS)
         {
             import core.stdc.stdio : printf;
-            printf("%s.leastAsSpecialized(%s, %s)\n", toChars(), g.toChars(), names ? names.toChars() : "null");
-            printf("%s, %s\n", type.toChars(), g.type.toChars());
+            printf("leastAsSpecialized(%s, %s, %s)\n", f.toChars(), g.toChars(), names ? names.toChars() : "null");
+            printf("%s, %s\n", f.type.toChars(), g.type.toChars());
         }
 
         /* This works by calling g() with f()'s parameters, and
@@ -1125,15 +974,15 @@ extern (C++) class FuncDeclaration : Declaration
          * as g() is.
          */
 
-        TypeFunction tf = type.toTypeFunction();
+        TypeFunction tf = f.type.toTypeFunction();
         TypeFunction tg = g.type.toTypeFunction();
 
         /* If both functions have a 'this' pointer, and the mods are not
          * the same and g's is not const, then this is less specialized.
          */
-        if (needThis() && g.needThis() && tf.mod != tg.mod)
+        if (f.needThis() && g.needThis() && tf.mod != tg.mod)
         {
-            if (isCtorDeclaration())
+            if (f.isCtorDeclaration())
             {
                 if (!MODimplicitConv(tg.mod, tf.mod))
                     return MATCH.nomatch;
@@ -3037,7 +2886,7 @@ Expression addInvariant(AggregateDeclaration ad, VarDeclaration vthis)
             // Workaround for https://issues.dlang.org/show_bug.cgi?id=13394
             // For the correct mangling,
             // run attribute inference on inv if needed.
-            inv.functionSemantic();
+            functionSemantic(inv);
         }
 
         //e = new DsymbolExp(Loc.initial, inv);
@@ -3316,7 +3165,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
         if (m.count == 1) // exactly one match
         {
             if (!(flags & FuncResolveFlag.quiet))
-                m.lastf.functionSemantic();
+                functionSemantic(m.lastf);
             return m.lastf;
         }
         if ((flags & FuncResolveFlag.overloadOnly) && !tthis && m.lastf.needThis())
@@ -3386,12 +3235,18 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
         // all of overloads are templates
         if (td)
         {
-            const(char)* msg = "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`";
             if (!od && !td.overnext)
-                msg = "%s `%s.%s` is not callable using argument types `!(%s)%s`";
-            .error(loc, msg,
+            {
+                .error(loc, "%s `%s` is not callable using argument types `!(%s)%s`",
+                   td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars());
+            }
+            else
+            {
+                .error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`",
                    td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
                    tiargsBuf.peekChars(), fargsBuf.peekChars());
+            }
+
 
             if (!global.gag || global.params.v.showGaggedErrors)
                 printCandidates(loc, td, sc.isDeprecated());
@@ -3574,7 +3429,11 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
 
             if (!print)
                 return true;
-            const tmsg = td.toCharsNoConstraints();
+            OutBuffer buf;
+            HdrGenState hgs;
+            hgs.skipConstraints = true;
+            toCharsMaybeConstraints(td, buf, hgs);
+            const tmsg = buf.peekChars();
             const cmsg = td.getConstraintEvalError(constraintsTip);
 
             // add blank space if there are multiple candidates
diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d
new file mode 100644
index 0000000000000000000000000000000000000000..84201793c0ef1a6ab4994d4d4e8bca93ea7702fc
--- /dev/null
+++ b/gcc/d/dmd/funcsem.d
@@ -0,0 +1,219 @@
+/**
+ * Does semantic analysis for functions.
+ *
+ * Specification: $(LINK2 https://dlang.org/spec/function.html, Functions)
+ *
+ * Copyright:   Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
+ * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
+ * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/funcsem.d, _funcsem.d)
+ * Documentation:  https://dlang.org/phobos/dmd_funcsem.html
+ * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/funcsem.d
+ */
+
+module dmd.funcsem;
+
+import core.stdc.stdio;
+
+import dmd.aggregate;
+import dmd.arraytypes;
+import dmd.astenums;
+import dmd.blockexit;
+import dmd.gluelayer;
+import dmd.dcast;
+import dmd.dclass;
+import dmd.declaration;
+import dmd.delegatize;
+import dmd.dinterpret;
+import dmd.dmodule;
+import dmd.dscope;
+import dmd.dstruct;
+import dmd.dsymbol;
+import dmd.dsymbolsem;
+import dmd.dtemplate;
+import dmd.errors;
+import dmd.escape;
+import dmd.expression;
+import dmd.func;
+import dmd.globals;
+import dmd.hdrgen;
+import dmd.id;
+import dmd.identifier;
+import dmd.init;
+import dmd.location;
+import dmd.mtype;
+import dmd.objc;
+import dmd.root.aav;
+import dmd.common.outbuffer;
+import dmd.rootobject;
+import dmd.root.string;
+import dmd.root.stringtable;
+import dmd.semantic2;
+import dmd.semantic3;
+import dmd.statement_rewrite_walker;
+import dmd.statement;
+import dmd.statementsem;
+import dmd.tokens;
+import dmd.visitor;
+
+/****************************************************
+ * Resolve forward reference of function signature -
+ * parameter types, return type, and attributes.
+ * Params:
+ *  fd = function declaration
+ * Returns:
+ *  false if any errors exist in the signature.
+ */
+public
+extern (C++)
+bool functionSemantic(FuncDeclaration fd)
+{
+    //printf("functionSemantic() %p %s\n", this, toChars());
+    if (!fd._scope)
+        return !fd.errors;
+
+    fd.cppnamespace = fd._scope.namespace;
+
+    if (!fd.originalType) // semantic not yet run
+    {
+        TemplateInstance spec = fd.isSpeculative();
+        uint olderrs = global.errors;
+        uint oldgag = global.gag;
+        if (global.gag && !spec)
+            global.gag = 0;
+        dsymbolSemantic(fd, fd._scope);
+        global.gag = oldgag;
+        if (spec && global.errors != olderrs)
+            spec.errors = (global.errors - olderrs != 0);
+        if (olderrs != global.errors) // if errors compiling this function
+            return false;
+    }
+
+    // if inferring return type, sematic3 needs to be run
+    // - When the function body contains any errors, we cannot assume
+    //   the inferred return type is valid.
+    //   So, the body errors should become the function signature error.
+    if (fd.inferRetType && fd.type && !fd.type.nextOf())
+        return fd.functionSemantic3();
+
+    TemplateInstance ti;
+    if (fd.isInstantiated() && !fd.isVirtualMethod() &&
+        ((ti = fd.parent.isTemplateInstance()) is null || ti.isTemplateMixin() || ti.tempdecl.ident == fd.ident))
+    {
+        AggregateDeclaration ad = fd.isMemberLocal();
+        if (ad && ad.sizeok != Sizeok.done)
+        {
+            /* Currently dmd cannot resolve forward references per methods,
+             * then setting SIZOKfwd is too conservative and would break existing code.
+             * So, just stop method attributes inference until ad.dsymbolSemantic() done.
+             */
+            //ad.sizeok = Sizeok.fwd;
+        }
+        else
+            return fd.functionSemantic3() || !fd.errors;
+    }
+
+    if (fd.storage_class & STC.inference)
+        return fd.functionSemantic3() || !fd.errors;
+
+    return !fd.errors;
+}
+
+/****************************************************
+ * Resolve forward reference of function body.
+ * Returns false if any errors exist in the body.
+ */
+public
+extern (C++)
+bool functionSemantic3(FuncDeclaration fd)
+{
+    if (fd.semanticRun < PASS.semantic3 && fd._scope)
+    {
+        /* Forward reference - we need to run semantic3 on this function.
+         * If errors are gagged, and it's not part of a template instance,
+         * we need to temporarily ungag errors.
+         */
+        TemplateInstance spec = fd.isSpeculative();
+        uint olderrs = global.errors;
+        uint oldgag = global.gag;
+        if (global.gag && !spec)
+            global.gag = 0;
+        semantic3(fd, fd._scope);
+        global.gag = oldgag;
+
+        // If it is a speculatively-instantiated template, and errors occur,
+        // we need to mark the template as having errors.
+        if (spec && global.errors != olderrs)
+            spec.errors = (global.errors - olderrs != 0);
+        if (olderrs != global.errors) // if errors compiling this function
+            return false;
+    }
+
+    return !fd.errors && !fd.hasSemantic3Errors();
+}
+
+// called from semantic3
+/**
+ * Creates and returns the hidden parameters for this function declaration.
+ *
+ * Hidden parameters include the `this` parameter of a class, struct or
+ * nested function and the selector parameter for Objective-C methods.
+ */
+extern (D) void declareThis(FuncDeclaration fd, Scope* sc)
+{
+    const bool dualCtx = (fd.toParent2() != fd.toParentLocal());
+    if (dualCtx)
+        fd.hasDualContext = true;
+    auto ad = fd.isThis();
+    if (!dualCtx && !ad && !fd.isNested())
+    {
+        fd.vthis = null;
+        fd.objc.selectorParameter = null;
+        return;
+    }
+
+    Type addModStc(Type t)
+    {
+        return t.addMod(fd.type.mod).addStorageClass(fd.storage_class);
+    }
+
+    if (dualCtx || fd.isNested())
+    {
+        /* The 'this' for a nested function is the link to the
+         * enclosing function's stack frame.
+         * Note that nested functions and member functions are disjoint.
+         */
+        Type tthis = addModStc(dualCtx ?
+                               Type.tvoidptr.sarrayOf(2).pointerTo() :
+                               Type.tvoid.pointerTo());
+        fd.vthis = new VarDeclaration(fd.loc, tthis, dualCtx ? Id.this2 : Id.capture, null);
+        fd.vthis.storage_class |= STC.parameter | STC.nodtor;
+    }
+    else if (ad)
+    {
+        Type thandle = addModStc(ad.handleType());
+        fd.vthis = new ThisDeclaration(fd.loc, thandle);
+        fd.vthis.storage_class |= STC.parameter;
+        if (thandle.ty == Tstruct)
+        {
+            fd.vthis.storage_class |= STC.ref_;
+        }
+    }
+
+    if (auto tf = fd.type.isTypeFunction())
+    {
+        if (tf.isreturn)
+            fd.vthis.storage_class |= STC.return_;
+        if (tf.isScopeQual)
+            fd.vthis.storage_class |= STC.scope_;
+        if (tf.isreturnscope)
+            fd.vthis.storage_class |= STC.returnScope;
+    }
+
+    fd.vthis.dsymbolSemantic(sc);
+    if (!sc.insert(fd.vthis))
+        assert(0);
+    fd.vthis.parent = fd;
+    if (ad)
+        fd.objc.selectorParameter = .objc.createSelectorParameter(fd, sc);
+}
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index e9e73e8af667e2371d18d7f87d597fde140c9420..af7b1fa371d0afdf82abbfb9f582b50f88037f1b 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -219,8 +219,8 @@ extern (C++) struct Param
 
     const(char)[] argv0;                // program name
     Array!(const(char)*) modFileAliasStrings; // array of char*'s of -I module filename alias strings
-    Array!(const(char)*)* imppath;      // array of char*'s of where to look for import modules
-    Array!(const(char)*)* fileImppath;  // array of char*'s of where to look for file import modules
+    Array!(const(char)*) imppath;       // array of char*'s of where to look for import modules
+    Array!(const(char)*) fileImppath;   // array of char*'s of where to look for file import modules
     const(char)[] objdir;                // .obj/.lib file output directory
     const(char)[] objname;               // .obj file output name
     const(char)[] libname;               // .lib file output name
@@ -280,8 +280,8 @@ extern (C++) struct Global
     string copyright = "Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved";
     string written = "written by Walter Bright";
 
-    Array!(const(char)*)* path;         /// Array of char*'s which form the import lookup path
-    Array!(const(char)*)* filePath;     /// Array of char*'s which form the file import lookup path
+    Array!(const(char)*) path;         /// Array of char*'s which form the import lookup path
+    Array!(const(char)*) filePath;     /// Array of char*'s which form the file import lookup path
 
     private enum string _version = import("VERSION");
     char[26] datetime;      /// string returned by ctime()
@@ -296,8 +296,8 @@ extern (C++) struct Global
 
     void* console;         /// opaque pointer to console for controlling text attributes
 
-    Array!Identifier* versionids; /// command line versions and predefined versions
-    Array!Identifier* debugids;   /// command line debug versions and predefined versions
+    Array!Identifier versionids; /// command line versions and predefined versions
+    Array!Identifier debugids;   /// command line debug versions and predefined versions
 
     bool hasMainFunction; /// Whether a main function has already been compiled in (for -main switch)
     uint varSequenceNumber = 1; /// Relative lifetime of `VarDeclaration` within a function, used for `scope` checks
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 93e7c643d4c0e692245b2dfa4a84c00ddc35b8a9..f553ae6d8a9e7466fd64102825c3907cbe301c43 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -202,8 +202,8 @@ struct Param
 
     DString  argv0;    // program name
     Array<const char *> modFileAliasStrings; // array of char*'s of -I module filename alias strings
-    Array<const char *> *imppath;     // array of char*'s of where to look for import modules
-    Array<const char *> *fileImppath; // array of char*'s of where to look for file import modules
+    Array<const char *> imppath;     // array of char*'s of where to look for import modules
+    Array<const char *> fileImppath; // array of char*'s of where to look for file import modules
     DString objdir;    // .obj/.lib file output directory
     DString objname;   // .obj file output name
     DString libname;   // .lib file output name
@@ -282,8 +282,8 @@ struct Global
 
     const DString copyright;
     const DString written;
-    Array<const char *> *path;        // Array of char*'s which form the import lookup path
-    Array<const char *> *filePath;    // Array of char*'s which form the file import lookup path
+    Array<const char *> path;        // Array of char*'s which form the import lookup path
+    Array<const char *> filePath;    // Array of char*'s which form the file import lookup path
 
     char datetime[26];       /// string returned by ctime()
     CompileEnv compileEnv;
@@ -297,8 +297,8 @@ struct Global
 
     void* console;         // opaque pointer to console for controlling text attributes
 
-    Array<class Identifier*>* versionids; // command line versions and predefined versions
-    Array<class Identifier*>* debugids;   // command line debug versions and predefined versions
+    Array<class Identifier*> versionids; // command line versions and predefined versions
+    Array<class Identifier*> debugids;   // command line debug versions and predefined versions
 
     d_bool hasMainFunction;
     unsigned varSequenceNumber;
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 570c662624c7f0fe9e3e614d17216925a7ed6e86..030153c91da2ad436a5bc93599f90876151d7287 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -60,6 +60,7 @@ struct HdrGenState
     bool importcHdr;    /// true if generating a .di file from an ImportC file
     bool doFuncBodies;  /// include function bodies in output
     bool vcg_ast;       /// write out codegen-ast
+    bool skipConstraints;  // skip constraints when doing templates
 
     bool fullQual;      /// fully qualify types when printing
     int tpltMember;
@@ -1957,6 +1958,47 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
     s.accept(v);
 }
 
+// Note: this function is not actually `const`, because iterating the
+// function parameter list may run dsymbolsemantic on enum types
+public
+void toCharsMaybeConstraints(const TemplateDeclaration td, ref OutBuffer buf, ref HdrGenState hgs)
+{
+    buf.writestring(td.ident == Id.ctor ? "this" : td.ident.toString());
+    buf.writeByte('(');
+    foreach (i, const tp; *td.parameters)
+    {
+        if (i)
+            buf.writestring(", ");
+        toCBuffer(tp, buf, hgs);
+    }
+    buf.writeByte(')');
+
+    if (td.onemember)
+    {
+        if (const fd = td.onemember.isFuncDeclaration())
+        {
+            if (TypeFunction tf = cast(TypeFunction)fd.type.isTypeFunction())
+            {
+                // !! Casted away const
+                buf.writestring(parametersTypeToChars(tf.parameterList));
+                if (tf.mod)
+                {
+                    buf.writeByte(' ');
+                    buf.MODtoBuffer(tf.mod);
+                }
+            }
+        }
+    }
+
+    if (!hgs.skipConstraints &&
+        td.constraint)
+    {
+        buf.writestring(" if (");
+        toCBuffer(td.constraint, buf, hgs);
+        buf.writeByte(')');
+    }
+}
+
 
 /*****************************************
  * Pretty-print a template parameter list to a buffer.
@@ -2234,6 +2276,16 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
 
     void visitString(StringExp e)
     {
+        if (e.hexString || e.sz == 8)
+        {
+            buf.writeByte('x');
+            buf.writeByte('"');
+            buf.writeHexString(e.peekData, true);
+            buf.writeByte('"');
+            if (e.postfix)
+                buf.writeByte(e.postfix);
+            return;
+        }
         buf.writeByte('"');
         const o = buf.length;
         foreach (i; 0 .. e.len)
@@ -2247,6 +2299,37 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
             buf.writeByte(e.postfix);
     }
 
+    void visitInterpolation(InterpExp e)
+    {
+        buf.writeByte('i');
+        buf.writeByte('"');
+        const o = buf.length;
+
+        foreach (idx, str; e.interpolatedSet.parts)
+        {
+            if (idx % 2 == 0)
+            {
+                foreach(ch; str)
+                    writeCharLiteral(buf, ch);
+            }
+            else
+            {
+                buf.writeByte('$');
+                buf.writeByte('(');
+                foreach(ch; str)
+                    buf.writeByte(ch);
+                buf.writeByte(')');
+            }
+        }
+
+        if (hgs.ddoc)
+            escapeDdocString(buf, o);
+        buf.writeByte('"');
+        if (e.postfix)
+            buf.writeByte(e.postfix);
+
+    }
+
     void visitArrayLiteral(ArrayLiteralExp e)
     {
         buf.writeByte('[');
@@ -2827,6 +2910,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
         case EXP.super_:        return visitSuper(e.isSuperExp());
         case EXP.null_:         return visitNull(e.isNullExp());
         case EXP.string_:       return visitString(e.isStringExp());
+        case EXP.interpolated:  return visitInterpolation(e.isInterpExp());
         case EXP.arrayLiteral:  return visitArrayLiteral(e.isArrayLiteralExp());
         case EXP.assocArrayLiteral:     return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
         case EXP.structLiteral: return visitStructLiteral(e.isStructLiteralExp());
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index a66f2af4678305bd3e410d2400ffe71286025558..5ad324d60527d94f9dfc637b1215e62e96415157 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -335,6 +335,12 @@ immutable Msgtable[] msgtable =
     { "_d_arrayassign_l" },
     { "_d_arrayassign_r" },
 
+    { "imported" },
+    { "InterpolationHeader" },
+    { "InterpolationFooter" },
+    { "InterpolatedLiteral" },
+    { "InterpolatedExpression" },
+
     // For pragma's
     { "Pinline", "inline" },
     { "lib" },
diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d
index 9819c3a90cc9c9d466d147f79377c5d3b51e2f06..7c6506712fc521af2039b31b0eed77dc7e16ae4d 100644
--- a/gcc/d/dmd/json.d
+++ b/gcc/d/dmd/json.d
@@ -873,12 +873,9 @@ public:
 
         propertyStart("predefinedVersions");
         arrayStart();
-        if (global.versionids)
+        foreach (const versionid; global.versionids)
         {
-            foreach (const versionid; *global.versionids)
-            {
-                item(versionid.toString());
-            }
+            item(versionid.toString());
         }
         arrayEnd();
 
@@ -905,12 +902,9 @@ public:
 
         propertyStart("importPaths");
         arrayStart();
-        if (global.params.imppath)
+        foreach (importPath; global.params.imppath[])
         {
-            foreach (importPath; *global.params.imppath)
-            {
-                item(importPath.toDString);
-            }
+            item(importPath.toDString);
         }
         arrayEnd();
 
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index 5eadd721f645c42843ae5af99cd8fa4ceb1a2b54..937597cdf89d10a75a5b4c3a29d903a3758378dd 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -506,6 +506,29 @@ class Lexer
                 }
                 else
                     goto case_ident;
+            case 'i':
+                if (Ccompile)
+                    goto case_ident;
+                if (p[1] == '"')
+                {
+                    p++; // skip the i
+                    escapeStringConstant(t, true);
+                    return;
+                }
+                else if (p[1] == '`')
+                {
+                    p++; // skip the i
+                    wysiwygStringConstant(t, true);
+                    return;
+                }
+                else if (p[1] == 'q' && p[2] == '{')
+                {
+                    p += 2; // skip the i and q
+                    tokenStringConstant(t, true);
+                    return;
+                }
+                else
+                    goto case_ident;
             case '"':
                 escapeStringConstant(t);
                 return;
@@ -517,7 +540,7 @@ class Lexer
             case 'f':
             case 'g':
             case 'h':
-            case 'i':
+                /*case 'i':*/
             case 'j':
             case 'k':
             case 'l':
@@ -1429,9 +1452,18 @@ class Lexer
     Params:
         result = pointer to the token that accepts the result
     */
-    private void wysiwygStringConstant(Token* result)
+    private void wysiwygStringConstant(Token* result, bool supportInterpolation = false)
     {
-        result.value = TOK.string_;
+        if (supportInterpolation)
+        {
+            result.value = TOK.interpolated;
+            result.interpolatedSet = null;
+        }
+        else
+        {
+            result.value = TOK.string_;
+        }
+
         Loc start = loc();
         auto terminator = p[0];
         p++;
@@ -1451,6 +1483,14 @@ class Lexer
                 c = '\n'; // treat EndOfLine as \n character
                 endOfLine();
                 break;
+            case '$':
+                if (!supportInterpolation)
+                    goto default;
+
+                if (!handleInterpolatedSegment(result, start))
+                    goto default;
+
+                continue;
             case 0:
             case 0x1A:
                 error("unterminated string constant starting at %s", start.toChars());
@@ -1461,7 +1501,11 @@ class Lexer
             default:
                 if (c == terminator)
                 {
-                    result.setString(stringbuffer);
+                    if (supportInterpolation)
+                        result.appendInterpolatedPart(stringbuffer);
+                    else
+                        result.setString(stringbuffer);
+
                     stringPostfix(result);
                     return;
                 }
@@ -1736,13 +1780,21 @@ class Lexer
     Params:
         result = pointer to the token that accepts the result
     */
-    private void tokenStringConstant(Token* result)
+    private void tokenStringConstant(Token* result, bool supportInterpolation = false)
     {
-        result.value = TOK.string_;
+        if (supportInterpolation)
+        {
+            result.value = TOK.interpolated;
+            result.interpolatedSet = null;
+        }
+        else
+        {
+            result.value = TOK.string_;
+        }
 
         uint nest = 1;
         const start = loc();
-        const pstart = ++p;
+        auto pstart = ++p;
         inTokenStringConstant++;
         scope(exit) inTokenStringConstant--;
         while (1)
@@ -1757,10 +1809,28 @@ class Lexer
             case TOK.rightCurly:
                 if (--nest == 0)
                 {
-                    result.setString(pstart, p - 1 - pstart);
+                    if (supportInterpolation)
+                        result.appendInterpolatedPart(pstart, p - 1 - pstart);
+                    else
+                        result.setString(pstart, p - 1 - pstart);
+
                     stringPostfix(result);
                     return;
                 }
+                continue;
+            case TOK.dollar:
+                if (!supportInterpolation)
+                    goto default;
+
+                stringbuffer.setsize(0);
+                stringbuffer.write(pstart, p - 1 - pstart);
+                if (!handleInterpolatedSegment(result, start))
+                    goto default;
+
+                stringbuffer.setsize(0);
+
+                pstart = p;
+
                 continue;
             case TOK.endOfFile:
                 error("unterminated token string constant starting at %s", start.toChars());
@@ -1772,6 +1842,52 @@ class Lexer
         }
     }
 
+    // returns true if it got special treatment as an interpolated segment
+    // otherwise returns false, indicating to treat it as just part of a normal string
+    private bool handleInterpolatedSegment(Token* token, Loc start)
+    {
+        switch(*p)
+        {
+        case '(':
+            // expression, at this level we need to scan until the closing ')'
+
+            // always put the string part in first
+            token.appendInterpolatedPart(stringbuffer);
+            stringbuffer.setsize(0);
+
+            int openParenCount = 1;
+            p++; // skip the first open paren
+            auto pstart = p;
+            while (openParenCount > 0)
+            {
+                // need to scan with the lexer to support embedded strings and other complex cases
+                Token tok;
+                scan(&tok);
+                if (tok.value == TOK.leftParenthesis)
+                    openParenCount++;
+                if (tok.value == TOK.rightParenthesis)
+                    openParenCount--;
+                if (tok.value == TOK.endOfFile)
+                {
+                    // FIXME: make this error better, it spams a lot
+                    error("unterminated interpolated string constant starting at %s", start.toChars());
+                    return false;
+                }
+            }
+
+            // then put the interpolated string segment
+            token.appendInterpolatedPart(pstart[0 .. p - 1 - pstart]);
+
+            stringbuffer.setsize(0); // make sure this is reset from the last token scan
+            // otherwise something like i"$(func("thing")) stuff" can still include it
+
+            return true;
+        default:
+            // nothing special
+            return false;
+        }
+    }
+
     /**
     Scan a quoted string while building the processed string value by
     handling escape sequences. The result is returned in the given `t` token.
@@ -1783,9 +1899,17 @@ class Lexer
     *   D https://dlang.org/spec/lex.html#double_quoted_strings
     *   ImportC C11 6.4.5
     */
-    private void escapeStringConstant(Token* t)
+    private void escapeStringConstant(Token* t, bool supportInterpolation = false)
     {
-        t.value = TOK.string_;
+        if (supportInterpolation)
+        {
+            t.value = TOK.interpolated;
+            t.interpolatedSet = null;
+        }
+        else
+        {
+            t.value = TOK.string_;
+        }
 
         const start = loc();
         const tc = *p++;        // opening quote
@@ -1813,11 +1937,28 @@ class Lexer
                     c = escapeSequence(c2);
                     stringbuffer.writeUTF8(c);
                     continue;
+                case '$':
+                    if (supportInterpolation)
+                    {
+                        p++; // skip escaped $
+                        stringbuffer.writeByte('$');
+                        continue;
+                    }
+                    else
+                        goto default;
                 default:
                     c = escapeSequence(c2);
                     break;
                 }
                 break;
+            case '$':
+                if (!supportInterpolation)
+                    goto default;
+
+                if (!handleInterpolatedSegment(t, start))
+                    goto default;
+
+                continue;
             case '\n':
                 endOfLine();
                 if (Ccompile)
@@ -1835,7 +1976,10 @@ class Lexer
             case '"':
                 if (c != tc)
                     goto default;
-                t.setString(stringbuffer);
+                if (supportInterpolation)
+                    t.appendInterpolatedPart(stringbuffer);
+                else
+                    t.setString(stringbuffer);
                 if (!Ccompile)
                     stringPostfix(t);
                 return;
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 3d88a1dfad3802d73a975daceeccbc9ba8e6d85e..276f209d4aa56464ed6f32a186d0e0fa6be9d3ef 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -27,9 +27,11 @@ import dmd.denum;
 import dmd.dstruct;
 import dmd.dsymbol;
 import dmd.dtemplate;
+import dmd.enumsem;
 import dmd.errors;
 import dmd.expression;
 import dmd.func;
+import dmd.funcsem;
 import dmd.globals;
 import dmd.hdrgen;
 import dmd.id;
@@ -516,16 +518,39 @@ extern (C++) abstract class Type : ASTNode
             Terror
         ];
 
+        static Type merge(Type t)
+        {
+            import dmd.basicmangle : tyToDecoBuffer;
+
+            OutBuffer buf;
+            buf.reserve(3);
+
+            if (t.ty == Tnoreturn)
+                buf.writestring("Nn");
+            else
+                tyToDecoBuffer(buf, t.ty);
+
+            auto sv = t.stringtable.update(buf[]);
+            if (sv.value)
+                return sv.value;
+            else
+            {
+                t.deco = cast(char*)sv.toDchars();
+                sv.value = t;
+                return t;
+            }
+        }
+
         for (size_t i = 0; basetab[i] != Terror; i++)
         {
             Type t = new TypeBasic(basetab[i]);
-            t = t.merge();
+            t = merge(t);
             basic[basetab[i]] = t;
         }
         basic[Terror] = new TypeError();
 
         tnoreturn = new TypeNoreturn();
-        tnoreturn.deco = tnoreturn.merge().deco;
+        tnoreturn.deco = merge(tnoreturn).deco;
         basic[Tnoreturn] = tnoreturn;
 
         tvoid = basic[Tvoid];
@@ -560,7 +585,7 @@ extern (C++) abstract class Type : ASTNode
         terror = basic[Terror];
         tnoreturn = basic[Tnoreturn];
         tnull = new TypeNull();
-        tnull.deco = tnull.merge().deco;
+        tnull.deco = merge(tnull).deco;
 
         tvoidptr = tvoid.pointerTo();
         tstring = tchar.immutableOf().arrayOf();
@@ -601,29 +626,6 @@ extern (C++) abstract class Type : ASTNode
         return cast(uint)size(Loc.initial);
     }
 
-    /*************************************
-     * This version does a merge even if the deco is already computed.
-     * Necessary for types that have a deco, but are not merged.
-     */
-    final Type merge2()
-    {
-        //printf("merge2(%s)\n", toChars());
-        Type t = this;
-        assert(t);
-        if (!t.deco)
-            return t.merge();
-
-        auto sv = stringtable.lookup(t.deco, strlen(t.deco));
-        if (sv && sv.value)
-        {
-            t = sv.value;
-            assert(t.deco);
-        }
-        else
-            assert(0);
-        return t;
-    }
-
     /*********************************
      * Store this type's modifier name into buf.
      */
@@ -1693,7 +1695,7 @@ extern (C++) abstract class Type : ASTNode
         if (callable)
         {
             auto fd = resolveFuncCall(Loc.initial, null, callable, null, this, ArgumentList(), FuncResolveFlag.quiet);
-            if (!fd || fd.errors || !fd.functionSemantic())
+            if (!fd || fd.errors || !functionSemantic(fd))
                 return Type.terror;
 
             auto t = fd.type.nextOf();
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index c777f359da4bdc938e9539f9ca7f6ec72f8e080a..8b0a1b24ef1b67d457f7f185cdac5df0bd9d7013 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -233,7 +233,6 @@ public:
     uinteger_t size();
     virtual uinteger_t size(const Loc &loc);
     virtual unsigned alignsize();
-    Type *merge2();
     void modToBuffer(OutBuffer& buf) const;
     char *modToChars() const;
 
@@ -909,3 +908,4 @@ Covariant covariant(Type *, Type *, StorageClass * = NULL, bool = false);
 bool isBaseOf(Type *tthis, Type *t, int *poffset);
 Type *trySemantic(Type *type, const Loc &loc, Scope *sc);
 void purityLevel(TypeFunction *type);
+Type *merge2(Type *type);
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 268622a82fccadbc42df7235d501cb7c8dd49193..0dc54ffe762410a339fe6603312d64913414790a 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -2015,6 +2015,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         case TOK.wcharLiteral:
         case TOK.dcharLiteral:
         case TOK.string_:
+        case TOK.interpolated:
         case TOK.hexadecimalString:
         case TOK.file:
         case TOK.fileFullPath:
@@ -5820,6 +5821,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         case TOK.true_:
         case TOK.false_:
         case TOK.string_:
+        case TOK.interpolated:
         case TOK.hexadecimalString:
         case TOK.leftParenthesis:
         case TOK.cast_:
@@ -7313,6 +7315,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     case TOK.wcharLiteral:
                     case TOK.dcharLiteral:
                     case TOK.string_:
+                    case TOK.interpolated:
                     case TOK.hexadecimalString:
                     case TOK.file:
                     case TOK.fileFullPath:
@@ -8177,6 +8180,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             nextToken();
             break;
 
+        case TOK.interpolated:
+            e = new AST.InterpExp(loc, token.interpolatedSet, token.postfix);
+            nextToken();
+            break;
+
         case TOK.string_:
         case TOK.hexadecimalString:
             const bool hexString = token.value == TOK.hexadecimalString;
@@ -8810,6 +8818,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                         case TOK.wcharLiteral:
                         case TOK.dcharLiteral:
                         case TOK.string_:
+                        case TOK.interpolated:
                         case TOK.function_:
                         case TOK.delegate_:
                         case TOK.typeof_:
diff --git a/gcc/d/dmd/parsetimevisitor.d b/gcc/d/dmd/parsetimevisitor.d
index 3d0a5854625186c1d75288418e7d118125d4a0d1..422c1c8c0ec5d20a8bd0368acd787eae8cf09141 100644
--- a/gcc/d/dmd/parsetimevisitor.d
+++ b/gcc/d/dmd/parsetimevisitor.d
@@ -183,6 +183,7 @@ public:
     void visit(AST.TypeidExp e) { visit(cast(AST.Expression)e); }
     void visit(AST.TraitsExp e) { visit(cast(AST.Expression)e); }
     void visit(AST.StringExp e) { visit(cast(AST.Expression)e); }
+    void visit(AST.InterpExp e) { visit(cast(AST.Expression)e); }
     void visit(AST.NewExp e) { visit(cast(AST.Expression)e); }
     void visit(AST.AssocArrayLiteralExp e) { visit(cast(AST.Expression)e); }
     void visit(AST.ArrayLiteralExp e) { visit(cast(AST.Expression)e); }
diff --git a/gcc/d/dmd/res/default_ddoc_theme.ddoc b/gcc/d/dmd/res/default_ddoc_theme.ddoc
index 7ae0db898eff72071a1b787b54c6216684646332..20269e1a084dc1e1c90b36f2b539077f5422a017 100644
--- a/gcc/d/dmd/res/default_ddoc_theme.ddoc
+++ b/gcc/d/dmd/res/default_ddoc_theme.ddoc
@@ -70,7 +70,7 @@ D_CODE =
   <div class="code_sample">
     <div class="dlang">
       <ol class="code_lines">
-        <li><code class="code">$0</code></li>
+        <li><pre><code class="code">$0</code></pre></li>
       </ol>
     </div>
   </div>
@@ -81,7 +81,7 @@ OTHER_CODE =
   <div class="code_sample">
     <div class="dlang">
       <ol class="code_lines">
-        <li><code class="code language-$1">$+</code></li>
+        <li><pre><code class="code language-$1">$+</code></pre></li>
       </ol>
     </div>
   </div>
@@ -517,6 +517,10 @@ DDOC =
         white-space: pre-wrap;
       }
 
+      .ddoc .code_lines pre {
+        display: contents;
+      }
+
       .ddoc .code_lines li:only-of-type::before {
         color: rgba(255, 255, 255, 1);
         content: " ";
diff --git a/gcc/d/dmd/root/filename.d b/gcc/d/dmd/root/filename.d
index 5b0bba42fc21fb7297d2df6983d19c1fffc0dd4e..41c2050057d32932d2a55266e178f3b554845608 100644
--- a/gcc/d/dmd/root/filename.d
+++ b/gcc/d/dmd/root/filename.d
@@ -78,7 +78,7 @@ nothrow:
     private const(char)[] str;
 
     ///
-    extern (D) this(const(char)[] str) pure
+    extern (D) this(const char[] str) pure
     {
         this.str = str.xarraydup;
     }
@@ -96,7 +96,7 @@ nothrow:
     }
 
     /// Ditto
-    extern (D) static bool equals(const(char)[] name1, const(char)[] name2) pure @nogc
+    extern (D) static bool equals(const char[] name1, const char[] name2) pure @nogc
     {
         if (name1.length != name2.length)
             return false;
@@ -125,7 +125,7 @@ nothrow:
     }
 
     /// Ditto
-    extern (D) static bool absolute(const(char)[] name) pure @nogc @safe
+    extern (D) static bool absolute(const char[] name) pure @nogc @safe
     {
         if (!name.length)
             return false;
@@ -189,7 +189,7 @@ nothrow:
     }
 
     /// Ditto
-    extern (D) static const(char)[] ext(const(char)[] str) nothrow pure @safe @nogc
+    extern (D) static const(char)[] ext(const char[] str) nothrow pure @safe @nogc
     {
         foreach_reverse (idx, char e; str)
         {
@@ -249,7 +249,7 @@ nothrow:
     }
 
     /// Ditto
-    extern (D) static const(char)[] removeExt(const(char)[] str)
+    extern (D) static const(char)[] removeExt(const char[] str)
     {
         auto e = ext(str);
         if (e.length)
@@ -278,7 +278,7 @@ nothrow:
     }
 
     /// Ditto
-    extern (D) static const(char)[] name(const(char)[] str) pure @nogc @safe
+    extern (D) static const(char)[] name(const char[] str) pure @nogc @safe
     {
         foreach_reverse (idx, char e; str)
         {
@@ -333,7 +333,7 @@ nothrow:
     }
 
     /// Ditto
-    extern (D) static const(char)[] path(const(char)[] str)
+    extern (D) static const(char)[] path(const char[] str)
     {
         const n = name(str);
         bool hasTrailingSlash;
@@ -358,7 +358,7 @@ nothrow:
     /**************************************
      * Replace filename portion of path.
      */
-    extern (D) static const(char)[] replaceName(const(char)[] path, const(char)[] name)
+    extern (D) static const(char)[] replaceName(const char[] path, const char[] name)
     {
         if (absolute(name))
             return name;
@@ -387,7 +387,7 @@ nothrow:
     }
 
     /// Ditto
-    extern(D) static const(char)[] combine(const(char)[] path, const(char)[] name)
+    extern(D) static const(char)[] combine(const char[] path, const char[] name)
     {
         return !path.length ? name : buildPath(path, name);
     }
@@ -401,7 +401,7 @@ nothrow:
         assert(combine("foo/"[], "bar"[]) == "foo/bar");
     }
 
-    static const(char)[] buildPath(const(char)[][] fragments...)
+    static const(char)[] buildPath(const char[][] fragments...)
     {
         size_t size;
         foreach (f; fragments)
@@ -563,7 +563,7 @@ nothrow:
      * Returns:
      *   A newly allocated string (free with `FileName.free`)
      */
-    extern(D) static char[] addExt(const(char)[] name, const(char)[] ext) pure
+    extern(D) static char[] addExt(const char[] name, const char[] ext) pure
     {
         const len = name.length + ext.length + 2;
         auto s = cast(char*)mem.xmalloc(len);
@@ -584,7 +584,7 @@ nothrow:
     }
 
     /// Ditto
-    extern (D) static const(char)[] defaultExt(const(char)[] name, const(char)[] ext)
+    extern (D) static const(char)[] defaultExt(const char[] name, const char[] ext)
     {
         auto e = FileName.ext(name);
         if (e.length) // it already has an extension
@@ -608,7 +608,7 @@ nothrow:
     }
 
     /// Ditto
-    extern (D) static const(char)[] forceExt(const(char)[] name, const(char)[] ext)
+    extern (D) static const(char)[] forceExt(const char[] name, const char[] ext)
     {
         if (auto e = FileName.ext(name))
             return addExt(name[0 .. $ - e.length - 1], ext);
@@ -630,7 +630,7 @@ nothrow:
     }
 
     /// Ditto
-    extern (D) static bool equalsExt(const(char)[] name, const(char)[] ext) pure @nogc
+    extern (D) static bool equalsExt(const char[] name, const char[] ext) pure @nogc
     {
         auto e = FileName.ext(name);
         if (!e.length && !ext.length)
@@ -665,12 +665,12 @@ nothrow:
      * Returns:
      *  if found, filename combined with path, otherwise null
      */
-    extern (C++) static const(char)* searchPath(Strings* path, const(char)* name, bool cwd)
+    extern (C++) static const(char)* searchPath(const ref Strings path, const char* name, bool cwd)
     {
-        return searchPath(path, name.toDString, cwd).ptr;
+        return searchPath(path[], name.toDString, cwd).ptr;
     }
 
-    extern (D) static const(char)[] searchPath(Strings* path, const(char)[] name, bool cwd)
+    extern (D) static const(char)[] searchPath(const char*[] path, const char[] name, bool cwd)
     {
         if (absolute(name))
         {
@@ -681,24 +681,21 @@ nothrow:
             if (exists(name))
                 return name;
         }
-        if (path)
+        foreach (p; path)
         {
-            foreach (p; *path)
+            auto n = combine(p.toDString, name);
+            if (exists(n))
+                return n;
+            //combine might return name
+            if (n.ptr != name.ptr)
             {
-                auto n = combine(p.toDString, name);
-                if (exists(n))
-                    return n;
-                //combine might return name
-                if (n.ptr != name.ptr)
-                {
-                    mem.xfree(cast(void*)n.ptr);
-                }
+                mem.xfree(cast(void*)n.ptr);
             }
         }
         return null;
     }
 
-    extern (D) static const(char)[] searchPath(const(char)* path, const(char)[] name, bool cwd)
+    extern (D) static const(char)[] searchPath(const char* path, const char[] name, bool cwd)
     {
         if (absolute(name))
         {
@@ -738,7 +735,7 @@ nothrow:
      * Returns:
      *  index of the first reserved character in path if found, size_t.max otherwise
      */
-    extern (D) static size_t findReservedChar(const(char)[] name) pure @nogc @safe
+    extern (D) static size_t findReservedChar(const char[] name) pure @nogc @safe
     {
         version (Windows)
         {
@@ -787,7 +784,7 @@ nothrow:
      * Returns:
      *  true if path contains '..' reference to parent directory
      */
-    extern (D) static bool refersToParentDir(const(char)[] name) pure @nogc @safe
+    extern (D) static bool refersToParentDir(const char[] name) pure @nogc @safe
     {
         size_t s = 0;
         foreach (i; 0 .. name.length)
@@ -845,7 +842,7 @@ nothrow:
     }
 
     /// Ditto
-    extern (D) static int exists(const(char)[] name)
+    extern (D) static int exists(const char[] name)
     {
         if (!name.length)
             return 0;
@@ -892,7 +889,7 @@ nothrow:
        Returns:
          `true` if the directory exists or was successfully created
      */
-    extern (D) static bool ensurePathExists(const(char)[] path)
+    extern (D) static bool ensurePathExists(const char[] path)
     {
         //printf("FileName::ensurePathExists(%s)\n", path ? path : "");
         if (!path.length)
@@ -967,7 +964,7 @@ nothrow:
     }
 
     /// Ditto
-    extern (D) static const(char)[] canonicalName(const(char)[] name)
+    extern (D) static const(char)[] canonicalName(const char[] name)
     {
         version (Posix)
         {
@@ -1127,7 +1124,7 @@ version(Windows)
      * References:
      *  https://msdn.microsoft.com/en-us/library/windows/desktop/aa363855(v=vs.85).aspx
      */
-    private int _mkdir(const(char)[] path) nothrow
+    private int _mkdir(const char[] path) nothrow
     {
         const createRet = path.extendedPathThen!(
             p => CreateDirectoryW(&p[0], null /*securityAttributes*/));
@@ -1175,7 +1172,7 @@ version(Windows)
      * Returns:
      *  The result of calling F on the UTF16 version of str.
      */
-    private auto toWStringzThen(alias F)(const(char)[] str) nothrow
+    private auto toWStringzThen(alias F)(const char[] str) nothrow
     {
         import dmd.common.smallbuffer : SmallBuffer, toWStringz;
 
diff --git a/gcc/d/dmd/root/filename.h b/gcc/d/dmd/root/filename.h
index d8834a19282b38d2b0f40fbde19520a4a052eebc..0e52b98232339d521b4420377454a4e82e076c5c 100644
--- a/gcc/d/dmd/root/filename.h
+++ b/gcc/d/dmd/root/filename.h
@@ -38,7 +38,7 @@ public:
 
     bool equalsExt(const char *ext);
 
-    static const char *searchPath(Strings *path, const char *name, bool cwd);
+    static const char *searchPath(Strings& path, const char *name, bool cwd);
     static int exists(const char *name);
     static bool ensurePathExists(const char *path);
     static const char *canonicalName(const char *name);
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index 174d9b4dc147f6fc8e4e013099051ff1ecee8df9..125a39d179fc45a193a8ff3fa7716234170dd024 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -41,6 +41,7 @@ import dmd.escape;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
+import dmd.funcsem;
 import dmd.globals;
 import dmd.id;
 import dmd.identifier;
@@ -384,7 +385,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                 }
             }
 
-            funcdecl.declareThis(sc2);
+            declareThis(funcdecl, sc2);
 
             // Reverts: https://issues.dlang.org/show_bug.cgi?id=5710
             // No compiler supports this, and there was never any spec for it.
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index d4827ae6aa134287cb7c23d0c7c5bc5cce74afcd..840035c46cf228d746266a2d742433b839684072 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -43,6 +43,7 @@ import dmd.escape;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
+import dmd.funcsem;
 import dmd.globals;
 import dmd.gluelayer;
 import dmd.hdrgen;
@@ -1284,7 +1285,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
                 Type tfront;
                 if (auto fd = sfront.isFuncDeclaration())
                 {
-                    if (!fd.functionSemantic())
+                    if (!functionSemantic(fd))
                         return rangeError();
                     tfront = fd.type;
                 }
diff --git a/gcc/d/dmd/templatesem.d b/gcc/d/dmd/templatesem.d
new file mode 100644
index 0000000000000000000000000000000000000000..1942afe44ae23cd3207427c06319d3e944b38269
--- /dev/null
+++ b/gcc/d/dmd/templatesem.d
@@ -0,0 +1,1497 @@
+/**
+ * Template semantics.
+ *
+ * Copyright:   Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
+ * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
+ * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/templatesem.d, _templatesem.d)
+ * Documentation:  https://dlang.org/phobos/dmd_templatesem.html
+ * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/templatesem.d
+ */
+
+module dmd.templatesem;
+
+import core.stdc.stdio;
+import core.stdc.string;
+import dmd.aggregate;
+import dmd.aliasthis;
+import dmd.arraytypes;
+import dmd.astenums;
+import dmd.ast_node;
+import dmd.attrib;
+import dmd.dcast;
+import dmd.dclass;
+import dmd.declaration;
+import dmd.dinterpret;
+import dmd.dmangle;
+import dmd.dmodule;
+import dmd.dscope;
+import dmd.dsymbol;
+import dmd.dsymbolsem;
+import dmd.dtemplate;
+import dmd.errors;
+import dmd.errorsink;
+import dmd.expression;
+import dmd.expressionsem;
+import dmd.func;
+import dmd.funcsem;
+import dmd.globals;
+import dmd.hdrgen;
+import dmd.id;
+import dmd.identifier;
+import dmd.impcnvtab;
+import dmd.init;
+import dmd.initsem;
+import dmd.location;
+import dmd.mtype;
+import dmd.opover;
+import dmd.optimize;
+import dmd.root.array;
+import dmd.common.outbuffer;
+import dmd.rootobject;
+import dmd.semantic2;
+import dmd.semantic3;
+import dmd.tokens;
+import dmd.typesem;
+import dmd.visitor;
+
+/***************************************
+ * Given that ti is an instance of this TemplateDeclaration,
+ * deduce the types of the parameters to this, and store
+ * those deduced types in dedtypes[].
+ * Params:
+ *  sc = context
+ *  td = template
+ *  ti = instance of td
+ *  dedtypes = fill in with deduced types
+ *  argumentList = arguments to template instance
+ *  flag = 1 - don't do semantic() because of dummy types
+ *         2 - don't change types in matchArg()
+ * Returns: match level.
+ */
+public
+MATCH matchWithInstance(Scope* sc, TemplateDeclaration td, TemplateInstance ti, ref Objects dedtypes, ArgumentList argumentList, int flag)
+{
+    enum LOGM = 0;
+    static if (LOGM)
+    {
+        printf("\n+TemplateDeclaration.matchWithInstance(td = %s, ti = %s, flag = %d)\n", td.toChars(), ti.toChars(), flag);
+    }
+    version (none)
+    {
+        printf("dedtypes.length = %d, parameters.length = %d\n", dedtypes.length, parameters.length);
+        if (ti.tiargs.length)
+            printf("ti.tiargs.length = %d, [0] = %p\n", ti.tiargs.length, (*ti.tiargs)[0]);
+    }
+    MATCH nomatch()
+    {
+        static if (LOGM)
+        {
+            printf(" no match\n");
+        }
+        return MATCH.nomatch;
+    }
+    MATCH m;
+    size_t dedtypes_dim = dedtypes.length;
+
+    dedtypes.zero();
+
+    if (td.errors)
+        return MATCH.nomatch;
+
+    size_t parameters_dim = td.parameters.length;
+    int variadic = td.isVariadic() !is null;
+
+    // If more arguments than parameters, no match
+    if (ti.tiargs.length > parameters_dim && !variadic)
+    {
+        static if (LOGM)
+        {
+            printf(" no match: more arguments than parameters\n");
+        }
+        return MATCH.nomatch;
+    }
+
+    assert(dedtypes_dim == parameters_dim);
+    assert(dedtypes_dim >= ti.tiargs.length || variadic);
+
+    assert(td._scope);
+
+    // Set up scope for template parameters
+    Scope* paramscope = createScopeForTemplateParameters(td, ti, sc);
+
+    // Attempt type deduction
+    m = MATCH.exact;
+    for (size_t i = 0; i < dedtypes_dim; i++)
+    {
+        MATCH m2;
+        TemplateParameter tp = (*td.parameters)[i];
+        Declaration sparam;
+
+        //printf("\targument [%d]\n", i);
+        static if (LOGM)
+        {
+            //printf("\targument [%d] is %s\n", i, oarg ? oarg.toChars() : "null");
+            TemplateTypeParameter ttp = tp.isTemplateTypeParameter();
+            if (ttp)
+                printf("\tparameter[%d] is %s : %s\n", i, tp.ident.toChars(), ttp.specType ? ttp.specType.toChars() : "");
+        }
+
+        m2 = tp.matchArg(ti.loc, paramscope, ti.tiargs, i, td.parameters, dedtypes, &sparam);
+        //printf("\tm2 = %d\n", m2);
+        if (m2 == MATCH.nomatch)
+        {
+            version (none)
+            {
+                printf("\tmatchArg() for parameter %i failed\n", i);
+            }
+            return nomatch();
+        }
+
+        if (m2 < m)
+            m = m2;
+
+        if (!flag)
+            sparam.dsymbolSemantic(paramscope);
+        if (!paramscope.insert(sparam)) // TODO: This check can make more early
+        {
+            // in TemplateDeclaration.semantic, and
+            // then we don't need to make sparam if flags == 0
+            return nomatch();
+        }
+    }
+
+    if (!flag)
+    {
+        /* Any parameter left without a type gets the type of
+         * its corresponding arg
+         */
+        foreach (i, ref dedtype; dedtypes)
+        {
+            if (!dedtype)
+            {
+                assert(i < ti.tiargs.length);
+                dedtype = cast(Type)(*ti.tiargs)[i];
+            }
+        }
+    }
+
+    if (m > MATCH.nomatch && td.constraint && !flag)
+    {
+        if (ti.hasNestedArgs(ti.tiargs, td.isstatic)) // TODO: should gag error
+            ti.parent = ti.enclosing;
+        else
+            ti.parent = td.parent;
+
+        // Similar to doHeaderInstantiation
+        FuncDeclaration fd = td.onemember ? td.onemember.isFuncDeclaration() : null;
+        if (fd)
+        {
+            TypeFunction tf = fd.type.isTypeFunction().syntaxCopy();
+            if (argumentList.hasNames)
+                return nomatch();
+            Expressions* fargs = argumentList.arguments;
+            // TODO: Expressions* fargs = tf.resolveNamedArgs(argumentList, null);
+            // if (!fargs)
+            //     return nomatch();
+
+            fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, tf);
+            fd.parent = ti;
+            fd.inferRetType = true;
+
+            // Shouldn't run semantic on default arguments and return type.
+            foreach (ref param; *tf.parameterList.parameters)
+                param.defaultArg = null;
+
+            tf.next = null;
+            tf.incomplete = true;
+
+            // Resolve parameter types and 'auto ref's.
+            tf.fargs = fargs;
+            uint olderrors = global.startGagging();
+            fd.type = tf.typeSemantic(td.loc, paramscope);
+            global.endGagging(olderrors);
+            if (fd.type.ty != Tfunction)
+                return nomatch();
+            fd.originalType = fd.type; // for mangling
+        }
+
+        // TODO: dedtypes => ti.tiargs ?
+        if (!evaluateConstraint(td, ti, sc, paramscope, &dedtypes, fd))
+            return nomatch();
+    }
+
+    static if (LOGM)
+    {
+        // Print out the results
+        printf("--------------------------\n");
+        printf("template %s\n", toChars());
+        printf("instance %s\n", ti.toChars());
+        if (m > MATCH.nomatch)
+        {
+            for (size_t i = 0; i < dedtypes_dim; i++)
+            {
+                TemplateParameter tp = (*parameters)[i];
+                RootObject oarg;
+                printf(" [%d]", i);
+                if (i < ti.tiargs.length)
+                    oarg = (*ti.tiargs)[i];
+                else
+                    oarg = null;
+                tp.print(oarg, (*dedtypes)[i]);
+            }
+        }
+        else
+            return nomatch();
+    }
+    static if (LOGM)
+    {
+        printf(" match = %d\n", m);
+    }
+
+    paramscope.pop();
+    static if (LOGM)
+    {
+        printf("-TemplateDeclaration.matchWithInstance(td = %s, ti = %s) = %d\n", td.toChars(), ti.toChars(), m);
+    }
+    return m;
+}
+
+/****************************
+ * Check to see if constraint is satisfied.
+ */
+bool evaluateConstraint(TemplateDeclaration td, TemplateInstance ti, Scope* sc, Scope* paramscope, Objects* dedargs, FuncDeclaration fd)
+{
+    /* Detect recursive attempts to instantiate this template declaration,
+     * https://issues.dlang.org/show_bug.cgi?id=4072
+     *  void foo(T)(T x) if (is(typeof(foo(x)))) { }
+     *  static assert(!is(typeof(foo(7))));
+     * Recursive attempts are regarded as a constraint failure.
+     */
+    /* There's a chicken-and-egg problem here. We don't know yet if this template
+     * instantiation will be a local one (enclosing is set), and we won't know until
+     * after selecting the correct template. Thus, function we're nesting inside
+     * is not on the sc scope chain, and this can cause errors in FuncDeclaration.getLevel().
+     * Workaround the problem by setting a flag to relax the checking on frame errors.
+     */
+
+    for (TemplatePrevious* p = td.previous; p; p = p.prev)
+    {
+        if (!arrayObjectMatch(*p.dedargs, *dedargs))
+            continue;
+        //printf("recursive, no match p.sc=%p %p %s\n", p.sc, this, this.toChars());
+        /* It must be a subscope of p.sc, other scope chains are not recursive
+         * instantiations.
+         * the chain of enclosing scopes is broken by paramscope (its enclosing
+         * scope is _scope, but paramscope.callsc is the instantiating scope). So
+         * it's good enough to check the chain of callsc
+         */
+        for (Scope* scx = paramscope.callsc; scx; scx = scx.callsc)
+        {
+            // The first scx might be identical for nested eponymeous templates, e.g.
+            // template foo() { void foo()() {...} }
+            if (scx == p.sc && scx !is paramscope.callsc)
+                return false;
+        }
+        /* BUG: should also check for ref param differences
+         */
+    }
+
+    TemplatePrevious pr;
+    pr.prev = td.previous;
+    pr.sc = paramscope.callsc;
+    pr.dedargs = dedargs;
+    td.previous = &pr; // add this to threaded list
+
+    Scope* scx = paramscope.push(ti);
+    scx.parent = ti;
+    scx.tinst = null;
+    scx.minst = null;
+    // Set SCOPE.constraint before declaring function parameters for the static condition
+    // (previously, this was immediately before calling evalStaticCondition), so the
+    // semantic pass knows not to issue deprecation warnings for these throw-away decls.
+    // https://issues.dlang.org/show_bug.cgi?id=21831
+    scx.flags |= SCOPE.constraint;
+
+    assert(!ti.symtab);
+    if (fd)
+    {
+        /* Declare all the function parameters as variables and add them to the scope
+         * Making parameters is similar to FuncDeclaration.semantic3
+         */
+        auto tf = fd.type.isTypeFunction();
+
+        scx.parent = fd;
+
+        Parameters* fparameters = tf.parameterList.parameters;
+        const nfparams = tf.parameterList.length;
+        foreach (i, fparam; tf.parameterList)
+        {
+            fparam.storageClass &= (STC.IOR | STC.lazy_ | STC.final_ | STC.TYPECTOR | STC.nodtor);
+            fparam.storageClass |= STC.parameter;
+            if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nfparams)
+            {
+                fparam.storageClass |= STC.variadic;
+                /* Don't need to set STC.scope_ because this will only
+                 * be evaluated at compile time
+                 */
+            }
+        }
+        foreach (fparam; *fparameters)
+        {
+            if (!fparam.ident)
+                continue;
+            // don't add it, if it has no name
+            auto v = new VarDeclaration(fparam.loc, fparam.type, fparam.ident, null);
+            fparam.storageClass |= STC.parameter;
+            v.storage_class = fparam.storageClass;
+            v.dsymbolSemantic(scx);
+            if (!ti.symtab)
+                ti.symtab = new DsymbolTable();
+            if (!scx.insert(v))
+                .error(td.loc, "%s `%s` parameter `%s.%s` is already defined", td.kind, td.toPrettyChars, td.toChars(), v.toChars());
+            else
+                v.parent = fd;
+        }
+        if (td.isstatic)
+            fd.storage_class |= STC.static_;
+        declareThis(fd, scx);
+    }
+
+    td.lastConstraint = td.constraint.syntaxCopy();
+    td.lastConstraintTiargs = ti.tiargs;
+    td.lastConstraintNegs.setDim(0);
+
+    import dmd.staticcond;
+
+    assert(ti.inst is null);
+    ti.inst = ti; // temporary instantiation to enable genIdent()
+    bool errors;
+    const bool result = evalStaticCondition(scx, td.constraint, td.lastConstraint, errors, &td.lastConstraintNegs);
+    if (result || errors)
+    {
+        td.lastConstraint = null;
+        td.lastConstraintTiargs = null;
+        td.lastConstraintNegs.setDim(0);
+    }
+    ti.inst = null;
+    ti.symtab = null;
+    scx = scx.pop();
+    td.previous = pr.prev; // unlink from threaded list
+    if (errors)
+        return false;
+    return result;
+}
+
+/*******************************************
+ * Append to buf a textual representation of template parameters with their arguments.
+ * Params:
+ *  parameters = the template parameters
+ *  tiargs = the correspondeing template arguments
+ *  variadic = if it's a variadic argument list
+ *  buf = where the text output goes
+ */
+void formatParamsWithTiargs(ref TemplateParameters parameters, ref Objects tiargs, bool variadic, ref OutBuffer buf)
+{
+    buf.writestring("  with `");
+
+    // write usual arguments line-by-line
+    // skips trailing default ones - they are not present in `tiargs`
+    const end = parameters.length - (variadic ? 1 : 0);
+    size_t i;
+    for (; i < tiargs.length && i < end; i++)
+    {
+        if (i)
+        {
+            buf.writeByte(',');
+            buf.writenl();
+            buf.writestring("       ");
+        }
+        write(buf, parameters[i]);
+        buf.writestring(" = ");
+        write(buf, tiargs[i]);
+    }
+    // write remaining variadic arguments on the last line
+    if (variadic)
+    {
+        if (i)
+        {
+            buf.writeByte(',');
+            buf.writenl();
+            buf.writestring("       ");
+        }
+        write(buf, parameters[end]);
+        buf.writestring(" = ");
+        buf.writeByte('(');
+        if (end < tiargs.length)
+        {
+            write(buf, tiargs[end]);
+            foreach (j; parameters.length .. tiargs.length)
+            {
+                buf.writestring(", ");
+                write(buf, tiargs[j]);
+            }
+        }
+        buf.writeByte(')');
+    }
+    buf.writeByte('`');
+}
+
+/******************************
+ * Create a scope for the parameters of the TemplateInstance
+ * `ti` in the parent scope sc from the ScopeDsymbol paramsym.
+ *
+ * If paramsym is null a new ScopeDsymbol is used in place of
+ * paramsym.
+ * Params:
+ *      td = template that ti is an instance of
+ *      ti = the TemplateInstance whose parameters to generate the scope for.
+ *      sc = the parent scope of ti
+ * Returns:
+ *      new scope for the parameters of ti
+ */
+Scope* createScopeForTemplateParameters(TemplateDeclaration td, TemplateInstance ti, Scope* sc)
+{
+    ScopeDsymbol paramsym = new ScopeDsymbol();
+    paramsym.parent = td._scope.parent;
+    Scope* paramscope = td._scope.push(paramsym);
+    paramscope.tinst = ti;
+    paramscope.minst = sc.minst;
+    paramscope.callsc = sc;
+    paramscope.stc = 0;
+    return paramscope;
+}
+
+/********************************************
+ * Determine partial specialization order of `td` vs `td2`.
+ * Params:
+ *  sc = context
+ *  td = first template
+ *  td2 = second template
+ *  argumentList = arguments to template
+ * Returns:
+ *      MATCH - td is at least as specialized as td2
+ *      MATCH.nomatch - td2 is more specialized than td
+ */
+MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration td, TemplateDeclaration td2, ArgumentList argumentList)
+{
+    enum LOG_LEASTAS = 0;
+    static if (LOG_LEASTAS)
+    {
+        printf("%s.leastAsSpecialized(%s)\n", toChars(), td2.toChars());
+    }
+
+    /* This works by taking the template parameters to this template
+     * declaration and feeding them to td2 as if it were a template
+     * instance.
+     * If it works, then this template is at least as specialized
+     * as td2.
+     */
+
+    // Set type arguments to dummy template instance to be types
+    // generated from the parameters to this template declaration
+    auto tiargs = new Objects();
+    tiargs.reserve(td.parameters.length);
+    foreach (tp; *td.parameters)
+    {
+        if (tp.dependent)
+            break;
+        RootObject p = tp.dummyArg();
+        if (!p) //TemplateTupleParameter
+            break;
+
+        tiargs.push(p);
+    }
+    scope TemplateInstance ti = new TemplateInstance(Loc.initial, td.ident, tiargs); // create dummy template instance
+
+    // Temporary Array to hold deduced types
+    Objects dedtypes = Objects(td2.parameters.length);
+
+    // Attempt a type deduction
+    MATCH m = matchWithInstance(sc, td2, ti, dedtypes, argumentList, 1);
+    if (m > MATCH.nomatch)
+    {
+        /* A non-variadic template is more specialized than a
+         * variadic one.
+         */
+        TemplateTupleParameter tp = td.isVariadic();
+        if (tp && !tp.dependent && !td2.isVariadic())
+            goto L1;
+
+        static if (LOG_LEASTAS)
+        {
+            printf("  matches %d, so is least as specialized\n", m);
+        }
+        return m;
+    }
+L1:
+    static if (LOG_LEASTAS)
+    {
+        printf("  doesn't match, so is not as specialized\n");
+    }
+    return MATCH.nomatch;
+}
+
+/*************************************************
+ * Match function arguments against a specific template function.
+ *
+ * Params:
+ *     td = template declaration for template instance
+ *     ti = template instance. `ti.tdtypes` will be set to Expression/Type deduced template arguments
+ *     sc = instantiation scope
+ *     fd = Partially instantiated function declaration, which is set to an instantiated function declaration
+ *     tthis = 'this' argument if !NULL
+ *     argumentList = arguments to function
+ *
+ * Returns:
+ *      match pair of initial and inferred template arguments
+ */
+extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, TemplateInstance ti, Scope* sc, ref FuncDeclaration fd, Type tthis, ArgumentList argumentList)
+{
+    version (none)
+    {
+        printf("\nTemplateDeclaration.deduceFunctionTemplateMatch() %s\n", td.toChars());
+        for (size_t i = 0; i < (fargs ? fargs.length : 0); i++)
+        {
+            Expression e = (*fargs)[i];
+            printf("\tfarg[%d] is %s, type is %s\n", cast(int) i, e.toChars(), e.type.toChars());
+        }
+        printf("fd = %s\n", fd.toChars());
+        printf("fd.type = %s\n", fd.type.toChars());
+        if (tthis)
+            printf("tthis = %s\n", tthis.toChars());
+    }
+
+    assert(td._scope);
+
+    auto dedargs = new Objects(td.parameters.length);
+    dedargs.zero();
+
+    Objects* dedtypes = &ti.tdtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
+    dedtypes.setDim(td.parameters.length);
+    dedtypes.zero();
+
+    if (td.errors || fd.errors)
+        return MATCHpair(MATCH.nomatch, MATCH.nomatch);
+
+    // Set up scope for parameters
+    Scope* paramscope = createScopeForTemplateParameters(td, ti,sc);
+
+    MATCHpair nomatch()
+    {
+        paramscope.pop();
+        //printf("\tnomatch\n");
+        return MATCHpair(MATCH.nomatch, MATCH.nomatch);
+    }
+
+    MATCHpair matcherror()
+    {
+        // todo: for the future improvement
+        paramscope.pop();
+        //printf("\terror\n");
+        return MATCHpair(MATCH.nomatch, MATCH.nomatch);
+    }
+    // Mark the parameter scope as deprecated if the templated
+    // function is deprecated (since paramscope.enclosing is the
+    // calling scope already)
+    paramscope.stc |= fd.storage_class & STC.deprecated_;
+
+    TemplateTupleParameter tp = td.isVariadic();
+    Tuple declaredTuple = null;
+
+    version (none)
+    {
+        for (size_t i = 0; i < dedargs.length; i++)
+        {
+            printf("\tdedarg[%d] = ", i);
+            RootObject oarg = (*dedargs)[i];
+            if (oarg)
+                printf("%s", oarg.toChars());
+            printf("\n");
+        }
+    }
+
+    size_t ntargs = 0; // array size of tiargs
+    size_t inferStart = 0; // index of first parameter to infer
+    const Loc instLoc = ti.loc;
+    MATCH matchTiargs = MATCH.exact;
+
+    if (auto tiargs = ti.tiargs)
+    {
+        // Set initial template arguments
+        ntargs = tiargs.length;
+        size_t n = td.parameters.length;
+        if (tp)
+            n--;
+        if (ntargs > n)
+        {
+            if (!tp)
+                return nomatch();
+
+            /* The extra initial template arguments
+             * now form the tuple argument.
+             */
+            auto t = new Tuple(ntargs - n);
+            assert(td.parameters.length);
+            (*dedargs)[td.parameters.length - 1] = t;
+
+            for (size_t i = 0; i < t.objects.length; i++)
+            {
+                t.objects[i] = (*tiargs)[n + i];
+            }
+            td.declareParameter(paramscope, tp, t);
+            declaredTuple = t;
+        }
+        else
+            n = ntargs;
+
+        memcpy(dedargs.tdata(), tiargs.tdata(), n * (*dedargs.tdata()).sizeof);
+
+        for (size_t i = 0; i < n; i++)
+        {
+            assert(i < td.parameters.length);
+            Declaration sparam = null;
+            MATCH m = (*td.parameters)[i].matchArg(instLoc, paramscope, dedargs, i, td.parameters, *dedtypes, &sparam);
+            //printf("\tdeduceType m = %d\n", m);
+            if (m == MATCH.nomatch)
+                return nomatch();
+            if (m < matchTiargs)
+                matchTiargs = m;
+
+            sparam.dsymbolSemantic(paramscope);
+            if (!paramscope.insert(sparam))
+                return nomatch();
+        }
+        if (n < td.parameters.length && !declaredTuple)
+        {
+            inferStart = n;
+        }
+        else
+            inferStart = td.parameters.length;
+        //printf("tiargs matchTiargs = %d\n", matchTiargs);
+    }
+    version (none)
+    {
+        for (size_t i = 0; i < dedargs.length; i++)
+        {
+            printf("\tdedarg[%d] = ", i);
+            RootObject oarg = (*dedargs)[i];
+            if (oarg)
+                printf("%s", oarg.toChars());
+            printf("\n");
+        }
+    }
+
+    ParameterList fparameters = fd.getParameterList(); // function parameter list
+    const nfparams = fparameters.length; // number of function parameters
+    if (argumentList.hasNames)
+        return matcherror(); // TODO: resolve named args
+    Expression[] fargs = argumentList.arguments ? (*argumentList.arguments)[] : null;
+
+    /* Check for match of function arguments with variadic template
+     * parameter, such as:
+     *
+     * void foo(T, A...)(T t, A a);
+     * void main() { foo(1,2,3); }
+     */
+    size_t fptupindex = IDX_NOTFOUND;
+    if (tp) // if variadic
+    {
+        // TemplateTupleParameter always makes most lesser matching.
+        matchTiargs = MATCH.convert;
+
+        if (nfparams == 0 && argumentList.length != 0) // if no function parameters
+        {
+            if (!declaredTuple)
+            {
+                auto t = new Tuple();
+                //printf("t = %p\n", t);
+                (*dedargs)[td.parameters.length - 1] = t;
+                td.declareParameter(paramscope, tp, t);
+                declaredTuple = t;
+            }
+        }
+        else
+        {
+            /* Figure out which of the function parameters matches
+             * the tuple template parameter. Do this by matching
+             * type identifiers.
+             * Set the index of this function parameter to fptupindex.
+             */
+            for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
+            {
+                auto fparam = (*fparameters.parameters)[fptupindex]; // fparameters[fptupindex] ?
+                if (fparam.type.ty != Tident)
+                    continue;
+                TypeIdentifier tid = fparam.type.isTypeIdentifier();
+                if (!tp.ident.equals(tid.ident) || tid.idents.length)
+                    continue;
+
+                if (fparameters.varargs != VarArg.none) // variadic function doesn't
+                    return nomatch(); // go with variadic template
+
+                goto L1;
+            }
+            fptupindex = IDX_NOTFOUND;
+        L1:
+        }
+    }
+
+    MATCH match = MATCH.exact;
+    if (td.toParent().isModule())
+        tthis = null;
+    if (tthis)
+    {
+        bool hasttp = false;
+
+        // Match 'tthis' to any TemplateThisParameter's
+        foreach (param; *td.parameters)
+        {
+            if (auto ttp = param.isTemplateThisParameter())
+            {
+                hasttp = true;
+
+                Type t = new TypeIdentifier(Loc.initial, ttp.ident);
+                MATCH m = deduceType(tthis, paramscope, t, *td.parameters, *dedtypes);
+                if (m == MATCH.nomatch)
+                    return nomatch();
+                if (m < match)
+                    match = m; // pick worst match
+            }
+        }
+
+        // Match attributes of tthis against attributes of fd
+        if (fd.type && !fd.isCtorDeclaration() && !(td._scope.stc & STC.static_))
+        {
+            StorageClass stc = td._scope.stc | fd.storage_class2;
+            // Propagate parent storage class, https://issues.dlang.org/show_bug.cgi?id=5504
+            Dsymbol p = td.parent;
+            while (p.isTemplateDeclaration() || p.isTemplateInstance())
+                p = p.parent;
+            AggregateDeclaration ad = p.isAggregateDeclaration();
+            if (ad)
+                stc |= ad.storage_class;
+
+            ubyte mod = fd.type.mod;
+            if (stc & STC.immutable_)
+                mod = MODFlags.immutable_;
+            else
+            {
+                if (stc & (STC.shared_ | STC.synchronized_))
+                    mod |= MODFlags.shared_;
+                if (stc & STC.const_)
+                    mod |= MODFlags.const_;
+                if (stc & STC.wild)
+                    mod |= MODFlags.wild;
+            }
+
+            ubyte thismod = tthis.mod;
+            if (hasttp)
+                mod = MODmerge(thismod, mod);
+            MATCH m = MODmethodConv(thismod, mod);
+            if (m == MATCH.nomatch)
+                return nomatch();
+            if (m < match)
+                match = m;
+        }
+    }
+
+    // Loop through the function parameters
+    {
+        //printf("%s\n\tnfargs = %d, nfparams = %d, tuple_dim = %d\n", toChars(), nfargs, nfparams, declaredTuple ? declaredTuple.objects.length : 0);
+        //printf("\ttp = %p, fptupindex = %d, found = %d, declaredTuple = %s\n", tp, fptupindex, fptupindex != IDX_NOTFOUND, declaredTuple ? declaredTuple.toChars() : NULL);
+        size_t argi = 0;
+        size_t nfargs2 = fargs.length; // nfargs + supplied defaultArgs
+        uint inoutMatch = 0; // for debugging only
+        for (size_t parami = 0; parami < nfparams; parami++)
+        {
+            Parameter fparam = fparameters[parami];
+
+            // Apply function parameter storage classes to parameter types
+            Type prmtype = fparam.type.addStorageClass(fparam.storageClass);
+
+            Expression farg;
+
+            /* See function parameters which wound up
+             * as part of a template tuple parameter.
+             */
+            if (fptupindex != IDX_NOTFOUND && parami == fptupindex)
+            {
+                TypeIdentifier tid = prmtype.isTypeIdentifier();
+                assert(tid);
+                if (!declaredTuple)
+                {
+                    /* The types of the function arguments
+                     * now form the tuple argument.
+                     */
+                    declaredTuple = new Tuple();
+                    (*dedargs)[td.parameters.length - 1] = declaredTuple;
+
+                    /* Count function parameters with no defaults following a tuple parameter.
+                     * void foo(U, T...)(int y, T, U, double, int bar = 0) {}  // rem == 2 (U, double)
+                     */
+                    size_t rem = 0;
+                    foreach (j; parami + 1 .. nfparams)
+                    {
+                        Parameter p = fparameters[j];
+                        if (p.defaultArg)
+                        {
+                           break;
+                        }
+                        if (!reliesOnTemplateParameters(p.type, (*td.parameters)[inferStart .. td.parameters.length]))
+                        {
+                            Type pt = p.type.syntaxCopy().typeSemantic(fd.loc, paramscope);
+                            if (auto ptt = pt.isTypeTuple())
+                                rem += ptt.arguments.length;
+                            else
+                                rem += 1;
+                        }
+                        else
+                        {
+                            ++rem;
+                        }
+                    }
+
+                    if (nfargs2 - argi < rem)
+                        return nomatch();
+                    declaredTuple.objects.setDim(nfargs2 - argi - rem);
+                    foreach (i; 0 .. declaredTuple.objects.length)
+                    {
+                        farg = fargs[argi + i];
+
+                        // Check invalid arguments to detect errors early.
+                        if (farg.op == EXP.error || farg.type.ty == Terror)
+                            return nomatch();
+
+                        if (!fparam.isLazy() && farg.type.ty == Tvoid)
+                            return nomatch();
+
+                        Type tt;
+                        MATCH m;
+                        if (ubyte wm = deduceWildHelper(farg.type, &tt, tid))
+                        {
+                            inoutMatch |= wm;
+                            m = MATCH.constant;
+                        }
+                        else
+                        {
+                            m = deduceTypeHelper(farg.type, tt, tid);
+                        }
+                        if (m == MATCH.nomatch)
+                            return nomatch();
+                        if (m < match)
+                            match = m;
+
+                        /* Remove top const for dynamic array types and pointer types
+                         */
+                        if ((tt.ty == Tarray || tt.ty == Tpointer) && !tt.isMutable() && (!(fparam.storageClass & STC.ref_) || (fparam.storageClass & STC.auto_) && !farg.isLvalue()))
+                        {
+                            tt = tt.mutableOf();
+                        }
+                        declaredTuple.objects[i] = tt;
+                    }
+                    td.declareParameter(paramscope, tp, declaredTuple);
+                }
+                else
+                {
+                    // https://issues.dlang.org/show_bug.cgi?id=6810
+                    // If declared tuple is not a type tuple,
+                    // it cannot be function parameter types.
+                    for (size_t i = 0; i < declaredTuple.objects.length; i++)
+                    {
+                        if (!isType(declaredTuple.objects[i]))
+                            return nomatch();
+                    }
+                }
+                assert(declaredTuple);
+                argi += declaredTuple.objects.length;
+                continue;
+            }
+
+            // If parameter type doesn't depend on inferred template parameters,
+            // semantic it to get actual type.
+            if (!reliesOnTemplateParameters(prmtype, (*td.parameters)[inferStart .. td.parameters.length]))
+            {
+                // should copy prmtype to avoid affecting semantic result
+                prmtype = prmtype.syntaxCopy().typeSemantic(fd.loc, paramscope);
+
+                if (TypeTuple tt = prmtype.isTypeTuple())
+                {
+                    const tt_dim = tt.arguments.length;
+                    for (size_t j = 0; j < tt_dim; j++, ++argi)
+                    {
+                        Parameter p = (*tt.arguments)[j];
+                        if (j == tt_dim - 1 && fparameters.varargs == VarArg.typesafe &&
+                            parami + 1 == nfparams && argi < fargs.length)
+                        {
+                            prmtype = p.type;
+                            goto Lvarargs;
+                        }
+                        if (argi >= fargs.length)
+                        {
+                            if (p.defaultArg)
+                                continue;
+
+                            // https://issues.dlang.org/show_bug.cgi?id=19888
+                            if (fparam.defaultArg)
+                                break;
+
+                            return nomatch();
+                        }
+                        farg = fargs[argi];
+                        if (!farg.implicitConvTo(p.type))
+                            return nomatch();
+                    }
+                    continue;
+                }
+            }
+
+            if (argi >= fargs.length) // if not enough arguments
+            {
+                if (!fparam.defaultArg)
+                    goto Lvarargs;
+
+                /* https://issues.dlang.org/show_bug.cgi?id=2803
+                 * Before the starting of type deduction from the function
+                 * default arguments, set the already deduced parameters into paramscope.
+                 * It's necessary to avoid breaking existing acceptable code. Cases:
+                 *
+                 * 1. Already deduced template parameters can appear in fparam.defaultArg:
+                 *  auto foo(A, B)(A a, B b = A.stringof);
+                 *  foo(1);
+                 *  // at fparam == 'B b = A.string', A is equivalent with the deduced type 'int'
+                 *
+                 * 2. If prmtype depends on default-specified template parameter, the
+                 * default type should be preferred.
+                 *  auto foo(N = size_t, R)(R r, N start = 0)
+                 *  foo([1,2,3]);
+                 *  // at fparam `N start = 0`, N should be 'size_t' before
+                 *  // the deduction result from fparam.defaultArg.
+                 */
+                if (argi == fargs.length)
+                {
+                    foreach (ref dedtype; *dedtypes)
+                    {
+                        Type at = isType(dedtype);
+                        if (at && at.ty == Tnone)
+                        {
+                            TypeDeduced xt = cast(TypeDeduced)at;
+                            dedtype = xt.tded; // 'unbox'
+                        }
+                    }
+                    for (size_t i = ntargs; i < dedargs.length; i++)
+                    {
+                        TemplateParameter tparam = (*td.parameters)[i];
+
+                        RootObject oarg = (*dedargs)[i];
+                        RootObject oded = (*dedtypes)[i];
+                        if (oarg)
+                            continue;
+
+                        if (oded)
+                        {
+                            if (tparam.specialization() || !tparam.isTemplateTypeParameter())
+                            {
+                                /* The specialization can work as long as afterwards
+                                 * the oded == oarg
+                                 */
+                                (*dedargs)[i] = oded;
+                                MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, td.parameters, *dedtypes, null);
+                                //printf("m2 = %d\n", m2);
+                                if (m2 == MATCH.nomatch)
+                                    return nomatch();
+                                if (m2 < matchTiargs)
+                                    matchTiargs = m2; // pick worst match
+                                if (!(*dedtypes)[i].equals(oded))
+                                    .error(td.loc, "%s `%s` specialization not allowed for deduced parameter `%s`",
+                                        td.kind, td.toPrettyChars, td.kind, td.toPrettyChars, tparam.ident.toChars());
+                            }
+                            else
+                            {
+                                if (MATCH.convert < matchTiargs)
+                                    matchTiargs = MATCH.convert;
+                            }
+                            (*dedargs)[i] = td.declareParameter(paramscope, tparam, oded);
+                        }
+                        else
+                        {
+                            oded = tparam.defaultArg(instLoc, paramscope);
+                            if (oded)
+                                (*dedargs)[i] = td.declareParameter(paramscope, tparam, oded);
+                        }
+                    }
+                }
+                nfargs2 = argi + 1;
+
+                /* If prmtype does not depend on any template parameters:
+                 *
+                 *  auto foo(T)(T v, double x = 0);
+                 *  foo("str");
+                 *  // at fparam == 'double x = 0'
+                 *
+                 * or, if all template parameters in the prmtype are already deduced:
+                 *
+                 *  auto foo(R)(R range, ElementType!R sum = 0);
+                 *  foo([1,2,3]);
+                 *  // at fparam == 'ElementType!R sum = 0'
+                 *
+                 * Deducing prmtype from fparam.defaultArg is not necessary.
+                 */
+                if (prmtype.deco || prmtype.syntaxCopy().trySemantic(td.loc, paramscope))
+                {
+                    ++argi;
+                    continue;
+                }
+
+                // Deduce prmtype from the defaultArg.
+                farg = fparam.defaultArg.syntaxCopy();
+                farg = farg.expressionSemantic(paramscope);
+                farg = resolveProperties(paramscope, farg);
+            }
+            else
+            {
+                farg = fargs[argi];
+            }
+            {
+                // Check invalid arguments to detect errors early.
+                if (farg.op == EXP.error || farg.type.ty == Terror)
+                    return nomatch();
+
+                Type att = null;
+            Lretry:
+                version (none)
+                {
+                    printf("\tfarg.type   = %s\n", farg.type.toChars());
+                    printf("\tfparam.type = %s\n", prmtype.toChars());
+                }
+                Type argtype = farg.type;
+
+                if (!fparam.isLazy() && argtype.ty == Tvoid && farg.op != EXP.function_)
+                    return nomatch();
+
+                // https://issues.dlang.org/show_bug.cgi?id=12876
+                // Optimize argument to allow CT-known length matching
+                farg = farg.optimize(WANTvalue, fparam.isReference());
+                //printf("farg = %s %s\n", farg.type.toChars(), farg.toChars());
+
+                RootObject oarg = farg;
+                if ((fparam.storageClass & STC.ref_) && (!(fparam.storageClass & STC.auto_) || farg.isLvalue()))
+                {
+                    /* Allow expressions that have CT-known boundaries and type [] to match with [dim]
+                     */
+                    bool inferIndexType = (argtype.ty == Tarray) && (prmtype.ty == Tsarray || prmtype.ty == Taarray);
+                    if (auto aaType = prmtype.isTypeAArray())
+                    {
+                        if (auto indexType = aaType.index.isTypeIdentifier())
+                        {
+                            inferIndexType = indexType.idents.length == 0;
+                        }
+                    }
+                    if (inferIndexType)
+                    {
+                        if (StringExp se = farg.isStringExp())
+                        {
+                            argtype = se.type.nextOf().sarrayOf(se.len);
+                        }
+                        else if (ArrayLiteralExp ae = farg.isArrayLiteralExp())
+                        {
+                            argtype = ae.type.nextOf().sarrayOf(ae.elements.length);
+                        }
+                        else if (SliceExp se = farg.isSliceExp())
+                        {
+                            if (Type tsa = toStaticArrayType(se))
+                                argtype = tsa;
+                        }
+                    }
+
+                    oarg = argtype;
+                }
+                else if ((fparam.storageClass & STC.out_) == 0 &&
+                         (argtype.ty == Tarray || argtype.ty == Tpointer) &&
+                         templateParameterLookup(prmtype, td.parameters) != IDX_NOTFOUND &&
+                         prmtype.isTypeIdentifier().idents.length == 0)
+                {
+                    /* The farg passing to the prmtype always make a copy. Therefore,
+                     * we can shrink the set of the deduced type arguments for prmtype
+                     * by adjusting top-qualifier of the argtype.
+                     *
+                     *  prmtype         argtype     ta
+                     *  T            <- const(E)[]  const(E)[]
+                     *  T            <- const(E[])  const(E)[]
+                     *  qualifier(T) <- const(E)[]  const(E[])
+                     *  qualifier(T) <- const(E[])  const(E[])
+                     */
+                    Type ta = argtype.castMod(prmtype.mod ? argtype.nextOf().mod : 0);
+                    if (ta != argtype)
+                    {
+                        Expression ea = farg.copy();
+                        ea.type = ta;
+                        oarg = ea;
+                    }
+                }
+
+                if (fparameters.varargs == VarArg.typesafe && parami + 1 == nfparams && argi + 1 < fargs.length)
+                    goto Lvarargs;
+
+                uint im = 0;
+                MATCH m = deduceType(oarg, paramscope, prmtype, *td.parameters, *dedtypes, &im, inferStart);
+                //printf("\tL%d deduceType m = %d, im = x%x, inoutMatch = x%x\n", __LINE__, m, im, inoutMatch);
+                inoutMatch |= im;
+
+                /* If no match, see if the argument can be matched by using
+                 * implicit conversions.
+                 */
+                if (m == MATCH.nomatch && prmtype.deco)
+                    m = farg.implicitConvTo(prmtype);
+
+                if (m == MATCH.nomatch)
+                {
+                    AggregateDeclaration ad = isAggregate(farg.type);
+                    if (ad && ad.aliasthis && !isRecursiveAliasThis(att, argtype))
+                    {
+                        // https://issues.dlang.org/show_bug.cgi?id=12537
+                        // The isRecursiveAliasThis() call above
+
+                        /* If a semantic error occurs while doing alias this,
+                         * eg purity(https://issues.dlang.org/show_bug.cgi?id=7295),
+                         * just regard it as not a match.
+                         *
+                         * We also save/restore sc.func.flags to avoid messing up
+                         * attribute inference in the evaluation.
+                        */
+                        const oldflags = sc.func ? sc.func.flags : 0;
+                        auto e = resolveAliasThis(sc, farg, true);
+                        if (sc.func)
+                            sc.func.flags = oldflags;
+                        if (e)
+                        {
+                            farg = e;
+                            goto Lretry;
+                        }
+                    }
+                }
+
+                if (m > MATCH.nomatch && (fparam.storageClass & (STC.ref_ | STC.auto_)) == STC.ref_)
+                {
+                    if (!farg.isLvalue())
+                    {
+                        if ((farg.op == EXP.string_ || farg.op == EXP.slice) && (prmtype.ty == Tsarray || prmtype.ty == Taarray))
+                        {
+                            // Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
+                        }
+                        else if (global.params.rvalueRefParam == FeatureState.enabled)
+                        {
+                            // Allow implicit conversion to ref
+                        }
+                        else
+                            return nomatch();
+                    }
+                }
+                if (m > MATCH.nomatch && (fparam.storageClass & STC.out_))
+                {
+                    if (!farg.isLvalue())
+                        return nomatch();
+                    if (!farg.type.isMutable()) // https://issues.dlang.org/show_bug.cgi?id=11916
+                        return nomatch();
+                }
+                if (m == MATCH.nomatch && fparam.isLazy() && prmtype.ty == Tvoid && farg.type.ty != Tvoid)
+                    m = MATCH.convert;
+                if (m != MATCH.nomatch)
+                {
+                    if (m < match)
+                        match = m; // pick worst match
+                    argi++;
+                    continue;
+                }
+            }
+
+        Lvarargs:
+            /* The following code for variadic arguments closely
+             * matches TypeFunction.callMatch()
+             */
+            if (!(fparameters.varargs == VarArg.typesafe && parami + 1 == nfparams))
+                return nomatch();
+
+            /* Check for match with function parameter T...
+             */
+            Type tb = prmtype.toBasetype();
+            switch (tb.ty)
+            {
+                // 6764 fix - TypeAArray may be TypeSArray have not yet run semantic().
+            case Tsarray:
+            case Taarray:
+                {
+                    // Perhaps we can do better with this, see TypeFunction.callMatch()
+                    if (TypeSArray tsa = tb.isTypeSArray())
+                    {
+                        dinteger_t sz = tsa.dim.toInteger();
+                        if (sz != fargs.length - argi)
+                            return nomatch();
+                    }
+                    else if (TypeAArray taa = tb.isTypeAArray())
+                    {
+                        Expression dim = new IntegerExp(instLoc, fargs.length - argi, Type.tsize_t);
+
+                        size_t i = templateParameterLookup(taa.index, td.parameters);
+                        if (i == IDX_NOTFOUND)
+                        {
+                            Expression e;
+                            Type t;
+                            Dsymbol s;
+                            Scope *sco;
+
+                            uint errors = global.startGagging();
+                            /* ref: https://issues.dlang.org/show_bug.cgi?id=11118
+                             * The parameter isn't part of the template
+                             * ones, let's try to find it in the
+                             * instantiation scope 'sc' and the one
+                             * belonging to the template itself. */
+                            sco = sc;
+                            taa.index.resolve(instLoc, sco, e, t, s);
+                            if (!e)
+                            {
+                                sco = paramscope;
+                                taa.index.resolve(instLoc, sco, e, t, s);
+                            }
+                            global.endGagging(errors);
+
+                            if (!e)
+                                return nomatch();
+
+                            e = e.ctfeInterpret();
+                            e = e.implicitCastTo(sco, Type.tsize_t);
+                            e = e.optimize(WANTvalue);
+                            if (!dim.equals(e))
+                                return nomatch();
+                        }
+                        else
+                        {
+                            // This code matches code in TypeInstance.deduceType()
+                            TemplateParameter tprm = (*td.parameters)[i];
+                            TemplateValueParameter tvp = tprm.isTemplateValueParameter();
+                            if (!tvp)
+                                return nomatch();
+                            Expression e = cast(Expression)(*dedtypes)[i];
+                            if (e)
+                            {
+                                if (!dim.equals(e))
+                                    return nomatch();
+                            }
+                            else
+                            {
+                                Type vt = tvp.valType.typeSemantic(Loc.initial, sc);
+                                MATCH m = dim.implicitConvTo(vt);
+                                if (m == MATCH.nomatch)
+                                    return nomatch();
+                                (*dedtypes)[i] = dim;
+                            }
+                        }
+                    }
+                    goto case Tarray;
+                }
+            case Tarray:
+                {
+                    TypeArray ta = cast(TypeArray)tb;
+                    Type tret = fparam.isLazyArray();
+                    for (; argi < fargs.length; argi++)
+                    {
+                        Expression arg = fargs[argi];
+                        assert(arg);
+
+                        MATCH m;
+                        /* If lazy array of delegates,
+                         * convert arg(s) to delegate(s)
+                         */
+                        if (tret)
+                        {
+                            if (ta.next.equals(arg.type))
+                            {
+                                m = MATCH.exact;
+                            }
+                            else
+                            {
+                                m = arg.implicitConvTo(tret);
+                                if (m == MATCH.nomatch)
+                                {
+                                    if (tret.toBasetype().ty == Tvoid)
+                                        m = MATCH.convert;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            uint wm = 0;
+                            m = deduceType(arg, paramscope, ta.next, *td.parameters, *dedtypes, &wm, inferStart);
+                            inoutMatch |= wm;
+                        }
+                        if (m == MATCH.nomatch)
+                            return nomatch();
+                        if (m < match)
+                            match = m;
+                    }
+                    goto Lmatch;
+                }
+            case Tclass:
+            case Tident:
+                goto Lmatch;
+
+            default:
+                return nomatch();
+            }
+            assert(0);
+        }
+        //printf(". argi = %d, nfargs = %d, nfargs2 = %d\n", argi, nfargs, nfargs2);
+        if (argi != nfargs2 && fparameters.varargs == VarArg.none)
+            return nomatch();
+    }
+
+Lmatch:
+    foreach (ref dedtype; *dedtypes)
+    {
+        if (Type at = isType(dedtype))
+        {
+            if (at.ty == Tnone)
+            {
+                TypeDeduced xt = cast(TypeDeduced)at;
+                at = xt.tded; // 'unbox'
+            }
+            dedtype = at.merge2();
+        }
+    }
+    for (size_t i = ntargs; i < dedargs.length; i++)
+    {
+        TemplateParameter tparam = (*td.parameters)[i];
+        //printf("tparam[%d] = %s\n", i, tparam.ident.toChars());
+
+        /* For T:T*, the dedargs is the T*, dedtypes is the T
+         * But for function templates, we really need them to match
+         */
+        RootObject oarg = (*dedargs)[i];
+        RootObject oded = (*dedtypes)[i];
+        //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
+        //if (oarg) printf("oarg: %s\n", oarg.toChars());
+        //if (oded) printf("oded: %s\n", oded.toChars());
+        if (oarg)
+            continue;
+
+        if (oded)
+        {
+            if (tparam.specialization() || !tparam.isTemplateTypeParameter())
+            {
+                /* The specialization can work as long as afterwards
+                 * the oded == oarg
+                 */
+                (*dedargs)[i] = oded;
+                MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, td.parameters, *dedtypes, null);
+                //printf("m2 = %d\n", m2);
+                if (m2 == MATCH.nomatch)
+                    return nomatch();
+                if (m2 < matchTiargs)
+                    matchTiargs = m2; // pick worst match
+                if (!(*dedtypes)[i].equals(oded))
+                    .error(td.loc, "%s `%s` specialization not allowed for deduced parameter `%s`", td.kind, td.toPrettyChars, tparam.ident.toChars());
+            }
+            else
+            {
+                // Discussion: https://issues.dlang.org/show_bug.cgi?id=16484
+                if (MATCH.convert < matchTiargs)
+                    matchTiargs = MATCH.convert;
+            }
+        }
+        else
+        {
+            oded = tparam.defaultArg(instLoc, paramscope);
+            if (!oded)
+            {
+                // if tuple parameter and
+                // tuple parameter was not in function parameter list and
+                // we're one or more arguments short (i.e. no tuple argument)
+                if (tparam == tp &&
+                    fptupindex == IDX_NOTFOUND &&
+                    ntargs <= dedargs.length - 1)
+                {
+                    // make tuple argument an empty tuple
+                    oded = new Tuple();
+                }
+                else
+                    return nomatch();
+            }
+            if (isError(oded))
+                return matcherror();
+            ntargs++;
+
+            /* At the template parameter T, the picked default template argument
+             * X!int should be matched to T in order to deduce dependent
+             * template parameter A.
+             *  auto foo(T : X!A = X!int, A...)() { ... }
+             *  foo();  // T <-- X!int, A <-- (int)
+             */
+            if (tparam.specialization())
+            {
+                (*dedargs)[i] = oded;
+                MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, td.parameters, *dedtypes, null);
+                //printf("m2 = %d\n", m2);
+                if (m2 == MATCH.nomatch)
+                    return nomatch();
+                if (m2 < matchTiargs)
+                    matchTiargs = m2; // pick worst match
+                if (!(*dedtypes)[i].equals(oded))
+                    .error(td.loc, "%s `%s` specialization not allowed for deduced parameter `%s`", td.kind, td.toPrettyChars, tparam.ident.toChars());
+            }
+        }
+        oded = td.declareParameter(paramscope, tparam, oded);
+        (*dedargs)[i] = oded;
+    }
+
+    /* https://issues.dlang.org/show_bug.cgi?id=7469
+     * As same as the code for 7469 in findBestMatch,
+     * expand a Tuple in dedargs to normalize template arguments.
+     */
+    if (auto d = dedargs.length)
+    {
+        if (auto va = isTuple((*dedargs)[d - 1]))
+        {
+            dedargs.setDim(d - 1);
+            dedargs.insert(d - 1, &va.objects);
+        }
+    }
+    ti.tiargs = dedargs; // update to the normalized template arguments.
+
+    // Partially instantiate function for constraint and fd.leastAsSpecialized()
+    {
+        assert(paramscope.scopesym);
+        Scope* sc2 = td._scope;
+        sc2 = sc2.push(paramscope.scopesym);
+        sc2 = sc2.push(ti);
+        sc2.parent = ti;
+        sc2.tinst = ti;
+        sc2.minst = sc.minst;
+        sc2.stc |= fd.storage_class & STC.deprecated_;
+
+        fd = td.doHeaderInstantiation(ti, sc2, fd, tthis, argumentList.arguments);
+        sc2 = sc2.pop();
+        sc2 = sc2.pop();
+
+        if (!fd)
+            return nomatch();
+    }
+
+    if (td.constraint)
+    {
+        if (!evaluateConstraint(td, ti, sc, paramscope, dedargs, fd))
+            return nomatch();
+    }
+
+    version (none)
+    {
+        for (size_t i = 0; i < dedargs.length; i++)
+        {
+            RootObject o = (*dedargs)[i];
+            printf("\tdedargs[%d] = %d, %s\n", i, o.dyncast(), o.toChars());
+        }
+    }
+
+    paramscope.pop();
+    //printf("\tmatch %d\n", match);
+    return MATCHpair(matchTiargs, match);
+}
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index 589bc2b53cdc3de182f2180477b6879912ce0ed2..da4a3ee209ef1f49116131d0645ab3d3e7d6a37e 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -124,6 +124,7 @@ enum TOK : ubyte
     // Leaf operators
     identifier,
     string_,
+    interpolated,
     hexadecimalString,
     this_,
     super_,
@@ -380,6 +381,7 @@ enum EXP : ubyte
     // Leaf operators
     identifier,
     string_,
+    interpolated,
     this_,
     super_,
     halt,
@@ -623,6 +625,10 @@ static immutable TOK[TOK.max + 1] Ckeywords =
     }
 } ();
 
+struct InterpolatedSet {
+    // all strings in the parts are zero terminated at length+1
+    string[] parts;
+}
 
 /***********************************************************
  */
@@ -645,7 +651,11 @@ extern (C++) struct Token
 
         struct
         {
-            const(char)* ustring; // UTF8 string
+            union
+            {
+                const(char)* ustring; // UTF8 string
+                InterpolatedSet* interpolatedSet;
+            }
             uint len;
             ubyte postfix; // 'c', 'w', 'd'
         }
@@ -833,6 +843,7 @@ extern (C++) struct Token
         // For debugging
         TOK.error: "error",
         TOK.string_: "string",
+        TOK.interpolated: "interpolated string",
         TOK.onScopeExit: "scope(exit)",
         TOK.onScopeSuccess: "scope(success)",
         TOK.onScopeFailure: "scope(failure)",
@@ -910,6 +921,24 @@ nothrow:
         return 0;
     }
 
+    extern(D) void appendInterpolatedPart(const ref OutBuffer buf) {
+        appendInterpolatedPart(cast(const(char)*)buf[].ptr, buf.length);
+    }
+    extern(D) void appendInterpolatedPart(const(char)[] str) {
+        appendInterpolatedPart(str.ptr, str.length);
+    }
+    extern(D) void appendInterpolatedPart(const(char)* ptr, size_t length) {
+        assert(value == TOK.interpolated);
+        if (interpolatedSet is null)
+            interpolatedSet = new InterpolatedSet;
+
+        auto s = cast(char*)mem.xmalloc_noscan(length + 1);
+        memcpy(s, ptr, length);
+        s[length] = 0;
+
+        interpolatedSet.parts ~= cast(string) s[0 .. length];
+    }
+
     /****
      * Set to contents of ptr[0..length]
      * Params:
@@ -918,6 +947,7 @@ nothrow:
      */
     void setString(const(char)* ptr, size_t length)
     {
+        value = TOK.string_;
         auto s = cast(char*)mem.xmalloc_noscan(length + 1);
         memcpy(s, ptr, length);
         s[length] = 0;
@@ -941,6 +971,7 @@ nothrow:
      */
     void setString()
     {
+        value = TOK.string_;
         ustring = "";
         len = 0;
         postfix = 0;
diff --git a/gcc/d/dmd/tokens.h b/gcc/d/dmd/tokens.h
index f944663e43052292ed7676044854b466459a957c..ef91001a99692b1008cc093fc4a0b2dd1cedf135 100644
--- a/gcc/d/dmd/tokens.h
+++ b/gcc/d/dmd/tokens.h
@@ -133,6 +133,7 @@ enum class TOK : unsigned char
     // Leaf operators
     identifier,
     string_,
+    interpolated,
     hexadecimalString,
     this_,
     super_,
@@ -390,6 +391,7 @@ enum class EXP : unsigned char
     // Leaf operators
     identifier,
     string_,
+    interpolated,
     this_,
     super_,
     halt,
@@ -461,7 +463,12 @@ struct Token
         real_t floatvalue;
 
         struct
-        {   utf8_t *ustring;     // UTF8 string
+        {
+            union
+            {
+                utf8_t *ustring;     // UTF8 string
+                void *interpolatedSet;
+            };
             unsigned len;
             unsigned char postfix;      // 'c', 'w', 'd'
         };
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index c67ee816d2c5a9031be4de9435716f1d8a689900..be7aa9923c03697483a84952ec1a773929937a46 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -36,6 +36,7 @@ import dmd.errorsink;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
+import dmd.funcsem;
 import dmd.globals;
 import dmd.hdrgen;
 import dmd.id;
@@ -1306,7 +1307,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         // attribute inference.
         if (fd && fd.parent && fd.parent.isTemplateInstance)
         {
-            fd.functionSemantic3();
+            functionSemantic3(fd);
             tf = fd.type.isTypeFunction();
         }
 
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 714af8a05686565e02c1279edc5d1f89fc72bcf8..6721fa6544a7e4b6f8ceaaea7e36655d9c623607 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -35,6 +35,7 @@ import dmd.dstruct;
 import dmd.dsymbol;
 import dmd.dsymbolsem;
 import dmd.dtemplate;
+import dmd.enumsem;
 import dmd.errors;
 import dmd.errorsink;
 import dmd.expression;
@@ -2919,6 +2920,29 @@ extern (C++) Type merge(Type type)
     return type;
 }
 
+/*************************************
+ * This version does a merge even if the deco is already computed.
+ * Necessary for types that have a deco, but are not merged.
+ */
+extern(C++) Type merge2(Type type)
+{
+    //printf("merge2(%s)\n", toChars());
+    Type t = type;
+    assert(t);
+    if (!t.deco)
+        return t.merge();
+
+    auto sv = Type.stringtable.lookup(t.deco, strlen(t.deco));
+    if (sv && sv.value)
+    {
+        t = sv.value;
+        assert(t.deco);
+    }
+    else
+        assert(0);
+    return t;
+}
+
 /***************************************
  * Calculate built-in properties which just the type is necessary.
  *
@@ -5697,7 +5721,7 @@ Type getComplexLibraryType(const ref Loc loc, Scope* sc, TY ty)
  * Returns:
  *     An enum value of either `Covariant.yes` or a reason it's not covariant.
  */
-extern (C++) Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovariant = false)
+extern(C++) Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovariant = false)
 {
     version (none)
     {
diff --git a/gcc/d/dmd/typinf.d b/gcc/d/dmd/typinf.d
index 9e062bd631d7e376edeab70b70ec67bf40688b8a..6ae6df0e9b5a9bb54ec98718e07118435564e4d2 100644
--- a/gcc/d/dmd/typinf.d
+++ b/gcc/d/dmd/typinf.d
@@ -65,6 +65,7 @@ extern (C++) bool genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope
         fatal();
     }
 
+    import dmd.typesem : merge2;
     Type t = torig.merge2(); // do this since not all Type's are merge'd
     bool needsCodegen = false;
     if (!t.vtinfo)
diff --git a/gcc/d/dmd/visitor.h b/gcc/d/dmd/visitor.h
index 7fa08cb0e8bcea49183732f536ffe753e958b22c..6e3d31518888e0e610cc4cc77fe4085a562368c7 100644
--- a/gcc/d/dmd/visitor.h
+++ b/gcc/d/dmd/visitor.h
@@ -195,6 +195,7 @@ class ThisExp;
 class SuperExp;
 class NullExp;
 class StringExp;
+class InterpExp;
 class TupleExp;
 class ArrayLiteralExp;
 class AssocArrayLiteralExp;
@@ -480,6 +481,7 @@ public:
     virtual void visit(TypeidExp *e) { visit((Expression *)e); }
     virtual void visit(TraitsExp *e) { visit((Expression *)e); }
     virtual void visit(StringExp *e) { visit((Expression *)e); }
+    virtual void visit(InterpExp *e) { visit((Expression *)e); }
     virtual void visit(NewExp *e) { visit((Expression *)e); }
     virtual void visit(AssocArrayLiteralExp *e) { visit((Expression *)e); }
     virtual void visit(ArrayLiteralExp *e) { visit((Expression *)e); }
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 6f596c5ac20fcc1ae1aca0ffb2a523f10fd442b3..0a85a55b397bf42af09d18453034a68b62032204 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -2495,17 +2495,18 @@ public:
 
 	for (size_t i = 0; i < e->len; i++)
 	  {
-	    tree value = build_integer_cst (e->getCodeUnit (i), etype);
+	    tree value = build_integer_cst (e->getIndex (i), etype);
 	    CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
 	  }
 
 	tree ctor = build_constructor (type, elms);
 	TREE_CONSTANT (ctor) = 1;
 	this->result_ = ctor;
+	return;
       }
     else
       {
-	/* Copy the string contents to a null terminated string.  */
+	/* Copy the string contents to a null terminated STRING_CST.  */
 	dinteger_t length = (e->len * e->sz);
 	char *string = XALLOCAVEC (char, length + e->sz);
 	memset (string, 0, length + e->sz);
@@ -2514,7 +2515,18 @@ public:
 
 	/* String value and type includes the null terminator.  */
 	tree value = build_string (length + e->sz, string);
-	TREE_TYPE (value) = make_array_type (tb->nextOf (), length + 1);
+	if (e->sz <= 4)
+	  TREE_TYPE (value) = make_array_type (tb->nextOf (), length + 1);
+	else
+	  {
+	    /* Hexadecimal literal strings with an 8-byte character type are
+	       just an alternative way to store an array of `ulong'.
+	       Treat it as if it were a `uint[]' array instead.  */
+	    dinteger_t resize = e->sz / 4;
+	    TREE_TYPE (value) = make_array_type (Type::tuns32,
+						 (length * resize) + resize);
+	  }
+
 	value = build_address (value);
 
 	if (tb->ty == TY::Tarray)
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index dfab0e651b979e8c21d6e574e99da62ae9de96b6..1600ca92bd4e3b20f3a4d85eaad32f8f65b6b577 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -259,8 +259,9 @@ create_tinfo_types (Module *mod)
 			  array_type_node, array_type_node, array_type_node,
 			  array_type_node, ptr_type_node, ptr_type_node,
 			  ptr_type_node, d_uint_type, ptr_type_node,
-			  array_type_node, ptr_type_node, d_ulong_type,
-			  d_ulong_type, ptr_type_node, NULL);
+			  array_type_node, ptr_type_node, ptr_type_node,
+			  d_uint_type, d_uint_type, d_uint_type, d_uint_type,
+			  NULL);
 
   object_module = mod;
 }
@@ -577,7 +578,7 @@ public:
   void visit (TypeInfoConstDeclaration *d) final override
   {
     Type *tm = d->tinfo->mutableOf ();
-    tm = tm->merge2 ();
+    tm = merge2 (tm);
 
     /* The vtable for TypeInfo_Const.  */
     this->layout_base (Type::typeinfoconst);
@@ -594,7 +595,7 @@ public:
   void visit (TypeInfoInvariantDeclaration *d) final override
   {
     Type *tm = d->tinfo->mutableOf ();
-    tm = tm->merge2 ();
+    tm = merge2 (tm);
 
     /* The vtable for TypeInfo_Invariant.  */
     this->layout_base (Type::typeinfoinvariant);
@@ -611,7 +612,7 @@ public:
   void visit (TypeInfoSharedDeclaration *d) final override
   {
     Type *tm = d->tinfo->unSharedOf ();
-    tm = tm->merge2 ();
+    tm = merge2 (tm);
 
     /* The vtable for TypeInfo_Shared.  */
     this->layout_base (Type::typeinfoshared);
@@ -628,7 +629,7 @@ public:
   void visit (TypeInfoWildDeclaration *d) final override
   {
     Type *tm = d->tinfo->mutableOf ();
-    tm = tm->merge2 ();
+    tm = merge2 (tm);
 
     /* The vtable for TypeInfo_Inout.  */
     this->layout_base (Type::typeinfowild);
@@ -934,10 +935,6 @@ public:
 	else
 	  this->layout_field (null_pointer_node);
 
-	/* ulong[2] nameSig;  */
-	this->layout_field (build_zero_cst (d_ulong_type));
-	this->layout_field (build_zero_cst (d_ulong_type));
-
 	/* immutable(void)* m_RTInfo;  */
 	if (cd->getRTInfo)
 	  this->layout_field (build_expr (cd->getRTInfo, true));
@@ -945,6 +942,12 @@ public:
 	  this->layout_field (size_one_node);
 	else
 	  this->layout_field (null_pointer_node);
+
+	/* uint[4] nameSig;  */
+	this->layout_field (build_zero_cst (d_uint_type));
+	this->layout_field (build_zero_cst (d_uint_type));
+	this->layout_field (build_zero_cst (d_uint_type));
+	this->layout_field (build_zero_cst (d_uint_type));
       }
     else
       {
@@ -985,15 +988,17 @@ public:
 	this->layout_field (null_array_node);
 	this->layout_field (null_pointer_node);
 
-	/* ulong[2] nameSig;  */
-	this->layout_field (build_zero_cst (d_ulong_type));
-	this->layout_field (build_zero_cst (d_ulong_type));
-
 	/* immutable(void)* m_RTInfo;  */
 	if (cd->getRTInfo)
 	  this->layout_field (build_expr (cd->getRTInfo, true));
 	else
 	  this->layout_field (null_pointer_node);
+
+	/* uint[4] nameSig;  */
+	this->layout_field (build_zero_cst (d_uint_type));
+	this->layout_field (build_zero_cst (d_uint_type));
+	this->layout_field (build_zero_cst (d_uint_type));
+	this->layout_field (build_zero_cst (d_uint_type));
       }
 
     /* Put out array of Interfaces.  */
@@ -1546,7 +1551,7 @@ create_typeinfo (Type *type, Module *mod, bool generate)
     create_frontend_tinfo_types ();
 
   /* Do this since not all Type's are merged.  */
-  Type *t = type->merge2 ();
+  Type *t = merge2 (type);
   Identifier *ident;
 
   if (!t->vtinfo)
diff --git a/gcc/testsuite/gdc.test/compilable/test13281.d b/gcc/testsuite/gdc.test/compilable/test13281.d
index 0d747faf3fd948753607d9f992e6403bc18e857d..ab92fcc02a076b6b017a47676740afe40852029c 100644
--- a/gcc/testsuite/gdc.test/compilable/test13281.d
+++ b/gcc/testsuite/gdc.test/compilable/test13281.d
@@ -36,12 +36,27 @@ static assert((123  ).stringof == "123");
 static assert((123u ).stringof == "123u");
 static assert((123L ).stringof == "123L");
 static assert((123uL).stringof == "123LU");
-static assert((123.5  ).stringof == "1.235e+2");
-static assert((123.5f ).stringof == "1.235e+2F");
-static assert((123.5L ).stringof == "1.235e+2L");
-static assert((123.5i ).stringof == "1.235e+2i");
-static assert((123.5fi).stringof == "1.235e+2Fi");
-static assert((123.5Li).stringof == "1.235e+2Li");
-static assert((123.5 +5.5i ).stringof == "1.235e+2 + 5.5e+0i");
-static assert((123.5f+5.5fi).stringof == "1.235e+2F + 5.5e+0Fi");
-static assert((123.5L+5.5Li).stringof == "1.235e+2L + 5.5e+0Li");
+version (GNU)
+{
+    static assert((123.5  ).stringof == "1.235e+2");
+    static assert((123.5f ).stringof == "1.235e+2F");
+    static assert((123.5L ).stringof == "1.235e+2L");
+    static assert((123.5i ).stringof == "1.235e+2i");
+    static assert((123.5fi).stringof == "1.235e+2Fi");
+    static assert((123.5Li).stringof == "1.235e+2Li");
+    static assert((123.5 +5.5i ).stringof == "1.235e+2 + 5.5e+0i");
+    static assert((123.5f+5.5fi).stringof == "1.235e+2F + 5.5e+0Fi");
+    static assert((123.5L+5.5Li).stringof == "1.235e+2L + 5.5e+0Li");
+}
+else
+{
+    static assert((123.5  ).stringof == "123.5");
+    static assert((123.5f ).stringof == "123.5F");
+    static assert((123.5L ).stringof == "123.5L");
+    static assert((123.5i ).stringof == "123.5i");
+    static assert((123.5fi).stringof == "123.5Fi");
+    static assert((123.5Li).stringof == "123.5Li");
+    static assert((123.5 +5.5i ).stringof == "123.5 + 5.5i");
+    static assert((123.5f+5.5fi).stringof == "123.5F + 5.5Fi");
+    static assert((123.5L+5.5Li).stringof == "123.5L + 5.5Li");
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b19523.d b/gcc/testsuite/gdc.test/fail_compilation/b19523.d
index 36266669a32d1d34dc64286fedbb40abffac3732..d2a05c73dc1adfb15f48565596bbcfd2d0937169 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/b19523.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/b19523.d
@@ -1,10 +1,11 @@
 /*
 TEST_OUTPUT:
----
-fail_compilation/b19523.d(12): Error: undefined identifier `SomeStruct`
-fail_compilation/b19523.d(13): Error: function `b19523.foo(int delegate() arg)` is not callable using argument types `(_error_)`
-fail_compilation/b19523.d(13):        cannot pass argument `__lambda2` of type `_error_` to parameter `int delegate() arg`
----
+----
+fail_compilation/b19523.d(13): Error: undefined identifier `SomeStruct`
+fail_compilation/b19523.d(14): Error: function `foo` is not callable using argument types `(_error_)`
+fail_compilation/b19523.d(14):        cannot pass argument `__lambda2` of type `_error_` to parameter `int delegate() arg`
+fail_compilation/b19523.d(19):        `b19523.foo(int delegate() arg)` declared here
+----
 */
 module b19523;
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b20011.d b/gcc/testsuite/gdc.test/fail_compilation/b20011.d
index 3ddcdaaf76b7b4866ee7121787902a3e8e994b25..50ef6aff6097688842097471fa5c454e3d6e9bcb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/b20011.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/b20011.d
@@ -1,16 +1,19 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/b20011.d(25): Error: cannot modify expression `S1(cast(ubyte)0u).member` because it is not an lvalue
-fail_compilation/b20011.d(28): Error: cannot modify expression `S2(null).member` because it is not an lvalue
-fail_compilation/b20011.d(29): Error: cannot modify expression `S2(null).member` because it is not an lvalue
-fail_compilation/b20011.d(32): Error: cannot modify expression `U1(cast(ubyte)0u, ).m2` because it is not an lvalue
-fail_compilation/b20011.d(37): Error: function `b20011.main.assignableByRef(ref ubyte p)` is not callable using argument types `(ubyte)`
-fail_compilation/b20011.d(37):        cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref ubyte p`
-fail_compilation/b20011.d(38): Error: function `b20011.main.assignableByOut(out ubyte p)` is not callable using argument types `(ubyte)`
-fail_compilation/b20011.d(38):        cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `out ubyte p`
-fail_compilation/b20011.d(39): Error: function `b20011.main.assignableByConstRef(ref const(ubyte) p)` is not callable using argument types `(ubyte)`
-fail_compilation/b20011.d(39):        cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref const(ubyte) p`
+fail_compilation/b20011.d(28): Error: cannot modify expression `S1(cast(ubyte)0u).member` because it is not an lvalue
+fail_compilation/b20011.d(31): Error: cannot modify expression `S2(null).member` because it is not an lvalue
+fail_compilation/b20011.d(32): Error: cannot modify expression `S2(null).member` because it is not an lvalue
+fail_compilation/b20011.d(35): Error: cannot modify expression `U1(cast(ubyte)0u, ).m2` because it is not an lvalue
+fail_compilation/b20011.d(40): Error: function `assignableByRef` is not callable using argument types `(ubyte)`
+fail_compilation/b20011.d(40):        cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref ubyte p`
+fail_compilation/b20011.d(37):        `b20011.main.assignableByRef(ref ubyte p)` declared here
+fail_compilation/b20011.d(41): Error: function `assignableByOut` is not callable using argument types `(ubyte)`
+fail_compilation/b20011.d(41):        cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `out ubyte p`
+fail_compilation/b20011.d(38):        `b20011.main.assignableByOut(out ubyte p)` declared here
+fail_compilation/b20011.d(42): Error: function `assignableByConstRef` is not callable using argument types `(ubyte)`
+fail_compilation/b20011.d(42):        cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref const(ubyte) p`
+fail_compilation/b20011.d(39):        `b20011.main.assignableByConstRef(ref const(ubyte) p)` declared here
 ---
 */
 module b20011;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug15613.d b/gcc/testsuite/gdc.test/fail_compilation/bug15613.d
index 5b16f72ca232ebf11ced105efad69c4e728a32c4..ac167f3f8e9556295d6b82821f21258a839f10bd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/bug15613.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug15613.d
@@ -1,10 +1,12 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/bug15613.d(16): Error: function `bug15613.f(int...)` is not callable using argument types `(typeof(null))`
-fail_compilation/bug15613.d(16):        cannot pass argument `null` of type `typeof(null)` to parameter `int...`
-fail_compilation/bug15613.d(17): Error: function `bug15613.g(Object, ...)` is not callable using argument types `(int)`
-fail_compilation/bug15613.d(17):        cannot pass argument `8` of type `int` to parameter `Object`
+fail_compilation/bug15613.d(18): Error: function `f` is not callable using argument types `(typeof(null))`
+fail_compilation/bug15613.d(18):        cannot pass argument `null` of type `typeof(null)` to parameter `int...`
+fail_compilation/bug15613.d(13):        `bug15613.f(int...)` declared here
+fail_compilation/bug15613.d(19): Error: function `g` is not callable using argument types `(int)`
+fail_compilation/bug15613.d(19):        cannot pass argument `8` of type `int` to parameter `Object`
+fail_compilation/bug15613.d(14):        `bug15613.g(Object, ...)` declared here
 ---
 */
 
@@ -20,8 +22,9 @@ void main()
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/bug15613.d(32): Error: function `bug15613.h(int[]...)` is not callable using argument types `(int, void function(int[]...))`
-fail_compilation/bug15613.d(32):        cannot pass argument `& h` of type `void function(int[]...)` to parameter `int[]...`
+fail_compilation/bug15613.d(35): Error: function `h` is not callable using argument types `(int, void function(int[]...))`
+fail_compilation/bug15613.d(35):        cannot pass argument `& h` of type `void function(int[]...)` to parameter `int[]...`
+fail_compilation/bug15613.d(31):        `bug15613.h(int[]...)` declared here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug16165.d b/gcc/testsuite/gdc.test/fail_compilation/bug16165.d
index ca9879733ce2cbc0d8bff20db8b96cfc38790617..608e347851580408b956d7c8cafd996a5ae6a8e3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/bug16165.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug16165.d
@@ -10,9 +10,11 @@ void g()
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/bug16165.d(6): Error: function `bug16165.f(int x, Object y)` is not callable using argument types `(Object, Object, int)`
+fail_compilation/bug16165.d(6): Error: function `f` is not callable using argument types `(Object, Object, int)`
 fail_compilation/bug16165.d(6):        cannot pass argument `o` of type `object.Object` to parameter `int x`
-fail_compilation/bug16165.d(7): Error: function `bug16165.f(int x, Object y)` is not callable using argument types `(int, int, int)`
+fail_compilation/bug16165.d(1):        `bug16165.f(int x, Object y)` declared here
+fail_compilation/bug16165.d(7): Error: function `f` is not callable using argument types `(int, int, int)`
 fail_compilation/bug16165.d(7):        cannot pass argument `6` of type `int` to parameter `Object y`
+fail_compilation/bug16165.d(1):        `bug16165.f(int x, Object y)` declared here
 ---
  */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug9631.d b/gcc/testsuite/gdc.test/fail_compilation/bug9631.d
index f0a9456035b94b7c3ef2985197afd802812676f6..13974aa0e9a6fa8986fb47ce51df8482b2f0b852 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/bug9631.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug9631.d
@@ -62,12 +62,13 @@ void test3()
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/bug9631.d(79): Error: function `bug9631.arg.f(int i, S s)` is not callable using argument types `(int, S)`
-fail_compilation/bug9631.d(79):        cannot pass argument `y` of type `bug9631.tem!().S` to parameter `bug9631.S s`
-fail_compilation/bug9631.d(80): Error: function literal `__lambda4(S s)` is not callable using argument types `(S)`
-fail_compilation/bug9631.d(80):        cannot pass argument `x` of type `bug9631.S` to parameter `bug9631.tem!().S s`
-fail_compilation/bug9631.d(86): Error: constructor `bug9631.arg.A.this(S __param_0)` is not callable using argument types `(S)`
-fail_compilation/bug9631.d(86):        cannot pass argument `S(0)` of type `bug9631.tem!().S` to parameter `bug9631.S __param_0`
+fail_compilation/bug9631.d(80): Error: function `f` is not callable using argument types `(int, S)`
+fail_compilation/bug9631.d(80):        cannot pass argument `y` of type `bug9631.tem!().S` to parameter `bug9631.S s`
+fail_compilation/bug9631.d(79):        `bug9631.arg.f(int i, S s)` declared here
+fail_compilation/bug9631.d(81): Error: function literal `__lambda4(S s)` is not callable using argument types `(S)`
+fail_compilation/bug9631.d(81):        cannot pass argument `x` of type `bug9631.S` to parameter `bug9631.tem!().S s`
+fail_compilation/bug9631.d(87): Error: constructor `bug9631.arg.A.this(S __param_0)` is not callable using argument types `(S)`
+fail_compilation/bug9631.d(87):        cannot pass argument `S(0)` of type `bug9631.tem!().S` to parameter `bug9631.S __param_0`
 ---
 */
 void arg()
@@ -89,12 +90,13 @@ void arg()
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/bug9631.d(106): Error: function `bug9631.targ.ft!().ft(S __param_0)` is not callable using argument types `(S)`
-fail_compilation/bug9631.d(106):        cannot pass argument `x` of type `bug9631.S` to parameter `bug9631.tem!().S __param_0`
-fail_compilation/bug9631.d(107): Error: template `bug9631.targ.ft` is not callable using argument types `!()(S)`
-fail_compilation/bug9631.d(105):        Candidate is: `ft()(tem!().S)`
-fail_compilation/bug9631.d(109): Error: template `bug9631.targ.ft2` is not callable using argument types `!()(S, int)`
-fail_compilation/bug9631.d(108):        Candidate is: `ft2(T)(S, T)`
+fail_compilation/bug9631.d(108): Error: function `ft` is not callable using argument types `(S)`
+fail_compilation/bug9631.d(108):        cannot pass argument `x` of type `bug9631.S` to parameter `bug9631.tem!().S __param_0`
+fail_compilation/bug9631.d(107):        `bug9631.targ.ft!().ft(S __param_0)` declared here
+fail_compilation/bug9631.d(109): Error: template `ft` is not callable using argument types `!()(S)`
+fail_compilation/bug9631.d(107):        Candidate is: `ft()(tem!().S)`
+fail_compilation/bug9631.d(111): Error: template `ft2` is not callable using argument types `!()(S, int)`
+fail_compilation/bug9631.d(110):        Candidate is: `ft2(T)(S, T)`
 ---
 */
 void targ()
diff --git a/gcc/testsuite/gdc.test/fail_compilation/callconst.d b/gcc/testsuite/gdc.test/fail_compilation/callconst.d
index 74c1902b2d452ea7666a8d1abbbd1bb8c1b56977..a3aee7c6b59f0c788ebd77bdf9420cdce4a6ff23 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/callconst.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/callconst.d
@@ -1,8 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/callconst.d(13): Error: function `callconst.func(ref X)` is not callable using argument types `(const(X))`
-fail_compilation/callconst.d(13):        cannot pass argument `x` of type `const(X)` to parameter `ref X`
+fail_compilation/callconst.d(14): Error: function `func` is not callable using argument types `(const(X))`
+fail_compilation/callconst.d(14):        cannot pass argument `x` of type `const(X)` to parameter `ref X`
+fail_compilation/callconst.d(17):        `callconst.func(ref X)` declared here
 ---
 */
 struct X {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/constraints_aggr.d b/gcc/testsuite/gdc.test/fail_compilation/constraints_aggr.d
index a3ad34a0ea3a5ee96a60f18c594f96fda9d700b6..4c31e9e729b9f2f4a75503fc64820445535894c8 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/constraints_aggr.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/constraints_aggr.d
@@ -2,12 +2,12 @@
 EXTRA_FILES: imports/constraints.d
 TEST_OUTPUT:
 ---
-fail_compilation/constraints_aggr.d(32): Error: template `imports.constraints.C.f` is not callable using argument types `!()(int)`
+fail_compilation/constraints_aggr.d(32): Error: template `f` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(60):        Candidate is: `f(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       !P!T`
-fail_compilation/constraints_aggr.d(33): Error: template `imports.constraints.C.g` is not callable using argument types `!()()`
+fail_compilation/constraints_aggr.d(33): Error: template `g` is not callable using argument types `!()()`
 fail_compilation/imports/constraints.d(63):        Candidate is: `g(this T)()`
   with `T = imports.constraints.C`
   must satisfy the following constraint:
diff --git a/gcc/testsuite/gdc.test/fail_compilation/constraints_func1.d b/gcc/testsuite/gdc.test/fail_compilation/constraints_func1.d
index fbb4aa94d5337fc6a28739ac1b7e65979a63ca7e..d15d2817df03199bfa2d6f9646cf54e36b5b05f5 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/constraints_func1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/constraints_func1.d
@@ -2,72 +2,72 @@
 EXTRA_FILES: imports/constraints.d
 TEST_OUTPUT:
 ---
-fail_compilation/constraints_func1.d(79): Error: template `imports.constraints.test1` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(79): Error: template `test1` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(9):        Candidate is: `test1(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func1.d(80): Error: template `imports.constraints.test2` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(80): Error: template `test2` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(10):        Candidate is: `test2(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       !P!T`
-fail_compilation/constraints_func1.d(81): Error: template `imports.constraints.test3` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(81): Error: template `test3` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(11):        Candidate is: `test3(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func1.d(82): Error: template `imports.constraints.test4` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(82): Error: template `test4` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(12):        Candidate is: `test4(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func1.d(83): Error: template `imports.constraints.test5` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(83): Error: template `test5` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(13):        Candidate is: `test5(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T`
-fail_compilation/constraints_func1.d(84): Error: template `imports.constraints.test6` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(84): Error: template `test6` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(14):        Candidate is: `test6(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T
        !P!T`
-fail_compilation/constraints_func1.d(85): Error: template `imports.constraints.test7` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(85): Error: template `test7` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(15):        Candidate is: `test7(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T`
-fail_compilation/constraints_func1.d(86): Error: template `imports.constraints.test8` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(86): Error: template `test8` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(16):        Candidate is: `test8(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func1.d(87): Error: template `imports.constraints.test9` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(87): Error: template `test9` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(17):        Candidate is: `test9(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       !P!T`
-fail_compilation/constraints_func1.d(88): Error: template `imports.constraints.test10` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(88): Error: template `test10` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(18):        Candidate is: `test10(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       !P!T`
-fail_compilation/constraints_func1.d(89): Error: template `imports.constraints.test11` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(89): Error: template `test11` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(19):        Candidate is: `test11(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        !P!T`
-fail_compilation/constraints_func1.d(90): Error: template `imports.constraints.test12` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func1.d(90): Error: template `test12` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(20):        Candidate is: `test12(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       !P!T`
-fail_compilation/constraints_func1.d(92): Error: template `imports.constraints.test1` is not callable using argument types `!()(int, int)`
+fail_compilation/constraints_func1.d(92): Error: template `test1` is not callable using argument types `!()(int, int)`
 fail_compilation/imports/constraints.d(9):        Candidate is: `test1(T)(T v)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/constraints_func2.d b/gcc/testsuite/gdc.test/fail_compilation/constraints_func2.d
index 4b8ebd5da2b72da4c1b9a6453900a1ea0f4c7d10..36fa55423d572b9391b79d2f2dd7eb23cffee77b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/constraints_func2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/constraints_func2.d
@@ -2,83 +2,83 @@
 EXTRA_FILES: imports/constraints.d
 TEST_OUTPUT:
 ---
-fail_compilation/constraints_func2.d(94): Error: template `imports.constraints.test13` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(94): Error: template `test13` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(23):        Candidate is: `test13(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        !P!T`
-fail_compilation/constraints_func2.d(95): Error: template `imports.constraints.test14` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(95): Error: template `test14` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(24):        Candidate is: `test14(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       !P!T
        N!T`
-fail_compilation/constraints_func2.d(96): Error: template `imports.constraints.test15` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(96): Error: template `test15` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(25):        Candidate is: `test15(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       !P!T
        !P!T`
-fail_compilation/constraints_func2.d(97): Error: template `imports.constraints.test16` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(97): Error: template `test16` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(26):        Candidate is: `test16(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T`
-fail_compilation/constraints_func2.d(98): Error: template `imports.constraints.test17` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(98): Error: template `test17` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(27):        Candidate is: `test17(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func2.d(99): Error: template `imports.constraints.test18` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(99): Error: template `test18` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(28):        Candidate is: `test18(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T`
-fail_compilation/constraints_func2.d(100): Error: template `imports.constraints.test19` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(100): Error: template `test19` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(29):        Candidate is: `test19(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        !P!T
        N!T`
-fail_compilation/constraints_func2.d(101): Error: template `imports.constraints.test20` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(101): Error: template `test20` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(30):        Candidate is: `test20(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func2.d(102): Error: template `imports.constraints.test21` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(102): Error: template `test21` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(31):        Candidate is: `test21(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       N!T
        N!T`
-fail_compilation/constraints_func2.d(103): Error: template `imports.constraints.test22` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(103): Error: template `test22` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(32):        Candidate is: `test22(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       !P!T
        !P!T`
-fail_compilation/constraints_func2.d(104): Error: template `imports.constraints.test23` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(104): Error: template `test23` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(33):        Candidate is: `test23(T)(T v)`
   with `T = int`
   must satisfy one of the following constraints:
 `       !P!T
        N!T
        !P!T`
-fail_compilation/constraints_func2.d(105): Error: template `imports.constraints.test24` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(105): Error: template `test24` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(34):        Candidate is: `test24(R)(R r)`
   with `R = int`
   must satisfy the following constraint:
 `       __traits(hasMember, R, "stuff")`
-fail_compilation/constraints_func2.d(106): Error: template `imports.constraints.test25` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func2.d(106): Error: template `test25` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(35):        Candidate is: `test25(T)(T v)`
   with `T = int`
   must satisfy the following constraint:
 `       N!T`
-fail_compilation/constraints_func2.d(107): Error: template `imports.constraints.test26` is not callable using argument types `!(float)(int)`
+fail_compilation/constraints_func2.d(107): Error: template `test26` is not callable using argument types `!(float)(int)`
 fail_compilation/imports/constraints.d(36):        Candidate is: `test26(T, U)(U u)`
   with `T = float,
        U = int`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/constraints_func3.d b/gcc/testsuite/gdc.test/fail_compilation/constraints_func3.d
index d16bdf0959c65645004ce97beadfbfef7adf9f10..b4bc3fe0279451423f8dfe2a1bcb666f6f0c5574 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/constraints_func3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/constraints_func3.d
@@ -1,7 +1,7 @@
 /*
 EXTRA_FILES: imports/constraints.d
 TEST_OUTPUT:
----
+----
 fail_compilation/constraints_func3.d(53): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(39):        Candidates are: `overload(T)(T v)`
   with `T = int`
@@ -23,27 +23,27 @@ fail_compilation/imports/constraints.d(42):                        `overload(T,
   must satisfy one of the following constraints:
 `       N!T
        N!V`
-fail_compilation/constraints_func3.d(56): Error: template `imports.constraints.variadic` is not callable using argument types `!()()`
+fail_compilation/constraints_func3.d(56): Error: template `variadic` is not callable using argument types `!()()`
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
-fail_compilation/constraints_func3.d(57): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func3.d(57): Error: template `variadic` is not callable using argument types `!()(int)`
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
   with `A = int,
        T = ()`
   must satisfy the following constraint:
 `       N!int`
-fail_compilation/constraints_func3.d(58): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int, int)`
+fail_compilation/constraints_func3.d(58): Error: template `variadic` is not callable using argument types `!()(int, int)`
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
   with `A = int,
        T = (int)`
   must satisfy the following constraint:
 `       N!int`
-fail_compilation/constraints_func3.d(59): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int, int, int)`
+fail_compilation/constraints_func3.d(59): Error: template `variadic` is not callable using argument types `!()(int, int, int)`
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
   with `A = int,
        T = (int, int)`
   must satisfy the following constraint:
 `       N!int`
----
+----
 */
 
 void main()
diff --git a/gcc/testsuite/gdc.test/fail_compilation/constraints_func4.d b/gcc/testsuite/gdc.test/fail_compilation/constraints_func4.d
index c4dea0ec4510c22ac1c4c9bb977974090cc16752..536a3d46a5abdb4c3f9d950cebc356f63826a578 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/constraints_func4.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/constraints_func4.d
@@ -2,7 +2,7 @@
 EXTRA_FILES: imports/constraints.d
 REQUIRED_ARGS: -verrors=context
 TEST_OUTPUT:
----
+----
 fail_compilation/constraints_func4.d(90): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int)`
     overload(0);
             ^
@@ -44,13 +44,13 @@ fail_compilation/imports/constraints.d(42):                        `overload(T,
        N!V`
 void overload(T, V)(T v1, V v2) if (N!T || N!V);
      ^
-fail_compilation/constraints_func4.d(93): Error: template `imports.constraints.variadic` is not callable using argument types `!()()`
+fail_compilation/constraints_func4.d(93): Error: template `variadic` is not callable using argument types `!()()`
     variadic();
             ^
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
 void variadic(A, T...)(A a, T v) if (N!int);
      ^
-fail_compilation/constraints_func4.d(94): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int)`
+fail_compilation/constraints_func4.d(94): Error: template `variadic` is not callable using argument types `!()(int)`
     variadic(0);
             ^
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
@@ -60,7 +60,7 @@ fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T.
 `       N!int`
 void variadic(A, T...)(A a, T v) if (N!int);
      ^
-fail_compilation/constraints_func4.d(95): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int, int)`
+fail_compilation/constraints_func4.d(95): Error: template `variadic` is not callable using argument types `!()(int, int)`
     variadic(0, 1);
             ^
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
@@ -70,7 +70,7 @@ fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T.
 `       N!int`
 void variadic(A, T...)(A a, T v) if (N!int);
      ^
-fail_compilation/constraints_func4.d(96): Error: template `imports.constraints.variadic` is not callable using argument types `!()(int, int, int)`
+fail_compilation/constraints_func4.d(96): Error: template `variadic` is not callable using argument types `!()(int, int, int)`
     variadic(0, 1, 2);
             ^
 fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T...)(A a, T v)`
@@ -80,7 +80,7 @@ fail_compilation/imports/constraints.d(43):        Candidate is: `variadic(A, T.
 `       N!int`
 void variadic(A, T...)(A a, T v) if (N!int);
      ^
----
+----
 */
 
 void main()
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13942.d b/gcc/testsuite/gdc.test/fail_compilation/diag13942.d
index 25e0515a5bcf8a219e936a8bb789b38053092170..9248e094c15bd67b12e3eacefe6f54847bf41914 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag13942.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag13942.d
@@ -2,7 +2,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/diag13942.d(18): Error: template instance `isRawStaticArray!()` does not match template declaration `isRawStaticArray(T, A...)`
-fail_compilation/diag13942.d(26): Error: template `diag13942.to!double.to` is not callable using argument types `!()()`
+fail_compilation/diag13942.d(26): Error: template `to` is not callable using argument types `!()()`
 fail_compilation/diag13942.d(17):        Candidate is: `to(A...)(A args)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag16977.d b/gcc/testsuite/gdc.test/fail_compilation/diag16977.d
index fc8f66032e21ed29969bbe72370bef8035e2ba4e..7e2efd2bfa222904d64174df78592f949ae66dd8 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag16977.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag16977.d
@@ -3,7 +3,7 @@ TEST_OUTPUT:
 ---
 fail_compilation/diag16977.d(25): Error: undefined identifier `undefined`, did you mean function `undefinedId`?
 fail_compilation/diag16977.d(26): Error: cannot implicitly convert expression `"\x01string"` of type `string` to `int`
-fail_compilation/diag16977.d(27): Error: template `diag16977.templ` is not callable using argument types `!()(int)`
+fail_compilation/diag16977.d(27): Error: template `templ` is not callable using argument types `!()(int)`
 fail_compilation/diag16977.d(20):        Candidate is: `templ(S)(S s)`
   with `S = int`
   must satisfy the following constraint:
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag20268.d b/gcc/testsuite/gdc.test/fail_compilation/diag20268.d
index 053626a603c9738d6b83c9977c766c43f51cce91..0653490267005f5440a8fe1db36406409007055c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag20268.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag20268.d
@@ -3,7 +3,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag20268.d(12): Error: template `diag20268.__lambda4` is not callable using argument types `!()(int)`
+fail_compilation/diag20268.d(12): Error: template `__lambda4` is not callable using argument types `!()(int)`
 fail_compilation/diag20268.d(11):        Candidate is: `__lambda4(__T1, __T2)(x, y)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag23355.d b/gcc/testsuite/gdc.test/fail_compilation/diag23355.d
index a530eb60ef0866bd7aa1f4e127fce5e10444e15f..c21226fa85ef79fd0bf6eeadc72e87da0a933604 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag23355.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag23355.d
@@ -2,10 +2,10 @@
 TEST_OUTPUT:
 ---
 fail_compilation/diag23355.d(1): Error: undefined identifier `n`
-fail_compilation/diag23355.d(4): Error: template `diag23355.ffi1` is not callable using argument types `!()(int[4])`
+fail_compilation/diag23355.d(4): Error: template `ffi1` is not callable using argument types `!()(int[4])`
 fail_compilation/diag23355.d(1):        Candidate is: `ffi1(T)(T[n] s)`
 fail_compilation/diag23355.d(2): Error: undefined identifier `n`
-fail_compilation/diag23355.d(4): Error: template `diag23355.ffi2` is not callable using argument types `!()(int[4])`
+fail_compilation/diag23355.d(4): Error: template `ffi2` is not callable using argument types `!()(int[4])`
 fail_compilation/diag23355.d(2):        Candidate is: `ffi2()(T[n] s)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8101.d b/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
index 4c8dfe881abff61087a5cd9b353ec8028fb2d4db..0d196205640d55d6a818a7d4a94438b97d5fb62d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8101.d
@@ -1,32 +1,33 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag8101.d(61): Error: function `diag8101.f_0(int)` is not callable using argument types `()`
-fail_compilation/diag8101.d(61):        too few arguments, expected 1, got 0
-fail_compilation/diag8101.d(62): Error: none of the overloads of `f_1` are callable using argument types `()`
-fail_compilation/diag8101.d(35):        Candidates are: `diag8101.f_1(int)`
-fail_compilation/diag8101.d(36):                        `diag8101.f_1(int, int)`
-fail_compilation/diag8101.d(63): Error: none of the overloads of `f_2` are callable using argument types `()`
-fail_compilation/diag8101.d(38):        Candidates are: `diag8101.f_2(int)`
-fail_compilation/diag8101.d(39):                        `diag8101.f_2(int, int)`
-fail_compilation/diag8101.d(40):                        `diag8101.f_2(int, int, int)`
-fail_compilation/diag8101.d(41):                        `diag8101.f_2(int, int, int, int)`
-fail_compilation/diag8101.d(42):                        `diag8101.f_2(int, int, int, int, int)`
-fail_compilation/diag8101.d(43):                        `diag8101.f_2(int, int, int, int, int, int)`
-fail_compilation/diag8101.d(63):        ... (1 more, -v to show) ...
-fail_compilation/diag8101.d(65): Error: template `diag8101.t_0` is not callable using argument types `!()()`
-fail_compilation/diag8101.d(46):        Candidate is: `t_0(T1)()`
-fail_compilation/diag8101.d(66): Error: none of the overloads of template `diag8101.t_1` are callable using argument types `!()()`
-fail_compilation/diag8101.d(48):        Candidates are: `t_1(T1)()`
-fail_compilation/diag8101.d(49):                        `t_1(T1, T2)()`
-fail_compilation/diag8101.d(67): Error: none of the overloads of template `diag8101.t_2` are callable using argument types `!()()`
-fail_compilation/diag8101.d(51):        Candidates are: `t_2(T1)()`
-fail_compilation/diag8101.d(52):                        `t_2(T1, T2)()`
-fail_compilation/diag8101.d(53):                        `t_2(T1, T2, T3)()`
-fail_compilation/diag8101.d(54):                        `t_2(T1, T2, T3, T4)()`
-fail_compilation/diag8101.d(55):                        `t_2(T1, T2, T3, T4, T5)()`
-fail_compilation/diag8101.d(56):                        `t_2(T1, T2, T3, T4, T5, T6)()`
-fail_compilation/diag8101.d(67):        ... (1 more, -v to show) ...
+fail_compilation/diag8101.d(62): Error: function `f_0` is not callable using argument types `()`
+fail_compilation/diag8101.d(62):        too few arguments, expected 1, got 0
+fail_compilation/diag8101.d(34):        `diag8101.f_0(int)` declared here
+fail_compilation/diag8101.d(63): Error: none of the overloads of `f_1` are callable using argument types `()`
+fail_compilation/diag8101.d(36):        Candidates are: `diag8101.f_1(int)`
+fail_compilation/diag8101.d(37):                        `diag8101.f_1(int, int)`
+fail_compilation/diag8101.d(64): Error: none of the overloads of `f_2` are callable using argument types `()`
+fail_compilation/diag8101.d(39):        Candidates are: `diag8101.f_2(int)`
+fail_compilation/diag8101.d(40):                        `diag8101.f_2(int, int)`
+fail_compilation/diag8101.d(41):                        `diag8101.f_2(int, int, int)`
+fail_compilation/diag8101.d(42):                        `diag8101.f_2(int, int, int, int)`
+fail_compilation/diag8101.d(43):                        `diag8101.f_2(int, int, int, int, int)`
+fail_compilation/diag8101.d(44):                        `diag8101.f_2(int, int, int, int, int, int)`
+fail_compilation/diag8101.d(64):        ... (1 more, -v to show) ...
+fail_compilation/diag8101.d(66): Error: template `t_0` is not callable using argument types `!()()`
+fail_compilation/diag8101.d(47):        Candidate is: `t_0(T1)()`
+fail_compilation/diag8101.d(67): Error: none of the overloads of template `diag8101.t_1` are callable using argument types `!()()`
+fail_compilation/diag8101.d(49):        Candidates are: `t_1(T1)()`
+fail_compilation/diag8101.d(50):                        `t_1(T1, T2)()`
+fail_compilation/diag8101.d(68): Error: none of the overloads of template `diag8101.t_2` are callable using argument types `!()()`
+fail_compilation/diag8101.d(52):        Candidates are: `t_2(T1)()`
+fail_compilation/diag8101.d(53):                        `t_2(T1, T2)()`
+fail_compilation/diag8101.d(54):                        `t_2(T1, T2, T3)()`
+fail_compilation/diag8101.d(55):                        `t_2(T1, T2, T3, T4)()`
+fail_compilation/diag8101.d(56):                        `t_2(T1, T2, T3, T4, T5)()`
+fail_compilation/diag8101.d(57):                        `t_2(T1, T2, T3, T4, T5, T6)()`
+fail_compilation/diag8101.d(68):        ... (1 more, -v to show) ...
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8648.d b/gcc/testsuite/gdc.test/fail_compilation/diag8648.d
index e48f569b74d4eee4c0db791554a28876d771c920..8066d6e8bbe51ff80229e7199659de9dc934b5c6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8648.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8648.d
@@ -2,13 +2,13 @@
 TEST_OUTPUT:
 ---
 fail_compilation/diag8648.d(18): Error: undefined identifier `X`
-fail_compilation/diag8648.d(29): Error: template `diag8648.foo` is not callable using argument types `!()(Foo!(int, 1))`
+fail_compilation/diag8648.d(29): Error: template `foo` is not callable using argument types `!()(Foo!(int, 1))`
 fail_compilation/diag8648.d(18):        Candidate is: `foo(T, n)(X!(T, n))`
 fail_compilation/diag8648.d(20): Error: undefined identifier `a`
-fail_compilation/diag8648.d(31): Error: template `diag8648.bar` is not callable using argument types `!()(Foo!(int, 1))`
+fail_compilation/diag8648.d(31): Error: template `bar` is not callable using argument types `!()(Foo!(int, 1))`
 fail_compilation/diag8648.d(20):        Candidate is: `bar(T)(Foo!(T, a))`
 fail_compilation/diag8648.d(20): Error: undefined identifier `a`
-fail_compilation/diag8648.d(32): Error: template `diag8648.bar` is not callable using argument types `!()(Foo!(int, f))`
+fail_compilation/diag8648.d(32): Error: template `bar` is not callable using argument types `!()(Foo!(int, f))`
 fail_compilation/diag8648.d(20):        Candidate is: `bar(T)(Foo!(T, a))`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag9004.d b/gcc/testsuite/gdc.test/fail_compilation/diag9004.d
index 30589bf0cacc9aec84304a9eac94f0694aa90f31..4c63bb26d7367c0ad4af2ff46eeb8d91f34d8978 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag9004.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag9004.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag9004.d(21): Error: template `diag9004.bar` is not callable using argument types `!()(Foo!int, int)`
+fail_compilation/diag9004.d(21): Error: template `bar` is not callable using argument types `!()(Foo!int, int)`
 fail_compilation/diag9004.d(14):        Candidate is: `bar(FooT)(FooT foo, FooT.T x)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diagin.d b/gcc/testsuite/gdc.test/fail_compilation/diagin.d
index 5b8e33162cd818622cc4c7a8e38eab66b8d637c3..6e8a472cee688dfd698052549c6f54015aad1708 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diagin.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diagin.d
@@ -2,10 +2,11 @@
 REQUIRED_ARGS: -preview=in
 TEST_OUTPUT:
 ---
-fail_compilation/diagin.d(14): Error: function `diagin.foo(in int)` is not callable using argument types `()`
-fail_compilation/diagin.d(14):        too few arguments, expected 1, got 0
-fail_compilation/diagin.d(16): Error: template `diagin.foo1` is not callable using argument types `!()(bool[])`
-fail_compilation/diagin.d(20):        Candidate is: `foo1(T)(in T v, string)`
+fail_compilation/diagin.d(15): Error: function `foo` is not callable using argument types `()`
+fail_compilation/diagin.d(15):        too few arguments, expected 1, got 0
+fail_compilation/diagin.d(20):        `diagin.foo(in int)` declared here
+fail_compilation/diagin.d(17): Error: template `foo1` is not callable using argument types `!()(bool[])`
+fail_compilation/diagin.d(21):        Candidate is: `foo1(T)(in T v, string)`
 ---
  */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail12744.d b/gcc/testsuite/gdc.test/fail_compilation/fail12744.d
index 711e57fad30dab6fccb2403e62030199dab10dc0..3b1ab723b9ed762d99ed550fd229dbcd11c38bce 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail12744.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail12744.d
@@ -14,10 +14,10 @@ fail_compilation/fail12744.d(61): Error: template instance `fail12744.bar12744L!
 fail_compilation/fail12744.d(40): Error: incompatible parameter storage classes `lazy` and `out`
 fail_compilation/fail12744.d(62): Error: template instance `fail12744.bar12744L!(foo12744O)` error instantiating
 fail_compilation/fail12744.d(41): Error: incompatible parameter storage classes `auto ref` and `out`
-fail_compilation/fail12744.d(67): Error: template `fail12744.bar12744A` is not callable using argument types `!(foo12744O)(int)`
+fail_compilation/fail12744.d(67): Error: template `bar12744A` is not callable using argument types `!(foo12744O)(int)`
 fail_compilation/fail12744.d(41):        Candidate is: `bar12744A(alias f)(auto ref PTT12744!f args)`
 fail_compilation/fail12744.d(41): Error: incompatible parameter storage classes `auto ref` and `lazy`
-fail_compilation/fail12744.d(68): Error: template `fail12744.bar12744A` is not callable using argument types `!(foo12744L)(int)`
+fail_compilation/fail12744.d(68): Error: template `bar12744A` is not callable using argument types `!(foo12744L)(int)`
 fail_compilation/fail12744.d(41):        Candidate is: `bar12744A(alias f)(auto ref PTT12744!f args)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail136.d b/gcc/testsuite/gdc.test/fail_compilation/fail136.d
index 3bc86537ed6d9cc3e671276c732a914684489202..3fa42e6cc841397c7f2dbc1671972be655072b21 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail136.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail136.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation\fail136.d(10): Error: `"\xef\xbb\xbf"` has no effect
+fail_compilation/fail136.d(10): Error: `x"EFBBBF"` has no effect
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail14669.d b/gcc/testsuite/gdc.test/fail_compilation/fail14669.d
index 45fe146355164070cf2e305b0257b4153a0dbfa4..2c2661f8ef5a75bdf5a2cbc64ca199c404078274 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail14669.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail14669.d
@@ -4,7 +4,7 @@ TEST_OUTPUT:
 fail_compilation/fail14669.d(11): Error: `auto` can only be used as part of `auto ref` for template function parameters
 fail_compilation/fail14669.d(16): Error: template instance `fail14669.foo1!()` error instantiating
 fail_compilation/fail14669.d(12): Error: `auto` can only be used as part of `auto ref` for template function parameters
-fail_compilation/fail14669.d(17): Error: template `fail14669.foo2` is not callable using argument types `!()(int)`
+fail_compilation/fail14669.d(17): Error: template `foo2` is not callable using argument types `!()(int)`
 fail_compilation/fail14669.d(12):        Candidate is: `foo2()(auto int a)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail162.d b/gcc/testsuite/gdc.test/fail_compilation/fail162.d
index c79f8d8d548aff9cb4fe1b249c7ddb0f07b62b81..600e2c9d69c9500ab5f7d573dc6ffe8ba2c95d99 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail162.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail162.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail162.d(25): Error: template `fail162.testHelper` is not callable using argument types `!()(string, string)`
+fail_compilation/fail162.d(25): Error: template `testHelper` is not callable using argument types `!()(string, string)`
 fail_compilation/fail162.d(10):        Candidate is: `testHelper(A...)()`
 fail_compilation/fail162.d(30): Error: template instance `fail162.test!("hello", "world")` error instantiating
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19948.d b/gcc/testsuite/gdc.test/fail_compilation/fail19948.d
index ae67443fea437c401aedfa280c583a18e07e4759..9c23b78df926ecc59d5d0a9eca5ea52da2c3b125 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19948.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19948.d
@@ -3,8 +3,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail19948.d(15): Error: function `fail19948.func(const(X))` is not callable using argument types `(X)`
-fail_compilation/fail19948.d(15):        cannot pass argument `X()` of type `fail19948.main.X` to parameter `const(fail19948.X)`
+fail_compilation/fail19948.d(16): Error: function `func` is not callable using argument types `(X)`
+fail_compilation/fail19948.d(16):        cannot pass argument `X()` of type `fail19948.main.X` to parameter `const(fail19948.X)`
+fail_compilation/fail19948.d(19):        `fail19948.func(const(X))` declared here
 ---
 */
 // DISABLED: win32
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20183.d b/gcc/testsuite/gdc.test/fail_compilation/fail20183.d
index 8a08844f8432372379c22628fb19f42b6b69cbd1..f04db02493263e03085450ba66730c409afc5b32 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail20183.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail20183.d
@@ -1,8 +1,9 @@
 /* REQUIRED_ARGS: -preview=dip1000
 TEST_OUTPUT:
 ---
-fail_compilation/fail20183.d(1016): Error: function `fail20183.addr(return ref int b)` is not callable using argument types `(int)`
+fail_compilation/fail20183.d(1016): Error: function `addr` is not callable using argument types `(int)`
 fail_compilation/fail20183.d(1016):        cannot pass rvalue argument `S(0).i` of type `int` to parameter `return ref int b`
+fail_compilation/fail20183.d(1005):        `fail20183.addr(return ref int b)` declared here
 fail_compilation/fail20183.d(1017): Error: address of struct temporary returned by `s()` assigned to longer lived variable `q`
 ---
  */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20730b.d b/gcc/testsuite/gdc.test/fail_compilation/fail20730b.d
index d36bb0b6e89536e7a0cb8e7c43f24c38f7f7fb5e..7269f42514a33cdaba81126cfc406942e236e904 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail20730b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail20730b.d
@@ -3,7 +3,7 @@ REQUIRED_ARGS: -verrors=spec -o-
 TEST_OUTPUT:
 ---
 (spec:1) fail_compilation/fail20730b.d-mixin-43(43): Error: C style cast illegal, use `cast(int)mod`
-fail_compilation/fail20730b.d(26): Error: template `fail20730b.atomicOp` is not callable using argument types `!("+=")(shared(uint), int)`
+fail_compilation/fail20730b.d(26): Error: template `atomicOp` is not callable using argument types `!("+=")(shared(uint), int)`
 fail_compilation/fail20730b.d(41):        Candidate is: `atomicOp(string op, T, V1)(shared ref T val, V1 mod)`
   with `op = "+=",
        T = uint,
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20800.d b/gcc/testsuite/gdc.test/fail_compilation/fail20800.d
index 026b7c2df0a3c805555ba6387d958b92af5cbaa1..4464222f237119b00d19c92f48422d80d2c1f357 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail20800.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail20800.d
@@ -2,10 +2,11 @@
 
 /*
 TEST_OUTPUT:
----
-fail_compilation/fail20800.d(22): Error: function `fail20800.fun(int a)` is not callable using argument types `(string)`
-fail_compilation/fail20800.d(22):        cannot pass argument `(m()).index()` of type `string` to parameter `int a`
----
+----
+fail_compilation/fail20800.d(23): Error: function `fun` is not callable using argument types `(string)`
+fail_compilation/fail20800.d(23):        cannot pass argument `(m()).index()` of type `string` to parameter `int a`
+fail_compilation/fail20800.d(19):        `fail20800.fun(int a)` declared here
+----
 */
 
 struct RegexMatch
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22202.d b/gcc/testsuite/gdc.test/fail_compilation/fail22202.d
index d865fd95553af8786aa1872432e3f5901de0c5bb..9fb5165a711f111d8bb4b15455a4486a5d42aef7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail22202.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22202.d
@@ -3,8 +3,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail22202.d(21): Error: function `fail22202.fun(SystemCopy __param_0)` is not callable using argument types `(SystemCopy)`
-fail_compilation/fail22202.d(21):        `inout ref inout(SystemCopy)(ref inout(SystemCopy) other)` copy constructor cannot be called from a `pure @safe nogc` context
+fail_compilation/fail22202.d(22): Error: function `fun` is not callable using argument types `(SystemCopy)`
+fail_compilation/fail22202.d(22):        `inout ref inout(SystemCopy)(ref inout(SystemCopy) other)` copy constructor cannot be called from a `pure @safe nogc` context
+fail_compilation/fail22202.d(17):        `fail22202.fun(SystemCopy __param_0)` declared here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail236.d b/gcc/testsuite/gdc.test/fail_compilation/fail236.d
index accc0e17dd2b051e6de9f809f645df835d70d878..96f0ae655187f18505e96689de200e6bed822d25 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail236.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail236.d
@@ -2,7 +2,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/fail236.d(14): Error: undefined identifier `x`
-fail_compilation/fail236.d(22): Error: template `fail236.Templ2` is not callable using argument types `!()(int)`
+fail_compilation/fail236.d(22): Error: template `Templ2` is not callable using argument types `!()(int)`
 fail_compilation/fail236.d(12):        Candidate is: `Templ2(alias a)(x)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail24301.d b/gcc/testsuite/gdc.test/fail_compilation/fail24301.d
index be09c883e1c64e6433e02448eeac80b9361d28da..6ddece6c341bb21a1a5889c901a62c06e9210934 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail24301.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail24301.d
@@ -1,8 +1,9 @@
 /+
 TEST_OUTPUT:
 ---
-fail_compilation/fail24301.d(18): Error: function `fail24301.fun(S __param_0)` is not callable using argument types `(S)`
-fail_compilation/fail24301.d(18):        `ref S(ref S)` copy constructor cannot be used because it is annotated with `@disable`
+fail_compilation/fail24301.d(19): Error: function `fun` is not callable using argument types `(S)`
+fail_compilation/fail24301.d(19):        `ref S(ref S)` copy constructor cannot be used because it is annotated with `@disable`
+fail_compilation/fail24301.d(14):        `fail24301.fun(S __param_0)` declared here
 ---
 +/
 struct S
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail263.d b/gcc/testsuite/gdc.test/fail_compilation/fail263.d
index 0fa2f86a14a51e7236ae55750e11a4b05314de5f..e57fc50a1a384171a8a943b5e18099cffa279885 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail263.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail263.d
@@ -1,9 +1,10 @@
 /*
 TEST_OUTPUT:
----
-fail_compilation/fail263.d(19): Error: function `fail263.f(byte* p)` is not callable using argument types `(const(byte)*)`
-fail_compilation/fail263.d(19):        cannot pass argument `cast(const(byte)*)A` of type `const(byte)*` to parameter `byte* p`
----
+----
+fail_compilation/fail263.d(20): Error: function `f` is not callable using argument types `(const(byte)*)`
+fail_compilation/fail263.d(20):        cannot pass argument `cast(const(byte)*)A` of type `const(byte)*` to parameter `byte* p`
+fail_compilation/fail263.d(14):        `fail263.f(byte* p)` declared here
+----
 */
 
 // https://issues.dlang.org/show_bug.cgi?id=2766
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail322.d b/gcc/testsuite/gdc.test/fail_compilation/fail322.d
index 491111fe610200c021aeb0a81f75141e11702d05..faaab68a6ee720a57ba810abaa0ba76aeb2aac77 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail322.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail322.d
@@ -1,11 +1,13 @@
 /*
 TEST_OUTPUT:
----
-fail_compilation/fail322.d(13): Error: function `fail322.digestToString2(ref char[16] digest)` is not callable using argument types `(string)`
-fail_compilation/fail322.d(13):        cannot pass rvalue argument `"1234567890123456"` of type `string` to parameter `ref char[16] digest`
-fail_compilation/fail322.d(15): Error: function `fail322.digestToString2(ref char[16] digest)` is not callable using argument types `(const(char[16]))`
-fail_compilation/fail322.d(15):        cannot pass argument `s` of type `const(char[16])` to parameter `ref char[16] digest`
----
+----
+fail_compilation/fail322.d(15): Error: function `digestToString2` is not callable using argument types `(string)`
+fail_compilation/fail322.d(15):        cannot pass rvalue argument `"1234567890123456"` of type `string` to parameter `ref char[16] digest`
+fail_compilation/fail322.d(20):        `fail322.digestToString2(ref char[16] digest)` declared here
+fail_compilation/fail322.d(17): Error: function `digestToString2` is not callable using argument types `(const(char[16]))`
+fail_compilation/fail322.d(17):        cannot pass argument `s` of type `const(char[16])` to parameter `ref char[16] digest`
+fail_compilation/fail322.d(20):        `fail322.digestToString2(ref char[16] digest)` declared here
+----
 */
 
 void main()
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail332.d b/gcc/testsuite/gdc.test/fail_compilation/fail332.d
index 77e8cd8eb00e722366c03bfc006e5fd78d7c1b00..de20333481f36b3b4fcf200222fe14e910d1bd0f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail332.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail332.d
@@ -1,14 +1,18 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail332.d(22): Error: function `fail332.foo(int __param_0, ...)` is not callable using argument types `()`
-fail_compilation/fail332.d(22):        missing argument for parameter #1: `int __param_0`
-fail_compilation/fail332.d(23): Error: function `fail332.foo(int __param_0, ...)` is not callable using argument types `(typeof(null))`
-fail_compilation/fail332.d(23):        cannot pass argument `null` of type `typeof(null)` to parameter `int __param_0`
-fail_compilation/fail332.d(25): Error: function `fail332.baz(int[] __param_0...)` is not callable using argument types `(string)`
-fail_compilation/fail332.d(25):        cannot pass argument `""` of type `string` to parameter `int[] __param_0...`
-fail_compilation/fail332.d(26): Error: function `fail332.baz(int[] __param_0...)` is not callable using argument types `(int, typeof(null))`
-fail_compilation/fail332.d(26):        cannot pass argument `null` of type `typeof(null)` to parameter `int[] __param_0...`
+fail_compilation/fail332.d(26): Error: function `foo` is not callable using argument types `()`
+fail_compilation/fail332.d(26):        missing argument for parameter #1: `int __param_0`
+fail_compilation/fail332.d(21):        `fail332.foo(int __param_0, ...)` declared here
+fail_compilation/fail332.d(27): Error: function `foo` is not callable using argument types `(typeof(null))`
+fail_compilation/fail332.d(27):        cannot pass argument `null` of type `typeof(null)` to parameter `int __param_0`
+fail_compilation/fail332.d(21):        `fail332.foo(int __param_0, ...)` declared here
+fail_compilation/fail332.d(29): Error: function `baz` is not callable using argument types `(string)`
+fail_compilation/fail332.d(29):        cannot pass argument `""` of type `string` to parameter `int[] __param_0...`
+fail_compilation/fail332.d(22):        `fail332.baz(int[] __param_0...)` declared here
+fail_compilation/fail332.d(30): Error: function `baz` is not callable using argument types `(int, typeof(null))`
+fail_compilation/fail332.d(30):        cannot pass argument `null` of type `typeof(null)` to parameter `int[] __param_0...`
+fail_compilation/fail332.d(22):        `fail332.baz(int[] __param_0...)` declared here
 ---
 */
 
@@ -29,18 +33,24 @@ void test()
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail332.d(50): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `()`
-fail_compilation/fail332.d(50):        missing argument for parameter #1: `Object`
-fail_compilation/fail332.d(51): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(int)`
-fail_compilation/fail332.d(51):        cannot pass argument `4` of type `int` to parameter `Object`
-fail_compilation/fail332.d(52): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null))`
-fail_compilation/fail332.d(52):        expected 2 variadic argument(s), not 0
-fail_compilation/fail332.d(53): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int)`
-fail_compilation/fail332.d(53):        expected 2 variadic argument(s), not 1
-fail_compilation/fail332.d(54): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int, string)`
-fail_compilation/fail332.d(54):        cannot pass argument `""` of type `string` to parameter `int[2]...`
-fail_compilation/fail332.d(55): Error: function `fail332.bar(Object, int[2]...)` is not callable using argument types `(typeof(null), int, int, int)`
-fail_compilation/fail332.d(55):        expected 2 variadic argument(s), not 3
+fail_compilation/fail332.d(60): Error: function `bar` is not callable using argument types `()`
+fail_compilation/fail332.d(60):        missing argument for parameter #1: `Object`
+fail_compilation/fail332.d(56):        `fail332.bar(Object, int[2]...)` declared here
+fail_compilation/fail332.d(61): Error: function `bar` is not callable using argument types `(int)`
+fail_compilation/fail332.d(61):        cannot pass argument `4` of type `int` to parameter `Object`
+fail_compilation/fail332.d(56):        `fail332.bar(Object, int[2]...)` declared here
+fail_compilation/fail332.d(62): Error: function `bar` is not callable using argument types `(typeof(null))`
+fail_compilation/fail332.d(62):        expected 2 variadic argument(s), not 0
+fail_compilation/fail332.d(56):        `fail332.bar(Object, int[2]...)` declared here
+fail_compilation/fail332.d(63): Error: function `bar` is not callable using argument types `(typeof(null), int)`
+fail_compilation/fail332.d(63):        expected 2 variadic argument(s), not 1
+fail_compilation/fail332.d(56):        `fail332.bar(Object, int[2]...)` declared here
+fail_compilation/fail332.d(64): Error: function `bar` is not callable using argument types `(typeof(null), int, string)`
+fail_compilation/fail332.d(64):        cannot pass argument `""` of type `string` to parameter `int[2]...`
+fail_compilation/fail332.d(56):        `fail332.bar(Object, int[2]...)` declared here
+fail_compilation/fail332.d(65): Error: function `bar` is not callable using argument types `(typeof(null), int, int, int)`
+fail_compilation/fail332.d(65):        expected 2 variadic argument(s), not 3
+fail_compilation/fail332.d(56):        `fail332.bar(Object, int[2]...)` declared here
 ---
 */
 void bar(Object, int[2]...);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail58.d b/gcc/testsuite/gdc.test/fail_compilation/fail58.d
index 89b2351acfe00be4227fcf8644ee7c12b74a2a6f..ae70da259b69019726d29b1102b705fb46f04e25 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail58.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail58.d
@@ -1,11 +1,13 @@
 /*
 TEST_OUTPUT:
----
-fail_compilation/fail58.d(26): Error: function `fail58.SomeFunc(dchar[] pText, out int pStopPosn)` is not callable using argument types `(string, int)`
-fail_compilation/fail58.d(26):        cannot pass argument `"123"` of type `string` to parameter `dchar[] pText`
-fail_compilation/fail58.d(30): Error: function `fail58.SomeFunc(dchar[] pText, out int pStopPosn)` is not callable using argument types `(string, int)`
-fail_compilation/fail58.d(30):        cannot pass argument `""` of type `string` to parameter `dchar[] pText`
----
+----
+fail_compilation/fail58.d(28): Error: function `SomeFunc` is not callable using argument types `(string, int)`
+fail_compilation/fail58.d(28):        cannot pass argument `"123"` of type `string` to parameter `dchar[] pText`
+fail_compilation/fail58.d(14):        `fail58.SomeFunc(dchar[] pText, out int pStopPosn)` declared here
+fail_compilation/fail58.d(32): Error: function `SomeFunc` is not callable using argument types `(string, int)`
+fail_compilation/fail58.d(32):        cannot pass argument `""` of type `string` to parameter `dchar[] pText`
+fail_compilation/fail58.d(14):        `fail58.SomeFunc(dchar[] pText, out int pStopPosn)` declared here
+----
 */
 debug import std.stdio;
 const int anything = -1000; // Line #2
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail8009.d b/gcc/testsuite/gdc.test/fail_compilation/fail8009.d
index a4844bf66f57a63c2009fcaac504a25a2a5269b8..f2abfcc0083fb7a70887a8f6e06ceb11f1ba714a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail8009.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail8009.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail8009.d(9): Error: template `fail8009.filter` is not callable using argument types `!()(void)`
+fail_compilation/fail8009.d(9): Error: template `filter` is not callable using argument types `!()(void)`
 fail_compilation/fail8009.d(8):        Candidate is: `filter(R)(scope bool delegate(ref BAD!R) func)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail95.d b/gcc/testsuite/gdc.test/fail_compilation/fail95.d
index 7065bc11516baf69cabc1f929412a1f7dc9b3dca..0e613363b0878553cef591d89ec8d0865b3577a7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail95.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail95.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail95.d(19): Error: template `fail95.A` is not callable using argument types `!()(int)`
+fail_compilation/fail95.d(19): Error: template `A` is not callable using argument types `!()(int)`
 fail_compilation/fail95.d(11):        Candidate is: `A(alias T)(T)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/hexstring.d b/gcc/testsuite/gdc.test/fail_compilation/hexstring.d
index de83db9c5ed1bc37310435382a09616c8dcf3f77..caca3b3e97e7afdf2a7415907a061e486313c234 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/hexstring.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/hexstring.d
@@ -1,18 +1,39 @@
-/**
-TEST_OUTPUT:
----
-fail_compilation\hexstring.d(16): Error: cannot implicitly convert expression `"123F"` of type `string` to `immutable(ubyte[])`
-fail_compilation\hexstring.d(17): Error: cannot implicitly convert expression `"\x12?"c` of type `string` to `immutable(ubyte[])`
-fail_compilation\hexstring.d(18): Error: cannot implicitly convert expression `"\x12?"` of type `string` to `immutable(ubyte[])`
-fail_compilation\hexstring.d(15): Error: cannot implicitly convert expression `"\x12?"` of type `string` to `ubyte[]`
----
-*/
-immutable ubyte[] s0 = x"123F";
-static assert(s0[0] == 0x12);
-static assert(s0[1] == 0x3F);
-immutable byte[] s1 = x"123F";
-
-ubyte[] f1 = x"123F";
-immutable ubyte[] f2 = "123F";
-immutable ubyte[] f3 = x"123F"c;
-immutable ubyte[] f4 = cast(string) x"123F";
+/**
+TEST_OUTPUT:
+---
+fail_compilation/hexstring.d(29): Error: cannot implicitly convert expression `"123F"` of type `string` to `immutable(ubyte[])`
+fail_compilation/hexstring.d(30): Error: cannot implicitly convert expression `x"123F"c` of type `string` to `immutable(ubyte[])`
+fail_compilation/hexstring.d(31): Error: cannot implicitly convert expression `x"123F"` of type `string` to `immutable(ubyte[])`
+fail_compilation/hexstring.d(33): Error: hex string length 1 must be a multiple of 2 to cast to `immutable(ushort[])`
+fail_compilation/hexstring.d(34): Error: hex string length 3 must be a multiple of 4 to cast to `immutable(uint[])`
+fail_compilation/hexstring.d(35): Error: hex string length 5 must be a multiple of 8 to cast to `immutable(ulong[])`
+fail_compilation/hexstring.d(36): Error: array cast from `wstring` to `immutable(ulong[])` is not supported at compile time
+fail_compilation/hexstring.d(36):        perhaps remove postfix `w` from hex string
+fail_compilation/hexstring.d(37): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time
+fail_compilation/hexstring.d(38): Error: array cast from `string` to `immutable(ushort[])` is not supported at compile time
+fail_compilation/hexstring.d(39): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time
+fail_compilation/hexstring.d(39):        perhaps remove postfix `c` from hex string
+fail_compilation/hexstring.d(28): Error: cannot implicitly convert expression `x"123F"` of type `string` to `ubyte[]`
+---
+*/
+
+immutable ubyte[] s0 = x"123F";
+static assert(s0[0] == 0x12);
+static assert(s0[1] == 0x3F);
+immutable byte[] s1 = x"123F";
+
+enum E(X) = cast(X[]) x"AABBCCDD";
+static assert(E!int[0] == 0xAABBCCDD);
+
+ubyte[] f1 = x"123F";
+immutable ubyte[] f2 = "123F";
+immutable ubyte[] f3 = x"123F"c;
+immutable ubyte[] f4 = cast(string) x"123F";
+
+immutable ushort[] f5 = cast(immutable ushort[]) x"11";
+immutable uint[] f6 = cast(immutable uint[]) x"112233";
+immutable ulong[] f7 = cast(immutable ulong[]) x"1122334455";
+immutable ulong[] f8 = cast(immutable ulong[]) x"1122334455"w;
+immutable uint[] f9 = cast(immutable uint[]) "ABCD";
+immutable ushort[] f10 = cast(immutable ushort[]) (x"1122" ~ "");
+immutable uint[] f11 = cast(immutable uint[]) x"AABBCCDD"c;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10922.d b/gcc/testsuite/gdc.test/fail_compilation/ice10922.d
index e76d4ac050ddc11db9af868dc23cb163c91fbcc3..552a9824f32e6a892d1e6c5187184a8d48394e36 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10922.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10922.d
@@ -1,8 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice10922.d(10): Error: function `ice10922.__lambda4(in uint n)` is not callable using argument types `()`
-fail_compilation/ice10922.d(10):        too few arguments, expected 1, got 0
+fail_compilation/ice10922.d(11): Error: function `__lambda4` is not callable using argument types `()`
+fail_compilation/ice10922.d(11):        too few arguments, expected 1, got 0
+fail_compilation/ice10922.d(10):        `ice10922.__lambda4(in uint n)` declared here
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d b/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d
index 448e629602db45f7e1bdc370f982f0e2dae1cc5b..476c6559c8288917151aa79a8e3c01d106975083 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice11856_1.d
@@ -1,14 +1,14 @@
 /*
 TEST_OUTPUT:
----
+----
 fail_compilation/ice11856_1.d(18): Error: no property `g` for `A()` of type `A`
 fail_compilation/ice11856_1.d(18):        the following error occured while looking for a UFCS match
-fail_compilation/ice11856_1.d(18): Error: template `ice11856_1.g` is not callable using argument types `!()(A)`
+fail_compilation/ice11856_1.d(18): Error: template `g` is not callable using argument types `!()(A)`
 fail_compilation/ice11856_1.d(16):        Candidate is: `g(T)(T x)`
   with `T = A`
   must satisfy the following constraint:
 `       is(typeof(x.f()))`
----
+----
 */
 struct A {}
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12501.d b/gcc/testsuite/gdc.test/fail_compilation/ice12501.d
index 2c45c8a359daff644682534b16b20c597dfdbd52..c1b1e38a965fd8a8acf3f0dd3e07a14cf583aab5 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice12501.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice12501.d
@@ -1,12 +1,14 @@
 /*
 TEST_OUTPUT:
----
-fail_compilation/ice12501.d(31): Error: function `ice12501.foo(int value)` is not callable using argument types `(int, int)`
-fail_compilation/ice12501.d(31):        expected 1 argument(s), not 2
-fail_compilation/ice12501.d(31): Error: function `ice12501.foo(int value)` is not callable using argument types `(int, int)`
-fail_compilation/ice12501.d(31):        expected 1 argument(s), not 2
-fail_compilation/ice12501.d(45): Error: template instance `ice12501.reduce!(foo, foo).reduce!(Tuple!(int, int), int[])` error instantiating
----
+----
+fail_compilation/ice12501.d(33): Error: function `foo` is not callable using argument types `(int, int)`
+fail_compilation/ice12501.d(33):        expected 1 argument(s), not 2
+fail_compilation/ice12501.d(40):        `ice12501.foo(int value)` declared here
+fail_compilation/ice12501.d(33): Error: function `foo` is not callable using argument types `(int, int)`
+fail_compilation/ice12501.d(33):        expected 1 argument(s), not 2
+fail_compilation/ice12501.d(40):        `ice12501.foo(int value)` declared here
+fail_compilation/ice12501.d(47): Error: template instance `ice12501.reduce!(foo, foo).reduce!(Tuple!(int, int), int[])` error instantiating
+----
 */
 
 struct Tuple(T...)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14130.d b/gcc/testsuite/gdc.test/fail_compilation/ice14130.d
index 151bf17535c19eb64aa18f5d2c1f981a289da9ff..4b12f8b65ad2e3d39124ec8706a1f462d3851834 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice14130.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice14130.d
@@ -2,7 +2,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/ice14130.d(10): Error: undefined identifier `Undef`
-fail_compilation/ice14130.d(14): Error: template `ice14130.foo` is not callable using argument types `!()(int)`
+fail_compilation/ice14130.d(14): Error: template `foo` is not callable using argument types `!()(int)`
 fail_compilation/ice14130.d(10):        Candidate is: `foo(R, F = Undef)(R r, F s = 0)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14907.d b/gcc/testsuite/gdc.test/fail_compilation/ice14907.d
index 5d676cd1a122fa6daee070961a89085c01e333f4..eeca1b3b3b3a47fa616b73562bf6a587a44a5e91 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice14907.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice14907.d
@@ -1,14 +1,14 @@
 /*
 TEST_OUTPUT:
----
+----
 fail_compilation/ice14907.d(14): Error: struct `ice14907.S(int v = S)` recursive template expansion
 fail_compilation/ice14907.d(19):        while looking for match for `S!()`
 fail_compilation/ice14907.d(15): Error: template `ice14907.f(int v = f)()` recursive template expansion
 fail_compilation/ice14907.d(20):        while looking for match for `f!()`
 fail_compilation/ice14907.d(15): Error: template `ice14907.f(int v = f)()` recursive template expansion
-fail_compilation/ice14907.d(21): Error: template `ice14907.f` is not callable using argument types `!()()`
+fail_compilation/ice14907.d(21): Error: template `f` is not callable using argument types `!()()`
 fail_compilation/ice14907.d(15):        Candidate is: `f(int v = f)()`
----
+----
 */
 
 struct S(int v = S) {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14923.d b/gcc/testsuite/gdc.test/fail_compilation/ice14923.d
index e3b677e2cdb3d31c1adc861e71e1a591f27fcf2c..99d2eeed714019fc924cfd3fcc2417a90c719b0f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice14923.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice14923.d
@@ -1,10 +1,11 @@
 /*
 TEST_OUTPUT:
----
-fail_compilation/ice14923.d(22): Error: function `ice14923.parse(C a)` is not callable using argument types `(A)`
-fail_compilation/ice14923.d(22):        cannot pass argument `b` of type `ice14923.A` to parameter `C a`
-fail_compilation/ice14923.d(22):        instantiated from here: `bar!((b) => parse(b))`
----
+----
+fail_compilation/ice14923.d(23): Error: function `parse` is not callable using argument types `(A)`
+fail_compilation/ice14923.d(23):        cannot pass argument `b` of type `ice14923.A` to parameter `C a`
+fail_compilation/ice14923.d(21):        `ice14923.parse(C a)` declared here
+fail_compilation/ice14923.d(23):        instantiated from here: `bar!((b) => parse(b))`
+----
 */
 
 auto bar(alias fun)()
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice23097.d b/gcc/testsuite/gdc.test/fail_compilation/ice23097.d
index 90cf03f1b48d7da94b017d1d9c696162ee05764e..5cde816c668ed61a134658660baa9f984ce42424 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice23097.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice23097.d
@@ -1,10 +1,11 @@
 /* https://issues.dlang.org/show_bug.cgi?id=23097
 TEST_OUTPUT:
 ---
-fail_compilation/ice23097.d(12): Error: undefined identifier `ICE`
-fail_compilation/ice23097.d(27): Error: template instance `ice23097.ice23097!(S23097)` error instantiating
-fail_compilation/ice23097.d(27): Error: function `ice23097.ice23097!(S23097).ice23097(S23097 __param_0)` is not callable using argument types `(S23097)`
-fail_compilation/ice23097.d(27):        generating a copy constructor for `struct S23097` failed, therefore instances of it are uncopyable
+fail_compilation/ice23097.d(13): Error: undefined identifier `ICE`
+fail_compilation/ice23097.d(28): Error: template instance `ice23097.ice23097!(S23097)` error instantiating
+fail_compilation/ice23097.d(28): Error: function `ice23097` is not callable using argument types `(S23097)`
+fail_compilation/ice23097.d(28):        generating a copy constructor for `struct S23097` failed, therefore instances of it are uncopyable
+fail_compilation/ice23097.d(11):        `ice23097.ice23097!(S23097).ice23097(S23097 __param_0)` declared here
 ---
 */
 auto ice23097(I)(I)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice6538.d b/gcc/testsuite/gdc.test/fail_compilation/ice6538.d
index 9355a0fcafdf21e3a21cfa01c4585ae46e0d3631..de9fe295dcac66d625791a7772dd2588c585b295 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice6538.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice6538.d
@@ -7,7 +7,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/ice6538.d(23): Error: template instance `Sym!(super)` expression `super` is not a valid template value argument
-fail_compilation/ice6538.d(28): Error: template `ice6538.D.foo` is not callable using argument types `!()()`
+fail_compilation/ice6538.d(28): Error: template `foo` is not callable using argument types `!()()`
 fail_compilation/ice6538.d(23):        Candidate is: `foo()()`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice9284.d b/gcc/testsuite/gdc.test/fail_compilation/ice9284.d
index c9ab014b6e6d4b70b45311a5044f70514772803c..1e87f0a141d9f0fddad0514b04b386de6d7b73c7 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice9284.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice9284.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice9284.d(14): Error: template `ice9284.C.__ctor` is not callable using argument types `!()(int)`
+fail_compilation/ice9284.d(14): Error: template `__ctor` is not callable using argument types `!()(int)`
 fail_compilation/ice9284.d(12):        Candidate is: `this()(string)`
 fail_compilation/ice9284.d(20): Error: template instance `ice9284.C.__ctor!()` error instantiating
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice9540.d b/gcc/testsuite/gdc.test/fail_compilation/ice9540.d
index 456d3e12f236cea486a14d578efeb540fc7313e3..662038c19cf98118a8324e776c737746ab06d66e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice9540.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice9540.d
@@ -1,10 +1,11 @@
 /*
 TEST_OUTPUT:
----
-fail_compilation/ice9540.d(35): Error: function `ice9540.A.test.AddFront!(this, f).AddFront.dg(int __param_0)` is not callable using argument types `()`
-fail_compilation/ice9540.d(35):        too few arguments, expected 1, got 0
-fail_compilation/ice9540.d(26): Error: template instance `ice9540.A.test.AddFront!(this, f)` error instantiating
----
+----
+fail_compilation/ice9540.d(36): Error: function `dg` is not callable using argument types `()`
+fail_compilation/ice9540.d(36):        too few arguments, expected 1, got 0
+fail_compilation/ice9540.d(33):        `ice9540.A.test.AddFront!(this, f).AddFront.dg(int __param_0)` declared here
+fail_compilation/ice9540.d(27): Error: template instance `ice9540.A.test.AddFront!(this, f)` error instantiating
+----
 */
 
 template Tuple(E...) { alias E Tuple; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/iconv_interface_array.d b/gcc/testsuite/gdc.test/fail_compilation/iconv_interface_array.d
new file mode 100644
index 0000000000000000000000000000000000000000..53c1450835868883dbe3b441ac0ab4e63c3c7106
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/iconv_interface_array.d
@@ -0,0 +1,51 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/iconv_interface_array.d(48): Error: function `testA` is not callable using argument types `(C[4])`
+fail_compilation/iconv_interface_array.d(48):        cannot pass argument `arr` of type `C[4]` to parameter `I1[4] arr`
+fail_compilation/iconv_interface_array.d(27):        `iconv_interface_array.testA(I1[4] arr)` declared here
+fail_compilation/iconv_interface_array.d(49): Error: function `testB` is not callable using argument types `(C[4])`
+fail_compilation/iconv_interface_array.d(49):        cannot pass argument `arr` of type `C[4]` to parameter `I2[4] arr`
+fail_compilation/iconv_interface_array.d(33):        `iconv_interface_array.testB(I2[4] arr)` declared here
+fail_compilation/iconv_interface_array.d(50): Error: function `testC` is not callable using argument types `(C[4])`
+fail_compilation/iconv_interface_array.d(50):        cannot pass argument `arr` of type `C[4]` to parameter `I3[4] arr`
+fail_compilation/iconv_interface_array.d(39):        `iconv_interface_array.testC(I3[4] arr)` declared here
+---
+*/
+
+interface I1 { int a(int); }
+interface I2 { int b(int); }
+interface I3 { int c(int); }
+
+class C : I1, I2, I3
+{
+    int a(int i) { return 1 * i; }
+    int b(int i) { return 2 * i; }
+    int c(int i) { return 3 * i; }
+}
+
+void testA(I1[4] arr)
+{
+    foreach (uint idx, obj; arr)
+        assert(obj.a(idx) == 1 * idx);
+}
+
+void testB(I2[4] arr)
+{
+    foreach (idx, obj; arr)
+        assert(obj.b(cast(int) idx) == 2 * idx);
+}
+
+void testC(I3[4] arr)
+{
+    foreach (idx, obj; arr)
+        assert(obj.c(cast(int) idx) == 3 * idx);
+}
+
+void main()
+{
+    C[4] arr = [ new C, new C, new C, new C ];
+    testA(arr);
+    testB(arr);
+    testC(arr);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/interpolatedexpressionsequence_postfix.d b/gcc/testsuite/gdc.test/fail_compilation/interpolatedexpressionsequence_postfix.d
new file mode 100644
index 0000000000000000000000000000000000000000..c915c446b49907fd63958964127cc48a99a02565
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/interpolatedexpressionsequence_postfix.d
@@ -0,0 +1,13 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/interpolatedexpressionsequence_postfix.d(10): Error: String postfixes on interpolated expression sequences are not allowed.
+fail_compilation/interpolatedexpressionsequence_postfix.d(11): Error: String postfixes on interpolated expression sequences are not allowed.
+fail_compilation/interpolatedexpressionsequence_postfix.d(12): Error: String postfixes on interpolated expression sequences are not allowed.
+---
+*/
+void main() {
+    // all postfixes are banned
+    auto c = i"foo"c;
+    auto w = i"foo"w;
+    auto d = i"foo"d;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
index 5129f30146012e51f5f9f18ecc8ec3e73a7d9334..b634a119564acfe32888a6f04872ce3b876b7536 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
@@ -1,22 +1,27 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/named_arguments_error.d(32): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)`
-fail_compilation/named_arguments_error.d(32):        parameter `x` assigned twice
-fail_compilation/named_arguments_error.d(33): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)`
-fail_compilation/named_arguments_error.d(33):        argument `4` goes past end of parameter list
-fail_compilation/named_arguments_error.d(34): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)`
-fail_compilation/named_arguments_error.d(34):        parameter `y` assigned twice
-fail_compilation/named_arguments_error.d(35): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)`
-fail_compilation/named_arguments_error.d(35):        no parameter named `a`
-fail_compilation/named_arguments_error.d(36): Error: function `named_arguments_error.g(int x, int y, int z = 3)` is not callable using argument types `(int, int)`
-fail_compilation/named_arguments_error.d(36):        missing argument for parameter #1: `int x`
-fail_compilation/named_arguments_error.d(38): Error: no named argument `element` allowed for array dimension
-fail_compilation/named_arguments_error.d(39): Error: no named argument `number` allowed for scalar
-fail_compilation/named_arguments_error.d(40): Error: cannot implicitly convert expression `g(x: 3, y: 4, z: 5)` of type `int` to `string`
-fail_compilation/named_arguments_error.d(41): Error: named arguments with Implicit Function Template Instantiation are not supported yet
-fail_compilation/named_arguments_error.d(41): Error: template `named_arguments_error.tempfun` is not callable using argument types `!()(string, int)`
-fail_compilation/named_arguments_error.d(45):        Candidate is: `tempfun(T, U)(T t, U u)`
+fail_compilation/named_arguments_error.d(37): Error: function `f` is not callable using argument types `(int, int, int)`
+fail_compilation/named_arguments_error.d(37):        parameter `x` assigned twice
+fail_compilation/named_arguments_error.d(31):        `named_arguments_error.f(int x, int y, int z)` declared here
+fail_compilation/named_arguments_error.d(38): Error: function `f` is not callable using argument types `(int, int, int)`
+fail_compilation/named_arguments_error.d(38):        argument `4` goes past end of parameter list
+fail_compilation/named_arguments_error.d(31):        `named_arguments_error.f(int x, int y, int z)` declared here
+fail_compilation/named_arguments_error.d(39): Error: function `f` is not callable using argument types `(int, int, int)`
+fail_compilation/named_arguments_error.d(39):        parameter `y` assigned twice
+fail_compilation/named_arguments_error.d(31):        `named_arguments_error.f(int x, int y, int z)` declared here
+fail_compilation/named_arguments_error.d(40): Error: function `f` is not callable using argument types `(int, int, int)`
+fail_compilation/named_arguments_error.d(40):        no parameter named `a`
+fail_compilation/named_arguments_error.d(31):        `named_arguments_error.f(int x, int y, int z)` declared here
+fail_compilation/named_arguments_error.d(41): Error: function `g` is not callable using argument types `(int, int)`
+fail_compilation/named_arguments_error.d(41):        missing argument for parameter #1: `int x`
+fail_compilation/named_arguments_error.d(33):        `named_arguments_error.g(int x, int y, int z = 3)` declared here
+fail_compilation/named_arguments_error.d(43): Error: no named argument `element` allowed for array dimension
+fail_compilation/named_arguments_error.d(44): Error: no named argument `number` allowed for scalar
+fail_compilation/named_arguments_error.d(45): Error: cannot implicitly convert expression `g(x: 3, y: 4, z: 5)` of type `int` to `string`
+fail_compilation/named_arguments_error.d(46): Error: named arguments with Implicit Function Template Instantiation are not supported yet
+fail_compilation/named_arguments_error.d(46): Error: template `tempfun` is not callable using argument types `!()(string, int)`
+fail_compilation/named_arguments_error.d(50):        Candidate is: `tempfun(T, U)(T t, U u)`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/previewin.d b/gcc/testsuite/gdc.test/fail_compilation/previewin.d
index d0e97c8bcd3f355272332e921062eab3ba5197d4..486dcd5244d28da01bf35f1fd7b670417e796e27 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/previewin.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/previewin.d
@@ -1,20 +1,23 @@
 /*
 REQUIRED_ARGS: -preview=in -preview=dip1000
 TEST_OUTPUT:
----
-fail_compilation/previewin.d(4): Error: function `previewin.takeFunction(void function(in real) f)` is not callable using argument types `(void function(real x) pure nothrow @nogc @safe)`
+----
+fail_compilation/previewin.d(4): Error: function `takeFunction` is not callable using argument types `(void function(real x) pure nothrow @nogc @safe)`
 fail_compilation/previewin.d(4):        cannot pass argument `__lambda1` of type `void function(real x) pure nothrow @nogc @safe` to parameter `void function(in real) f`
-fail_compilation/previewin.d(5): Error: function `previewin.takeFunction(void function(in real) f)` is not callable using argument types `(void function(scope const(real) x) pure nothrow @nogc @safe)`
+fail_compilation/previewin.d(11):        `previewin.takeFunction(void function(in real) f)` declared here
+fail_compilation/previewin.d(5): Error: function `takeFunction` is not callable using argument types `(void function(scope const(real) x) pure nothrow @nogc @safe)`
 fail_compilation/previewin.d(5):        cannot pass argument `__lambda2` of type `void function(scope const(real) x) pure nothrow @nogc @safe` to parameter `void function(in real) f`
-fail_compilation/previewin.d(6): Error: function `previewin.takeFunction(void function(in real) f)` is not callable using argument types `(void function(ref scope const(real) x) pure nothrow @nogc @safe)`
+fail_compilation/previewin.d(11):        `previewin.takeFunction(void function(in real) f)` declared here
+fail_compilation/previewin.d(6): Error: function `takeFunction` is not callable using argument types `(void function(ref scope const(real) x) pure nothrow @nogc @safe)`
 fail_compilation/previewin.d(6):        cannot pass argument `__lambda3` of type `void function(ref scope const(real) x) pure nothrow @nogc @safe` to parameter `void function(in real) f`
+fail_compilation/previewin.d(11):        `previewin.takeFunction(void function(in real) f)` declared here
 fail_compilation/previewin.d(15): Error: scope variable `arg` assigned to global variable `myGlobal`
 fail_compilation/previewin.d(16): Error: scope variable `arg` assigned to global variable `myGlobal`
 fail_compilation/previewin.d(17): Error: scope parameter `arg` may not be returned
 fail_compilation/previewin.d(18): Error: scope variable `arg` assigned to `ref` variable `escape` with longer lifetime
 fail_compilation/previewin.d(22): Error: returning `arg` escapes a reference to parameter `arg`
 fail_compilation/previewin.d(22):        perhaps annotate the parameter with `return`
----
+----
  */
 
 #line 1
diff --git a/gcc/testsuite/gdc.test/fail_compilation/pull12941.d b/gcc/testsuite/gdc.test/fail_compilation/pull12941.d
index fce4ab7345e46fa66adf62d0782ce1f03f0b2016..ca78050e6acfed89fbd14a1167cb3c7b1f644747 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/pull12941.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/pull12941.d
@@ -4,10 +4,12 @@ fail_compilation/pull12941.d(110): Error: `pull12941.foo` called with argument t
 fail_compilation/pull12941.d(101):     `pull12941.foo(return ref scope int* p)`
 and:
 fail_compilation/pull12941.d(102):     `pull12941.foo(return out scope int* p)`
-fail_compilation/pull12941.d(111): Error: function `pull12941.bar(return scope int* p)` is not callable using argument types `(int)`
+fail_compilation/pull12941.d(111): Error: function `bar` is not callable using argument types `(int)`
 fail_compilation/pull12941.d(111):        cannot pass argument `1` of type `int` to parameter `return scope int* p`
-fail_compilation/pull12941.d(112): Error: function `pull12941.abc(return ref int* p)` is not callable using argument types `(int)`
+fail_compilation/pull12941.d(104):        `pull12941.bar(return scope int* p)` declared here
+fail_compilation/pull12941.d(112): Error: function `abc` is not callable using argument types `(int)`
 fail_compilation/pull12941.d(112):        cannot pass rvalue argument `1` of type `int` to parameter `return ref int* p`
+fail_compilation/pull12941.d(105):        `pull12941.abc(return ref int* p)` declared here
 ---
  */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test19107.d b/gcc/testsuite/gdc.test/fail_compilation/test19107.d
index c80212294270954236b8ccbc1ec5d7f511d96b3f..9a6e335864779fbb07b52035c10e27a5ed37924b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test19107.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test19107.d
@@ -2,7 +2,7 @@
 EXTRA_FILES: imports/imp19661.d imports/test19107a.d imports/test19107b.d
 TEST_OUTPUT:
 ---
-fail_compilation/test19107.d(24): Error: template `test19107.all` is not callable using argument types `!((c) => c)(string[])`
+fail_compilation/test19107.d(24): Error: template `all` is not callable using argument types `!((c) => c)(string[])`
 fail_compilation/test19107.d(18):        Candidate is: `all(alias pred, T)(T t)`
   with `pred = __lambda2,
        T = string[]`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test19971.d b/gcc/testsuite/gdc.test/fail_compilation/test19971.d
index f854362459b180745ed3a651425da6b3668ed193..3d46eeb82ef07feb8beb80a45a97616b74e7dc75 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test19971.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test19971.d
@@ -1,9 +1,10 @@
 /* TEST_OUTPUT:
 ---
-fail_compilation/test19971.d(15): Error: function `test19971.f(int x)` is not callable using argument types `(string)`
-fail_compilation/test19971.d(15):        cannot pass argument `"%s"` of type `string` to parameter `int x`
-fail_compilation/test19971.d(16): Error: function literal `__lambda1(int x)` is not callable using argument types `(string)`
+fail_compilation/test19971.d(16): Error: function `f` is not callable using argument types `(string)`
 fail_compilation/test19971.d(16):        cannot pass argument `"%s"` of type `string` to parameter `int x`
+fail_compilation/test19971.d(13):        `test19971.f(int x)` declared here
+fail_compilation/test19971.d(17): Error: function literal `__lambda1(int x)` is not callable using argument types `(string)`
+fail_compilation/test19971.d(17):        cannot pass argument `"%s"` of type `string` to parameter `int x`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21008.d b/gcc/testsuite/gdc.test/fail_compilation/test21008.d
index 9949107847635ac1c3053f607a1f526dc1240661..11cfc393cf83ce2631267f759e27e1bcd412625d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21008.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21008.d
@@ -4,13 +4,16 @@ TEST_OUTPUT:
 fail_compilation/test21008.d(110): Error: function `test21008.C.after` circular reference to class `C`
 fail_compilation/test21008.d(117): Error: calling non-static function `toString` requires an instance of type `Object`
 fail_compilation/test21008.d(117): Error: calling non-static function `toHash` requires an instance of type `Object`
-fail_compilation/test21008.d(117): Error: function `object.Object.opCmp(Object o)` is not callable using argument types `()`
+fail_compilation/test21008.d(117): Error: function `opCmp` is not callable using argument types `()`
 fail_compilation/test21008.d(117):        too few arguments, expected 1, got 0
-fail_compilation/test21008.d(117): Error: function `object.Object.opEquals(Object o)` is not callable using argument types `()`
+$p:druntime/import/object.d$($n$):        `object.Object.opCmp(Object o)` declared here
+fail_compilation/test21008.d(117): Error: function `opEquals` is not callable using argument types `()`
 fail_compilation/test21008.d(117):        too few arguments, expected 1, got 0
+$p:druntime/import/object.d$($n$):        `object.Object.opEquals(Object o)` declared here
 fail_compilation/test21008.d(117): Error: `Monitor` has no effect
-fail_compilation/test21008.d(117): Error: function `object.Object.factory(string classname)` is not callable using argument types `()`
+fail_compilation/test21008.d(117): Error: function `factory` is not callable using argument types `()`
 fail_compilation/test21008.d(117):        too few arguments, expected 1, got 0
+$p:druntime/import/object.d$($n$):        `object.Object.factory(string classname)` declared here
 fail_compilation/test21008.d(105):        called from here: `handleMiddlewareAnnotation()`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21025.d b/gcc/testsuite/gdc.test/fail_compilation/test21025.d
index 85641998751954a631a845215c607a4afb5c3f63..6b2496a5840627b3de4ba40b7c296623ea0f53dd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21025.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21025.d
@@ -6,7 +6,7 @@ TEST_OUTPUT:
 ---
 fail_compilation/test21025.d(15): Error: variable `r` cannot be read at compile time
 fail_compilation/test21025.d(15):        called from here: `binaryFun(r, r)`
-fail_compilation/test21025.d(24): Error: template `test21025.uniq` is not callable using argument types `!()(void[])`
+fail_compilation/test21025.d(24): Error: template `uniq` is not callable using argument types `!()(void[])`
 fail_compilation/test21025.d(14):        Candidate is: `uniq()(int[] r)`
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21807.d b/gcc/testsuite/gdc.test/fail_compilation/test21807.d
index 9f56bf73a90ee265680d45d67b8a8dc4b6d4fb73..aaa56f9709878a1cf002ea86ff0c5fb74fee14bd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21807.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21807.d
@@ -27,8 +27,9 @@ class Foo
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/test21807.d(117): Error: function `test21807.addr(return ref int b)` is not callable using argument types `(int)`
+fail_compilation/test21807.d(117): Error: function `addr` is not callable using argument types `(int)`
 fail_compilation/test21807.d(117):        cannot pass rvalue argument `S(0).i` of type `int` to parameter `return ref int b`
+fail_compilation/test21807.d(106):        `test21807.addr(return ref int b)` declared here
 ---
 */
 #line 100
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ufcs.d b/gcc/testsuite/gdc.test/fail_compilation/ufcs.d
index 501ef81927f6c670c68afef647f3d081dbfcf604..3a92a691e2f415cac86597fe53e1a18b001c9980 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ufcs.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ufcs.d
@@ -1,19 +1,20 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ufcs.d(25): Error: no property `regularF` for `s` of type `S`
-fail_compilation/ufcs.d(25):        the following error occured while looking for a UFCS match
-fail_compilation/ufcs.d(25): Error: function `ufcs.regularF()` is not callable using argument types `(S)`
-fail_compilation/ufcs.d(25):        expected 0 argument(s), not 1
-fail_compilation/ufcs.d(26): Error: no property `templateF` for `s` of type `S`
+fail_compilation/ufcs.d(26): Error: no property `regularF` for `s` of type `S`
 fail_compilation/ufcs.d(26):        the following error occured while looking for a UFCS match
-fail_compilation/ufcs.d(26): Error: template `ufcs.templateF` is not callable using argument types `!()(S)`
-fail_compilation/ufcs.d(31):        Candidate is: `templateF()()`
-fail_compilation/ufcs.d(27): Error: no property `templateO` for `s` of type `S`
+fail_compilation/ufcs.d(26): Error: function `regularF` is not callable using argument types `(S)`
+fail_compilation/ufcs.d(26):        expected 0 argument(s), not 1
+fail_compilation/ufcs.d(31):        `ufcs.regularF()` declared here
+fail_compilation/ufcs.d(27): Error: no property `templateF` for `s` of type `S`
 fail_compilation/ufcs.d(27):        the following error occured while looking for a UFCS match
-fail_compilation/ufcs.d(27): Error: none of the overloads of template `ufcs.templateO` are callable using argument types `!()(S)`
-fail_compilation/ufcs.d(33):        Candidates are: `templateO()(int x)`
-fail_compilation/ufcs.d(34):                        `templateO()(float y)`
+fail_compilation/ufcs.d(27): Error: template `templateF` is not callable using argument types `!()(S)`
+fail_compilation/ufcs.d(32):        Candidate is: `templateF()()`
+fail_compilation/ufcs.d(28): Error: no property `templateO` for `s` of type `S`
+fail_compilation/ufcs.d(28):        the following error occured while looking for a UFCS match
+fail_compilation/ufcs.d(28): Error: none of the overloads of template `ufcs.templateO` are callable using argument types `!()(S)`
+fail_compilation/ufcs.d(34):        Candidates are: `templateO()(int x)`
+fail_compilation/ufcs.d(35):                        `templateO()(float y)`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/vararg2.d b/gcc/testsuite/gdc.test/fail_compilation/vararg2.d
index eb235583efa590b6e06b39bbb72128e3061e2e64..1a2846aa01dec8ea414092bc4e1c880bf41a25c5 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/vararg2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/vararg2.d
@@ -1,10 +1,12 @@
 /* TEST_OUTPUT:
----
-fail_compilation/vararg2.d(106): Error: function `vararg2.foo(int x, const return ...)` is not callable using argument types `(double)`
+----
+fail_compilation/vararg2.d(106): Error: function `foo` is not callable using argument types `(double)`
 fail_compilation/vararg2.d(106):        cannot pass argument `1.0` of type `double` to parameter `int x`
-fail_compilation/vararg2.d(111): Error: function `vararg2.bar(int x, scope shared ...)` is not callable using argument types `(double)`
+fail_compilation/vararg2.d(101):        `vararg2.foo(int x, const return ...)` declared here
+fail_compilation/vararg2.d(111): Error: function `bar` is not callable using argument types `(double)`
 fail_compilation/vararg2.d(111):        cannot pass argument `1.0` of type `double` to parameter `int x`
----
+fail_compilation/vararg2.d(102):        `vararg2.bar(int x, scope shared ...)` declared here
+----
 */
 
 #line 100
diff --git a/gcc/testsuite/gdc.test/runnable/interpolatedexpressionsequence.d b/gcc/testsuite/gdc.test/runnable/interpolatedexpressionsequence.d
new file mode 100644
index 0000000000000000000000000000000000000000..831150792f9eb8013d6e18d266c458f75bbd5719
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/interpolatedexpressionsequence.d
@@ -0,0 +1,51 @@
+import core.interpolation;
+
+alias AliasSeq(T...) = T;
+
+string simpleToString(T...)(T thing) {
+    string s;
+    foreach(item; thing)
+        // all the items provided by core.interpolation have
+        // toString to return an appropriate value
+        //
+        // then this particular example only has embedded strings
+        // and chars, to we can append them directly
+        static if(__traits(hasMember, item, "toString"))
+            s ~= item.toString();
+        else
+            s ~= item;
+
+    return s;
+}
+
+void main() {
+	int a = 1;
+	string b = "one";
+	// parser won't permit alias = i".." directly; i"..." is meant to
+	// be used as a function/template parameter at this time.
+	alias expr = AliasSeq!i"$(a) $(b)";
+	// elements from the source code are available at compile time, so
+	// we static assert those, but the values, of course, are different
+	static assert(expr[0] == InterpolationHeader());
+	static assert(expr[1] == InterpolatedExpression!"a"());
+	assert(expr[2] == a); // actual value not available at compile time
+	static assert(expr[3] == InterpolatedLiteral!" "());
+	// the parens around the expression are not included
+	static assert(expr[4] == InterpolatedExpression!"b"());
+	assert(expr[5] == b); // actual value not available at compile time
+	static assert(expr[6] == InterpolationFooter());
+
+	// it does currently allow `auto` to be used, it creates a value tuple
+	// you can embed any D expressions inside the parenthesis, and the
+	// token is not ended until you get the *outer* ) and ".
+	auto thing = i"$(b) $("$" ~ ')' ~ `"`)";
+	assert(simpleToString(thing) == "one $)\"");
+
+        assert(simpleToString(i"$b") == "$b"); // support for $ident removed by popular demand
+
+        // i`` and iq{} should also work
+        assert(simpleToString(i` $(b) is $(b)!`) == " one is one!");
+        assert(simpleToString(iq{ $(b) is $(b)!}) == " one is one!");
+        assert(simpleToString(i`\$('$')`) == "\\$"); // no \ escape there
+        assert(simpleToString(iq{{$('$')}}) == "{$}"); // {} needs to work
+}
diff --git a/gcc/testsuite/gdc.test/runnable/literal.d b/gcc/testsuite/gdc.test/runnable/literal.d
index 99b177759b4e4c9b9741a10b90c9f91b166eeb9e..69971240d9487ce0d46aec70d5939ea50c383eb7 100644
--- a/gcc/testsuite/gdc.test/runnable/literal.d
+++ b/gcc/testsuite/gdc.test/runnable/literal.d
@@ -241,6 +241,27 @@ void test12950()
     assert(0b00_00_00_01UL.op12950() == 12951);
 }
 
+void testHexstring()
+{
+    static immutable uint[] x = cast(immutable uint[]) x"FFAADDEE";
+    static assert(x[0] == 0xFFAADDEE);
+    assert(x[0] == 0xFFAADDEE);
+
+    static immutable ulong[] y = cast(immutable ulong[]) x"1122334455667788AABBCCDDEEFF0099";
+    static assert(y[0] == 0x1122334455667788);
+    static assert(y[1] == 0xAABBCCDDEEFF0099);
+    assert(y[0] == 0x1122334455667788);
+    assert(y[1] == 0xAABBCCDDEEFF0099);
+
+    // Test that mangling of StringExp with size 8 is the same as array literal mangling:
+    void f(immutable ulong[] a)() {}
+    static assert(f!y.mangleof == f!([0x1122334455667788, 0xAABBCCDDEEFF0099]).mangleof);
+
+    // Test printing StringExp with size 8
+    enum toStr(immutable ulong[] v) = v.stringof;
+    static assert(toStr!y == `x"88776655443322119900FFEEDDCCBBAA"`);
+}
+
 /***************************************************/
 
 int main()
@@ -249,6 +270,7 @@ int main()
     test2();
     test13907();
     test12950();
+    testHexstring();
 
     printf("Success\n");
     return 0;
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 138b0b6fa7c0ba978651e4122b0c435391885321..9217c654225b3ca5910e645498e1b6a72b51954b 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-bce5c1f7b521d22dcf1ea4e2bc3f76d9d28274fa
+e7709452775d374c1e2dfb67566668ada3dec5fc
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 3ef98dcc737b2d2a700ff23411eb1fa4fa68dab6..d2fb6e218c1f6152a6004f9b28aefdba816c6268 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -196,32 +196,33 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/internal/parseoptions.d core/internal/postblit.d \
 	core/internal/qsort.d core/internal/spinlock.d core/internal/string.d \
 	core/internal/switch_.d core/internal/traits.d core/internal/utf.d \
-	core/internal/util/array.d core/internal/util/math.d core/lifetime.d \
-	core/math.d core/memory.d core/runtime.d core/simd.d \
-	core/stdc/assert_.d core/stdc/complex.d core/stdc/config.d \
-	core/stdc/ctype.d core/stdc/errno.d core/stdc/fenv.d \
-	core/stdc/float_.d core/stdc/inttypes.d core/stdc/limits.d \
-	core/stdc/locale.d core/stdc/math.d core/stdc/signal.d \
-	core/stdc/stdarg.d core/stdc/stdatomic.d core/stdc/stddef.d \
-	core/stdc/stdint.d core/stdc/stdio.d core/stdc/stdlib.d \
-	core/stdc/string.d core/stdc/tgmath.d core/stdc/time.d \
-	core/stdc/wchar_.d core/stdc/wctype.d core/sync/barrier.d \
-	core/sync/condition.d core/sync/config.d core/sync/event.d \
-	core/sync/exception.d core/sync/mutex.d core/sync/package.d \
-	core/sync/rwmutex.d core/sync/semaphore.d core/thread/context.d \
-	core/thread/fiber.d core/thread/osthread.d core/thread/package.d \
-	core/thread/threadbase.d core/thread/threadgroup.d core/thread/types.d \
-	core/time.d core/vararg.d core/volatile.d etc/valgrind/valgrind.d \
-	gcc/attribute.d gcc/attributes.d gcc/backtrace.d gcc/builtins.d \
-	gcc/deh.d gcc/emutls.d gcc/gthread.d gcc/sections/common.d \
-	gcc/sections/elf.d gcc/sections/macho.d gcc/sections/package.d \
-	gcc/sections/pecoff.d gcc/simd.d gcc/unwind/arm.d \
-	gcc/unwind/arm_common.d gcc/unwind/c6x.d gcc/unwind/generic.d \
-	gcc/unwind/package.d gcc/unwind/pe.d object.d rt/aApply.d rt/aApplyR.d \
-	rt/aaA.d rt/adi.d rt/arraycat.d rt/cast_.d rt/config.d rt/critical_.d \
-	rt/deh.d rt/dmain2.d rt/ehalloc.d rt/invariant.d rt/lifetime.d \
-	rt/memory.d rt/minfo.d rt/monitor_.d rt/profilegc.d rt/sections.d \
-	rt/tlsgc.d rt/util/typeinfo.d rt/util/utility.d
+	core/internal/util/array.d core/internal/util/math.d \
+	core/interpolation.d core/lifetime.d core/math.d core/memory.d \
+	core/runtime.d core/simd.d core/stdc/assert_.d core/stdc/complex.d \
+	core/stdc/config.d core/stdc/ctype.d core/stdc/errno.d \
+	core/stdc/fenv.d core/stdc/float_.d core/stdc/inttypes.d \
+	core/stdc/limits.d core/stdc/locale.d core/stdc/math.d \
+	core/stdc/signal.d core/stdc/stdarg.d core/stdc/stdatomic.d \
+	core/stdc/stddef.d core/stdc/stdint.d core/stdc/stdio.d \
+	core/stdc/stdlib.d core/stdc/string.d core/stdc/tgmath.d \
+	core/stdc/time.d core/stdc/wchar_.d core/stdc/wctype.d \
+	core/sync/barrier.d core/sync/condition.d core/sync/config.d \
+	core/sync/event.d core/sync/exception.d core/sync/mutex.d \
+	core/sync/package.d core/sync/rwmutex.d core/sync/semaphore.d \
+	core/thread/context.d core/thread/fiber.d core/thread/osthread.d \
+	core/thread/package.d core/thread/threadbase.d \
+	core/thread/threadgroup.d core/thread/types.d core/time.d \
+	core/vararg.d core/volatile.d etc/valgrind/valgrind.d gcc/attribute.d \
+	gcc/attributes.d gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d \
+	gcc/gthread.d gcc/sections/common.d gcc/sections/elf.d \
+	gcc/sections/macho.d gcc/sections/package.d gcc/sections/pecoff.d \
+	gcc/simd.d gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
+	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
+	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arraycat.d rt/cast_.d \
+	rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d rt/ehalloc.d \
+	rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d \
+	rt/profilegc.d rt/sections.d rt/tlsgc.d rt/util/typeinfo.d \
+	rt/util/utility.d
 
 DRUNTIME_DSOURCES_STDCXX = core/stdcpp/allocator.d core/stdcpp/array.d \
 	core/stdcpp/exception.d core/stdcpp/memory.d core/stdcpp/new_.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 1d2bd66817d876eaaa57fabd9f9d6e1ce490f902..3e3ab567a82e6a85eba0fdf29a5c2b86489492c7 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -220,29 +220,29 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	core/internal/string.lo core/internal/switch_.lo \
 	core/internal/traits.lo core/internal/utf.lo \
 	core/internal/util/array.lo core/internal/util/math.lo \
-	core/lifetime.lo core/math.lo core/memory.lo core/runtime.lo \
-	core/simd.lo core/stdc/assert_.lo core/stdc/complex.lo \
-	core/stdc/config.lo core/stdc/ctype.lo core/stdc/errno.lo \
-	core/stdc/fenv.lo core/stdc/float_.lo core/stdc/inttypes.lo \
-	core/stdc/limits.lo core/stdc/locale.lo core/stdc/math.lo \
-	core/stdc/signal.lo core/stdc/stdarg.lo core/stdc/stdatomic.lo \
-	core/stdc/stddef.lo core/stdc/stdint.lo core/stdc/stdio.lo \
-	core/stdc/stdlib.lo core/stdc/string.lo core/stdc/tgmath.lo \
-	core/stdc/time.lo core/stdc/wchar_.lo core/stdc/wctype.lo \
-	core/sync/barrier.lo core/sync/condition.lo \
-	core/sync/config.lo core/sync/event.lo core/sync/exception.lo \
-	core/sync/mutex.lo core/sync/package.lo core/sync/rwmutex.lo \
-	core/sync/semaphore.lo core/thread/context.lo \
-	core/thread/fiber.lo core/thread/osthread.lo \
-	core/thread/package.lo core/thread/threadbase.lo \
-	core/thread/threadgroup.lo core/thread/types.lo core/time.lo \
-	core/vararg.lo core/volatile.lo etc/valgrind/valgrind.lo \
-	gcc/attribute.lo gcc/attributes.lo gcc/backtrace.lo \
-	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
-	gcc/sections/common.lo gcc/sections/elf.lo \
-	gcc/sections/macho.lo gcc/sections/package.lo \
-	gcc/sections/pecoff.lo gcc/simd.lo gcc/unwind/arm.lo \
-	gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
+	core/interpolation.lo core/lifetime.lo core/math.lo \
+	core/memory.lo core/runtime.lo core/simd.lo \
+	core/stdc/assert_.lo core/stdc/complex.lo core/stdc/config.lo \
+	core/stdc/ctype.lo core/stdc/errno.lo core/stdc/fenv.lo \
+	core/stdc/float_.lo core/stdc/inttypes.lo core/stdc/limits.lo \
+	core/stdc/locale.lo core/stdc/math.lo core/stdc/signal.lo \
+	core/stdc/stdarg.lo core/stdc/stdatomic.lo core/stdc/stddef.lo \
+	core/stdc/stdint.lo core/stdc/stdio.lo core/stdc/stdlib.lo \
+	core/stdc/string.lo core/stdc/tgmath.lo core/stdc/time.lo \
+	core/stdc/wchar_.lo core/stdc/wctype.lo core/sync/barrier.lo \
+	core/sync/condition.lo core/sync/config.lo core/sync/event.lo \
+	core/sync/exception.lo core/sync/mutex.lo core/sync/package.lo \
+	core/sync/rwmutex.lo core/sync/semaphore.lo \
+	core/thread/context.lo core/thread/fiber.lo \
+	core/thread/osthread.lo core/thread/package.lo \
+	core/thread/threadbase.lo core/thread/threadgroup.lo \
+	core/thread/types.lo core/time.lo core/vararg.lo \
+	core/volatile.lo etc/valgrind/valgrind.lo gcc/attribute.lo \
+	gcc/attributes.lo gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo \
+	gcc/emutls.lo gcc/gthread.lo gcc/sections/common.lo \
+	gcc/sections/elf.lo gcc/sections/macho.lo \
+	gcc/sections/package.lo gcc/sections/pecoff.lo gcc/simd.lo \
+	gcc/unwind/arm.lo gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
 	gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
 	object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \
 	rt/arraycat.lo rt/cast_.lo rt/config.lo rt/critical_.lo \
@@ -874,32 +874,33 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/internal/parseoptions.d core/internal/postblit.d \
 	core/internal/qsort.d core/internal/spinlock.d core/internal/string.d \
 	core/internal/switch_.d core/internal/traits.d core/internal/utf.d \
-	core/internal/util/array.d core/internal/util/math.d core/lifetime.d \
-	core/math.d core/memory.d core/runtime.d core/simd.d \
-	core/stdc/assert_.d core/stdc/complex.d core/stdc/config.d \
-	core/stdc/ctype.d core/stdc/errno.d core/stdc/fenv.d \
-	core/stdc/float_.d core/stdc/inttypes.d core/stdc/limits.d \
-	core/stdc/locale.d core/stdc/math.d core/stdc/signal.d \
-	core/stdc/stdarg.d core/stdc/stdatomic.d core/stdc/stddef.d \
-	core/stdc/stdint.d core/stdc/stdio.d core/stdc/stdlib.d \
-	core/stdc/string.d core/stdc/tgmath.d core/stdc/time.d \
-	core/stdc/wchar_.d core/stdc/wctype.d core/sync/barrier.d \
-	core/sync/condition.d core/sync/config.d core/sync/event.d \
-	core/sync/exception.d core/sync/mutex.d core/sync/package.d \
-	core/sync/rwmutex.d core/sync/semaphore.d core/thread/context.d \
-	core/thread/fiber.d core/thread/osthread.d core/thread/package.d \
-	core/thread/threadbase.d core/thread/threadgroup.d core/thread/types.d \
-	core/time.d core/vararg.d core/volatile.d etc/valgrind/valgrind.d \
-	gcc/attribute.d gcc/attributes.d gcc/backtrace.d gcc/builtins.d \
-	gcc/deh.d gcc/emutls.d gcc/gthread.d gcc/sections/common.d \
-	gcc/sections/elf.d gcc/sections/macho.d gcc/sections/package.d \
-	gcc/sections/pecoff.d gcc/simd.d gcc/unwind/arm.d \
-	gcc/unwind/arm_common.d gcc/unwind/c6x.d gcc/unwind/generic.d \
-	gcc/unwind/package.d gcc/unwind/pe.d object.d rt/aApply.d rt/aApplyR.d \
-	rt/aaA.d rt/adi.d rt/arraycat.d rt/cast_.d rt/config.d rt/critical_.d \
-	rt/deh.d rt/dmain2.d rt/ehalloc.d rt/invariant.d rt/lifetime.d \
-	rt/memory.d rt/minfo.d rt/monitor_.d rt/profilegc.d rt/sections.d \
-	rt/tlsgc.d rt/util/typeinfo.d rt/util/utility.d
+	core/internal/util/array.d core/internal/util/math.d \
+	core/interpolation.d core/lifetime.d core/math.d core/memory.d \
+	core/runtime.d core/simd.d core/stdc/assert_.d core/stdc/complex.d \
+	core/stdc/config.d core/stdc/ctype.d core/stdc/errno.d \
+	core/stdc/fenv.d core/stdc/float_.d core/stdc/inttypes.d \
+	core/stdc/limits.d core/stdc/locale.d core/stdc/math.d \
+	core/stdc/signal.d core/stdc/stdarg.d core/stdc/stdatomic.d \
+	core/stdc/stddef.d core/stdc/stdint.d core/stdc/stdio.d \
+	core/stdc/stdlib.d core/stdc/string.d core/stdc/tgmath.d \
+	core/stdc/time.d core/stdc/wchar_.d core/stdc/wctype.d \
+	core/sync/barrier.d core/sync/condition.d core/sync/config.d \
+	core/sync/event.d core/sync/exception.d core/sync/mutex.d \
+	core/sync/package.d core/sync/rwmutex.d core/sync/semaphore.d \
+	core/thread/context.d core/thread/fiber.d core/thread/osthread.d \
+	core/thread/package.d core/thread/threadbase.d \
+	core/thread/threadgroup.d core/thread/types.d core/time.d \
+	core/vararg.d core/volatile.d etc/valgrind/valgrind.d gcc/attribute.d \
+	gcc/attributes.d gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d \
+	gcc/gthread.d gcc/sections/common.d gcc/sections/elf.d \
+	gcc/sections/macho.d gcc/sections/package.d gcc/sections/pecoff.d \
+	gcc/simd.d gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
+	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
+	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arraycat.d rt/cast_.d \
+	rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d rt/ehalloc.d \
+	rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d \
+	rt/profilegc.d rt/sections.d rt/tlsgc.d rt/util/typeinfo.d \
+	rt/util/utility.d
 
 DRUNTIME_DSOURCES_STDCXX = core/stdcpp/allocator.d core/stdcpp/array.d \
 	core/stdcpp/exception.d core/stdcpp/memory.d core/stdcpp/new_.d \
@@ -1296,6 +1297,7 @@ core/internal/util/$(am__dirstamp):
 	@: > core/internal/util/$(am__dirstamp)
 core/internal/util/array.lo: core/internal/util/$(am__dirstamp)
 core/internal/util/math.lo: core/internal/util/$(am__dirstamp)
+core/interpolation.lo: core/$(am__dirstamp)
 core/lifetime.lo: core/$(am__dirstamp)
 core/math.lo: core/$(am__dirstamp)
 core/memory.lo: core/$(am__dirstamp)
diff --git a/libphobos/libdruntime/core/internal/array/construction.d b/libphobos/libdruntime/core/internal/array/construction.d
index 655acc8db57546eaecb72a2bbcc4c2e19f4ef885..0950b5a5aa9079b03e28bb95c2ce5b609fe336ec 100644
--- a/libphobos/libdruntime/core/internal/array/construction.d
+++ b/libphobos/libdruntime/core/internal/array/construction.d
@@ -339,17 +339,20 @@ void _d_arraysetctor(Tarr : T[], T)(scope Tarr p, scope ref T value) @trusted
  * Returns:
  *      newly allocated array
  */
-T[] _d_newarrayU(T)(size_t length, bool isShared=false) pure nothrow @nogc @trusted
+T[] _d_newarrayUPureNothrow(T)(size_t length, bool isShared=false) pure nothrow @trusted
 {
-    alias PureType = T[] function(size_t length, bool isShared) pure nothrow @nogc @trusted;
-    return (cast(PureType) &_d_newarrayUImpl!T)(length, isShared);
+    alias PureType = T[] function(size_t length, bool isShared) pure nothrow @trusted;
+    return (cast(PureType) &_d_newarrayU!T)(length, isShared);
 }
 
-T[] _d_newarrayUImpl(T)(size_t length, bool isShared=false) @trusted
+T[] _d_newarrayU(T)(size_t length, bool isShared=false) @trusted
 {
     import core.exception : onOutOfMemoryError;
+    import core.internal.traits : Unqual;
     import core.internal.array.utils : __arrayStart, __setArrayAllocLength, __arrayAlloc;
 
+    alias UnqT = Unqual!T;
+
     size_t elemSize = T.sizeof;
     size_t arraySize;
 
@@ -392,14 +395,14 @@ Loverflow:
     assert(0);
 
 Lcontinue:
-    auto info = __arrayAlloc!T(arraySize);
+    auto info = __arrayAlloc!UnqT(arraySize);
     if (!info.base)
         goto Loverflow;
     debug(PRINTF) printf("p = %p\n", info.base);
 
     auto arrstart = __arrayStart(info);
 
-    __setArrayAllocLength!T(info, arraySize, isShared);
+    __setArrayAllocLength!UnqT(info, arraySize, isShared);
 
     return (cast(T*) arrstart)[0 .. length];
 }
diff --git a/libphobos/libdruntime/core/internal/array/duplication.d b/libphobos/libdruntime/core/internal/array/duplication.d
index 21894c29d38585a3361803d18310afb47662f951..eec6af92fef55b99298c1f2c060e6a62a326edaa 100644
--- a/libphobos/libdruntime/core/internal/array/duplication.d
+++ b/libphobos/libdruntime/core/internal/array/duplication.d
@@ -8,8 +8,6 @@ Source: $(DRUNTIMESRC core/internal/_array/_duplication.d)
 */
 module core.internal.array.duplication;
 
-private extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow;
-
 U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
 {
     if (__ctfe)
@@ -22,8 +20,9 @@ U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
     else
     {
         import core.stdc.string : memcpy;
-        auto arr = _d_newarrayU(typeid(T[]), a.length);
-        memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
+        import core.internal.array.construction: _d_newarrayUPureNothrow;
+        auto arr = _d_newarrayUPureNothrow!T(a.length, is(T == shared));
+        memcpy(cast(void*) arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
         return *cast(U[]*) &arr;
     }
 }
@@ -55,8 +54,9 @@ U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
     else
     {
         import core.lifetime: copyEmplace;
+        import core.internal.array.construction: _d_newarrayU;
         U[] res = () @trusted {
-            auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length);
+            auto arr = cast(U*) _d_newarrayU!T(a.length, is(T == shared));
             size_t i;
             scope (failure)
             {
diff --git a/libphobos/libdruntime/core/internal/array/utils.d b/libphobos/libdruntime/core/internal/array/utils.d
index 57eb14bd6a7efbcb6b083733db08cb93e8bca145..89ce6ca21837868dda61d3bb9d0c065e7fb3929e 100644
--- a/libphobos/libdruntime/core/internal/array/utils.d
+++ b/libphobos/libdruntime/core/internal/array/utils.d
@@ -33,7 +33,6 @@ private
 auto gcStatsPure() nothrow pure
 {
     import core.memory : GC;
-
     auto impureBypass = cast(GC.Stats function() pure nothrow)&GC.stats;
     return impureBypass();
 }
diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
index ca4577f0195082bc96e3761567aa41a4ef61db92..73fe087861a4abe0b355fe4db8261d3bfa207c45 100644
--- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
+++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
@@ -2283,7 +2283,7 @@ struct Gcx
         alias toscan = scanStack!precise;
 
         debug(MARK_PRINTF)
-            printf("marking range: [%p..%p] (%#llx)\n", pbot, ptop, cast(long)(ptop - pbot));
+            printf("marking range: [%p..%p] (%#llx)\n", rng.pbot, rng.ptop, cast(long)(rng.ptop - rng.pbot));
 
         // limit the amount of ranges added to the toscan stack
         enum FANOUT_LIMIT = 32;
@@ -2351,7 +2351,7 @@ struct Gcx
                 size_t bin = pool.pagetable[pn]; // not Bins to avoid multiple size extension instructions
 
                 debug(MARK_PRINTF)
-                    printf("\t\tfound pool %p, base=%p, pn = %lld, bin = %d\n", pool, pool.baseAddr, cast(long)pn, bin);
+                    printf("\t\tfound pool %p, base=%p, pn = %llu, bin = %llu\n", pool, pool.baseAddr, cast(ulong)pn, cast(ulong)bin);
 
                 // Adjust bit to be at start of allocated memory block
                 if (bin < Bins.B_PAGE)
diff --git a/libphobos/libdruntime/core/interpolation.d b/libphobos/libdruntime/core/interpolation.d
new file mode 100644
index 0000000000000000000000000000000000000000..0d45fe79088e0174a34d3e69832c0f6b4a9e5819
--- /dev/null
+++ b/libphobos/libdruntime/core/interpolation.d
@@ -0,0 +1,156 @@
+/++
+    This module provides definitions to support D's
+    interpolated expression sequence literal, sometimes
+    called string interpolation.
+
+
+    ---
+    string str;
+    int num;
+    // the compiler uses this module to implement the
+    // i"..." literal used here.
+    auto a = i"$​(str) has $​(num) items.";
+    ---
+
+    The variable `a` is a sequence of expressions:
+
+    ---
+    a[0] == InterpolationHeader()
+    a[$-1] == InterpolationFooter()
+    ---
+
+    First and last, you see the header and footer, to
+    clearly indicate where interpolation begins and ends.
+    Note that there may be nested interpolated sequences too,
+    each with their own header and footer. Think of them
+    as a set of balanced parenthesis around the contents.
+
+    Inside, you will find three general categories of
+    content: `InterpolatedLiteral!"string"` for string
+    expressions, `InterpolatedExpression!"code"` for code
+    expressions, and then the values themselves as their
+    own type.
+
+    In the example:
+    ---
+    auto a = i"$​(str) has $​(num) items.";
+    ---
+
+    We will find:
+    ---
+    a[0] == InterpolationHeader()
+    a[1] == InterpolatedExpression!"str"
+    a[2] == str
+    a[3] == InterpolatedLiteral!" has ";
+    a[4] == InterpolatedExpression!"num";
+    a[5] == num
+    a[6] == InterpolatedLiteral!" items.";
+    a[7] == InterpolationFooter()
+    a.length == 8;
+    ---
+
+    You can see the correspondence with the original
+    input: when you write `$​(expression)`, the string of the
+    expression is passed as `InterpolatedExpression!ThatString`,
+    (excluding any parenthesis around the expression),
+    and everything else is passed as `InterpolatedLiteral!str`,
+    in the same sequence as they appeared in the source.
+
+    After an `InterpolatedExpression!...`, you will find the
+    actual value(s) in the tuple. (If the expression expanded
+    to multiple values - for example, if it was itself a tuple,
+    there will be multiple values for a single expression.)
+
+    Library functions should NOT attempt to mixin the code
+    from an `InterpolatedExpression` themselves. Doing so
+    will fail, since it is coming from a different scope anyway.
+    The string is provided to you only for informational purposes
+    and as a sentinel to separate things the user wrote.
+
+    Your code should be able to handle an empty code string
+    in `InterpolatedExpression` or even an entirely missing
+    `InterpolatedExpression`, in case an implementation decides to
+    not emit these.
+
+    The `toString` members on these return `null`, except for
+    the `InterpolatedLiteral`, which returns the literal string.
+    This is to ease processing by generic functions like
+    `std.stdio.write` or `std.conv.text`, making them effectively
+    transparently skipped.
+
+    To extract the string from an `InterpolatedLiteral`, you can
+    use an `is` expression or the `.toString` method.
+
+    To extract the string from a `InterpolatedExpression`, you can
+    use an `is` expression or the `.expression` member.
+
+    None of these structures have runtime state.
+
+    History:
+        Added in dmd 2.10x frontend, released in late 2023.
++/
+module core.interpolation;
+
+/++
+    Sentinel values to indicate the beginning and end of an
+    interpolated expression sequence.
+
+    Note that these can nest, so while processing a sequence,
+    it may be helpful to keep a nesting count if that knowledge
+    is important to your application.
++/
+struct InterpolationHeader {
+    /++
+        Returns `null` for easy compatibility with existing functions
+        like `std.stdio.writeln` and `std.conv.text`.
+    +/
+    string toString() const @nogc pure nothrow @safe {
+        return null;
+    }
+}
+
+/// ditto
+struct InterpolationFooter {
+    /++
+        Returns `null` for easy compatibility with existing functions
+        like `std.stdio.writeln` and `std.conv.text`.
+    +/
+    string toString() const @nogc pure nothrow @safe {
+        return null;
+    }
+}
+
+/++
+    Represents a fragment of a string literal in between expressions
+    passed as part of an interpolated expression sequence.
++/
+struct InterpolatedLiteral(string text) {
+    /++
+        Returns the text of the interpolated string literal for this
+        segment of the tuple, for easy access and compatibility with
+        existing functions like `std.stdio.writeln` and `std.conv.text`.
+    +/
+    string toString() const @nogc pure nothrow @safe {
+        return text;
+    }
+}
+
+/++
+    Represents the source code of an expression passed as part of an
+    interpolated expression sequence.
++/
+struct InterpolatedExpression(string text) {
+    /++
+        Returns the text of an interpolated expression used in the
+        original literal, if provided by the implementation.
+    +/
+    enum expression = text;
+
+    /++
+        Returns `null` for easy compatibility with existing functions
+        like `std.stdio.writeln` and `std.conv.text`.
+    +/
+    string toString() const @nogc pure nothrow @safe {
+        return null;
+    }
+}
diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d
index 6b083eaa926f796257939b2acce977a2cef825e4..9e563ad43a30622fe58c04f77b13ca56e5761037 100644
--- a/libphobos/libdruntime/core/lifetime.d
+++ b/libphobos/libdruntime/core/lifetime.d
@@ -3009,5 +3009,5 @@ version (D_ProfileGC)
 template TypeInfoSize(T)
 {
     import core.internal.traits : hasElaborateDestructor;
-    enum TypeInfoSize = hasElaborateDestructor!T ? size_t.sizeof : 0;
+    enum TypeInfoSize = (is (T == struct) && hasElaborateDestructor!T) ? size_t.sizeof : 0;
 }
diff --git a/libphobos/libdruntime/core/stdc/string.d b/libphobos/libdruntime/core/stdc/string.d
index b9e3bb7568c16b3ab86ef689211bdafdd409b206..3e906b10d4af0b07798460cbde81affa34e6ebc3 100644
--- a/libphobos/libdruntime/core/stdc/string.d
+++ b/libphobos/libdruntime/core/stdc/string.d
@@ -64,6 +64,8 @@ size_t strcspn(scope const char* s1, scope const char* s2) pure;
 ///
 char*  strdup(scope const char *s);
 ///
+char*  strndup(scope const char *str, size_t size);
+///
 char*  strerror(int errnum);
 // This `strerror_r` definition is not following the POSIX standard
 version (ReturnStrerrorR)
diff --git a/libphobos/libdruntime/core/sys/posix/string.d b/libphobos/libdruntime/core/sys/posix/string.d
index 8c4ea38cc83388d6c662d11294508de8d18c4b7a..b2d6ea772ec22770dbfeefbcf635a255844825e1 100644
--- a/libphobos/libdruntime/core/sys/posix/string.d
+++ b/libphobos/libdruntime/core/sys/posix/string.d
@@ -39,8 +39,6 @@ char*  stpncpy(return scope char* dst, const char* src, size_t len) pure;
 int    strcoll_l(scope const char* s1, scope const char* s2, locale_t locale);
 ///
 char*  strerror_l(int, locale_t);
-/// Save a copy of a string
-char*  strndup(scope const char* str, size_t len);
 /// Find length of string up to `maxlen`
 size_t strnlen(scope const char* str, size_t maxlen) pure;
 /// System signal messages
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index 9ddc187b37480d7a9e8a0b7bc4bd9f20ae7a482f..93902439fbfd60479002e399c2d52d1a8957a415 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -493,9 +493,8 @@ class Thread : ThreadBase
         slock.lock_nothrow();
         scope(exit) slock.unlock_nothrow();
         {
-            ++nAboutToStart;
-            pAboutToStart = cast(ThreadBase*)realloc(pAboutToStart, Thread.sizeof * nAboutToStart);
-            pAboutToStart[nAboutToStart - 1] = this;
+            incrementAboutToStart(this);
+
             version (Windows)
             {
                 if ( ResumeThread( m_hndl ) == -1 )
diff --git a/libphobos/libdruntime/core/thread/threadbase.d b/libphobos/libdruntime/core/thread/threadbase.d
index 909bffc162b1f17517525b93e4384009fb94eb11..84f9203f23b8ac89baf38e3e2b110f63d93e59ef 100644
--- a/libphobos/libdruntime/core/thread/threadbase.d
+++ b/libphobos/libdruntime/core/thread/threadbase.d
@@ -588,8 +588,8 @@ package(core.thread):
     __gshared size_t        sm_tlen;
 
     // can't use core.internal.util.array in public code
-    __gshared ThreadBase* pAboutToStart;
-    __gshared size_t      nAboutToStart;
+    private __gshared ThreadBase* pAboutToStart;
+    private __gshared size_t      nAboutToStart;
 
     //
     // Used for ordering threads in the global thread list.
@@ -658,6 +658,12 @@ package(core.thread):
     // Global Thread List Operations
     ///////////////////////////////////////////////////////////////////////////
 
+    package static void incrementAboutToStart(ThreadBase t) nothrow @nogc
+    {
+        ++nAboutToStart;
+        pAboutToStart = cast(ThreadBase*)realloc(pAboutToStart, ThreadBase.sizeof * nAboutToStart);
+        pAboutToStart[nAboutToStart - 1] = t;
+    }
 
     //
     // Add a thread to the global thread list.
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index 710f4cc90d171f66cdd6c27ee8b09bd338d0fcf3..4264ecf6fd62f8c1de2d95e27f5e5c32e1a3398c 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -65,7 +65,7 @@ alias ptrdiff_t = typeof(cast(void*)0 - cast(void*)0);
 alias sizediff_t = ptrdiff_t; // For backwards compatibility only.
 /**
  * Bottom type.
- * See $(DDSUBLINK spec/type, noreturn).
+ * See $(DDSUBLINK spec/type, noreturn, `noreturn`).
  */
 alias noreturn = typeof(*null);
 
@@ -1667,11 +1667,12 @@ class TypeInfo_Class : TypeInfo
     void*      deallocator;
     OffsetTypeInfo[] m_offTi;
     void function(Object) defaultConstructor;   // default Constructor
-    ulong[2] nameSig;            /// unique signature for `name`
 
     immutable(void)* m_RTInfo;        // data for precise GC
     override @property immutable(void)* rtInfo() const { return m_RTInfo; }
 
+    uint[4] nameSig;            /// unique signature for `name`
+
     /**
      * Search all modules for TypeInfo_Class corresponding to classname.
      * Returns: null if not found
diff --git a/libphobos/libdruntime/rt/cast_.d b/libphobos/libdruntime/rt/cast_.d
index 44e0f7a9cccaba4e377adb77baa6bdb301a9498f..43ddd5a9316490cc186a8216739b2eea1ac14559 100644
--- a/libphobos/libdruntime/rt/cast_.d
+++ b/libphobos/libdruntime/rt/cast_.d
@@ -24,11 +24,18 @@ pure:
 extern (D) private bool areClassInfosEqual(scope const ClassInfo a, scope const ClassInfo b) @safe
 {
     // same class if signatures match, works with potential duplicates across binaries
-    return a is b ||
-        (a.m_flags & TypeInfo_Class.ClassFlags.hasNameSig
-        ? (a.nameSig[0] == b.nameSig[0] &&
-           a.nameSig[1] == b.nameSig[1])  // new fast way
-        : (a is b || a.name == b.name));  // old slow way for temporary binary compatibility
+    if (a is b)
+        return true;
+
+    // new fast way
+    if (a.m_flags & TypeInfo_Class.ClassFlags.hasNameSig)
+        return a.nameSig[0] == b.nameSig[0]
+            && a.nameSig[1] == b.nameSig[1]
+            && a.nameSig[2] == b.nameSig[2]
+            && a.nameSig[3] == b.nameSig[3];
+
+    // old slow way for temporary binary compatibility
+    return a.name == b.name;
 }
 
 /******************************************
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index b04aee2c5816255899039e41ddd52a0e30578c40..1d41231db9dd250fdadc5d9878586db933b3cd7c 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-c6e1f98fab2cac046ed631b5c26c850a323aea53
+6d6e0b9b9fb5e882c7296f719baf829feb4939a3
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/bitmanip.d b/libphobos/src/std/bitmanip.d
index e9f61919b0dbedb028fc6c4d73f2cc3adaabd307..c9813e35476dfb94610b8a7ff51fa291a7c806be 100644
--- a/libphobos/src/std/bitmanip.d
+++ b/libphobos/src/std/bitmanip.d
@@ -263,9 +263,9 @@ Implementation_details: `Bitfields` are internally stored in an
 `ubyte`, `ushort`, `uint` or `ulong` depending on the number of bits
 used. The bits are filled in the order given by the parameters,
 starting with the lowest significant bit. The name of the (private)
-variable used for saving the `bitfield` is created by a prefix `_bf`
-and concatenating all of the variable names, each preceded by an
-underscore.
+variable used for saving the `bitfield` is created by concatenating
+all of the variable names, each preceded by an underscore, and
+a suffix `_bf`.
 
 Params: T = A list of template parameters divided into chunks of 3
             items. Each chunk consists (in this order) of a type, a
diff --git a/libphobos/src/std/range/primitives.d b/libphobos/src/std/range/primitives.d
index fec5c85cbef8e162db9139c295330cab4e829e94..dddcae9afd2ecde76e985d841d57b9156658c3b9 100644
--- a/libphobos/src/std/range/primitives.d
+++ b/libphobos/src/std/range/primitives.d
@@ -1011,6 +1011,15 @@ have a `save` function.
 
 See_Also:
     The header of $(MREF std,range) for tutorials on ranges.
+
+Params:
+    R = type to be tested
+    E = if present, the elements of the range must be
+        $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible)
+        to this type
+
+Returns:
+    `true` if R is a forward range (possibly with element type `E`), `false` if not
  */
 enum bool isForwardRange(R) = isInputRange!R
     && is(typeof((R r) { return r.save; } (R.init)) == R);
@@ -1068,12 +1077,25 @@ element in the range. Calling `r.back` is allowed only if calling
 
 See_Also:
     The header of $(MREF std,range) for tutorials on ranges.
+
+Params:
+    R = type to be tested
+    E = if present, the elements of the range must be
+        $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible)
+        to this type
+
+Returns:
+    `true` if R is a bidirectional range (possibly with element type `E`), `false` if not
  */
 enum bool isBidirectionalRange(R) = isForwardRange!R
     && is(typeof((R r) => r.popBack))
     && (is(typeof((return ref R r) => r.back)) || is(typeof(ref (return ref R r) => r.back)))
     && is(typeof(R.init.back.init) == ElementType!R);
 
+/// ditto
+enum bool isBidirectionalRange(R, E) =
+    .isBidirectionalRange!R && isQualifierConvertible!(ElementType!R, E);
+
 ///
 @safe unittest
 {
@@ -1084,6 +1106,18 @@ enum bool isBidirectionalRange(R) = isForwardRange!R
     auto t = r.back;                           // can get the back of the range
     auto w = r.front;
     static assert(is(typeof(t) == typeof(w))); // same type for front and back
+
+    // Checking the element type
+    static assert( isBidirectionalRange!(int[], const int));
+    static assert(!isBidirectionalRange!(int[], immutable int));
+
+    static assert(!isBidirectionalRange!(const(int)[], int));
+    static assert( isBidirectionalRange!(const(int)[], const int));
+    static assert(!isBidirectionalRange!(const(int)[], immutable int));
+
+    static assert(!isBidirectionalRange!(immutable(int)[], int));
+    static assert( isBidirectionalRange!(immutable(int)[], const int));
+    static assert( isBidirectionalRange!(immutable(int)[], immutable int));
 }
 
 @safe unittest
@@ -1133,6 +1167,15 @@ are bidirectional ranges only.
 
 See_Also:
     The header of $(MREF std,range) for tutorials on ranges.
+
+Params:
+    R = type to be tested
+    E = if present, the elements of the range must be
+        $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible)
+        to this type
+
+Returns:
+    `true` if R is a random-access range (possibly with element type `E`), `false` if not
  */
 enum bool isRandomAccessRange(R) =
     is(typeof(lvalueOf!R[1]) == ElementType!R)
@@ -1143,6 +1186,10 @@ enum bool isRandomAccessRange(R) =
     && (isInfinite!R || !is(typeof(lvalueOf!R[$ - 1]))
         || is(typeof(lvalueOf!R[$ - 1]) == ElementType!R));
 
+/// ditto
+enum bool isRandomAccessRange(R, E) =
+    .isRandomAccessRange!R && isQualifierConvertible!(ElementType!R, E);
+
 ///
 @safe unittest
 {
@@ -1171,6 +1218,18 @@ enum bool isRandomAccessRange(R) =
         static if (!isInfinite!R)
             static assert(is(typeof(f) == typeof(r[$ - 1])));
     }
+
+    // Checking the element type
+    static assert( isRandomAccessRange!(int[], const int));
+    static assert(!isRandomAccessRange!(int[], immutable int));
+
+    static assert(!isRandomAccessRange!(const(int)[], int));
+    static assert( isRandomAccessRange!(const(int)[], const int));
+    static assert(!isRandomAccessRange!(const(int)[], immutable int));
+
+    static assert(!isRandomAccessRange!(immutable(int)[], int));
+    static assert( isRandomAccessRange!(immutable(int)[], const int));
+    static assert( isRandomAccessRange!(immutable(int)[], immutable int));
 }
 
 @safe unittest
@@ -1695,11 +1754,9 @@ For finite ranges, the result of `opSlice` must be of the same type as the
 original range type. If the range defines `opDollar`, then it must support
 subtraction.
 
-For infinite ranges, when $(I not) using `opDollar`, the result of
-`opSlice` must be the result of $(LREF take) or $(LREF takeExactly) on the
-original range (they both return the same type for infinite ranges). However,
-when using `opDollar`, the result of `opSlice` must be that of the
-original range type.
+For infinite ranges, when $(I not) using `opDollar`, the result of `opSlice`
+may be a forward range of any type. However, when using `opDollar`, the result
+of `opSlice` must be of the same type as the original range type.
 
 The following expression must be true for `hasSlicing` to be `true`:
 
@@ -1774,6 +1831,38 @@ enum bool hasSlicing(R) = isForwardRange!R
     static assert(hasSlicing!InfOnes);
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=24348
+@safe unittest
+{
+    static struct Slice
+    {
+        size_t length;
+        bool empty() => length == 0;
+        int front() => 0;
+        void popFront() { --length; }
+        Slice save() => this;
+    }
+
+    static struct InfZeros
+    {
+        enum empty = false;
+        int front() => 0;
+        void popFront() {}
+        InfZeros save() => this;
+
+        Slice opIndex(size_t[2] bounds)
+        {
+            size_t i = bounds[0], j = bounds[1];
+            size_t length = i <= j ? j - i : 0;
+            return Slice(length);
+        }
+
+        size_t[2] opSlice(size_t dim : 0)(size_t i, size_t j) => [i, j];
+    }
+
+    static assert(hasSlicing!InfZeros);
+}
+
 /**
 This is a best-effort implementation of `length` for any kind of
 range.