diff mbox series

[committed] d: Merge upstream dmd 2503f17e5, phobos a74fa63e6.

Message ID 20220321195721.1638883-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Merge upstream dmd 2503f17e5, phobos a74fa63e6. | expand

Commit Message

Iain Buclaw March 21, 2022, 7:57 p.m. UTC
Hi,

This patch merges the D front-end with upstream dmd 2503f17e5, and
the standard library with phobos a74fa63e6.

D front-end changes:

    - Import dmd mainline development.
    - Removed internal d_intN and d_unsN aliases to stdint types, which
      caused a regression on Solaris where int8_t is a char (PR104911).

Phobos changes:

    - Import phobos mainline development.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and
committed to mainline.

Regards,
Iain.

---
	PR d/104911

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 2503f17e5.
	* d-convert.cc (convert_expr): Replace d_uns64 with dinteger_t.
	* d-lang.cc: Remove dmd/root/file.h include.
	(d_handle_option): Update for new front-end interface.
	(d_parse_file): Likewise.

libphobos/ChangeLog:

	* src/MERGE: Merge upstream phobos a74fa63e6.
---
 gcc/d/d-codegen.cc                            |   2 +-
 gcc/d/d-convert.cc                            |   4 +-
 gcc/d/d-lang.cc                               |  20 +-
 gcc/d/dmd/MERGE                               |   2 +-
 gcc/d/dmd/aggregate.d                         |   2 +-
 gcc/d/dmd/aggregate.h                         |   2 +-
 gcc/d/dmd/astenums.d                          |   9 +
 gcc/d/dmd/attrib.d                            |   8 +-
 gcc/d/dmd/blockexit.d                         |   2 +-
 gcc/d/dmd/canthrow.d                          |   2 +-
 gcc/d/dmd/constfold.d                         |  50 ++---
 gcc/d/dmd/cparse.d                            | 175 +++++++++++++++---
 gcc/d/dmd/cppmangle.d                         |   2 +
 gcc/d/dmd/ctfeexpr.d                          |  65 +++----
 gcc/d/dmd/dcast.d                             |   8 +-
 gcc/d/dmd/declaration.d                       |   8 +-
 gcc/d/dmd/declaration.h                       |   3 +-
 gcc/d/dmd/dinterpret.d                        |  84 +++------
 gcc/d/dmd/dmacro.d                            |  29 +--
 gcc/d/dmd/dmodule.d                           |  78 +++-----
 gcc/d/dmd/doc.d                               |   4 +-
 gcc/d/dmd/dscope.d                            |   2 +-
 gcc/d/dmd/dsymbol.d                           |   7 +-
 gcc/d/dmd/dsymbol.h                           |   2 +-
 gcc/d/dmd/dsymbolsem.d                        | 134 +++++++++++---
 gcc/d/dmd/dtemplate.d                         |   4 +-
 gcc/d/dmd/dtoh.d                              |  25 ++-
 gcc/d/dmd/escape.d                            | 120 ++++++++----
 gcc/d/dmd/expression.d                        |  22 +--
 gcc/d/dmd/expressionsem.d                     |  18 +-
 gcc/d/dmd/file_manager.d                      | 133 +++++++------
 gcc/d/dmd/file_manager.h                      |  19 --
 gcc/d/dmd/globals.d                           |  19 +-
 gcc/d/dmd/globals.h                           |  19 +-
 gcc/d/dmd/hdrgen.d                            |   1 -
 gcc/d/dmd/id.d                                |   3 +
 gcc/d/dmd/importc.d                           |  22 ++-
 gcc/d/dmd/lexer.d                             |  14 +-
 gcc/d/dmd/module.h                            |   6 +-
 gcc/d/dmd/mtype.d                             |  52 +++---
 gcc/d/dmd/mtype.h                             |  40 ++--
 gcc/d/dmd/optimize.d                          |   8 +-
 gcc/d/dmd/parse.d                             |   6 +-
 gcc/d/dmd/root/file.h                         |  41 ----
 gcc/d/dmd/root/filename.d                     |   7 +-
 gcc/d/dmd/root/string.d                       |   6 +-
 gcc/d/dmd/semantic2.d                         |  11 +-
 gcc/d/dmd/semantic3.d                         |  16 +-
 gcc/d/dmd/statementsem.d                      |  33 ++--
 gcc/d/dmd/target.d                            |  37 ++--
 gcc/d/dmd/target.h                            |  14 +-
 gcc/d/dmd/template.h                          |   1 +
 gcc/d/dmd/tokens.d                            |   6 +-
 gcc/d/dmd/traits.d                            |  48 ++---
 gcc/d/dmd/typesem.d                           |  25 +--
 gcc/testsuite/gdc.dg/pr105004.d               |  14 ++
 .../compilable/dtoh_AliasDeclaration.d        |   1 -
 .../compilable/dtoh_StructDeclaration.d       |  47 ++++-
 .../compilable/dtoh_TemplateDeclaration.d     |  18 --
 .../gdc.test/compilable/dtoh_forwarding.d     |   3 -
 .../gdc.test/compilable/dtoh_ignored.d        |   2 -
 .../compilable/dtoh_invalid_identifiers.d     |   2 -
 .../gdc.test/compilable/dtoh_names.d          |  12 --
 .../compilable/dtoh_required_symbols.d        |   4 +-
 gcc/testsuite/gdc.test/compilable/scope.d     |   2 +-
 .../gdc.test/fail_compilation/fail19948.d     |  18 ++
 .../gdc.test/fail_compilation/fail22881.d     |  60 ++++++
 .../gdc.test/fail_compilation/pull12941.d     |   4 +-
 .../gdc.test/fail_compilation/retscope2.d     |   2 +-
 .../gdc.test/fail_compilation/test15191.d     |   2 +-
 .../gdc.test/fail_compilation/test17422.d     |   2 +-
 .../gdc.test/fail_compilation/test20881.d     |  30 +++
 .../gdc.test/fail_compilation/test21912.d     |   4 +-
 .../runnable_cxx/extra-files/test22898.cpp    |   7 +
 .../gdc.test/runnable_cxx/test22898.d         |  28 +++
 libphobos/src/MERGE                           |   2 +-
 libphobos/src/std/conv.d                      |  35 ++--
 libphobos/src/std/sumtype.d                   |  35 +++-
 libphobos/src/std/traits.d                    |  40 ++++
 libphobos/src/std/uni/package.d               |   4 +-
 80 files changed, 1113 insertions(+), 745 deletions(-)
 delete mode 100644 gcc/d/dmd/file_manager.h
 delete mode 100644 gcc/d/dmd/root/file.h
 create mode 100644 gcc/testsuite/gdc.dg/pr105004.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail19948.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail22881.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test20881.d
 create mode 100644 gcc/testsuite/gdc.test/runnable_cxx/extra-files/test22898.cpp
 create mode 100644 gcc/testsuite/gdc.test/runnable_cxx/test22898.d
diff mbox series

Patch

diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 3e54d3bffd0..3206edd17e8 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -1161,7 +1161,7 @@  build_struct_literal (tree type, vec <constructor_elt, va_gc> *init)
   if (COMPLEX_FLOAT_TYPE_P (type))
     {
       gcc_assert (vec_safe_length (init) == 2);
-      return build_complex (type, (*init)[0].value, (*init)[1].value);
+      return complex_expr (type, (*init)[0].value, (*init)[1].value);
     }
 
   vec <constructor_elt, va_gc> *ve = NULL;
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index 5a7a64fdac1..3a6a32ab024 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -518,8 +518,8 @@  convert_expr (tree exp, Type *etype, Type *totype)
       else if (tbtype->ty == TY::Tarray)
 	{
 	  /* Assume tvoid->size() == 1.  */
-	  d_uns64 fsize = ebtype->nextOf ()->toBasetype ()->size ();
-	  d_uns64 tsize = tbtype->nextOf ()->toBasetype ()->size ();
+	  dinteger_t fsize = ebtype->nextOf ()->toBasetype ()->size ();
+	  dinteger_t tsize = tbtype->nextOf ()->toBasetype ()->size ();
 
 	  if (fsize != tsize)
 	    {
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index f887840f4bf..4a7aa8983b7 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -32,7 +32,6 @@  along with GCC; see the file COPYING3.  If not see
 #include "dmd/mangle.h"
 #include "dmd/module.h"
 #include "dmd/mtype.h"
-#include "dmd/root/file.h"
 #include "dmd/target.h"
 
 #include "opts.h"
@@ -579,7 +578,7 @@  d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       global.params.fix16997 = value;
       global.params.markdown = value;
       global.params.noSharedAccess = value;
-      global.params.rvalueRefParam = value;
+      global.params.rvalueRefParam = FeatureState::enabled;
       global.params.inclusiveInContracts = value;
       global.params.shortenedMethods = value;
       break;
@@ -625,7 +624,7 @@  d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       break;
 
     case OPT_fpreview_rvaluerefparam:
-      global.params.rvalueRefParam = value;
+      global.params.rvalueRefParam = FeatureState::enabled;
       break;
 
     case OPT_fpreview_shortenedmethods:
@@ -1069,9 +1068,8 @@  d_parse_file (void)
 
 	  /* Overwrite the source file for the module, the one created by
 	     Module::create would have a forced a `.d' suffix.  */
-	  m->srcBuffer = FileBuffer::create ();
-	  m->srcBuffer->data.length = len;
-	  m->srcBuffer->data.ptr = buffer;
+	  m->src.length = len;
+	  m->src.ptr = buffer;
 	}
       else
 	{
@@ -1108,7 +1106,7 @@  d_parse_file (void)
       m->importedFrom = m;
       m->parse ();
 
-      if (m->isDocFile)
+      if (m->filetype == FileType::ddoc)
 	{
 	  gendocfile (m);
 	  /* Remove M from list of modules.  */
@@ -1146,7 +1144,8 @@  d_parse_file (void)
       for (size_t i = 0; i < modules.length; i++)
 	{
 	  Module *m = modules[i];
-	  if (m->isHdrFile || (d_option.fonly && m != Module::rootModule))
+	  if (m->filetype == FileType::dhdr
+	      || (d_option.fonly && m != Module::rootModule))
 	    continue;
 
 	  if (global.params.verbose)
@@ -1374,7 +1373,7 @@  d_parse_file (void)
 
       /* Skip generating code for header files, or when the module wasn't
 	 specified by `-fonly=`.  */
-      if ((m->isHdrFile && m != main_module)
+      if ((m->filetype == FileType::dhdr && m != main_module)
 	  || (d_option.fonly && m != Module::rootModule))
 	continue;
 
@@ -1421,7 +1420,8 @@  d_parse_file (void)
       for (size_t i = 0; i < modules.length; i++)
 	{
 	  Module *m = modules[i];
-	  if (m->isHdrFile || (d_option.fonly && m != Module::rootModule))
+	  if (m->filetype == FileType::dhdr
+	      || (d_option.fonly && m != Module::rootModule))
 	    continue;
 
 	  remove (m->hdrfile.toChars ());
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 220088969c5..3e3e1134452 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-cbba5f41a32cfed7f22a213d537f8e2dee0b92f7
+2503f17e5767bc4fcd0cf3889c90fa0415b0edaa
 
 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/aggregate.d b/gcc/d/dmd/aggregate.d
index 1add36a0299..f790730fce9 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -234,7 +234,7 @@  extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
 
     abstract void finalizeSize();
 
-    override final d_uns64 size(const ref Loc loc)
+    override final uinteger_t size(const ref Loc loc)
     {
         //printf("+AggregateDeclaration::size() %s, scope = %p, sizeok = %d\n", toChars(), _scope, sizeok);
         bool ok = determineSize(loc);
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index 796144ac810..bdeb38e8b45 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -124,7 +124,7 @@  public:
     size_t nonHiddenFields();
     bool determineSize(const Loc &loc);
     virtual void finalizeSize() = 0;
-    d_uns64 size(const Loc &loc);
+    uinteger_t size(const Loc &loc);
     bool fill(const Loc &loc, Expressions *elements, bool ctorinit);
     Type *getType();
     bool isDeprecated() const;         // is aggregate deprecated?
diff --git a/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d
index ea10c4e9c40..1a2cf8b0641 100644
--- a/gcc/d/dmd/astenums.d
+++ b/gcc/d/dmd/astenums.d
@@ -430,3 +430,12 @@  enum PINLINE : ubyte
     never,    /// never inline
     always,   /// always inline
 }
+
+/// Source file type
+enum FileType : ubyte
+{
+    d,    /// normal D source file
+    dhdr, /// D header file (.di)
+    ddoc, /// Ddoc documentation file (.dd)
+    c,    /// C source file
+}
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index cf9e9ce5a22..9c2bbd672a7 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -247,12 +247,12 @@  extern (C++) class StorageClassDeclaration : AttribDeclaration
          */
         if (stc & (STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.manifest))
             scstc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.manifest);
-        if (stc & (STC.auto_ | STC.scope_ | STC.static_ | STC.tls | STC.manifest | STC.gshared))
-            scstc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.tls | STC.manifest | STC.gshared);
+        if (stc & (STC.auto_ | STC.scope_ | STC.static_ | STC.manifest | STC.gshared))
+            scstc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.manifest | STC.gshared);
         if (stc & (STC.const_ | STC.immutable_ | STC.manifest))
             scstc &= ~(STC.const_ | STC.immutable_ | STC.manifest);
-        if (stc & (STC.gshared | STC.shared_ | STC.tls))
-            scstc &= ~(STC.gshared | STC.shared_ | STC.tls);
+        if (stc & (STC.gshared | STC.shared_))
+            scstc &= ~(STC.gshared | STC.shared_);
         if (stc & (STC.safe | STC.trusted | STC.system))
             scstc &= ~(STC.safe | STC.trusted | STC.system);
         scstc |= stc;
diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d
index 5132a2dc46a..5c012049342 100644
--- a/gcc/d/dmd/blockexit.d
+++ b/gcc/d/dmd/blockexit.d
@@ -146,7 +146,7 @@  int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
                             else if (sd && (!sd.statement.hasCode() || sd.statement.isCaseStatement() || sd.statement.isErrorStatement()))
                             {
                             }
-                            else if (!func.getModule().isCFile)
+                            else if (func.getModule().filetype != FileType.c)
                             {
                                 const(char)* gototype = s.isCaseStatement() ? "case" : "default";
                                 s.error("switch case fallthrough - use 'goto %s;' if intended", gototype);
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index 745e552a8e2..a38cbb1610b 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -246,7 +246,7 @@  private CT Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow)
         if (vd.storage_class & STC.manifest)
         {
         }
-        else if (vd.isStatic() || vd.storage_class & (STC.extern_ | STC.tls | STC.gshared))
+        else if (vd.isStatic() || vd.storage_class & (STC.extern_ | STC.gshared))
         {
         }
         else
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index 96ca5207511..9941c167b06 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -619,31 +619,31 @@  UnionExp Shr(const ref Loc loc, Type type, Expression e1, Expression e2)
     switch (e1.type.toBasetype().ty)
     {
     case Tint8:
-        value = cast(d_int8)value >> count;
+        value = cast(byte)value >> count;
         break;
     case Tuns8:
     case Tchar:
-        value = cast(d_uns8)value >> count;
+        value = cast(ubyte)value >> count;
         break;
     case Tint16:
-        value = cast(d_int16)value >> count;
+        value = cast(short)value >> count;
         break;
     case Tuns16:
     case Twchar:
-        value = cast(d_uns16)value >> count;
+        value = cast(ushort)value >> count;
         break;
     case Tint32:
-        value = cast(d_int32)value >> count;
+        value = cast(int)value >> count;
         break;
     case Tuns32:
     case Tdchar:
-        value = cast(d_uns32)value >> count;
+        value = cast(uint)value >> count;
         break;
     case Tint64:
-        value = cast(d_int64)value >> count;
+        value = cast(long)value >> count;
         break;
     case Tuns64:
-        value = cast(d_uns64)value >> count;
+        value = cast(ulong)value >> count;
         break;
     case Terror:
         emplaceExp!(ErrorExp)(&ue);
@@ -1106,31 +1106,31 @@  UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
             switch (typeb.ty)
             {
             case Tint8:
-                result = cast(d_int8)cast(sinteger_t)r;
+                result = cast(byte)cast(sinteger_t)r;
                 break;
             case Tchar:
             case Tuns8:
-                result = cast(d_uns8)cast(dinteger_t)r;
+                result = cast(ubyte)cast(dinteger_t)r;
                 break;
             case Tint16:
-                result = cast(d_int16)cast(sinteger_t)r;
+                result = cast(short)cast(sinteger_t)r;
                 break;
             case Twchar:
             case Tuns16:
-                result = cast(d_uns16)cast(dinteger_t)r;
+                result = cast(ushort)cast(dinteger_t)r;
                 break;
             case Tint32:
-                result = cast(d_int32)r;
+                result = cast(int)r;
                 break;
             case Tdchar:
             case Tuns32:
-                result = cast(d_uns32)r;
+                result = cast(uint)r;
                 break;
             case Tint64:
-                result = cast(d_int64)r;
+                result = cast(long)r;
                 break;
             case Tuns64:
-                result = cast(d_uns64)r;
+                result = cast(ulong)r;
                 break;
             default:
                 assert(0);
@@ -1348,14 +1348,6 @@  UnionExp Slice(Type type, Expression e1, Expression lwr, Expression upr)
         }
     }
 
-    static bool sliceBoundsCheck(uinteger_t lwr, uinteger_t upr, uinteger_t newlwr, uinteger_t newupr) pure
-    {
-        assert(lwr <= upr);
-        return !(newlwr <= newupr &&
-                 lwr <= newlwr &&
-                 newupr <= upr);
-    }
-
     if (e1.op == EXP.string_ && lwr.op == EXP.int64 && upr.op == EXP.int64)
     {
         StringExp es1 = cast(StringExp)e1;
@@ -1395,6 +1387,16 @@  UnionExp Slice(Type type, Expression e1, Expression lwr, Expression upr)
     return ue;
 }
 
+/* Check whether slice `[newlwr .. newupr]` is in the range `[lwr .. upr]`
+ */
+bool sliceBoundsCheck(uinteger_t lwr, uinteger_t upr, uinteger_t newlwr, uinteger_t newupr) pure
+{
+    assert(lwr <= upr);
+    return !(newlwr <= newupr &&
+             lwr <= newlwr &&
+             newupr <= upr);
+}
+
 /* Set a slice of char/integer array literal 'existingAE' from a string 'newval'.
  * existingAE[firstIndex..firstIndex+newval.length] = newval.
  */
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 2edab14c2a4..fb52b63fe29 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -48,14 +48,16 @@  final class CParser(AST) : Parser!AST
         Array!structalign_t* packs;     // parallel alignment values
     }
 
-    /** C allows declaring a function with a typedef:
-     *   typedef int (myfunc)(); myfunc fun;
-     * but we need to distinguish `fun` being a function as opposed to a variable in the
-     * parse pass. This is accomplished by having a simple symbol table of typedefs
-     * where we know, by syntax, if they are function types or non-function types.
-     * funcTypeIds is the symbol table, of the identifiers of typedefs of function types.
+    /* C cannot be parsed without determining if an identifier is a type or a variable.
+     * For expressions like `(T)-3`, is it a cast or a minus expression?
+     * It also occurs with `typedef int (F)(); F fun;`
+     * but to build the AST we need to distinguish `fun` being a function as opposed to a variable.
+     * To fix, build a symbol table for the typedefs.
+     * Symbol table of typedefs indexed by Identifier cast to void*.
+     * 1. if an identifier is a typedef, then it will return a non-null Type
+     * 2. if an identifier is not a typedef, then it will return null
      */
-    AST.Identifiers funcTypeIds;  /// Identifiers in this are typedefs of function types
+    Array!(void*) typedefTab;  /// Array of AST.Type[Identifier], typedef's indexed by Identifier
 
     extern (D) this(TARGET)(AST.Module _module, const(char)[] input, bool doDocComment,
                             const ref TARGET target)
@@ -97,6 +99,7 @@  final class CParser(AST) : Parser!AST
     {
         //printf("cparseTranslationUnit()\n");
         symbols = new AST.Dsymbols();
+        typedefTab.push(null);  // C11 6.2.1-3 symbol table for "file scope"
         while (1)
         {
             if (token.value == TOK.endOfFile)
@@ -115,6 +118,10 @@  final class CParser(AST) : Parser!AST
                     wrap.push(s);
                 }
 
+                // end of file scope
+                typedefTab.pop();
+                assert(typedefTab.length == 0);
+
                 return wrap;
             }
 
@@ -150,10 +157,17 @@  final class CParser(AST) : Parser!AST
 
         //printf("cparseStatement()\n");
 
-        const funcTypeIdsLengthSave = funcTypeIds.length;
+        const typedefTabLengthSave = typedefTab.length;
         auto symbolsSave = symbols;
+        if (flags & ParseStatementFlags.scope_)
+        {
+            typedefTab.push(null);      // introduce new block scope
+        }
+
         if (!(flags & (ParseStatementFlags.scope_ | ParseStatementFlags.curlyScope)))
+        {
             symbols = new AST.Dsymbols();
+        }
 
         switch (token.value)
         {
@@ -593,7 +607,7 @@  final class CParser(AST) : Parser!AST
         if (pEndloc)
             *pEndloc = prevloc;
         symbols = symbolsSave;
-        funcTypeIds.setDim(funcTypeIdsLengthSave);
+        typedefTab.setDim(typedefTabLengthSave);
         return s;
     }
 
@@ -1002,8 +1016,18 @@  final class CParser(AST) : Parser!AST
     {
         if (token.value == TOK.leftParenthesis)
         {
+            auto tk = peek(&token);
+            if (tk.value == TOK.identifier &&
+                !isTypedef(tk.ident) &&
+                peek(tk).value == TOK.rightParenthesis)
+            {
+                // ( identifier ) is an expression
+                return cparseUnaryExp();
+            }
+
             // If ( type-name )
             auto pt = &token;
+
             if (isCastExpression(pt))
             {
                 // Expression may be either a cast or a compound literal, which
@@ -1573,7 +1597,7 @@  final class CParser(AST) : Parser!AST
             return;
         }
 
-        const funcTypeIdsLengthSave = funcTypeIds.length;
+        const typedefTabLengthSave = typedefTab.length;
         auto symbolsSave = symbols;
         Specifier specifier;
         specifier.packalign = this.packalign;
@@ -1683,13 +1707,13 @@  final class CParser(AST) : Parser!AST
                 t.value == TOK.leftCurly)  // start of compound-statement
             {
                 auto s = cparseFunctionDefinition(id, dt.isTypeFunction(), specifier);
-                funcTypeIds.setDim(funcTypeIdsLengthSave);
+                typedefTab.setDim(typedefTabLengthSave);
                 symbols = symbolsSave;
                 symbols.push(s);
                 return;
             }
             AST.Dsymbol s = null;
-            funcTypeIds.setDim(funcTypeIdsLengthSave);
+            typedefTab.setDim(typedefTabLengthSave);
             symbols = symbolsSave;
             if (!symbols)
                 symbols = new AST.Dsymbols;     // lazilly create it
@@ -1747,12 +1771,9 @@  final class CParser(AST) : Parser!AST
                         }
                     }
                 }
-                else if (isFunctionTypedef(dt))
-                {
-                    funcTypeIds.push(id);       // remember function typedefs
-                }
                 if (isalias)
                     s = new AST.AliasDeclaration(token.loc, id, dt);
+                insertTypedefToTypedefTab(id, dt);       // remember typedefs
             }
             else if (id)
             {
@@ -1791,6 +1812,8 @@  final class CParser(AST) : Parser!AST
                         initializer = new AST.VoidInitializer(token.loc);
                     s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(level, specifier));
                 }
+                if (level != LVL.global)
+                    insertIdToTypedefTab(id);   // non-typedef declarations can hide typedefs in outer scopes
             }
             if (s !is null)
             {
@@ -1868,6 +1891,10 @@  final class CParser(AST) : Parser!AST
      */
     AST.Dsymbol cparseFunctionDefinition(Identifier id, AST.TypeFunction ft, ref Specifier specifier)
     {
+        /* Start function scope
+         */
+        typedefTab.push(null);
+
         if (token.value != TOK.leftCurly)       // if not start of a compound-statement
         {
             // Do declaration-list
@@ -1930,6 +1957,8 @@  final class CParser(AST) : Parser!AST
         const locFunc = token.loc;
 
         auto body = cparseStatement(ParseStatementFlags.curly);  // don't start a new scope; continue with parameter scope
+        typedefTab.pop();                                        // end of function scope
+
         auto fd = new AST.FuncDeclaration(locFunc, prevloc, id, specifiersToSTC(LVL.global, specifier), ft, specifier.noreturn);
 
         if (addFuncName)
@@ -2737,6 +2766,16 @@  final class CParser(AST) : Parser!AST
             return AST.ParameterList(parameters, AST.VarArg.variadic, varargsStc);
         }
 
+        /* Create function prototype scope
+         */
+        typedefTab.push(null);
+
+        AST.ParameterList finish()
+        {
+            typedefTab.pop();
+            return AST.ParameterList(parameters, varargs, varargsStc);
+        }
+
         /* The check for identifier-list comes later,
          * when doing the trailing declaration-list (opt)
          */
@@ -2752,7 +2791,7 @@  final class CParser(AST) : Parser!AST
                 varargs = AST.VarArg.variadic;  // C-style variadics
                 nextToken();
                 check(TOK.rightParenthesis);
-                return AST.ParameterList(parameters, varargs, varargsStc);
+                return finish();
             }
 
             Specifier specifier;
@@ -2777,7 +2816,7 @@  final class CParser(AST) : Parser!AST
             check(TOK.comma);
         }
         nextToken();
-        return AST.ParameterList(parameters, varargs, varargsStc);
+        return finish();
     }
 
     /***********************************
@@ -4121,12 +4160,14 @@  final class CParser(AST) : Parser!AST
      *    ( expression )
      * Params:
      *    pt = starting token, updated to one past end of constant-expression if true
-     *    afterParenType = true if already seen ( type-name )
+     *    afterParenType = true if already seen `( type-name )`
      * Returns:
      *    true if matches ( type-name ) ...
      */
     private bool isCastExpression(ref Token* pt, bool afterParenType = false)
     {
+        enum log = false;
+        if (log) printf("isCastExpression(tk: `%s`, afterParenType: %d)\n", token.toChars(pt.value), afterParenType);
         auto t = pt;
         switch (t.value)
         {
@@ -4144,19 +4185,23 @@  final class CParser(AST) : Parser!AST
                 {
                     // ( type-name ) { initializer-list }
                     if (!isInitializer(tk))
+                    {
                         return false;
+                    }
                     t = tk;
                     break;
                 }
 
                 if (tk.value == TOK.leftParenthesis && peek(tk).value == TOK.rightParenthesis)
+                {
                     return false;    // (type-name)() is not a cast (it might be a function call)
+                }
 
                 if (!isCastExpression(tk, true))
                 {
                     if (afterParenType) // could be ( type-name ) ( unary-expression )
                         goto default;   // where unary-expression also matched type-name
-                    return false;
+                    return true;
                 }
                 // ( type-name ) cast-expression
                 t = tk;
@@ -4164,11 +4209,14 @@  final class CParser(AST) : Parser!AST
 
             default:
                 if (!afterParenType || !isUnaryExpression(t, afterParenType))
+                {
                     return false;
+                }
                 // if we've already seen ( type-name ), then this is a cast
                 break;
         }
         pt = t;
+        if (log) printf("isCastExpression true\n");
         return true;
     }
 
@@ -4576,9 +4624,14 @@  final class CParser(AST) : Parser!AST
         return s;
     }
 
+    //}
+
+    /******************************************************************************/
+    /************************** typedefTab symbol table ***************************/
+    //{
+
     /********************************
      * Determines if type t is a function type.
-     * Make this work without needing semantic analysis.
      * Params:
      *  t = type to test
      * Returns:
@@ -4591,20 +4644,84 @@  final class CParser(AST) : Parser!AST
             return true;
         if (auto tid = t.isTypeIdentifier())
         {
-            /* Scan array of typedef identifiers that are an alias for
-             * a function type
-             */
-            foreach (ftid; funcTypeIds[])
+            auto pt = lookupTypedef(tid.ident);
+            if (pt && *pt)
             {
-                if (tid.ident == ftid)
-                {
-                    return true;
-                }
+                return (*pt).isTypeFunction() !is null;
             }
         }
         return false;
     }
 
+    /********************************
+     * Determine if `id` is a symbol for a Typedef.
+     * Params:
+     *  id = possible typedef
+     * Returns:
+     *  true if id is a Type
+     */
+    bool isTypedef(Identifier id)
+    {
+        auto pt = lookupTypedef(id);
+        return (pt && *pt);
+    }
+
+    /*******************************
+     * Add `id` to typedefTab[], but only if it will mask an existing typedef.
+     * Params: id = identifier for non-typedef symbol
+     */
+    void insertIdToTypedefTab(Identifier id)
+    {
+        //printf("insertIdToTypedefTab(id: %s) level %d\n", id.toChars(), cast(int)typedefTab.length - 1);
+        if (isTypedef(id))  // if existing typedef
+        {
+            /* Add id as null, so we can later distinguish it from a non-null typedef
+             */
+            auto tab = cast(void*[void*])(typedefTab[$ - 1]);
+            tab[cast(void*)id] = cast(void*)null;
+        }
+    }
+
+    /*******************************
+     * Add `id` to typedefTab[]
+     * Params:
+     *  id = identifier for typedef symbol
+     *  t = type of the typedef symbol
+     */
+    void insertTypedefToTypedefTab(Identifier id, AST.Type t)
+    {
+        //printf("insertTypedefToTypedefTab(id: %s, t: %s) level %d\n", id.toChars(), t ? t.toChars() : "null".ptr, cast(int)typedefTab.length - 1);
+        if (auto tid = t.isTypeIdentifier())
+        {
+            // Try to resolve the TypeIdentifier to its type
+            auto pt = lookupTypedef(tid.ident);
+            if (pt && *pt)
+                t = *pt;
+        }
+        auto tab = cast(void*[void*])(typedefTab[$ - 1]);
+        tab[cast(void*)id] = cast(void*)t;
+        typedefTab[$ - 1] = cast(void*)tab;
+    }
+
+    /*********************************
+     * Lookup id in typedefTab[].
+     * Returns:
+     *  if not found, then null.
+     *  if found, then Type*. Deferencing it will yield null if it is not
+     *  a typedef, and a type if it is a typedef.
+     */
+    AST.Type* lookupTypedef(Identifier id)
+    {
+        foreach_reverse (tab; typedefTab[])
+        {
+            if (auto pt = cast(void*)id in cast(void*[void*])tab)
+            {
+                return cast(AST.Type*)pt;
+            }
+        }
+        return null; // not found
+    }
+
     //}
 
     /******************************************************************************/
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index 9564b03f753..13ef34c052b 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -1908,6 +1908,8 @@  extern(C++):
             return writeBasicType(t, 0, 'l');
         else if (id == Id.__c_ulong)
             return writeBasicType(t, 0, 'm');
+        else if (id == Id.__c_char)
+            return writeBasicType(t, 0, 'c');
         else if (id == Id.__c_wchar_t)
             return writeBasicType(t, 0, 'w');
         else if (id == Id.__c_longlong)
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index 9bc453de189..9078f90dc30 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -343,10 +343,9 @@  UnionExp copyLiteral(Expression e)
                 {
                     auto tsa = v.type.isTypeSArray();
                     auto len = cast(size_t)tsa.dim.toInteger();
-                    UnionExp uex = void;
-                    m = createBlockDuplicatedArrayLiteral(&uex, e.loc, v.type, m, len);
-                    if (m == uex.exp())
-                        m = uex.copy();
+                    m = createBlockDuplicatedArrayLiteral(&ue, e.loc, v.type, m, len);
+                    if (m == ue.exp())
+                        m = ue.copy();
                 }
             }
             el = m;
@@ -583,10 +582,9 @@  ArrayLiteralExp createBlockDuplicatedArrayLiteral(UnionExp* pue, const ref Loc l
         // If it is a multidimensional array literal, do it recursively
         auto tsa = type.nextOf().isTypeSArray();
         const len = cast(size_t)tsa.dim.toInteger();
-        UnionExp ue = void;
-        elem = createBlockDuplicatedArrayLiteral(&ue, loc, type.nextOf(), elem, len);
-        if (elem == ue.exp())
-            elem = ue.copy();
+        elem = createBlockDuplicatedArrayLiteral(pue, loc, type.nextOf(), elem, len);
+        if (elem == pue.exp())
+            elem = pue.copy();
     }
 
     // Buzilla 15681
@@ -791,9 +789,8 @@  bool pointToSameMemoryBlock(Expression agg1, Expression agg2)
 }
 
 // return e1 - e2 as an integer, or error if not possible
-UnionExp pointerDifference(const ref Loc loc, Type type, Expression e1, Expression e2)
+Expression pointerDifference(UnionExp* pue, const ref Loc loc, Type type, Expression e1, Expression e2)
 {
-    UnionExp ue = void;
     dinteger_t ofs1, ofs2;
     Expression agg1 = getAggregateFromPointer(e1, &ofs1);
     Expression agg2 = getAggregateFromPointer(e2, &ofs2);
@@ -801,39 +798,38 @@  UnionExp pointerDifference(const ref Loc loc, Type type, Expression e1, Expressi
     {
         Type pointee = (cast(TypePointer)agg1.type).next;
         const sz = pointee.size();
-        emplaceExp!(IntegerExp)(&ue, loc, (ofs1 - ofs2) * sz, type);
+        emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type);
     }
     else if (agg1.op == EXP.string_ && agg2.op == EXP.string_ &&
              (cast(StringExp)agg1).peekString().ptr == (cast(StringExp)agg2).peekString().ptr)
     {
         Type pointee = (cast(TypePointer)agg1.type).next;
         const sz = pointee.size();
-        emplaceExp!(IntegerExp)(&ue, loc, (ofs1 - ofs2) * sz, type);
+        emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type);
     }
     else if (agg1.op == EXP.symbolOffset && agg2.op == EXP.symbolOffset &&
              (cast(SymOffExp)agg1).var == (cast(SymOffExp)agg2).var)
     {
-        emplaceExp!(IntegerExp)(&ue, loc, ofs1 - ofs2, type);
+        emplaceExp!(IntegerExp)(pue, loc, ofs1 - ofs2, type);
     }
     else
     {
         error(loc, "`%s - %s` cannot be interpreted at compile time: cannot subtract pointers to two different memory blocks", e1.toChars(), e2.toChars());
-        emplaceExp!(CTFEExp)(&ue, EXP.cantExpression);
+        emplaceExp!(CTFEExp)(pue, EXP.cantExpression);
     }
-    return ue;
+    return pue.exp();
 }
 
 // Return eptr op e2, where eptr is a pointer, e2 is an integer,
 // and op is EXP.add or EXP.min
-UnionExp pointerArithmetic(const ref Loc loc, EXP op, Type type, Expression eptr, Expression e2)
+Expression pointerArithmetic(UnionExp* pue, const ref Loc loc, EXP op, Type type, Expression eptr, Expression e2)
 {
-    UnionExp ue;
     if (eptr.type.nextOf().ty == Tvoid)
     {
         error(loc, "cannot perform arithmetic on `void*` pointers at compile time");
     Lcant:
-        emplaceExp!(CTFEExp)(&ue, EXP.cantExpression);
-        return ue;
+        emplaceExp!(CTFEExp)(pue, EXP.cantExpression);
+        return pue.exp();
     }
     if (eptr.op == EXP.address)
         eptr = (cast(AddrExp)eptr).e1;
@@ -885,10 +881,10 @@  UnionExp pointerArithmetic(const ref Loc loc, EXP op, Type type, Expression eptr
     }
     if (agg1.op == EXP.symbolOffset)
     {
-        emplaceExp!(SymOffExp)(&ue, loc, (cast(SymOffExp)agg1).var, indx * sz);
-        SymOffExp se = cast(SymOffExp)ue.exp();
+        emplaceExp!(SymOffExp)(pue, loc, (cast(SymOffExp)agg1).var, indx * sz);
+        SymOffExp se = cast(SymOffExp)pue.exp();
         se.type = type;
-        return ue;
+        return pue.exp();
     }
     if (agg1.op != EXP.arrayLiteral && agg1.op != EXP.string_)
     {
@@ -903,17 +899,17 @@  UnionExp pointerArithmetic(const ref Loc loc, EXP op, Type type, Expression eptr
                 ctfeEmplaceExp!IntegerExp(loc, indx, Type.tsize_t),
                 ctfeEmplaceExp!IntegerExp(loc, indx + dim, Type.tsize_t));
         se.type = type.toBasetype().nextOf();
-        emplaceExp!(AddrExp)(&ue, loc, se);
-        ue.exp().type = type;
-        return ue;
+        emplaceExp!(AddrExp)(pue, loc, se);
+        pue.exp().type = type;
+        return pue.exp();
     }
     // Create a CTFE pointer &agg1[indx]
     auto ofs = ctfeEmplaceExp!IntegerExp(loc, indx, Type.tsize_t);
     Expression ie = ctfeEmplaceExp!IndexExp(loc, agg1, ofs);
     ie.type = type.toBasetype().nextOf(); // https://issues.dlang.org/show_bug.cgi?id=13992
-    emplaceExp!(AddrExp)(&ue, loc, ie);
-    ue.exp().type = type;
-    return ue;
+    emplaceExp!(AddrExp)(pue, loc, ie);
+    pue.exp().type = type;
+    return pue.exp();
 }
 
 // Return 1 if true, 0 if false
@@ -1755,9 +1751,8 @@  Expression assignAssocArrayElement(const ref Loc loc, AssocArrayLiteralExp aae,
 /// Given array literal oldval of type ArrayLiteralExp or StringExp, of length
 /// oldlen, change its length to newlen. If the newlen is longer than oldlen,
 /// all new elements will be set to the default initializer for the element type.
-UnionExp changeArrayLiteralLength(const ref Loc loc, TypeArray arrayType, Expression oldval, size_t oldlen, size_t newlen)
+Expression changeArrayLiteralLength(UnionExp* pue, const ref Loc loc, TypeArray arrayType, Expression oldval, size_t oldlen, size_t newlen)
 {
-    UnionExp ue;
     Type elemType = arrayType.next;
     assert(elemType);
     Expression defaultElem = elemType.defaultInitLiteral(loc);
@@ -1794,8 +1789,8 @@  UnionExp changeArrayLiteralLength(const ref Loc loc, TypeArray arrayType, Expres
                 assert(0);
             }
         }
-        emplaceExp!(StringExp)(&ue, loc, s[0 .. newlen * oldse.sz], newlen, oldse.sz);
-        StringExp se = cast(StringExp)ue.exp();
+        emplaceExp!(StringExp)(pue, loc, s[0 .. newlen * oldse.sz], newlen, oldse.sz);
+        StringExp se = cast(StringExp)pue.exp();
         se.type = arrayType;
         se.sz = oldse.sz;
         se.committed = oldse.committed;
@@ -1823,11 +1818,11 @@  UnionExp changeArrayLiteralLength(const ref Loc loc, TypeArray arrayType, Expres
             foreach (size_t i; copylen .. newlen)
                 (*elements)[i] = defaultElem;
         }
-        emplaceExp!(ArrayLiteralExp)(&ue, loc, arrayType, elements);
-        ArrayLiteralExp aae = cast(ArrayLiteralExp)ue.exp();
+        emplaceExp!(ArrayLiteralExp)(pue, loc, arrayType, elements);
+        ArrayLiteralExp aae = cast(ArrayLiteralExp)pue.exp();
         aae.ownedByCtfe = OwnedBy.ctfe;
     }
-    return ue;
+    return pue.exp();
 }
 
 /*************************** CTFE Sanity Checks ***************************/
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 69036ada483..887bb898383 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -1894,7 +1894,7 @@  Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
         if (e.committed && tb.ty == Tsarray && typeb.ty == Tarray)
         {
             se = e.copy().isStringExp();
-            d_uns64 szx = tb.nextOf().size();
+            uinteger_t szx = tb.nextOf().size();
             assert(szx <= 255);
             se.sz = cast(ubyte)szx;
             se.len = cast(size_t)tb.isTypeSArray().dim.toInteger();
@@ -2059,7 +2059,7 @@  Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 }
 
                 {
-                    d_uns64 szx = tb.nextOf().size();
+                    uinteger_t szx = tb.nextOf().size();
                     assert(szx <= 255);
                     se.setData(buffer.extractSlice().ptr, newlen, cast(ubyte)szx);
                 }
@@ -2742,7 +2742,7 @@  Expression scaleFactor(BinExp be, Scope* sc)
         // Replace (ptr + int) with (ptr + (int * stride))
         Type t = Type.tptrdiff_t;
 
-        d_uns64 stride = t1b.nextOf().size(be.loc);
+        uinteger_t stride = t1b.nextOf().size(be.loc);
         if (!t.equals(t2b))
             be.e2 = be.e2.castTo(sc, t);
         eoff = be.e2;
@@ -2757,7 +2757,7 @@  Expression scaleFactor(BinExp be, Scope* sc)
         Type t = Type.tptrdiff_t;
         Expression e;
 
-        d_uns64 stride = t2b.nextOf().size(be.loc);
+        uinteger_t stride = t2b.nextOf().size(be.loc);
         if (!t.equals(t1b))
             e = be.e1.castTo(sc, t);
         else
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 585ac2f0b60..82a5f3b72f9 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -250,7 +250,7 @@  extern (C++) abstract class Declaration : Dsymbol
         return "declaration";
     }
 
-    override final d_uns64 size(const ref Loc loc)
+    override final uinteger_t size(const ref Loc loc)
     {
         assert(type);
         const sz = type.size();
@@ -1141,7 +1141,7 @@  extern (C++) class VarDeclaration : Declaration
 
         if (!isField())
             return;
-        assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter | STC.tls)));
+        assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter)));
 
         //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
 
@@ -1217,7 +1217,7 @@  extern (C++) class VarDeclaration : Declaration
 
     override final inout(AggregateDeclaration) isThis() inout
     {
-        if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.tls | STC.gshared | STC.ctfe)))
+        if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe)))
         {
             /* The casting is necessary because `s = s.parent` is otherwise rejected
              */
@@ -1285,7 +1285,7 @@  extern (C++) class VarDeclaration : Declaration
                 error("forward referenced");
                 type = Type.terror;
             }
-            else if (storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared) ||
+            else if (storage_class & (STC.static_ | STC.extern_ | STC.gshared) ||
                 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
             {
                 assert(!isParameter() && !isResult());
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 93e3a5a0b5d..9986ea3ea36 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -71,7 +71,6 @@  struct IntRange;
     #define STCnodtor             0x10000000ULL    /// do not run destructor
     #define STCnothrow            0x20000000ULL    /// `nothrow` meaning never throws exceptions
     #define STCpure               0x40000000ULL    /// `pure` function
-    #define STCtls                0x80000000ULL    /// thread local
 
     #define STCalias              0x100000000ULL    /// `alias` parameter
     #define STCshared             0x200000000ULL    /// accessible from multiple threads
@@ -123,7 +122,7 @@  public:
     DString mangleOverride;     // overridden symbol with pragma(mangle, "...")
 
     const char *kind() const;
-    d_uns64 size(const Loc &loc);
+    uinteger_t size(const Loc &loc);
 
     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
 
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 6c3454daf10..30a8a444155 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -1886,7 +1886,7 @@  public:
         {
             // Check for unsupported type painting operations
             Type elemtype = (cast(TypeArray)val.type).next;
-            d_uns64 elemsize = elemtype.size();
+            const elemsize = elemtype.size();
 
             // It's OK to cast from fixed length to fixed length array, eg &int[n] to int[d]*.
             if (val.type.ty == Tsarray && pointee.ty == Tsarray && elemsize == pointee.nextOf().size())
@@ -2981,8 +2981,7 @@  public:
             Expression e2 = interpret(&ue2, e.e2, istate);
             if (exceptionOrCant(e2))
                 return;
-            *pue = pointerDifference(e.loc, e.type, e1, e2);
-            result = (*pue).exp();
+            result = pointerDifference(pue, e.loc, e.type, e1, e2);
             return;
         }
         if (e.e1.type.ty == Tpointer && e.e2.type.isintegral())
@@ -2995,8 +2994,7 @@  public:
             Expression e2 = interpret(&ue2, e.e2, istate);
             if (exceptionOrCant(e2))
                 return;
-            *pue = pointerArithmetic(e.loc, e.op, e.type, e1, e2);
-            result = (*pue).exp();
+            result = pointerArithmetic(pue, e.loc, e.op, e.type, e1, e2);
             return;
         }
         if (e.e2.type.ty == Tpointer && e.e1.type.isintegral() && e.op == EXP.add)
@@ -3009,8 +3007,7 @@  public:
             Expression e2 = interpret(&ue2, e.e2, istate);
             if (exceptionOrCant(e2))
                 return;
-            *pue = pointerArithmetic(e.loc, e.op, e.type, e2, e1);
-            result = (*pue).exp();
+            result = pointerArithmetic(pue, e.loc, e.op, e.type, e2, e1);
             return;
         }
         if (e.e1.type.ty == Tpointer || e.e2.type.ty == Tpointer)
@@ -3041,7 +3038,7 @@  public:
         if (e.op == EXP.rightShift || e.op == EXP.leftShift || e.op == EXP.unsignedRightShift)
         {
             const sinteger_t i2 = e2.toInteger();
-            const d_uns64 sz = e1.type.size() * 8;
+            const uinteger_t sz = e1.type.size() * 8;
             if (i2 < 0 || i2 >= sz)
             {
                 e.error("shift by %lld is outside the range 0..%llu", i2, cast(ulong)sz - 1);
@@ -3602,7 +3599,9 @@  public:
                       e.op == EXP.plusPlus ||
                       e.op == EXP.minusMinus))
             {
-                newval = pointerArithmetic(e.loc, e.op, e.type, oldval, newval).copy();
+                newval = pointerArithmetic(pue, e.loc, e.op, e.type, oldval, newval).copy();
+                if (newval == pue.exp())
+                    newval = pue.copy();
             }
             else
             {
@@ -3675,7 +3674,9 @@  public:
             UnionExp utmp = void;
             oldval = resolveSlice(oldval, &utmp);
 
-            newval = changeArrayLiteralLength(e.loc, cast(TypeArray)t, oldval, oldlen, newlen).copy();
+            newval = changeArrayLiteralLength(pue, e.loc, cast(TypeArray)t, oldval, oldlen, newlen);
+            if (newval == pue.exp())
+                newval = pue.copy();
 
             e1 = assignToLvalue(e, e1, newval);
             if (exceptionOrCant(e1))
@@ -3994,61 +3995,18 @@  public:
             //   aggregate[] = newval
             //   aggregate[low..upp] = newval
             // ------------------------------
-            version (all) // should be move in interpretAssignCommon as the evaluation of e1
-            {
-                Expression oldval = interpretRegion(se.e1, istate);
-
-                // Set the $ variable
-                uinteger_t dollar = resolveArrayLength(oldval);
-                if (se.lengthVar)
-                {
-                    Expression dollarExp = ctfeEmplaceExp!IntegerExp(e1.loc, dollar, Type.tsize_t);
-                    ctfeGlobals.stack.push(se.lengthVar);
-                    setValue(se.lengthVar, dollarExp);
-                }
-                Expression lwr = interpretRegion(se.lwr, istate);
-                if (exceptionOrCantInterpret(lwr))
-                {
-                    if (se.lengthVar)
-                        ctfeGlobals.stack.pop(se.lengthVar);
-                    return lwr;
-                }
-                Expression upr = interpretRegion(se.upr, istate);
-                if (exceptionOrCantInterpret(upr))
-                {
-                    if (se.lengthVar)
-                        ctfeGlobals.stack.pop(se.lengthVar);
-                    return upr;
-                }
-                if (se.lengthVar)
-                    ctfeGlobals.stack.pop(se.lengthVar); // $ is defined only in [L..U]
-
-                const dim = dollar;
-                lowerbound = lwr ? lwr.toInteger() : 0;
-                upperbound = upr ? upr.toInteger() : dim;
-
-                if (lowerbound < 0 || dim < upperbound)
-                {
-                    e.error("array bounds `[0..%llu]` exceeded in slice `[%llu..%llu]`",
-                        ulong(dim), ulong(lowerbound), ulong(upperbound));
-                    return CTFEExp.cantexp;
-                }
-            }
-            aggregate = oldval;
-            firstIndex = lowerbound;
+            aggregate = interpretRegion(se.e1, istate);
+            lowerbound = se.lwr ? se.lwr.toInteger() : 0;
+            upperbound = se.upr ? se.upr.toInteger() : resolveArrayLength(aggregate);
 
+            // Slice of a slice --> change the bounds
             if (auto oldse = aggregate.isSliceExp())
             {
-                // Slice of a slice --> change the bounds
-                if (oldse.upr.toInteger() < upperbound + oldse.lwr.toInteger())
-                {
-                    e.error("slice `[%llu..%llu]` exceeds array bounds `[0..%llu]`",
-                        ulong(lowerbound), ulong(upperbound), oldse.upr.toInteger() - oldse.lwr.toInteger());
-                    return CTFEExp.cantexp;
-                }
                 aggregate = oldse.e1;
                 firstIndex = lowerbound + oldse.lwr.toInteger();
             }
+            else
+                firstIndex = lowerbound;
         }
         else
         {
@@ -5520,7 +5478,7 @@  public:
             assert(agg.op == EXP.arrayLiteral || agg.op == EXP.string_);
             dinteger_t len = ArrayLength(Type.tsize_t, agg).exp().toInteger();
             //Type *pointee = ((TypePointer *)agg.type)->next;
-            if (iupr > (len + 1) || iupr < ilwr)
+            if (sliceBoundsCheck(0, len, ilwr, iupr))
             {
                 e.error("pointer slice `[%lld..%lld]` exceeds allocated memory block `[0..%lld]`", ilwr, iupr, len);
                 result = CTFEExp.cantexp;
@@ -5624,9 +5582,9 @@  public:
             //  aggregate[lo1..up1][lwr..upr] ---> aggregate[lwr'..upr']
             uinteger_t lo1 = se.lwr.toInteger();
             uinteger_t up1 = se.upr.toInteger();
-            if (ilwr > iupr || iupr > up1 - lo1)
+            if (sliceBoundsCheck(0, up1 - lo1, ilwr, iupr))
             {
-                e.error("slice `[%llu..%llu]` exceeds array bounds `[%llu..%llu]`", ilwr, iupr, lo1, up1);
+                e.error("slice `[%llu..%llu]` exceeds array bounds `[0..%llu]`", ilwr, iupr, up1 - lo1);
                 result = CTFEExp.cantexp;
                 return;
             }
@@ -5641,7 +5599,7 @@  public:
         }
         if (e1.op == EXP.arrayLiteral || e1.op == EXP.string_)
         {
-            if (iupr < ilwr || dollar < iupr)
+            if (sliceBoundsCheck(0, dollar, ilwr, iupr))
             {
                 e.error("slice `[%lld..%lld]` exceeds array bounds `[0..%lld]`", ilwr, iupr, dollar);
                 result = CTFEExp.cantexp;
diff --git a/gcc/d/dmd/dmacro.d b/gcc/d/dmd/dmacro.d
index 0e891fb3b79..9beac6b5dcd 100644
--- a/gcc/d/dmd/dmacro.d
+++ b/gcc/d/dmd/dmacro.d
@@ -31,18 +31,12 @@  extern (C++) struct MacroTable
     extern (D) void define(const(char)[] name, const(char)[] text)
     {
         //printf("MacroTable::define('%.*s' = '%.*s')\n", cast(int)name.length, name.ptr, text.length, text.ptr);
-        Macro* table;
-        for (table = mactab; table; table = table.next)
+        if (auto table = name in mactab)
         {
-            if (table.name == name)
-            {
-                table.text = text;
-                return;
-            }
+            (*table).text = text;
+            return;
         }
-        table = new Macro(name, text);
-        table.next = mactab;
-        mactab = table;
+        mactab[name] = new Macro(name, text);
     }
 
     /*****************************************************
@@ -266,20 +260,16 @@  extern (C++) struct MacroTable
 
     extern (D) Macro* search(const(char)[] name)
     {
-        Macro* table;
         //printf("Macro::search(%.*s)\n", cast(int)name.length, name.ptr);
-        for (table = mactab; table; table = table.next)
+        if (auto table = name in mactab)
         {
-            if (table.name == name)
-            {
-                //printf("\tfound %d\n", table.textlen);
-                break;
-            }
+            //printf("\tfound %d\n", table.textlen);
+            return *table;
         }
-        return table;
+        return null;
     }
 
-    Macro* mactab;
+    private Macro*[const(char)[]] mactab;
 }
 
 /* ************************************************************************ */
@@ -288,7 +278,6 @@  private:
 
 struct Macro
 {
-    Macro* next;            // next in list
     const(char)[] name;     // macro name
     const(char)[] text;     // macro replacement text
     int inuse;              // macro is in use (don't expand)
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 00fa031397c..35d2aba70d9 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -75,7 +75,7 @@  void removeHdrFilesAndFail(ref Param params, ref Modules modules)
     {
         foreach (m; modules)
         {
-            if (m.isHdrFile)
+            if (m.filetype == FileType.dhdr)
                 continue;
             File.remove(m.hdrfile.toChars());
         }
@@ -351,12 +351,10 @@  extern (C++) final class Module : Package
     const FileName objfile;     // output .obj file
     const FileName hdrfile;     // 'header' file
     FileName docfile;           // output documentation file
-    FileBuffer* srcBuffer;      // set during load(), free'd in parse()
+    const(ubyte)[] src;         /// Raw content of the file
     uint errors;                // if any errors in file
     uint numlines;              // number of lines in source file
-    bool isHdrFile;             // if it is a header (.di) file
-    bool isCFile;               // if it is a C (.c) file
-    bool isDocFile;             // if it is a documentation input file, not D source
+    FileType filetype;          // source file type
     bool hasAlwaysInlines;      // contains references to functions that must be inlined
     bool isPackageFile;         // if it is a package.d
     Package pkg;                // if isPackageFile is true, the Package that contains this package.d
@@ -590,24 +588,17 @@  extern (C++) final class Module : Package
     }
 
     /**
-     * Loads the source buffer from the given read result into `this.srcBuffer`.
+     * Trigger the relevant semantic error when a file cannot be read
      *
-     * Will take ownership of the buffer located inside `readResult`.
+     * We special case `object.d` as a failure is likely to be a rare
+     * but difficult to diagnose case for the user. Packages also require
+     * special handling to avoid exposing the compiler's internals.
      *
      * Params:
-     *  loc = the location
-     *  readResult = the result of reading a file containing the source code
-     *
-     * Returns: `true` if successful
+     *  loc = The location at which the file read originated (e.g. import)
      */
-    bool loadSourceBuffer(const ref Loc loc, ref File.ReadResult readResult)
+    private void onFileReadError(const ref Loc loc)
     {
-        //printf("Module::loadSourceBuffer('%s') file '%s'\n", toChars(), srcfile.toChars());
-        // take ownership of buffer
-        srcBuffer = new FileBuffer(readResult.extractSlice());
-        if (readResult.success)
-            return true;
-
         if (FileName.equals(srcfile.toString(), "object.d"))
         {
             .error(loc, "cannot find source code for runtime library file 'object.d'");
@@ -621,7 +612,6 @@  extern (C++) final class Module : Package
             // have a valid location come from the command-line.
             // Error that their file cannot be found and return early.
             .error(loc, "cannot find input file `%s`", srcfile.toChars());
-            return false;
         }
         else
         {
@@ -653,7 +643,6 @@  extern (C++) final class Module : Package
 
             removeHdrFilesAndFail(global.params, Module.amodules);
         }
-        return false;
     }
 
     /**
@@ -666,37 +655,23 @@  extern (C++) final class Module : Package
      *  loc = the location
      *
      * Returns: `true` if successful
-     * See_Also: loadSourceBuffer
      */
     bool read(const ref Loc loc)
     {
-        if (srcBuffer)
+        if (this.src)
             return true; // already read
 
         //printf("Module::read('%s') file '%s'\n", toChars(), srcfile.toChars());
-
-
-
-        bool success;
-        if (auto readResult = FileManager.fileManager.lookup(srcfile))
+        if (auto result = FileManager.fileManager.lookup(srcfile))
         {
-            srcBuffer = readResult;
-            success = true;
-        }
-        else
-        {
-            auto readResult = File.read(srcfile.toChars());
-            if (loadSourceBuffer(loc, readResult))
-            {
-                FileManager.fileManager.add(srcfile, srcBuffer);
-                success = true;
-            }
-        }
-        if (success && global.params.emitMakeDeps)
-        {
-            global.params.makeDeps.push(srcfile.toChars());
+            this.src = result.data;
+            if (global.params.emitMakeDeps)
+                global.params.makeDeps.push(srcfile.toChars());
+            return true;
         }
-        return success;
+
+        this.onFileReadError(loc);
+        return false;
     }
 
     /// syntactic parse
@@ -830,7 +805,7 @@  extern (C++) final class Module : Package
         //printf("Module::parse(srcname = '%s')\n", srcname);
         isPackageFile = (strcmp(srcfile.name(), package_d) == 0 ||
                          strcmp(srcfile.name(), package_di) == 0);
-        const(char)[] buf = cast(const(char)[]) srcBuffer.data;
+        const(char)[] buf = cast(const(char)[]) this.src;
 
         bool needsReencoding = true;
         bool hasBOM = true; //assume there's a BOM
@@ -942,7 +917,7 @@  extern (C++) final class Module : Package
         if (buf.length>= 4 && buf[0..4] == "Ddoc")
         {
             comment = buf.ptr + 4;
-            isDocFile = true;
+            filetype = FileType.ddoc;
             if (!docfile)
                 setDocfile();
             return this;
@@ -955,7 +930,7 @@  extern (C++) final class Module : Package
         if (FileName.equalsExt(arg, dd_ext))
         {
             comment = buf.ptr; // the optional Ddoc, if present, is handled above.
-            isDocFile = true;
+            filetype = FileType.ddoc;
             if (!docfile)
                 setDocfile();
             return this;
@@ -963,9 +938,7 @@  extern (C++) final class Module : Package
         /* If it has the extension ".di", it is a "header" file.
          */
         if (FileName.equalsExt(arg, hdr_ext))
-        {
-            isHdrFile = true;
-        }
+            filetype = FileType.dhdr;
 
         /// Promote `this` to a root module if requested via `-i`
         void checkCompiledImport()
@@ -982,7 +955,7 @@  extern (C++) final class Module : Package
          */
         if (FileName.equalsExt(arg, c_ext) || FileName.equalsExt(arg, i_ext))
         {
-            isCFile = true;
+            filetype = FileType.c;
 
             scope p = new CParser!AST(this, buf, cast(bool) docfile, target.c);
             p.nextToken();
@@ -1014,8 +987,7 @@  extern (C++) final class Module : Package
             members = p.parseModuleContent();
             numlines = p.scanloc.linnum;
         }
-        srcBuffer.destroy();
-        srcBuffer = null;
+
         /* The symbol table into which the module is to be inserted.
          */
 
@@ -1141,7 +1113,7 @@  extern (C++) final class Module : Package
         //printf("+Module::importAll(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
         if (_scope)
             return; // already done
-        if (isDocFile)
+        if (filetype == FileType.ddoc)
         {
             error("is a Ddoc file, cannot import it");
             return;
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index d03b5bb6398..d05060df045 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -425,7 +425,7 @@  extern(C++) void gendocfile(Module m)
         dc.copyright.nooutput = 1;
         m.macrotable.define("COPYRIGHT", dc.copyright.body_);
     }
-    if (m.isDocFile)
+    if (m.filetype == FileType.ddoc)
     {
         const ploc = m.md ? &m.md.loc : &m.loc;
         const loc = Loc(ploc.filename ? ploc.filename : srcfilename.ptr,
@@ -4991,7 +4991,7 @@  private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
 
         default:
             leadingBlank = false;
-            if (sc._module.isDocFile || inCode)
+            if (sc._module.filetype == FileType.ddoc || inCode)
                 break;
             const start = cast(char*)buf[].ptr + i;
             if (isIdStart(start))
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 936d19af623..aa30b5d7414 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -174,7 +174,7 @@  struct Scope
             m = m.parent;
         m.addMember(null, sc.scopesym);
         m.parent = null; // got changed by addMember()
-        if (_module.isCFile)
+        if (_module.filetype == FileType.c)
             sc.flags |= SCOPE.Cfile;
         // Create the module scope underneath the global scope
         sc = sc.push(_module);
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index f8ada2b1ea1..9e50bd56d43 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -465,10 +465,7 @@  extern (C++) class Dsymbol : ASTNode
      final bool isCsymbol()
      {
         if (Module m = getModule())
-        {
-            if (m.isCFile)
-                return true;
-        }
+            return m.filetype == FileType.c;
         return false;
     }
 
@@ -975,7 +972,7 @@  extern (C++) class Dsymbol : ASTNode
      * Returns:
      *  SIZE_INVALID when the size cannot be determined
      */
-    d_uns64 size(const ref Loc loc)
+    uinteger_t size(const ref Loc loc)
     {
         error("Dsymbol `%s` has no size", toChars());
         return SIZE_INVALID;
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index c5af06eb4cd..aad0f2da2b4 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -223,7 +223,7 @@  public:
     virtual void importAll(Scope *sc);
     virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone);
     virtual bool overloadInsert(Dsymbol *s);
-    virtual d_uns64 size(const Loc &loc);
+    virtual uinteger_t size(const Loc &loc);
     virtual bool isforwardRef();
     virtual AggregateDeclaration *isThis();     // is a 'this' required to access the member
     virtual bool isExport() const;              // is Dsymbol exported?
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index b68d840c396..b31dc9d0eb9 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -716,7 +716,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
         if (dsym.storage_class & STC.scope_)
         {
-            StorageClass stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.tls | STC.gshared);
+            StorageClass stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.gshared);
             if (stc)
             {
                 OutBuffer buf;
@@ -733,7 +733,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
             }
         }
 
-        if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.tls | STC.gshared | STC.ctfe))
+        if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe))
         {
         }
         else
@@ -794,7 +794,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
         if (dsym.type.hasWild())
         {
-            if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.field) || dsym.isDataseg())
+            if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field) || dsym.isDataseg())
             {
                 dsym.error("only parameters or stack based variables can be `inout`");
             }
@@ -841,7 +841,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
         FuncDeclaration fd = parent.isFuncDeclaration();
         if (dsym.type.isscope() && !(dsym.storage_class & STC.nodtor))
         {
-            if (dsym.storage_class & (STC.field | STC.out_ | STC.ref_ | STC.static_ | STC.manifest | STC.tls | STC.gshared) || !fd)
+            if (dsym.storage_class & (STC.field | STC.out_ | STC.ref_ | STC.static_ | STC.manifest | STC.gshared) || !fd)
             {
                 dsym.error("globals, statics, fields, manifest constants, ref and out parameters cannot be `scope`");
             }
@@ -871,7 +871,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 }
             }
             else if (!dsym._init &&
-                     !(dsym.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.field | STC.parameter)) &&
+                     !(dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field | STC.parameter)) &&
                      dsym.type.hasVoidInitPointers())
             {
                 if (sc.func.setUnsafe())
@@ -891,7 +891,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
             dsym.error("manifest constants must have initializers");
 
         bool isBlit = false;
-        d_uns64 sz;
+        uinteger_t sz;
         if (sc.flags & SCOPE.Cfile && !dsym._init)
         {
             addDefaultCInitializer(dsym);
@@ -977,7 +977,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
             {
                 // If local variable, use AssignExp to handle all the various
                 // possibilities.
-                if (fd && !(dsym.storage_class & (STC.manifest | STC.static_ | STC.tls | STC.gshared | STC.extern_)) && !dsym._init.isVoidInitializer())
+                if (fd && !(dsym.storage_class & (STC.manifest | STC.static_ | STC.gshared | STC.extern_)) && !dsym._init.isVoidInitializer())
                 {
                     //printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars());
                     if (!ei)
@@ -1476,7 +1476,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
         if (scd.decl)
         {
             sc = sc.push();
-            sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.tls | STC.gshared);
+            sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.gshared);
             sc.inunion = scd.isunion ? scd : null;
             sc.flags = 0;
             for (size_t i = 0; i < scd.decl.dim; i++)
@@ -4233,21 +4233,41 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
          */
         if (scd.isInstantiated() && scd.semanticRun < PASS.semantic)
         {
-            /* Add this prefix to the function:
-             *      static int gate;
-             *      if (++gate != 1) return;
-             * Note that this is not thread safe; should not have threads
-             * during static construction.
+            /* Add this prefix to the constructor:
+             * ```
+             * static int gate;
+             * if (++gate != 1) return;
+             * ```
+             * or, for shared constructor:
+             * ```
+             * shared int gate;
+             * if (core.atomic.atomicOp!"+="(gate, 1) != 1) return;
+             * ```
              */
+            const bool isShared = !!scd.isSharedStaticCtorDeclaration();
             auto v = new VarDeclaration(Loc.initial, Type.tint32, Id.gate, null);
-            v.storage_class = STC.temp | (scd.isSharedStaticCtorDeclaration() ? STC.static_ : STC.tls);
+            v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : 0);
 
             auto sa = new Statements();
             Statement s = new ExpStatement(Loc.initial, v);
             sa.push(s);
 
-            Expression e = new IdentifierExp(Loc.initial, v.ident);
-            e = new AddAssignExp(Loc.initial, e, IntegerExp.literal!1);
+            Expression e;
+            if (isShared)
+            {
+                e = doAtomicOp("+=", v.ident, IntegerExp.literal!(1));
+                if (e is null)
+                {
+                    scd.error("shared static constructor within a template require `core.atomic : atomicOp` to be present");
+                    return;
+                }
+            }
+            else
+            {
+                e = new AddAssignExp(
+                    Loc.initial, new IdentifierExp(Loc.initial, v.ident), IntegerExp.literal!1);
+            }
+
             e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!1);
             s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
 
@@ -4309,22 +4329,41 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
          */
         if (sdd.isInstantiated() && sdd.semanticRun < PASS.semantic)
         {
-            /* Add this prefix to the function:
-             *      static int gate;
-             *      if (--gate != 0) return;
-             * Increment gate during constructor execution.
-             * Note that this is not thread safe; should not have threads
-             * during static destruction.
+            /* Add this prefix to the constructor:
+             * ```
+             * static int gate;
+             * if (--gate != 0) return;
+             * ```
+             * or, for shared constructor:
+             * ```
+             * shared int gate;
+             * if (core.atomic.atomicOp!"-="(gate, 1) != 0) return;
+             * ```
              */
+            const bool isShared = !!sdd.isSharedStaticDtorDeclaration();
             auto v = new VarDeclaration(Loc.initial, Type.tint32, Id.gate, null);
-            v.storage_class = STC.temp | (sdd.isSharedStaticDtorDeclaration() ? STC.static_ : STC.tls);
+            v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : 0);
 
             auto sa = new Statements();
             Statement s = new ExpStatement(Loc.initial, v);
             sa.push(s);
 
-            Expression e = new IdentifierExp(Loc.initial, v.ident);
-            e = new AddAssignExp(Loc.initial, e, IntegerExp.literal!(-1));
+            Expression e;
+            if (isShared)
+            {
+                e = doAtomicOp("-=", v.ident, IntegerExp.literal!(1));
+                if (e is null)
+                {
+                    sdd.error("shared static destructo within a template require `core.atomic : atomicOp` to be present");
+                    return;
+                }
+            }
+            else
+            {
+                e = new AddAssignExp(
+                    Loc.initial, new IdentifierExp(Loc.initial, v.ident), IntegerExp.literal!(-1));
+            }
+
             e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!0);
             s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
 
@@ -6833,3 +6872,48 @@  bool determineFields(AggregateDeclaration ad)
 
     return true;
 }
+
+/// Do an atomic operation (currently tailored to [shared] static ctors|dtors) needs
+private CallExp doAtomicOp (string op, Identifier var, Expression arg)
+{
+    __gshared Import imp = null;
+    __gshared Identifier[1] id;
+
+    assert(op == "-=" || op == "+=");
+
+    const loc = Loc.initial;
+
+    // Below code is similar to `loadStdMath` (used for `^^` operator)
+    if (!imp)
+    {
+        id[0] = Id.core;
+        auto s = new Import(Loc.initial, id[], Id.atomic, null, true);
+        // Module.load will call fatal() if there's no std.math available.
+        // Gag the error here, pushing the error handling to the caller.
+        uint errors = global.startGagging();
+        s.load(null);
+        if (s.mod)
+        {
+            s.mod.importAll(null);
+            s.mod.dsymbolSemantic(null);
+        }
+        global.endGagging(errors);
+        imp = s;
+    }
+    // Module couldn't be loaded
+    if (imp.mod is null)
+        return null;
+
+    Objects* tiargs = new Objects(1);
+    (*tiargs)[0] = new StringExp(loc, op);
+
+    Expressions* args = new Expressions(2);
+    (*args)[0] = new IdentifierExp(loc, var);
+    (*args)[1] = arg;
+
+    auto sc = new ScopeExp(loc, imp.mod);
+    auto dti = new DotTemplateInstanceExp(
+        loc, sc, Id.atomicOp, tiargs);
+
+    return CallExp.create(loc, dti, args);
+}
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index adb91edec78..366ed60bf33 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -1943,7 +1943,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
                             {
                                 // Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
                             }
-                            else if (global.params.rvalueRefParam)
+                            else if (global.params.rvalueRefParam == FeatureState.enabled)
                             {
                                 // Allow implicit conversion to ref
                             }
@@ -8346,7 +8346,7 @@  struct TemplateStats
     }
 }
 
-void printTemplateStats()
+extern (C++) void printTemplateStats()
 {
     static struct TemplateDeclarationStats
     {
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 285b834f468..46982e391c0 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -860,7 +860,7 @@  public:
             origType = vd.originalType;
         scope(exit) origType = null;
 
-        if (!vd.alignment.isDefault())
+        if (!vd.alignment.isDefault() && !vd.alignment.isUnknown())
         {
             buf.printf("// Ignoring var %s alignment %d", vd.toChars(), vd.alignment.get());
             buf.writenl();
@@ -940,7 +940,7 @@  public:
             return;
         }
 
-        if (vd.storage_class & (AST.STC.static_ | AST.STC.extern_ | AST.STC.tls | AST.STC.gshared) ||
+        if (vd.storage_class & (AST.STC.static_ | AST.STC.extern_ | AST.STC.gshared) ||
         vd.parent && vd.parent.isModule())
         {
             if (vd.linkage != LINK.c && vd.linkage != LINK.cpp && !(tdparent && (this.linkage == LINK.c || this.linkage == LINK.cpp)))
@@ -948,11 +948,6 @@  public:
                 ignored("variable %s because of linkage", vd.toPrettyChars());
                 return;
             }
-            if (vd.storage_class & AST.STC.tls)
-            {
-                ignored("variable %s because of thread-local storage", vd.toPrettyChars());
-                return;
-            }
             if (!isSupportedType(type))
             {
                 ignored("variable %s because its type cannot be mapped to C++", vd.toPrettyChars());
@@ -1934,6 +1929,8 @@  public:
                 buf.writestring("unsigned long long");
             else if (ed.ident == DMDType.c_long_double)
                 buf.writestring("long double");
+            else if (ed.ident == DMDType.c_char)
+                buf.writestring("char");
             else if (ed.ident == DMDType.c_wchar_t)
                 buf.writestring("wchar_t");
             else if (ed.ident == DMDType.c_complex_float)
@@ -2681,6 +2678,18 @@  public:
     {
         if (vd._init && !vd._init.isVoidInitializer())
             return AST.initializerToExpression(vd._init);
+        else if (auto ts = vd.type.isTypeStruct())
+        {
+            if (!ts.sym.noDefaultCtor && !ts.sym.isUnionDeclaration())
+            {
+                // Generate a call to the default constructor that we've generated.
+                auto sle = new AST.StructLiteralExp(Loc.initial, ts.sym, new AST.Expressions(0));
+                sle.type = vd.type;
+                return sle;
+            }
+            else
+                return vd.type.defaultInitLiteral(Loc.initial);
+        }
         else
             return vd.type.defaultInitLiteral(Loc.initial);
     }
@@ -2971,6 +2980,7 @@  struct DMDType
     __gshared Identifier c_longlong;
     __gshared Identifier c_ulonglong;
     __gshared Identifier c_long_double;
+    __gshared Identifier c_char;
     __gshared Identifier c_wchar_t;
     __gshared Identifier c_complex_float;
     __gshared Identifier c_complex_double;
@@ -2984,6 +2994,7 @@  struct DMDType
         c_ulonglong     = Identifier.idPool("__c_ulonglong");
         c_long_double   = Identifier.idPool("__c_long_double");
         c_wchar_t       = Identifier.idPool("__c_wchar_t");
+        c_char          = Identifier.idPool("__c_char");
         c_complex_float  = Identifier.idPool("__c_complex_float");
         c_complex_double = Identifier.idPool("__c_complex_double");
         c_complex_real = Identifier.idPool("__c_complex_real");
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index be11f26b04a..e9dcdc0532c 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -658,7 +658,7 @@  bool checkAssignEscape(Scope* sc, Expression e, bool gag)
             p == fd)
         {
             if (log) printf("inferring 'return' for parameter %s in function %s\n", v.toChars(), fd.toChars());
-            inferReturn(fd, v);        // infer addition of 'return' to make `return scope`
+            inferReturn(fd, v, /*returnScope:*/ true); // infer addition of 'return' to make `return scope`
         }
 
         if (!(va && va.isScope()) || vaIsRef)
@@ -1215,7 +1215,7 @@  private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
             sc.func.flags & FUNCFLAG.returnInprocess &&
             p == sc.func)
         {
-            inferReturn(sc.func, v);        // infer addition of 'return'
+            inferReturn(sc.func, v, /*returnScope:*/ true); // infer addition of 'return'
             continue;
         }
 
@@ -1355,7 +1355,7 @@  private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
             if (sc.func.flags & FUNCFLAG.returnInprocess && p == sc.func &&
                 (vsr == ScopeRef.Ref || vsr == ScopeRef.RefScope))
             {
-                inferReturn(sc.func, v);        // infer addition of 'return'
+                inferReturn(sc.func, v, /*returnScope:*/ false); // infer addition of 'return'
             }
             else
             {
@@ -1404,23 +1404,25 @@  private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
  * Params:
  *      fd = function that v is a parameter to
  *      v = parameter that needs to be STC.return_
+ *      returnScope = infer `return scope` instead of `return ref`
  */
-
-private void inferReturn(FuncDeclaration fd, VarDeclaration v)
+private void inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope)
 {
     // v is a local in the current function
 
-    //printf("for function '%s' inferring 'return' for variable '%s'\n", fd.toChars(), v.toChars());
-    v.storage_class |= STC.return_ | STC.returninferred;
+    //printf("for function '%s' inferring 'return' for variable '%s', returnScope: %d\n", fd.toChars(), v.toChars(), returnScope);
+    auto newStcs = STC.return_ | STC.returninferred | (returnScope ? STC.returnScope : 0);
+    v.storage_class |= newStcs;
 
     if (v == fd.vthis)
     {
         /* v is the 'this' reference, so mark the function
          */
-        fd.storage_class |= STC.return_ | STC.returninferred;
+        fd.storage_class |= newStcs;
         if (auto tf = fd.type.isTypeFunction())
         {
             //printf("'this' too %p %s\n", tf, sc.func.toChars());
+            tf.isreturnscope = returnScope;
             tf.isreturn = true;
             tf.isreturninferred = true;
         }
@@ -1434,7 +1436,7 @@  private void inferReturn(FuncDeclaration fd, VarDeclaration v)
             {
                 if (p.ident == v.ident)
                 {
-                    p.storageClass |= STC.return_ | STC.returninferred;
+                    p.storageClass |= newStcs;
                     break;              // there can be only one
                 }
             }
@@ -1732,33 +1734,69 @@  void escapeByValue(Expression e, EscapeByResults* er, bool live = false)
             {
                 DotVarExp dve = e.e1.isDotVarExp();
                 FuncDeclaration fd = dve.var.isFuncDeclaration();
-                AggregateDeclaration ad;
-                if (global.params.useDIP1000 == FeatureState.enabled && tf.isreturn && fd && (ad = fd.isThis()) !is null)
+                if (global.params.useDIP1000 == FeatureState.enabled)
                 {
-                    if (ad.isClassDeclaration() || tf.isScopeQual)       // this is 'return scope'
-                        dve.e1.accept(this);
-                    else if (ad.isStructDeclaration()) // this is 'return ref'
-                    {
-                        if (tf.isref)
+                   if (fd && fd.isThis())
+                   {
+                        /* Calling a non-static member function dve.var, which is returning `this`, and with dve.e1 representing `this`
+                         */
+
+                        /*****************************
+                         * Concoct storage class for member function's implicit `this` parameter.
+                         * Params:
+                         *      fd = member function
+                         * Returns:
+                         *      storage class for fd's `this`
+                         */
+                        StorageClass getThisStorageClass(FuncDeclaration fd)
                         {
-                            /* Treat calling:
-                             *   struct S { ref S foo() return; }
-                             * as:
-                             *   this;
-                             */
+                            StorageClass stc;
+                            auto tf = fd.type.toBasetype().isTypeFunction();
+                            if (tf.isreturn)
+                                stc |= STC.return_;
+                            if (tf.isreturnscope)
+                                stc |= STC.returnScope;
+                            auto ad = fd.isThis();
+                            if (ad.isClassDeclaration() || tf.isScopeQual)
+                                stc |= STC.scope_;
+                            if (ad.isStructDeclaration())
+                                stc |= STC.ref_;        // `this` for a struct member function is passed by `ref`
+                            return stc;
+                        }
+
+                        const psr = buildScopeRef(getThisStorageClass(fd));
+                        if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
                             dve.e1.accept(this);
+                        else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
+                        {
+                            if (tf.isref)
+                            {
+                                /* Treat calling:
+                                 *   struct S { ref S foo() return; }
+                                 * as:
+                                 *   this;
+                                 */
+                                dve.e1.accept(this);
+                            }
+                            else
+                                escapeByRef(dve.e1, er, live);
                         }
-                        else
-                            escapeByRef(dve.e1, er, live);
                     }
                 }
-                else if (dve.var.storage_class & STC.return_ || tf.isreturn)
+                else
                 {
-                    if (dve.var.storage_class & STC.scope_)
+                    // Calling member function before dip1000
+                    StorageClass stc = dve.var.storage_class & (STC.return_ | STC.scope_ | STC.ref_);
+                    if (tf.isreturn)
+                        stc |= STC.return_;
+
+                    const psr = buildScopeRef(stc);
+                    if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
                         dve.e1.accept(this);
-                    else if (dve.var.storage_class & STC.ref_)
+                    else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
                         escapeByRef(dve.e1, er, live);
                 }
+
                 // If it's also a nested function that is 'return scope'
                 if (fd && fd.isNested())
                 {
@@ -1996,19 +2034,29 @@  void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
                         return;
                     }
 
-                    if (dve.var.storage_class & STC.return_ || tf.isreturn)
-                    {
-                        if (dve.var.storage_class & STC.ref_ || tf.isref)
-                            dve.e1.accept(this);
-                        else if (dve.var.storage_class & STC.scope_ || tf.isScopeQual)
-                            escapeByValue(dve.e1, er, live);
-                    }
+                    StorageClass stc = dve.var.storage_class & (STC.return_ | STC.scope_ | STC.ref_);
+                    if (tf.isreturn)
+                        stc |= STC.return_;
+                    if (tf.isref)
+                        stc |= STC.ref_;
+                    if (tf.isScopeQual)
+                        stc |= STC.scope_;
+                    if (tf.isreturnscope)
+                        stc |= STC.returnScope;
+
+                    const psr = buildScopeRef(stc);
+                    if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
+                         dve.e1.accept(this);
+                    else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
+                         escapeByValue(dve.e1, er, live);
+
                     // If it's also a nested function that is 'return ref'
-                    FuncDeclaration fd = dve.var.isFuncDeclaration();
-                    if (fd && fd.isNested())
+                    if (FuncDeclaration fd = dve.var.isFuncDeclaration())
                     {
-                        if (tf.isreturn)
+                        if (fd.isNested() && tf.isreturn)
+                        {
                             er.byexp.push(e);
+                        }
                     }
                 }
                 // If it's a delegate, check it too
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 45fefc03dea..7abfe7f0878 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -1797,7 +1797,7 @@  extern (C++) final class IntegerExp : Expression
     {
         super(Loc.initial, EXP.int64, __traits(classInstanceSize, IntegerExp));
         this.type = Type.tint32;
-        this.value = cast(d_int32)value;
+        this.value = cast(int)value;
     }
 
     static IntegerExp create(const ref Loc loc, dinteger_t value, Type type)
@@ -1838,8 +1838,8 @@  extern (C++) final class IntegerExp : Expression
         const val = normalize(ty, value);
         value = val;
         return (ty == Tuns64)
-            ? real_t(cast(d_uns64)val)
-            : real_t(cast(d_int64)val);
+            ? real_t(cast(ulong)val)
+            : real_t(cast(long)val);
     }
 
     override real_t toImaginary()
@@ -1895,38 +1895,38 @@  extern (C++) final class IntegerExp : Expression
             break;
 
         case Tint8:
-            result = cast(d_int8)value;
+            result = cast(byte)value;
             break;
 
         case Tchar:
         case Tuns8:
-            result = cast(d_uns8)value;
+            result = cast(ubyte)value;
             break;
 
         case Tint16:
-            result = cast(d_int16)value;
+            result = cast(short)value;
             break;
 
         case Twchar:
         case Tuns16:
-            result = cast(d_uns16)value;
+            result = cast(ushort)value;
             break;
 
         case Tint32:
-            result = cast(d_int32)value;
+            result = cast(int)value;
             break;
 
         case Tdchar:
         case Tuns32:
-            result = cast(d_uns32)value;
+            result = cast(uint)value;
             break;
 
         case Tint64:
-            result = cast(d_int64)value;
+            result = cast(long)value;
             break;
 
         case Tuns64:
-            result = cast(d_uns64)value;
+            result = cast(ulong)value;
             break;
 
         case Tpointer:
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index f8e5af4ac95..580281643ca 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -1992,7 +1992,7 @@  private bool functionParameters(const ref Loc loc, Scope* sc,
             }
             else if (p.storageClass & STC.ref_)
             {
-                if (global.params.rvalueRefParam &&
+                if (global.params.rvalueRefParam == FeatureState.enabled &&
                     !arg.isLvalue() &&
                     targ.isCopyable())
                 {   /* allow rvalues to be passed to ref parameters by copying
@@ -7118,6 +7118,8 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
+        exp.e1 = exp.e1.arrayFuncConv(sc);
+
         Type tb = exp.e1.type.toBasetype();
         switch (tb.ty)
         {
@@ -7441,6 +7443,9 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
+        if (exp.to && !exp.to.isTypeSArray() && !exp.to.isTypeFunction())
+            exp.e1 = exp.e1.arrayFuncConv(sc);
+
         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
         if (exp.e1.op == EXP.type)
             exp.e1 = resolveAliasThis(sc, exp.e1);
@@ -10336,7 +10341,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
                 // Need to divide the result by the stride
                 // Replace (ptr - ptr) with (ptr - ptr) / stride
-                d_int64 stride;
+                long stride;
 
                 // make sure pointer types are compatible
                 if (Expression ex = typeCombine(exp, sc))
@@ -10351,7 +10356,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 {
                     e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t);
                 }
-                else if (stride == cast(d_int64)SIZE_INVALID)
+                else if (stride == cast(long)SIZE_INVALID)
                     e = ErrorExp.get();
                 else
                 {
@@ -12575,6 +12580,13 @@  Expression semanticY(DotIdExp exp, Scope* sc, int flag)
         Expression e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
         return e;
     }
+    else if (sc.flags & SCOPE.Cfile && exp.ident == Id.__sizeof && exp.e1.isStringExp())
+    {
+        // Sizeof string literal includes the terminating 0
+        auto se = exp.e1.isStringExp();
+        Expression e = new IntegerExp(exp.loc, (se.len + 1) * se.sz, Type.tsize_t);
+        return e;
+    }
     else
     {
         if (exp.e1.isTypeExp() || exp.e1.isTemplateExp())
diff --git a/gcc/d/dmd/file_manager.d b/gcc/d/dmd/file_manager.d
index 7e0f404dd73..9ba38078c3f 100644
--- a/gcc/d/dmd/file_manager.d
+++ b/gcc/d/dmd/file_manager.d
@@ -20,38 +20,12 @@  import dmd.identifier;
 enum package_d  = "package." ~ mars_ext;
 enum package_di = "package." ~ hdr_ext;
 
-extern(C++) struct FileManager
+struct FileManager
 {
     private StringTable!(FileBuffer*) files;
     private __gshared bool initialized = false;
 
 nothrow:
-    extern(D) private FileBuffer* readToFileBuffer(const(char)[] filename)
-    {
-        if (!initialized)
-            FileManager._init();
-
-        auto readResult = File.read(filename);
-        if (readResult.success)
-        {
-            FileBuffer* fb;
-            if (auto val = files.lookup(filename))
-                fb = val.value;
-
-            if (!fb)
-                fb = FileBuffer.create();
-
-            fb.data = readResult.extractSlice();
-
-            return files.insert(filename, fb) == null ? null : fb;
-        }
-        else
-        {
-            return null;
-        }
-
-    }
-
     /********************************************
     * Look for the source file if it's different from filename.
     * Look for .di, .d, directory, and along global.path.
@@ -63,7 +37,7 @@  nothrow:
     *      the found file name or
     *      `null` if it is not different from filename.
     */
-    extern(D) static const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
+    static const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
     {
         //printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
         /* Search along path[] for .di file, then .d file, then .i file, then .c file.
@@ -74,6 +48,9 @@  nothrow:
         scope(exit) FileName.free(sdi.ptr);
 
         const sd = FileName.forceExt(filename, mars_ext);
+        // Special file name representing `stdin`, always assume its presence
+        if (sd == "__stdin.d")
+            return sd;
         if (FileName.exists(sd) == 1)
             return sd;
         scope(exit) FileName.free(sd.ptr);
@@ -164,33 +141,35 @@  nothrow:
      * Returns: the loaded source file if it was found in memory,
      *      otherwise `null`
      */
-    extern(D) FileBuffer* lookup(FileName filename)
+    const(FileBuffer)* lookup(FileName filename)
     {
         if (!initialized)
             FileManager._init();
 
-        if (auto val = files.lookup(filename.toString))
+        const name = filename.toString;
+        if (auto val = files.lookup(name))
+            return val.value;
+
+        if (name == "__stdin.d")
         {
-            // There is a chance that the buffer could've been
-            // stolen by a reader with extractSlice, so we should
-            // try and do our reading logic if that happens.
-            if (val !is null && val.value.data !is null)
-            {
-                return val.value;
-            }
+            auto buffer = new FileBuffer(readFromStdin().extractSlice());
+            if (this.files.insert(name, buffer) is null)
+                assert(0, "stdin: Insert after lookup failure should never return `null`");
+            return buffer;
         }
 
-        const name = filename.toString;
-        auto res = FileName.exists(name);
-        if (res == 1)
-            return readToFileBuffer(name);
+        if (FileName.exists(name) != 1)
+            return null;
 
-        return null;
-    }
+        auto readResult = File.read(name);
+        if (!readResult.success)
+            return null;
 
-    extern(C++) FileBuffer* lookup(const(char)* filename)
-    {
-        return lookup(FileName(filename.toDString));
+        FileBuffer* fb = new FileBuffer(readResult.extractSlice());
+        if (files.insert(name, fb) is null)
+            assert(0, "Insert after lookup failure should never return `null`");
+
+        return fb;
     }
 
     /**
@@ -201,15 +180,15 @@  nothrow:
      * Returns: the loaded source file if it was found in memory,
      *      otherwise `null`
      */
-    extern(D) const(char)[][] getLines(FileName file)
+    const(char)[][] getLines(FileName file)
     {
         if (!initialized)
             FileManager._init();
 
         const(char)[][] lines;
-        if (FileBuffer* buffer = lookup(file))
+        if (const buffer = lookup(file))
         {
-            ubyte[] slice = buffer.data[0 .. buffer.data.length];
+            const slice = buffer.data[0 .. buffer.data.length];
             size_t start, end;
             ubyte c;
             for (auto i = 0; i < slice.length; i++)
@@ -260,7 +239,7 @@  nothrow:
      *
      * Returns: The FileBuffer added, or null
      */
-    extern(D) FileBuffer* add(FileName filename, FileBuffer* filebuffer)
+    FileBuffer* add(FileName filename, FileBuffer* filebuffer)
     {
         if (!initialized)
             FileManager._init();
@@ -269,19 +248,10 @@  nothrow:
         return val == null ? null : val.value;
     }
 
-    extern(C++) FileBuffer* add(const(char)* filename, FileBuffer* filebuffer)
-    {
-        if (!initialized)
-            FileManager._init();
-
-        auto val = files.insert(filename.toDString, filebuffer);
-        return val == null ? null : val.value;
-    }
-
     __gshared fileManager = FileManager();
 
     // Initialize the global FileManager singleton
-    extern(C++) static __gshared void _init()
+    private void _init()
     {
         if (!initialized)
         {
@@ -295,3 +265,46 @@  nothrow:
         files._init();
     }
 }
+
+private FileBuffer readFromStdin() nothrow
+{
+    import core.stdc.stdio;
+    import dmd.errors;
+    import dmd.root.rmem;
+
+    enum bufIncrement = 128 * 1024;
+    size_t pos = 0;
+    size_t sz = bufIncrement;
+
+    ubyte* buffer = null;
+    for (;;)
+    {
+        buffer = cast(ubyte*)mem.xrealloc(buffer, sz + 4); // +2 for sentinel and +2 for lexer
+
+        // Fill up buffer
+        do
+        {
+            assert(sz > pos);
+            size_t rlen = fread(buffer + pos, 1, sz - pos, stdin);
+            pos += rlen;
+            if (ferror(stdin))
+            {
+                import core.stdc.errno;
+                error(Loc.initial, "cannot read from stdin, errno = %d", errno);
+                fatal();
+            }
+            if (feof(stdin))
+            {
+                // We're done
+                assert(pos < sz + 2);
+                buffer[pos .. pos + 4] = '\0';
+                return FileBuffer(buffer[0 .. pos]);
+            }
+        } while (pos < sz);
+
+        // Buffer full, expand
+        sz += bufIncrement;
+    }
+
+    assert(0);
+}
diff --git a/gcc/d/dmd/file_manager.h b/gcc/d/dmd/file_manager.h
deleted file mode 100644
index 6705f24301f..00000000000
--- a/gcc/d/dmd/file_manager.h
+++ /dev/null
@@ -1,19 +0,0 @@ 
-
-/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * https://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * https://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.h
- */
-
-#pragma once
-
-#include "root/file.h"
-
-struct FileManager
-{
-    static void _init();
-    FileBuffer* lookup(const char* filename);
-    FileBuffer* add(const char* filename, FileBuffer* filebuffer);
-};
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index eccd1ee183d..6697a05a142 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -161,11 +161,11 @@  extern (C++) struct Param
     FeatureState dtorFields; // destruct fields of partially constructed objects
                             // https://issues.dlang.org/show_bug.cgi?id=14246
     bool fieldwise;         // do struct equality testing field-wise rather than by memcmp()
-    bool rvalueRefParam;    // allow rvalues to be arguments to ref parameters
-                            // https://dconf.org/2019/talks/alexandrescu.html
-                            // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
-                            // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html
-                            // Implementation: https://github.com/dlang/dmd/pull/9817
+    FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters
+                                 // https://dconf.org/2019/talks/alexandrescu.html
+                                 // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
+                                 // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html
+                                 // Implementation: https://github.com/dlang/dmd/pull/9817
 
     CppStdRevision cplusplus = CppStdRevision.cpp11;    // version of C++ standard to support
 
@@ -486,15 +486,6 @@  alias dinteger_t = ulong;
 alias sinteger_t = long;
 alias uinteger_t = ulong;
 
-alias d_int8 = int8_t;
-alias d_uns8 = uint8_t;
-alias d_int16 = int16_t;
-alias d_uns16 = uint16_t;
-alias d_int32 = int32_t;
-alias d_uns32 = uint32_t;
-alias d_int64 = int64_t;
-alias d_uns64 = uint64_t;
-
 version (DMDLIB)
 {
     version = LocOffset;
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 49fa5b98e95..9bbe0c9fe03 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -145,7 +145,7 @@  struct Param
     FeatureState dtorFields;  // destruct fields of partially constructed objects
                               // https://issues.dlang.org/show_bug.cgi?id=14246
     bool fieldwise;         // do struct equality testing field-wise rather than by memcmp()
-    bool rvalueRefParam;    // allow rvalues to be arguments to ref parameters
+    FeatureState rvalueRefParam;    // allow rvalues to be arguments to ref parameters
     CppStdRevision cplusplus;  // version of C++ name mangling to support
     bool markdown;          // enable Markdown replacements in Ddoc
     bool vmarkdown;         // list instances of Markdown replacements in Ddoc
@@ -346,15 +346,6 @@  typedef long long sinteger_t;
 typedef unsigned long long uinteger_t;
 #endif
 
-typedef int8_t                  d_int8;
-typedef uint8_t                 d_uns8;
-typedef int16_t                 d_int16;
-typedef uint16_t                d_uns16;
-typedef int32_t                 d_int32;
-typedef uint32_t                d_uns32;
-typedef int64_t                 d_int64;
-typedef uint64_t                d_uns64;
-
 // file location
 struct Loc
 {
@@ -415,4 +406,12 @@  enum class PINLINE : uint8_t
     always        // always inline
 };
 
+enum class FileType : uint8_t
+{
+    d,    /// normal D source file
+    dhdr, /// D header file (.di)
+    ddoc, /// Ddoc documentation file (.dd)
+    c,    /// C source file
+};
+
 typedef uinteger_t StorageClass;
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 6b8ecc5c07f..f2552d4d1cf 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -2843,7 +2843,6 @@  string stcToString(ref StorageClass stc)
         SCstring(STC.pure_, Token.toString(TOK.pure_)),
         SCstring(STC.ref_, Token.toString(TOK.ref_)),
         SCstring(STC.return_, Token.toString(TOK.return_)),
-        SCstring(STC.tls, "__thread"),
         SCstring(STC.gshared, Token.toString(TOK.gshared)),
         SCstring(STC.nogc, "@nogc"),
         SCstring(STC.live, "@live"),
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 31a44db2542..2ec75ab2516 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -123,6 +123,7 @@  immutable Msgtable[] msgtable =
     { "__c_longlong" },
     { "__c_ulonglong" },
     { "__c_long_double" },
+    { "__c_char" },
     { "__c_wchar_t" },
     { "__c_complex_float" },
     { "__c_complex_double" },
@@ -359,6 +360,8 @@  immutable Msgtable[] msgtable =
     { "core" },
     { "etc" },
     { "attribute" },
+    { "atomic" },
+    { "atomicOp" },
     { "math" },
     { "sin" },
     { "cos" },
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index 72e0e1a93a5..ec44ee0df5c 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/dmd/importc.d
@@ -274,6 +274,7 @@  Expression castCallAmbiguity(Expression e, Scope* sc)
 
 bool cFuncEquivalence(TypeFunction tf1, TypeFunction tf2)
 {
+    //printf("cFuncEquivalence()\n  %s\n  %s\n", tf1.toChars(), tf2.toChars());
     if (tf1.equals(tf2))
         return true;
 
@@ -284,22 +285,31 @@  bool cFuncEquivalence(TypeFunction tf1, TypeFunction tf2)
     if (tf1.parameterList.length == 0 && tf2.parameterList.length == 0)
         return true;
 
-    if (!tf1.parameterList.hasIdentifierList &&
-        !tf2.parameterList.hasIdentifierList)
-        return false;   // both functions are prototyped
-
-    // Otherwise ignore variadicness, as K+R functions are all variadic
-
     if (!tf1.nextOf().equals(tf2.nextOf()))
         return false;   // function return types don't match
 
     if (tf1.parameterList.length != tf2.parameterList.length)
         return false;
 
+    if (!tf1.parameterList.hasIdentifierList && !tf2.parameterList.hasIdentifierList) // if both are prototyped
+    {
+        if (tf1.parameterList.varargs != tf2.parameterList.varargs)
+            return false;
+    }
+
     foreach (i, fparam ; tf1.parameterList)
     {
         Type t1 = fparam.type;
         Type t2 = tf2.parameterList[i].type;
+
+        /* Strip off head const.
+         * Not sure if this is C11, but other compilers treat
+         * `void fn(int)` and `fn(const int x)`
+         * as equivalent.
+         */
+        t1 = t1.mutableOf();
+        t2 = t2.mutableOf();
+
         if (!t1.equals(t2))
             return false;
     }
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index dbdf6a503d1..3ff2eae2651 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -371,6 +371,12 @@  class Lexer
                                 'd';
                     return;
                 }
+                else if (p[1] == '8' && p[2] == '\"') // C UTF-8 string literal
+                {
+                    p += 2;
+                    escapeStringConstant(t);
+                    return;
+                }
                 goto case_ident;
 
             case 'r':
@@ -1979,8 +1985,8 @@  class Lexer
                 if (base <= 10 && n > 0 && (isalpha(p[1]) || p[1] == '_' || p[1] & 0x80))
                 {
                     if (Ccompile && base == 10 &&
-                        (p[1] == 'f' || p[1] == 'F' || p[1] == 'l' || p[1] == 'L'))
-                        goto Lreal;  // if `1.f` or `1.L`
+                        (p[1] == 'e' || p[1] == 'E' || p[1] == 'f' || p[1] == 'F' || p[1] == 'l' || p[1] == 'L'))
+                        goto Lreal;  // if `1.e6` or `1.f` or `1.L`
                     goto Ldone; // if ".identifier" or ".unicode"
                 }
                 if (base == 16 && (!ishex(p[1]) || p[1] == '_' || p[1] & 0x80))
@@ -2495,8 +2501,10 @@  class Lexer
             }
         }
         const isLong = (result == TOK.float80Literal || result == TOK.imaginary80Literal);
-        if (isOutOfRange && !isLong)
+        if (isOutOfRange && !isLong && (!Ccompile || hex))
         {
+            /* C11 6.4.4.2 doesn't actually care if it is not representable if it is not hex
+             */
             const char* suffix = (result == TOK.float32Literal || result == TOK.imaginary32Literal) ? "f" : "";
             error(scanloc, "number `%s%s` is not representable", sbufptr, suffix);
         }
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index f020bfdb5a3..048b3a0452c 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -71,12 +71,10 @@  public:
     FileName objfile;   // output .obj file
     FileName hdrfile;   // 'header' file
     FileName docfile;   // output documentation file
-    FileBuffer *srcBuffer; // set during load(), free'd in parse()
+    DArray<unsigned char> src; // Raw content of the file
     unsigned errors;    // if any errors in file
     unsigned numlines;  // number of lines in source file
-    bool isHdrFile;     // if it is a header (.di) file
-    bool isCFile;       // if it is a C (.c) file
-    bool isDocFile;     // if it is a documentation input file, not D source
+    FileType filetype;  // source file type
     bool hasAlwaysInlines; // contains references to functions that must be inlined
     bool isPackageFile; // if it is a package.d
     Package *pkg;       // if isPackageFile is true, the Package that contains this package.d
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 18af7721df1..1494044da59 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -55,7 +55,7 @@  import dmd.visitor;
 enum LOGDOTEXP = 0;         // log ::dotExp()
 enum LOGDEFAULTINIT = 0;    // log ::defaultInit()
 
-enum SIZE_INVALID = (~cast(d_uns64)0);   // error return from size() functions
+enum SIZE_INVALID = (~cast(uinteger_t)0);   // error return from size() functions
 
 
 /***************************
@@ -887,12 +887,12 @@  extern (C++) abstract class Type : ASTNode
         stringtable = stringtable.init;
     }
 
-    final d_uns64 size()
+    final uinteger_t size()
     {
         return size(Loc.initial);
     }
 
-    d_uns64 size(const ref Loc loc)
+    uinteger_t size(const ref Loc loc)
     {
         error(loc, "no size for type `%s`", toChars());
         return SIZE_INVALID;
@@ -2770,7 +2770,7 @@  extern (C++) final class TypeError : Type
         return this;
     }
 
-    override d_uns64 size(const ref Loc loc)
+    override uinteger_t size(const ref Loc loc)
     {
         return SIZE_INVALID;
     }
@@ -3237,7 +3237,7 @@  extern (C++) final class TypeBasic : Type
         return this;
     }
 
-    override d_uns64 size(const ref Loc loc) const
+    override uinteger_t size(const ref Loc loc) const
     {
         uint size;
         //printf("TypeBasic::size()\n");
@@ -3411,8 +3411,8 @@  extern (C++) final class TypeBasic : Type
             // If converting from integral to integral
             if (tob.flags & TFlags.integral)
             {
-                d_uns64 sz = size(Loc.initial);
-                d_uns64 tosz = tob.size(Loc.initial);
+                const sz = size(Loc.initial);
+                const tosz = tob.size(Loc.initial);
 
                 /* Can't convert to smaller size
                  */
@@ -3512,7 +3512,7 @@  extern (C++) final class TypeVector : Type
         return new TypeVector(basetype.syntaxCopy());
     }
 
-    override d_uns64 size(const ref Loc loc)
+    override uinteger_t size(const ref Loc loc)
     {
         return basetype.size();
     }
@@ -3661,7 +3661,7 @@  extern (C++) final class TypeSArray : TypeArray
         return dim.isIntegerExp() && dim.isIntegerExp().getInteger() == 0;
     }
 
-    override d_uns64 size(const ref Loc loc)
+    override uinteger_t size(const ref Loc loc)
     {
         //printf("TypeSArray::size()\n");
         const n = numberOfElems(loc);
@@ -3860,7 +3860,7 @@  extern (C++) final class TypeDArray : TypeArray
         return result;
     }
 
-    override d_uns64 size(const ref Loc loc) const
+    override uinteger_t size(const ref Loc loc) const
     {
         //printf("TypeDArray::size()\n");
         return target.ptrsize * 2;
@@ -3964,7 +3964,7 @@  extern (C++) final class TypeAArray : TypeArray
         return result;
     }
 
-    override d_uns64 size(const ref Loc loc) const
+    override uinteger_t size(const ref Loc loc) const
     {
         return target.ptrsize;
     }
@@ -4056,7 +4056,7 @@  extern (C++) final class TypePointer : TypeNext
         return result;
     }
 
-    override d_uns64 size(const ref Loc loc) const
+    override uinteger_t size(const ref Loc loc) const
     {
         return target.ptrsize;
     }
@@ -4159,7 +4159,7 @@  extern (C++) final class TypeReference : TypeNext
         return result;
     }
 
-    override d_uns64 size(const ref Loc loc) const
+    override uinteger_t size(const ref Loc loc) const
     {
         return target.ptrsize;
     }
@@ -4596,8 +4596,10 @@  extern (C++) final class TypeFunction : TypeNext
         if (global.gag && !global.params.showGaggedErrors)
             return null;
         // show qualification when toChars() is the same but types are different
-        auto at = arg.type.toChars();
-        bool qual = !arg.type.equals(par.type) && strcmp(at, par.type.toChars()) == 0;
+        // https://issues.dlang.org/show_bug.cgi?id=19948
+        // when comparing the type with strcmp, we need to drop the qualifier
+        auto at = arg.type.mutableOf().toChars();
+        bool qual = !arg.type.equals(par.type) && strcmp(at, par.type.mutableOf().toChars()) == 0;
         if (qual)
             at = arg.type.toPrettyChars(true);
         OutBuffer buf;
@@ -4845,7 +4847,7 @@  extern (C++) final class TypeFunction : TypeNext
                             // Need to make this a rvalue through a temporary
                             m = MATCH.convert;
                         }
-                        else if (!global.params.rvalueRefParam ||
+                        else if (global.params.rvalueRefParam != FeatureState.enabled ||
                                  p.storageClass & STC.out_ ||
                                  !arg.type.isCopyable())  // can't copy to temp for ref parameter
                         {
@@ -5328,7 +5330,7 @@  extern (C++) final class TypeDelegate : TypeNext
         return t;
     }
 
-    override d_uns64 size(const ref Loc loc) const
+    override uinteger_t size(const ref Loc loc) const
     {
         return target.ptrsize * 2;
     }
@@ -5435,7 +5437,7 @@  extern (C++) final class TypeTraits : Type
         v.visit(this);
     }
 
-    override d_uns64 size(const ref Loc loc)
+    override uinteger_t size(const ref Loc loc)
     {
         return SIZE_INVALID;
     }
@@ -5562,7 +5564,7 @@  extern (C++) abstract class TypeQualified : Type
         idents.push(e);
     }
 
-    override d_uns64 size(const ref Loc loc)
+    override uinteger_t size(const ref Loc loc)
     {
         error(this.loc, "size of type `%s` is not known", toChars());
         return SIZE_INVALID;
@@ -5717,7 +5719,7 @@  extern (C++) final class TypeTypeof : TypeQualified
         return s;
     }
 
-    override d_uns64 size(const ref Loc loc)
+    override uinteger_t size(const ref Loc loc)
     {
         if (exp.type)
             return exp.type.size(loc);
@@ -5792,7 +5794,7 @@  extern (C++) final class TypeStruct : Type
         return "struct";
     }
 
-    override d_uns64 size(const ref Loc loc)
+    override uinteger_t size(const ref Loc loc)
     {
         return sym.size(loc);
     }
@@ -6148,7 +6150,7 @@  extern (C++) final class TypeEnum : Type
         return this;
     }
 
-    override d_uns64 size(const ref Loc loc)
+    override uinteger_t size(const ref Loc loc)
     {
         return sym.getMemtype(loc).size(loc);
     }
@@ -6315,7 +6317,7 @@  extern (C++) final class TypeClass : Type
         return "class";
     }
 
-    override d_uns64 size(const ref Loc loc) const
+    override uinteger_t size(const ref Loc loc) const
     {
         return target.ptrsize;
     }
@@ -6718,7 +6720,7 @@  extern (C++) final class TypeNull : Type
         return true;
     }
 
-    override d_uns64 size(const ref Loc loc) const
+    override uinteger_t size(const ref Loc loc) const
     {
         return tvoidptr.size(loc);
     }
@@ -6777,7 +6779,7 @@  extern (C++) final class TypeNoreturn : Type
         return true;  // bottom type can be implicitly converted to any other type
     }
 
-    override d_uns64 size(const ref Loc loc) const
+    override uinteger_t size(const ref Loc loc) const
     {
         return 0;
     }
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index 3f085b06091..07c574d42b7 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -100,7 +100,7 @@  enum class TY : uint8_t
     TMAX
 };
 
-#define SIZE_INVALID (~(d_uns64)0)   // error return from size() functions
+#define SIZE_INVALID (~(uinteger_t)0)   // error return from size() functions
 
 
 /**
@@ -230,8 +230,8 @@  public:
     char *toPrettyChars(bool QualifyTypes = false);
     static void _init();
 
-    d_uns64 size();
-    virtual d_uns64 size(const Loc &loc);
+    uinteger_t size();
+    virtual uinteger_t size(const Loc &loc);
     virtual unsigned alignsize();
     Type *trySemantic(const Loc &loc, Scope *sc);
     Type *merge2();
@@ -357,7 +357,7 @@  public:
     const char *kind();
     TypeError *syntaxCopy();
 
-    d_uns64 size(const Loc &loc);
+    uinteger_t size(const Loc &loc);
     Expression *defaultInitLiteral(const Loc &loc);
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -393,7 +393,7 @@  public:
 
     const char *kind();
     TypeBasic *syntaxCopy();
-    d_uns64 size(const Loc &loc) /*const*/;
+    uinteger_t size(const Loc &loc) /*const*/;
     unsigned alignsize();
     bool isintegral();
     bool isfloating() /*const*/;
@@ -418,7 +418,7 @@  public:
     static TypeVector *create(Type *basetype);
     const char *kind();
     TypeVector *syntaxCopy();
-    d_uns64 size(const Loc &loc);
+    uinteger_t size(const Loc &loc);
     unsigned alignsize();
     bool isintegral();
     bool isfloating();
@@ -448,7 +448,7 @@  public:
     const char *kind();
     TypeSArray *syntaxCopy();
     bool isIncomplete();
-    d_uns64 size(const Loc &loc);
+    uinteger_t size(const Loc &loc);
     unsigned alignsize();
     bool isString();
     bool isZeroInit(const Loc &loc);
@@ -471,7 +471,7 @@  class TypeDArray : public TypeArray
 public:
     const char *kind();
     TypeDArray *syntaxCopy();
-    d_uns64 size(const Loc &loc) /*const*/;
+    uinteger_t size(const Loc &loc) /*const*/;
     unsigned alignsize() /*const*/;
     bool isString();
     bool isZeroInit(const Loc &loc) /*const*/;
@@ -491,7 +491,7 @@  public:
     static TypeAArray *create(Type *t, Type *index);
     const char *kind();
     TypeAArray *syntaxCopy();
-    d_uns64 size(const Loc &loc);
+    uinteger_t size(const Loc &loc);
     bool isZeroInit(const Loc &loc) /*const*/;
     bool isBoolean() /*const*/;
     bool hasPointers() /*const*/;
@@ -507,7 +507,7 @@  public:
     static TypePointer *create(Type *t);
     const char *kind();
     TypePointer *syntaxCopy();
-    d_uns64 size(const Loc &loc) /*const*/;
+    uinteger_t size(const Loc &loc) /*const*/;
     MATCH implicitConvTo(Type *to);
     MATCH constConv(Type *to);
     bool isscalar() /*const*/;
@@ -522,7 +522,7 @@  class TypeReference : public TypeNext
 public:
     const char *kind();
     TypeReference *syntaxCopy();
-    d_uns64 size(const Loc &loc) /*const*/;
+    uinteger_t size(const Loc &loc) /*const*/;
     bool isZeroInit(const Loc &loc) /*const*/;
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -655,7 +655,7 @@  public:
     const char *kind();
     TypeDelegate *syntaxCopy();
     Type *addStorageClass(StorageClass stc);
-    d_uns64 size(const Loc &loc) /*const*/;
+    uinteger_t size(const Loc &loc) /*const*/;
     unsigned alignsize() /*const*/;
     MATCH implicitConvTo(Type *to);
     bool isZeroInit(const Loc &loc) /*const*/;
@@ -675,7 +675,7 @@  class TypeTraits : public Type
 
     const char *kind();
     TypeTraits *syntaxCopy();
-    d_uns64 size(const Loc &loc);
+    uinteger_t size(const Loc &loc);
     Dsymbol *toDsymbol(Scope *sc);
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -704,7 +704,7 @@  public:
     void addIdent(Identifier *ident);
     void addInst(TemplateInstance *inst);
     void addIndex(RootObject *expr);
-    d_uns64 size(const Loc &loc);
+    uinteger_t size(const Loc &loc);
 
     void accept(Visitor *v) { v->visit(this); }
 };
@@ -744,7 +744,7 @@  public:
     const char *kind();
     TypeTypeof *syntaxCopy();
     Dsymbol *toDsymbol(Scope *sc);
-    d_uns64 size(const Loc &loc);
+    uinteger_t size(const Loc &loc);
     void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -778,7 +778,7 @@  public:
 
     static TypeStruct *create(StructDeclaration *sym);
     const char *kind();
-    d_uns64 size(const Loc &loc);
+    uinteger_t size(const Loc &loc);
     unsigned alignsize();
     TypeStruct *syntaxCopy();
     Dsymbol *toDsymbol(Scope *sc);
@@ -808,7 +808,7 @@  public:
 
     const char *kind();
     TypeEnum *syntaxCopy();
-    d_uns64 size(const Loc &loc);
+    uinteger_t size(const Loc &loc);
     unsigned alignsize();
     Type *memType(const Loc &loc = Loc());
     Dsymbol *toDsymbol(Scope *sc);
@@ -844,7 +844,7 @@  public:
     CPPMANGLE cppmangle;
 
     const char *kind();
-    d_uns64 size(const Loc &loc) /*const*/;
+    uinteger_t size(const Loc &loc) /*const*/;
     TypeClass *syntaxCopy();
     Dsymbol *toDsymbol(Scope *sc);
     ClassDeclaration *isClassHandle();
@@ -899,7 +899,7 @@  public:
     MATCH implicitConvTo(Type *to);
     bool isBoolean() /*const*/;
 
-    d_uns64 size(const Loc &loc) /*const*/;
+    uinteger_t size(const Loc &loc) /*const*/;
     void accept(Visitor *v) { v->visit(this); }
 };
 
@@ -911,7 +911,7 @@  public:
     MATCH implicitConvTo(Type* to);
     MATCH constConv(Type* to);
     bool isBoolean() /* const */;
-    d_uns64 size(const Loc& loc) /* const */;
+    uinteger_t size(const Loc& loc) /* const */;
     unsigned alignsize();
 
     void accept(Visitor *v) { v->visit(this); }
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index cc02bd9ea7c..5a86931305a 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -221,7 +221,7 @@  package void setLengthVarIfKnown(VarDeclaration lengthVar, Expression arr)
         return;
     if (lengthVar._init && !lengthVar._init.isVoidInitializer())
         return; // we have previously calculated the length
-    d_uns64 len;
+    dinteger_t len;
     if (auto se = arr.isStringExp())
         len = se.len;
     else if (auto ale = arr.isArrayLiteralExp())
@@ -253,7 +253,7 @@  package void setLengthVarIfKnown(VarDeclaration lengthVar, Type type)
     auto tsa = type.toBasetype().isTypeSArray();
     if (!tsa)
         return; // we don't know the length yet
-    d_uns64 len = tsa.dim.toInteger();
+    const len = tsa.dim.toInteger();
     Expression dollar = new IntegerExp(Loc.initial, len, Type.tsize_t);
     lengthVar._init = new ExpInitializer(Loc.initial, dollar);
     lengthVar.storage_class |= STC.static_ | STC.const_;
@@ -809,7 +809,7 @@  Expression Expression_optimize(Expression e, int result, bool keepLvalue)
             if (e.e2.isConst() == 1)
             {
                 sinteger_t i2 = e.e2.toInteger();
-                d_uns64 sz = e.e1.type.size(e.e1.loc);
+                uinteger_t sz = e.e1.type.size(e.e1.loc);
                 assert(sz != SIZE_INVALID);
                 sz *= 8;
                 if (i2 < 0 || i2 >= sz)
@@ -895,7 +895,7 @@  Expression Expression_optimize(Expression e, int result, bool keepLvalue)
         if (e.e2.isConst() == 1)
         {
             sinteger_t i2 = e.e2.toInteger();
-            d_uns64 sz = e.e1.type.size(e.e1.loc);
+            uinteger_t sz = e.e1.type.size(e.e1.loc);
             assert(sz != SIZE_INVALID);
             sz *= 8;
             if (i2 < 0 || i2 >= sz)
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 480a96c25db..f6472bf925d 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -30,7 +30,7 @@  import dmd.tokens;
 
 /***********************************************************
  */
-class Parser(AST) : Lexer
+class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
 {
     AST.ModuleDeclaration* md;
 
@@ -1263,7 +1263,7 @@  class Parser(AST) : Lexer
         }
 
         checkConflictSTCGroup(STC.const_ | STC.immutable_ | STC.manifest);
-        checkConflictSTCGroup(STC.gshared | STC.shared_ | STC.tls);
+        checkConflictSTCGroup(STC.gshared | STC.shared_);
         checkConflictSTCGroup!true(STC.safeGroup);
 
         return orig;
@@ -9599,5 +9599,3 @@  private bool writeMixin(const(char)[] s, ref Loc loc)
 
     return true;
 }
-
-
diff --git a/gcc/d/dmd/root/file.h b/gcc/d/dmd/root/file.h
deleted file mode 100644
index 44ca024d105..00000000000
--- a/gcc/d/dmd/root/file.h
+++ /dev/null
@@ -1,41 +0,0 @@ 
-
-/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * https://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * https://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/root/file.h
- */
-
-#pragma once
-
-#include "array.h"
-#include "filename.h"
-
-struct FileBuffer
-{
-    DArray<unsigned char> data;
-
-    FileBuffer(const FileBuffer &) /* = delete */;
-    ~FileBuffer() { mem.xfree(data.ptr); }
-
-    static FileBuffer *create();
-};
-
-struct File
-{
-    struct ReadResult
-    {
-        bool success;
-        FileBuffer buffer;
-    };
-
-    // Read the full content of a file.
-    static ReadResult read(const char *name);
-
-    // Write a file, returning `true` on success.
-    static bool write(const char *name, const void *data, d_size_t size);
-
-    // Delete a file.
-    static void remove(const char *name);
-};
diff --git a/gcc/d/dmd/root/filename.d b/gcc/d/dmd/root/filename.d
index 292fccfb110..3b7b75b0aff 100644
--- a/gcc/d/dmd/root/filename.d
+++ b/gcc/d/dmd/root/filename.d
@@ -36,6 +36,8 @@  version (Windows)
     import core.sys.windows.windef;
     import core.sys.windows.winnls;
 
+    import dmd.common.string : extendedPathThen;
+
     extern (Windows) DWORD GetFullPathNameW(LPCWSTR, DWORD, LPWSTR, LPWSTR*) nothrow @nogc;
     extern (Windows) void SetLastError(DWORD) nothrow @nogc;
     extern (C) char* getcwd(char* buffer, size_t maxlen) nothrow;
@@ -855,7 +857,7 @@  nothrow:
         }
         else version (Windows)
         {
-            return name.toWStringzThen!((wname)
+            return name.extendedPathThen!((wname)
             {
                 const dw = GetFileAttributesW(&wname[0]);
                 if (dw == -1)
@@ -1005,7 +1007,7 @@  nothrow:
                 // Have canonicalize_file_name, which malloc's memory.
                 // We need a dmd.root.rmem allocation though.
                 auto path = name.toCStringThen!((n) => canonicalize_file_name(n.ptr));
-                scope(exit) .free(path.ptr);
+                scope(exit) .free(path);
                 if (path !is null)
                     return xarraydup(path.toDString);
             }
@@ -1124,7 +1126,6 @@  version(Windows)
      */
     private int _mkdir(const(char)[] path) nothrow
     {
-        import dmd.common.string : extendedPathThen;
         const createRet = path.extendedPathThen!(
             p => CreateDirectoryW(&p[0], null /*securityAttributes*/));
         // different conventions for CreateDirectory and mkdir
diff --git a/gcc/d/dmd/root/string.d b/gcc/d/dmd/root/string.d
index ec62292d7df..93c596ff0cd 100644
--- a/gcc/d/dmd/root/string.d
+++ b/gcc/d/dmd/root/string.d
@@ -201,10 +201,10 @@  int dstrcmp()( scope const char[] s1, scope const char[] s2 ) @trusted
 unittest
 {
     assert(dstrcmp("Fraise", "Fraise")      == 0);
-    assert(dstrcmp("Baguette", "Croissant") == -1);
-    assert(dstrcmp("Croissant", "Baguette") == 1);
+    assert(dstrcmp("Baguette", "Croissant") < 0);
+    assert(dstrcmp("Croissant", "Baguette") > 0);
 
-    static assert(dstrcmp("Baguette", "Croissant") == -1);
+    static assert(dstrcmp("Baguette", "Croissant") < 0);
 
     // UTF-8 decoding for the CT variant
     assert(dstrcmp("안녕하세요!", "안녕하세요!") == 0);
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index 85c4d5bf6a5..b9029a16ef8 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -330,11 +330,14 @@  private extern(C++) final class Semantic2Visitor : Visitor
         // gets imported, it is unaffected by context.
         Scope* sc = Scope.createGlobal(mod); // create root scope
         //printf("Module = %p\n", sc.scopesym);
-        // Pass 2 semantic routines: do initializers and function bodies
-        for (size_t i = 0; i < mod.members.dim; i++)
+        if (mod.members)
         {
-            Dsymbol s = (*mod.members)[i];
-            s.semantic2(sc);
+            // Pass 2 semantic routines: do initializers and function bodies
+            for (size_t i = 0; i < mod.members.dim; i++)
+            {
+                Dsymbol s = (*mod.members)[i];
+                s.semantic2(sc);
+            }
         }
         if (mod.userAttribDecl)
         {
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index b706777a1ed..d237caf9356 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -187,14 +187,17 @@  private extern(C++) final class Semantic3Visitor : Visitor
         // gets imported, it is unaffected by context.
         Scope* sc = Scope.createGlobal(mod); // create root scope
         //printf("Module = %p\n", sc.scopesym);
-        // Pass 3 semantic routines: do initializers and function bodies
-        for (size_t i = 0; i < mod.members.dim; i++)
+        if (mod.members)
         {
-            Dsymbol s = (*mod.members)[i];
-            //printf("Module %s: %s.semantic3()\n", toChars(), s.toChars());
-            s.semantic3(sc);
+            // Pass 3 semantic routines: do initializers and function bodies
+            for (size_t i = 0; i < mod.members.dim; i++)
+            {
+                Dsymbol s = (*mod.members)[i];
+                //printf("Module %s: %s.semantic3()\n", toChars(), s.toChars());
+                s.semantic3(sc);
 
-            mod.runDeferredSemantic2();
+                mod.runDeferredSemantic2();
+            }
         }
         if (mod.userAttribDecl)
         {
@@ -1282,6 +1285,7 @@  private extern(C++) final class Semantic3Visitor : Visitor
                 if (funcdecl.type == f)
                     f = cast(TypeFunction)f.copy();
                 f.isreturn = true;
+                f.isreturnscope = cast(bool) (funcdecl.storage_class & STC.returnScope);
                 if (funcdecl.storage_class & STC.returninferred)
                     f.isreturninferred = true;
             }
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index f229918d899..6ffba68fc49 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -987,18 +987,17 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
                 if (dim == 2)
                 {
                     Parameter p = (*fs.parameters)[0];
-                    auto var = new VarDeclaration(loc, p.type.mutableOf(), Identifier.generateId("__key"), null);
-                    var.storage_class |= STC.temp | STC.foreach_;
-                    if (var.storage_class & (STC.ref_ | STC.out_))
-                        var.storage_class |= STC.nodtor;
+                    fs.key = new VarDeclaration(loc, p.type.mutableOf(), Identifier.generateId("__key"), null);
+                    fs.key.storage_class |= STC.temp | STC.foreach_;
+                    if (fs.key.isReference())
+                        fs.key.storage_class |= STC.nodtor;
 
-                    fs.key = var;
                     if (p.storageClass & STC.ref_)
                     {
-                        if (var.type.constConv(p.type) == MATCH.nomatch)
+                        if (fs.key.type.constConv(p.type) == MATCH.nomatch)
                         {
                             fs.error("key type mismatch, `%s` to `ref %s`",
-                                     var.type.toChars(), p.type.toChars());
+                                     fs.key.type.toChars(), p.type.toChars());
                             return retError();
                         }
                     }
@@ -1008,7 +1007,7 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
                         IntRange dimrange = getIntRange(ta.dim);
                         // https://issues.dlang.org/show_bug.cgi?id=12504
                         dimrange.imax = SignExtendedNumber(dimrange.imax.value-1);
-                        if (!IntRange.fromType(var.type).contains(dimrange))
+                        if (!IntRange.fromType(fs.key.type).contains(dimrange))
                         {
                             fs.error("index type `%s` cannot cover index range 0..%llu",
                                      p.type.toChars(), ta.dim.toInteger());
@@ -1020,17 +1019,15 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
                 // Now declare the value
                 {
                     Parameter p = (*fs.parameters)[dim - 1];
-                    auto var = new VarDeclaration(loc, p.type, p.ident, null);
-                    var.storage_class |= STC.foreach_;
-                    var.storage_class |= p.storageClass & (STC.scope_ | STC.IOR | STC.TYPECTOR);
-                    if (var.isReference())
-                        var.storage_class |= STC.nodtor;
-
-                    fs.value = var;
-                    if (var.storage_class & STC.ref_)
+                    fs.value = new VarDeclaration(loc, p.type, p.ident, null);
+                    fs.value.storage_class |= STC.foreach_;
+                    fs.value.storage_class |= p.storageClass & (STC.scope_ | STC.IOR | STC.TYPECTOR);
+                    if (fs.value.isReference())
                     {
+                        fs.value.storage_class |= STC.nodtor;
+
                         if (fs.aggr.checkModifiable(sc2, ModifyFlags.noError) == Modifiable.initialization)
-                            var.setInCtorOnly = true;
+                            fs.value.setInCtorOnly = true;
 
                         Type t = tab.nextOf();
                         if (t.constConv(p.type) == MATCH.nomatch)
@@ -1053,7 +1050,7 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
                  */
                 auto id = Identifier.generateId("__r");
                 auto ie = new ExpInitializer(loc, new SliceExp(loc, fs.aggr, null, null));
-                const valueIsRef = cast(bool) ((*fs.parameters)[dim - 1].storageClass & STC.ref_);
+                const valueIsRef = (*fs.parameters)[$ - 1].isReference();
                 VarDeclaration tmp;
                 if (fs.aggr.op == EXP.arrayLiteral && !valueIsRef)
                 {
diff --git a/gcc/d/dmd/target.d b/gcc/d/dmd/target.d
index 7b9c454b33a..eb85c676a4b 100644
--- a/gcc/d/dmd/target.d
+++ b/gcc/d/dmd/target.d
@@ -61,7 +61,7 @@  extern (C++) struct Target
     import dmd.dscope : Scope;
     import dmd.expression : Expression;
     import dmd.func : FuncDeclaration;
-    import dmd.globals : Loc, d_int64;
+    import dmd.globals : Loc;
     import dmd.astenums : LINK, TY;
     import dmd.mtype : Type, TypeFunction, TypeTuple;
     import dmd.root.ctfloat : real_t;
@@ -125,18 +125,18 @@  extern (C++) struct Target
      */
     extern (C++) struct FPTypeProperties(T)
     {
-        real_t max;                         /// largest representable value that's not infinity
-        real_t min_normal;                  /// smallest representable normalized value that's not 0
-        real_t nan;                         /// NaN value
-        real_t infinity;                    /// infinity value
-        real_t epsilon;                     /// smallest increment to the value 1
-
-        d_int64 dig;                        /// number of decimal digits of precision
-        d_int64 mant_dig;                   /// number of bits in mantissa
-        d_int64 max_exp;                    /// maximum int value such that 2$(SUPERSCRIPT `max_exp-1`) is representable
-        d_int64 min_exp;                    /// minimum int value such that 2$(SUPERSCRIPT `min_exp-1`) is representable as a normalized value
-        d_int64 max_10_exp;                 /// maximum int value such that 10$(SUPERSCRIPT `max_10_exp` is representable)
-        d_int64 min_10_exp;                 /// minimum int value such that 10$(SUPERSCRIPT `min_10_exp`) is representable as a normalized value
+        real_t max;         /// largest representable value that's not infinity
+        real_t min_normal;  /// smallest representable normalized value that's not 0
+        real_t nan;         /// NaN value
+        real_t infinity;    /// infinity value
+        real_t epsilon;     /// smallest increment to the value 1
+
+        long dig;           /// number of decimal digits of precision
+        long mant_dig;      /// number of bits in mantissa
+        long max_exp;       /// maximum int value such that 2$(SUPERSCRIPT `max_exp-1`) is representable
+        long min_exp;       /// minimum int value such that 2$(SUPERSCRIPT `min_exp-1`) is representable as a normalized value
+        long max_10_exp;    /// maximum int value such that 10$(SUPERSCRIPT `max_10_exp` is representable)
+        long min_10_exp;    /// minimum int value such that 10$(SUPERSCRIPT `min_10_exp`) is representable as a normalized value
     }
 
     FPTypeProperties!float FloatProperties;     ///
@@ -245,17 +245,6 @@  extern (C++) struct Target
      */
     extern (C++) bool isReturnOnStack(TypeFunction tf, bool needsThis);
 
-    /***
-     * Determine the size a value of type `t` will be when it
-     * is passed on the function parameter stack.
-     * Params:
-     *  loc = location to use for error messages
-     *  t = type of parameter
-     * Returns:
-     *  size used on parameter stack
-     */
-    extern (C++) ulong parameterSize(const ref Loc loc, Type t);
-
     /**
      * Decides whether an `in` parameter of the specified POD type is to be
      * passed by reference or by value. To be used with `-preview=in` only!
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index f3d3859e224..096c16fd610 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -175,12 +175,12 @@  struct Target
         real_t infinity;
         real_t epsilon;
 
-        d_int64 dig;
-        d_int64 mant_dig;
-        d_int64 max_exp;
-        d_int64 min_exp;
-        d_int64 max_10_exp;
-        d_int64 min_10_exp;
+        int64_t dig;
+        int64_t mant_dig;
+        int64_t max_exp;
+        int64_t min_exp;
+        int64_t max_10_exp;
+        int64_t min_10_exp;
     };
 
     FPTypeProperties<float> FloatProperties;
@@ -194,7 +194,6 @@  private:
 public:
     void _init(const Param& params);
     // Type sizes and support.
-    void setTriple(const char* _triple);
     unsigned alignsize(Type *type);
     unsigned fieldalign(Type *type);
     Type *va_listType(const Loc &loc, Scope *sc);  // get type of va_list
@@ -204,7 +203,6 @@  public:
     LINK systemLinkage();
     TypeTuple *toArgTypes(Type *t);
     bool isReturnOnStack(TypeFunction *tf, bool needsThis);
-    d_uns64 parameterSize(const Loc& loc, Type *t);
     bool preferPassByRef(Type *t);
     Expression *getTargetInfo(const char* name, const Loc& loc);
     bool isCalleeDestroyingArgs(TypeFunction* tf);
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index 42517f6403c..86863769141 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -314,3 +314,4 @@  Tuple *isTuple(RootObject *o);
 Parameter *isParameter(RootObject *o);
 TemplateParameter *isTemplateParameter(RootObject *o);
 bool isError(const RootObject *const o);
+void printTemplateStats();
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index 6e56eb25474..1790996619b 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -942,17 +942,17 @@  nothrow:
         switch (value)
         {
         case TOK.int32Literal:
-            sprintf(&buffer[0], "%d", cast(d_int32)intvalue);
+            sprintf(&buffer[0], "%d", cast(int)intvalue);
             break;
         case TOK.uns32Literal:
         case TOK.wcharLiteral:
         case TOK.dcharLiteral:
         case TOK.wchar_tLiteral:
-            sprintf(&buffer[0], "%uU", cast(d_uns32)unsvalue);
+            sprintf(&buffer[0], "%uU", cast(uint)unsvalue);
             break;
         case TOK.charLiteral:
         {
-            const v = cast(d_int32)intvalue;
+            const v = cast(int)intvalue;
             if (v >= ' ' && v <= '~')
                 sprintf(&buffer[0], "'%c'", v);
             else
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 61602518163..dbdcfd4af85 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -166,28 +166,28 @@  shared static this()
 /**
  * get an array of size_t values that indicate possible pointer words in memory
  *  if interpreted as the type given as argument
- * Returns: the size of the type in bytes, d_uns64.max on error
+ * Returns: the size of the type in bytes, ulong.max on error
  */
-d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
+ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data)
 {
-    d_uns64 sz;
+    ulong sz;
     if (t.ty == Tclass && !(cast(TypeClass)t).sym.isInterfaceDeclaration())
         sz = (cast(TypeClass)t).sym.AggregateDeclaration.size(loc);
     else
         sz = t.size(loc);
     if (sz == SIZE_INVALID)
-        return d_uns64.max;
+        return ulong.max;
 
     const sz_size_t = Type.tsize_t.size(loc);
     if (sz > sz.max - sz_size_t)
     {
         error(loc, "size overflow for type `%s`", t.toChars());
-        return d_uns64.max;
+        return ulong.max;
     }
 
-    d_uns64 bitsPerWord = sz_size_t * 8;
-    d_uns64 cntptr = (sz + sz_size_t - 1) / sz_size_t;
-    d_uns64 cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord;
+    ulong bitsPerWord = sz_size_t * 8;
+    ulong cntptr = (sz + sz_size_t - 1) / sz_size_t;
+    ulong cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord;
 
     data.setDim(cast(size_t)cntdata);
     data.zero();
@@ -196,15 +196,15 @@  d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
     {
         alias visit = Visitor.visit;
     public:
-        extern (D) this(Array!(d_uns64)* _data, d_uns64 _sz_size_t)
+        extern (D) this(Array!(ulong)* _data, ulong _sz_size_t)
         {
             this.data = _data;
             this.sz_size_t = _sz_size_t;
         }
 
-        void setpointer(d_uns64 off)
+        void setpointer(ulong off)
         {
-            d_uns64 ptroff = off / sz_size_t;
+            ulong ptroff = off / sz_size_t;
             (*data)[cast(size_t)(ptroff / (8 * sz_size_t))] |= 1L << (ptroff % (8 * sz_size_t));
         }
 
@@ -242,12 +242,12 @@  d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
 
         override void visit(TypeSArray t)
         {
-            d_uns64 arrayoff = offset;
-            d_uns64 nextsize = t.next.size();
+            ulong arrayoff = offset;
+            ulong nextsize = t.next.size();
             if (nextsize == SIZE_INVALID)
                 error = true;
-            d_uns64 dim = t.dim.toInteger();
-            for (d_uns64 i = 0; i < dim; i++)
+            ulong dim = t.dim.toInteger();
+            for (ulong i = 0; i < dim; i++)
             {
                 offset = arrayoff + i * nextsize;
                 t.next.accept(this);
@@ -340,7 +340,7 @@  d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
 
         override void visit(TypeStruct t)
         {
-            d_uns64 structoff = offset;
+            ulong structoff = offset;
             foreach (v; t.sym.fields)
             {
                 offset = structoff + v.offset;
@@ -355,7 +355,7 @@  d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
         // a "toplevel" class is treated as an instance, while TypeClass fields are treated as references
         void visitClass(TypeClass t)
         {
-            d_uns64 classoff = offset;
+            ulong classoff = offset;
             // skip vtable-ptr and monitor
             if (t.sym.baseClass)
                 visitClass(cast(TypeClass)t.sym.baseClass.type);
@@ -367,9 +367,9 @@  d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
             offset = classoff;
         }
 
-        Array!(d_uns64)* data;
-        d_uns64 offset;
-        d_uns64 sz_size_t;
+        Array!(ulong)* data;
+        ulong offset;
+        ulong sz_size_t;
         bool error;
     }
 
@@ -378,7 +378,7 @@  d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
         pbv.visitClass(cast(TypeClass)t);
     else
         t.accept(pbv);
-    return pbv.error ? d_uns64.max : sz;
+    return pbv.error ? ulong.max : sz;
 }
 
 /**
@@ -406,9 +406,9 @@  private Expression pointerBitmap(TraitsExp e)
         return ErrorExp.get();
     }
 
-    Array!(d_uns64) data;
-    d_uns64 sz = getTypePointerBitmap(e.loc, t, &data);
-    if (sz == d_uns64.max)
+    Array!(ulong) data;
+    ulong sz = getTypePointerBitmap(e.loc, t, &data);
+    if (sz == ulong.max)
         return ErrorExp.get();
 
     auto exps = new Expressions(data.dim + 1);
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 57188af90d6..e5f839bb8a3 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -1304,7 +1304,7 @@  extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
             // default arg must be an lvalue
             if (isRefOrOut && !isAuto &&
                 !(global.params.previewIn && (fparam.storageClass & STC.in_)) &&
-                !(global.params.rvalueRefParam))
+                global.params.rvalueRefParam != FeatureState.enabled)
                 e = e.toLvalue(sc, e);
 
             fparam.defaultArg = e;
@@ -1504,16 +1504,6 @@  extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
 
                 /* Scope attribute is not necessary if the parameter type does not have pointers
                  */
-                /* Constructors are treated as if they are being returned through the hidden parameter,
-                 * which is by ref, and the ref there is ignored.
-                 */
-                const returnByRef = tf.isref && !tf.isctor;
-                if (!returnByRef && isRefReturnScope(fparam.storageClass))
-                {
-                    /* if `ref return scope`, evaluate to `ref` `return scope`
-                     */
-                    fparam.storageClass |= STC.returnScope;
-                }
                 const sr = buildScopeRef(fparam.storageClass);
                 switch (sr)
                 {
@@ -1534,17 +1524,6 @@  extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                         break;
                 }
 
-                /* now set STC.returnScope based only on tf.isref. This is inconsistent, as mentioned above,
-                 * but necessary for compatibility for now.
-                 */
-                fparam.storageClass &= ~STC.returnScope;
-                if (!tf.isref && isRefReturnScope(fparam.storageClass))
-                {
-                    /* if `ref return scope`, evaluate to `ref` `return scope`
-                     */
-                    fparam.storageClass |= STC.returnScope;
-                }
-
                 // Remove redundant storage classes for type, they are already applied
                 fparam.storageClass &= ~(STC.TYPECTOR);
 
@@ -2411,7 +2390,7 @@  Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
         }
         if (ident == Id.__sizeof)
         {
-            d_uns64 sz = mt.size(loc);
+            const sz = mt.size(loc);
             if (sz == SIZE_INVALID)
                 return ErrorExp.get();
             e = new IntegerExp(loc, sz, Type.tsize_t);
diff --git a/gcc/testsuite/gdc.dg/pr105004.d b/gcc/testsuite/gdc.dg/pr105004.d
new file mode 100644
index 00000000000..60b3c3f635e
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr105004.d
@@ -0,0 +1,14 @@ 
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105004
+// { dg-do compile }
+
+private struct _Complex(T)
+{
+    T re;
+    T im;
+}
+enum __c_complex_float  : _Complex!float;
+
+__c_complex_float pr105004(float re, float im)
+{
+    return typeof(return)(re, im);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration.d
index e0a96d4dfa3..10f5807f5c3 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_AliasDeclaration.d
@@ -125,7 +125,6 @@  typedef /* noreturn */ char Impossible[0];
 template <typename T>
 struct Array final
 {
-    // Ignoring var length alignment 0
     uint32_t length;
     Array()
     {
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d
index 1bfc25bd683..2d48999c410 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_StructDeclaration.d
@@ -175,7 +175,7 @@  struct A final
         s()
     {
     }
-    A(int32_t a, S s = S(0, 0, 0LL, {})) :
+    A(int32_t a, S s = S()) :
         a(a),
         s(s)
         {}
@@ -186,6 +186,37 @@  union U
     int32_t i;
     char c;
 };
+
+struct Array final
+{
+    uint32_t length;
+private:
+    _d_dynamicArray< char > data;
+    char smallarray[1$?:32=u|64=LLU$];
+public:
+    Array() :
+        length()
+    {
+    }
+    Array(uint32_t length) :
+        length(length)
+        {}
+};
+
+struct Params final
+{
+    bool obj;
+    Array ddocfiles;
+    Params() :
+        obj(true),
+        ddocfiles()
+    {
+    }
+    Params(bool obj, Array ddocfiles = Array()) :
+        obj(obj),
+        ddocfiles(ddocfiles)
+        {}
+};
 ---
 */
 
@@ -284,3 +315,17 @@  extern(C++) union U
     int i;
     char c;
 }
+
+extern (C++) struct Array
+{
+    uint length;
+private:
+    char[] data;
+    char[1] smallarray;
+}
+
+extern (C++) struct Params
+{
+    bool obj = true;
+    Array ddocfiles;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d
index 5f747fda8c8..e9e57da87f0 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_TemplateDeclaration.d
@@ -73,14 +73,10 @@  struct ActualBuffer final
 template <typename T>
 struct A final
 {
-    // Ignoring var x alignment 0
     T x;
-    // Ignoring var Enum alignment 0
     enum : int32_t { Enum = 42 };
 
-    // Ignoring var GsharedNum alignment 0
     static int32_t GsharedNum;
-    // Ignoring var MemNum alignment 0
     const int32_t MemNum;
     void foo();
     A()
@@ -91,8 +87,6 @@  struct A final
 template <typename T>
 struct NotInstantiated final
 {
-    // Ignoring var noInit alignment 0
-    // Ignoring var missingSem alignment 0
     NotInstantiated()
     {
     }
@@ -113,7 +107,6 @@  struct B final
 template <typename T>
 struct Foo final
 {
-    // Ignoring var val alignment 0
     T val;
     Foo()
     {
@@ -123,7 +116,6 @@  struct Foo final
 template <typename T>
 struct Bar final
 {
-    // Ignoring var v alignment 0
     Foo<T > v;
     Bar()
     {
@@ -141,9 +133,7 @@  struct Array final
     void get() const;
     template <typename T>
     bool opCast() const;
-    // Ignoring var i alignment 0
     typename T::Member i;
-    // Ignoring var j alignment 0
     typename Outer::Member::Nested j;
     void visit(typename T::Member::Nested i);
     Array()
@@ -159,7 +149,6 @@  extern A<A<int32_t > > aaint;
 template <typename T>
 class Parent
 {
-    // Ignoring var parentMember alignment 0
 public:
     T parentMember;
     void parentFinal();
@@ -169,7 +158,6 @@  public:
 template <typename T>
 class Child final : public Parent<T >
 {
-    // Ignoring var childMember alignment 0
 public:
     T childMember;
     void parentVirtual();
@@ -207,14 +195,10 @@  extern HasMixinsTemplate<bool > hmti;
 template <typename T>
 struct NotAA final
 {
-    // Ignoring var length alignment 0
     enum : int32_t { length = 12 };
 
-    // Ignoring var buffer alignment 0
     T buffer[length];
-    // Ignoring var otherBuffer alignment 0
     T otherBuffer[SomeOtherLength];
-    // Ignoring var calcBuffer alignment 0
     T calcBuffer[foo(1)];
     NotAA()
     {
@@ -224,9 +208,7 @@  struct NotAA final
 template <typename Buffer>
 struct BufferTmpl final
 {
-    // Ignoring var buffer alignment 0
     Buffer buffer;
-    // Ignoring var buffer2 alignment 0
     Buffer buffer2;
     BufferTmpl()
     {
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d b/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d
index 483e58f6ae5..2f5b7dfe68d 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d
@@ -86,7 +86,6 @@  struct ExternDStructRequired final
 template <typename T>
 struct ExternDTemplStruct final
 {
-    // Ignoring var member alignment 0
     T member;
     ExternDTemplStruct()
     {
@@ -129,7 +128,6 @@  extern TemplClass<int32_t >* templClass;
 template <typename T>
 class TemplClass
 {
-    // Ignoring var member alignment 0
 public:
     T member;
 };
@@ -139,7 +137,6 @@  extern TemplStruct<int32_t >* templStruct;
 template <typename T>
 class TemplStruct
 {
-    // Ignoring var member alignment 0
 public:
     T member;
 };
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d b/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d
index 47c0172009d..1e1b88736d4 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_ignored.d
@@ -62,11 +62,9 @@  private:
 template <typename T>
 struct WithImaginaryTemplate final
 {
-    // Ignoring var member alignment 0
     float member;
     // Ignored function onReturn because its return type cannot be mapped to C++
     // Ignored function onParam because one of its parameters has type `ifloat` which cannot be mapped to C++
-    // Ignoring var onVariable alignment 0
     // Ignored variable onVariable because its type cannot be mapped to C++
     WithImaginaryTemplate()
     {
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_invalid_identifiers.d b/gcc/testsuite/gdc.test/compilable/dtoh_invalid_identifiers.d
index 821c37c6d53..c7d4c14e0c7 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_invalid_identifiers.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_invalid_identifiers.d
@@ -58,7 +58,6 @@  namespace const_cast
 template <typename register_>
 struct S final
 {
-    // Ignoring var x alignment 0
     register_ x;
     S()
     {
@@ -104,7 +103,6 @@  extern void user(Alias<Base* >* i);
 template <typename typename_>
 struct InvalidNames final
 {
-    // Ignoring var register alignment 0
     typename_ register_;
     void foo(typename_ and_);
     InvalidNames()
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_names.d b/gcc/testsuite/gdc.test/compilable/dtoh_names.d
index 068fc68ef51..8a7eb7ffffb 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_names.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_names.d
@@ -63,13 +63,9 @@  struct Outer final
         template <typename U>
         struct InnerTmpl final
         {
-            // Ignoring var innerTmplOuterPtr alignment 0
             static Outer* innerTmplOuterPtr;
-            // Ignoring var innerTmplPtr alignment 0
             static Middle* innerTmplPtr;
-            // Ignoring var innerTmplInnerPtr alignment 0
             static Inner* innerTmplInnerPtr;
-            // Ignoring var innerTmplInnerTmplPtr alignment 0
             static InnerTmpl* innerTmplInnerTmplPtr;
             InnerTmpl()
             {
@@ -84,15 +80,11 @@  struct Outer final
     template <typename T>
     struct MiddleTmpl final
     {
-        // Ignoring var middleTmplPtr alignment 0
         static MiddleTmpl<T >* middleTmplPtr;
-        // Ignoring var middleTmplInnerTmplPtr alignment 0
         static MiddleTmpl<T >* middleTmplInnerTmplPtr;
         struct Inner final
         {
-            // Ignoring var ptr alignment 0
             static Inner* ptr;
-            // Ignoring var ptr2 alignment 0
             static MiddleTmpl<T >* ptr2;
             Inner()
             {
@@ -102,13 +94,9 @@  struct Outer final
         template <typename U>
         struct InnerTmpl final
         {
-            // Ignoring var innerTmplPtr alignment 0
             static InnerTmpl* innerTmplPtr;
-            // Ignoring var innerTmplPtrDiff alignment 0
             static InnerTmpl<char >* innerTmplPtrDiff;
-            // Ignoring var middleTmplInnerTmplPtr alignment 0
             static MiddleTmpl<T >* middleTmplInnerTmplPtr;
-            // Ignoring var a alignment 0
             static T a;
             static U bar();
             InnerTmpl()
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_required_symbols.d b/gcc/testsuite/gdc.test/compilable/dtoh_required_symbols.d
index 6e2d2f1e38c..d41cb1bc213 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_required_symbols.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_required_symbols.d
@@ -65,9 +65,7 @@  enum class ExternDEnum
 template <>
 struct ExternDStructTemplate final
 {
-    // Ignoring var i alignment 0
     int32_t i;
-    // Ignoring var d alignment 0
     double d;
     ExternDStructTemplate()
     {
@@ -131,7 +129,7 @@  struct ExternCppStruct final
         st()
     {
     }
-    ExternCppStruct(ExternDStruct s, ExternDEnum e = (ExternDEnum)0, ExternDStructTemplate< > st = ExternDStructTemplate< >(0, NAN)) :
+    ExternCppStruct(ExternDStruct s, ExternDEnum e = (ExternDEnum)0, ExternDStructTemplate< > st = ExternDStructTemplate< >()) :
         s(s),
         e(e),
         st(st)
diff --git a/gcc/testsuite/gdc.test/compilable/scope.d b/gcc/testsuite/gdc.test/compilable/scope.d
index 7e81028d278..95c784627fa 100644
--- a/gcc/testsuite/gdc.test/compilable/scope.d
+++ b/gcc/testsuite/gdc.test/compilable/scope.d
@@ -142,7 +142,7 @@  int f1_20682(return scope ref D d) @safe
     return d.pos;
 }
 
-ref int f2_20682(return scope ref D d) @safe
+ref int f2_20682(return ref scope D d) @safe
 {
     return d.pos;
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19948.d b/gcc/testsuite/gdc.test/fail_compilation/fail19948.d
new file mode 100644
index 00000000000..6122e418339
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19948.d
@@ -0,0 +1,18 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=19948
+
+/*
+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)`
+---
+*/
+
+struct X {}
+void main()
+{
+    struct X {}
+    func(X());
+}
+
+void func(const(X)) {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22881.d b/gcc/testsuite/gdc.test/fail_compilation/fail22881.d
new file mode 100644
index 00000000000..31195f6c7a5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22881.d
@@ -0,0 +1,60 @@ 
+/* TEST_OUTPUT:
+---
+fail_compilation/fail22881.d(101): Error: pointer slice `[0..6]` exceeds allocated memory block `[0..5]`
+fail_compilation/fail22881.d(102): Error: pointer slice `[0..6]` exceeds allocated memory block `[0..5]`
+fail_compilation/fail22881.d(110): Error: pointer slice `[3..5]` exceeds allocated memory block `[0..4]`
+fail_compilation/fail22881.d(113):        called from here: `ptr22881()`
+fail_compilation/fail22881.d(113):        while evaluating: `static assert(ptr22881())`
+fail_compilation/fail22881.d(203): Error: slice `[0..2]` is out of bounds
+fail_compilation/fail22881.d(207):        called from here: `null22881()`
+fail_compilation/fail22881.d(207):        while evaluating: `static assert(null22881())`
+fail_compilation/fail22881.d(305): Error: slice `[2..4]` exceeds array bounds `[0..3]`
+fail_compilation/fail22881.d(308):        called from here: `slice22881()`
+fail_compilation/fail22881.d(308):        while evaluating: `static assert(slice22881())`
+fail_compilation/fail22881.d(401): Error: slice `[0..1]` exceeds array bounds `[0..0]`
+fail_compilation/fail22881.d(403): Error: slice `[0..1]` exceeds array bounds `[0..0]`
+---
+*/
+#line 100
+// SliceExp: e1.type.ty == pointer
+static pstr22881 = "hello".ptr[0 .. 6];
+static parr22881 = ['h','e','l','l','o'].ptr[0 .. 6];
+
+bool ptr22881()
+{
+    char *p1 = new char[4].ptr;
+    p1[0 .. 4] = "str\0";
+    char *s1 = p1[1 .. 3].ptr;
+    char *s2 = s1[1 .. 3].ptr;  // = p1[2 .. 4]
+    char *s3 = s2[1 .. 3].ptr;  // = p1[3 .. 5]
+    return true;
+}
+static assert(ptr22881());
+
+
+#line 200
+// SliceExp: e1.op == null
+bool null22881()
+{
+    string[][1] nullexp;
+    nullexp[0][0 .. 2] = "st";
+    return true;
+}
+static assert(null22881());
+
+#line 300
+// SliceExp: e1.op == slice
+bool slice22881()
+{
+    char[] str = "abcd".dup;
+    char[] slice = str[1 .. 4];
+    slice[2 .. 4] = "ab";
+    return true;
+}
+static assert(slice22881());
+
+#line 400
+// SliceExp: e1.op == arrayLiteral
+static arr22881 = [][0 .. 1];
+// SliceExp: e1.op == string_
+static str22881 = ""[0 .. 1];
diff --git a/gcc/testsuite/gdc.test/fail_compilation/pull12941.d b/gcc/testsuite/gdc.test/fail_compilation/pull12941.d
index b0208686fe1..fce4ab7345e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/pull12941.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/pull12941.d
@@ -1,9 +1,9 @@ 
 /* TEST_OUTPUT:
 ---
 fail_compilation/pull12941.d(110): Error: `pull12941.foo` called with argument types `(int*)` matches both:
-fail_compilation/pull12941.d(101):     `pull12941.foo(ref return scope int* p)`
+fail_compilation/pull12941.d(101):     `pull12941.foo(return ref scope int* p)`
 and:
-fail_compilation/pull12941.d(102):     `pull12941.foo(out return scope int* p)`
+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):        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)`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope2.d b/gcc/testsuite/gdc.test/fail_compilation/retscope2.d
index 8e6e0a46c5f..68269ae2da3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope2.d
@@ -130,7 +130,7 @@  fail_compilation/retscope2.d(721): Error: returning `s.get1()` escapes a referen
 
 struct S700
 {
-    @safe S700* get1() return scope
+    @safe S700* get1() scope return
     {
         return &this;
     }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15191.d b/gcc/testsuite/gdc.test/fail_compilation/test15191.d
index 2ac3b562198..f2a117c0b80 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test15191.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test15191.d
@@ -56,7 +56,7 @@  int* addrOfRefGlobal()
 }
 
 // Slice:
-ref int*[1] identityArr(ref return scope int*[1] x)
+ref int*[1] identityArr(return ref scope int*[1] x)
 {
 	return x;
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17422.d b/gcc/testsuite/gdc.test/fail_compilation/test17422.d
index 7bb1315894e..80f8fbe2613 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test17422.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17422.d
@@ -7,7 +7,7 @@  fail_compilation/test17422.d(23): Error: scope variable `p` may not be returned
 */
 struct RC
 {
-    Object get() return scope @trusted
+    Object get() return @trusted
     {
         return cast(Object) &store[0];
     }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20881.d b/gcc/testsuite/gdc.test/fail_compilation/test20881.d
new file mode 100644
index 00000000000..72826352af2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test20881.d
@@ -0,0 +1,30 @@ 
+/*
+REQUIRED_ARGS: -preview=dip1000
+TEST_OUTPUT:
+---
+fail_compilation/test20881.d(27): Error: address of variable `s` assigned to `global` with longer lifetime
+fail_compilation/test20881.d(28): Error: address of variable `s` assigned to `global` with longer lifetime
+fail_compilation/test20881.d(29): Error: address of variable `s` assigned to `global` with longer lifetime
+---
+*/
+@safe:
+
+// https://issues.dlang.org/show_bug.cgi?id=20881
+
+struct S
+{
+    int* ptr;
+
+    auto borrowA() return /*scope inferred*/ { return ptr; }
+    int* borrowB() return { return ptr; }
+    int* borrowC() scope return { return ptr; }
+}
+
+void main()
+{
+    static int* global;
+    S s;
+    global = s.borrowA;
+    global = s.borrowB;
+    global = s.borrowC;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21912.d b/gcc/testsuite/gdc.test/fail_compilation/test21912.d
index 5bb92a352a1..925210bf875 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test21912.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21912.d
@@ -32,12 +32,12 @@  Dg escapeAssign(int i, return scope Dg dg)
     return dg;
 }
 
-ref Dg identityR(ref return scope Dg dg)
+ref Dg identityR(return ref scope Dg dg)
 {
     return dg;
 }
 
-ref Dg escapeAssignRef(int i, ref return scope Dg dg)
+ref Dg escapeAssignRef(int i, return ref scope Dg dg)
 {
     dg = () => i;
     return dg;
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test22898.cpp b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test22898.cpp
new file mode 100644
index 00000000000..28680074896
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/test22898.cpp
@@ -0,0 +1,7 @@ 
+int testCppCMangle (unsigned long long val, char ch)
+{
+    int vch = (char)val;
+    if (vch != ch)
+        return 0;
+    return vch;
+}
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/test22898.d b/gcc/testsuite/gdc.test/runnable_cxx/test22898.d
new file mode 100644
index 00000000000..32506238785
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable_cxx/test22898.d
@@ -0,0 +1,28 @@ 
+// EXTRA_CPP_SOURCES: test22898.cpp
+
+import core.stdc.config;
+
+extern(C++):
+
+version (AArch64) version = UnsignedChar;
+version (ARM)     version = UnsignedChar;
+version (RISCV32) version = UnsignedChar;
+version (RISCV64) version = UnsignedChar;
+version (PPC)     version = UnsignedChar;
+version (PPC64)   version = UnsignedChar;
+version (S390)    version = UnsignedChar;
+version (SystemZ) version = UnsignedChar;
+
+version (UnsignedChar)
+    enum __c_char : ubyte;
+else
+    enum __c_char : byte;
+
+int testCppCMangle (cpp_ulonglong, __c_char);
+
+void main()
+{
+    auto val = cast(cpp_ulonglong)18446744073709551488UL;
+    auto ch = cast(__c_char)val;
+    assert(testCppCMangle(val, ch) == cast(int)ch);
+}
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 963ffe020de..6eb555ed29b 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@ 
-16cb085b584f100fa677e2e64ff6b6dbb4921ad1
+a74fa63e6775d626850d8ebd854d9803c7ffb97d
 
 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/conv.d b/libphobos/src/std/conv.d
index 8512a445daf..06b37978ba6 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -1153,7 +1153,7 @@  if (!(isImplicitlyConvertible!(S, T) &&
 }
 
 // https://issues.dlang.org/show_bug.cgi?id=16108
-@system unittest
+@safe unittest
 {
     static struct A
     {
@@ -1341,12 +1341,12 @@  if (is (T == immutable) && isExactSomeString!T && is(S == enum))
     assert(to!string(a) == "[1.5, 2.5]");
 }
 
-@system unittest
+@safe unittest
 {
     // Conversion representing class object with string
     class A
     {
-        override string toString() const { return "an A"; }
+        override string toString() @safe const { return "an A"; }
     }
     A a;
     assert(to!string(a) == "null");
@@ -1354,7 +1354,7 @@  if (is (T == immutable) && isExactSomeString!T && is(S == enum))
     assert(to!string(a) == "an A");
 
     // https://issues.dlang.org/show_bug.cgi?id=7660
-    class C { override string toString() const { return "C"; } }
+    class C { override string toString() @safe const { return "C"; } }
     struct S { C c; alias c this; }
     S s; s.c = new C();
     assert(to!string(s) == "C");
@@ -1739,10 +1739,10 @@  if (!isImplicitlyConvertible!(S, T) && isAssociativeArray!S &&
     foreach (k1, v1; value)
     {
         // Cast values temporarily to Unqual!V2 to store them to result variable
-        result[to!K2(k1)] = cast(Unqual!V2) to!V2(v1);
+        result[to!K2(k1)] = to!(Unqual!V2)(v1);
     }
     // Cast back to original type
-    return cast(T) result;
+    return () @trusted { return cast(T) result; }();
 }
 
 @safe unittest
@@ -3105,7 +3105,7 @@  if (isSomeString!Source && !is(Source == enum) &&
  *     A $(LREF ConvException) if `source` is empty, if no number could be
  *     parsed, or if an overflow occurred.
  */
-auto parse(Target, Source, Flag!"doCount" doCount = No.doCount)(ref Source source)
+auto parse(Target, Source, Flag!"doCount" doCount = No.doCount)(ref scope Source source)
 if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
     isFloatingPoint!Target && !is(Target == enum))
 {
@@ -3122,6 +3122,13 @@  if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
         alias p = source;
     }
 
+    void advanceSource() @trusted
+    {
+        // p is assigned from source.representation above so the cast is valid
+        static if (isNarrowString!Source)
+            source = cast(Source) p;
+    }
+
     static immutable real[14] negtab =
         [ 1e-4096L,1e-2048L,1e-1024L,1e-512L,1e-256L,1e-128L,1e-64L,1e-32L,
                 1e-16L,1e-8L,1e-4L,1e-2L,1e-1L,1.0L ];
@@ -3138,6 +3145,7 @@  if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
 
     enforce(!p.empty, bailOut());
 
+
     size_t count = 0;
     bool sign = false;
     switch (p.front)
@@ -3168,8 +3176,7 @@  if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
         // skip past the last 'f'
         ++count;
         p.popFront();
-        static if (isNarrowString!Source)
-            source = cast(Source) p;
+        advanceSource();
         static if (doCount)
         {
             return tuple!("data", "count")(sign ? -Target.infinity : Target.infinity, count);
@@ -3189,8 +3196,7 @@  if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
         p.popFront();
         if (p.empty)
         {
-            static if (isNarrowString!Source)
-                source = cast(Source) p;
+            advanceSource();
             static if (doCount)
             {
                 return tuple!("data", "count")(cast (Target) (sign ? -0.0 : 0.0), count);
@@ -3222,8 +3228,7 @@  if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
         // skip past the last 'n'
         ++count;
         p.popFront();
-        static if (isNarrowString!Source)
-            source = cast(Source) p;
+        advanceSource();
         static if (doCount)
         {
             return tuple!("data", "count")(Target.nan, count);
@@ -3418,8 +3423,7 @@  if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
     // if overflow occurred
     enforce(ldval != real.infinity, new ConvException("Range error"));
 
-    static if (isNarrowString!Source)
-        source = cast(Source) p;
+    advanceSource();
     static if (doCount)
     {
         return tuple!("data", "count")(cast (Target) (sign ? -ldval : ldval), count);
@@ -3430,6 +3434,7 @@  if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
     }
 }
 
+
 ///
 @safe unittest
 {
diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d
index 8da38bdb4e6..f4f42167044 100644
--- a/libphobos/src/std/sumtype.d
+++ b/libphobos/src/std/sumtype.d
@@ -234,7 +234,7 @@  import std.meta : anySatisfy, allSatisfy;
 import std.traits : hasElaborateCopyConstructor, hasElaborateDestructor;
 import std.traits : isAssignable, isCopyable, isStaticArray, isRvalueAssignable;
 import std.traits : ConstOf, ImmutableOf, InoutOf, TemplateArgsOf;
-import std.traits : CommonType;
+import std.traits : CommonType, DeducedParameterType;
 import std.typecons : ReplaceTypeUnless;
 import std.typecons : Flag;
 
@@ -359,6 +359,10 @@  public:
 
         /// ditto
         this(immutable(T) value) immutable;
+
+        /// ditto
+        this(Value)(Value value) inout
+        if (is(Value == DeducedParameterType!(inout(T))));
     }
 
     static foreach (tid, T; Types)
@@ -414,6 +418,25 @@  public:
         {
             @disable this(immutable(T) value) immutable;
         }
+
+        static if (isCopyable!(inout(T)))
+        {
+            static if (IndexOf!(inout(T), Map!(InoutOf, Types)) == tid)
+            {
+                /// ditto
+                this(Value)(Value value) inout
+                if (is(Value == DeducedParameterType!(inout(T))))
+                {
+                    __traits(getMember, storage, Storage.memberName!T) = value;
+                    tag = tid;
+                }
+            }
+        }
+        else
+        {
+            @disable this(Value)(Value value) inout
+            if (is(Value == DeducedParameterType!(inout(T))));
+        }
     }
 
     static if (anySatisfy!(hasElaborateCopyConstructor, Types))
@@ -1554,6 +1577,16 @@  version (D_BetterC) {} else
     SumType!Value s;
 }
 
+// Construction of inout-qualified SumTypes
+// https://issues.dlang.org/show_bug.cgi?id=22901
+@safe unittest
+{
+    static inout(SumType!(int[])) example(inout(int[]) arr)
+    {
+        return inout(SumType!(int[]))(arr);
+    }
+}
+
 /// True if `T` is an instance of the `SumType` template, otherwise false.
 private enum bool isSumTypeInstance(T) = is(T == SumType!Args, Args...);
 
diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d
index 596c11cfb00..9ca676d312a 100644
--- a/libphobos/src/std/traits.d
+++ b/libphobos/src/std/traits.d
@@ -9080,3 +9080,43 @@  enum isCopyable(S) = __traits(isCopyable, S);
     static assert(isCopyable!int);
     static assert(isCopyable!(int[]));
 }
+
+/**
+ * The parameter type deduced by IFTI when an expression of type T is passed as
+ * an argument to a template function.
+ *
+ * For all types other than pointer and slice types, `DeducedParameterType!T`
+ * is the same as `T`. For pointer and slice types, it is `T` with the
+ * outer-most layer of qualifiers dropped.
+ */
+package(std) template DeducedParameterType(T)
+{
+    static if (is(T == U*, U) || is(T == U[], U))
+        alias DeducedParameterType = Unqual!T;
+    else
+        alias DeducedParameterType = T;
+}
+
+@safe unittest
+{
+    static assert(is(DeducedParameterType!(const(int)) == const(int)));
+    static assert(is(DeducedParameterType!(const(int[2])) == const(int[2])));
+
+    static assert(is(DeducedParameterType!(const(int*)) == const(int)*));
+    static assert(is(DeducedParameterType!(const(int[])) == const(int)[]));
+}
+
+@safe unittest
+{
+    static struct NoCopy
+    {
+        @disable this(this);
+    }
+
+    static assert(is(DeducedParameterType!NoCopy == NoCopy));
+}
+
+@safe unittest
+{
+    static assert(is(DeducedParameterType!(inout(int[])) == inout(int)[]));
+}
diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d
index 9780b1b318f..eeeda721813 100644
--- a/libphobos/src/std/uni/package.d
+++ b/libphobos/src/std/uni/package.d
@@ -9824,7 +9824,7 @@  dchar toLower(dchar c)
 
 /++
     Creates a new array which is identical to `s` except that all of its
-    characters are converted to lowercase (by preforming Unicode lowercase mapping).
+    characters are converted to lowercase (by performing Unicode lowercase mapping).
     If none of `s` characters were affected, then `s` itself is returned if `s` is a
     `string`-like type.
 
@@ -10028,7 +10028,7 @@  dchar toUpper(dchar c)
 
 /++
     Allocates a new array which is identical to `s` except that all of its
-    characters are converted to uppercase (by preforming Unicode uppercase mapping).
+    characters are converted to uppercase (by performing Unicode uppercase mapping).
     If none of `s` characters were affected, then `s` itself is returned if `s`
     is a `string`-like type.