diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 0cf9b5fd4a8..aa0062c10eb 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-65a3da148c0c700a6c928f0e13799b2a7d34fcbe
+ff57fec51558013b25cadb7e83da9f4675915d56
 
 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/VERSION b/gcc/d/dmd/VERSION
index b272d4bbe5c..41fdc654b14 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.106.0-beta.1
+v2.106.0-rc.1
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index d42ef951085..307bb0171c4 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -663,7 +663,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
      */
     extern (D) final Dsymbol searchCtor()
     {
-        auto s = search(Loc.initial, Id.ctor);
+        auto s = this.search(Loc.initial, Id.ctor);
         if (s)
         {
             if (!(s.isCtorDeclaration() ||
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index 58a0126de1a..cd8f1a15fbd 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -167,7 +167,6 @@ private:
 public:
     static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject);
     StructDeclaration *syntaxCopy(Dsymbol *s) override;
-    Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final;
     const char *kind() const override;
     void finalizeSize() override final;
     bool isPOD();
@@ -285,7 +284,6 @@ public:
     virtual bool isBaseOf(ClassDeclaration *cd, int *poffset);
 
     bool isBaseInfoComplete();
-    Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final;
     void finalizeSize() override;
     bool hasMonitor();
     bool isFuncHidden(FuncDeclaration *fd);
diff --git a/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d
index 77f36f304a5..6a9c0104a72 100644
--- a/gcc/d/dmd/astenums.d
+++ b/gcc/d/dmd/astenums.d
@@ -383,6 +383,7 @@ enum STMT : ubyte
 enum InitKind : ubyte
 {
     void_,
+    default_,
     error,
     struct_,
     array,
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index 49fc3082ba8..251e2e88ca5 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -32,7 +32,7 @@ import dmd.declaration;
 import dmd.dmodule;
 import dmd.dscope;
 import dmd.dsymbol;
-import dmd.dsymbolsem : dsymbolSemantic;
+import dmd.dsymbolsem;
 import dmd.errors;
 import dmd.expression;
 import dmd.expressionsem;
@@ -123,18 +123,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol
         return sc;
     }
 
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        Dsymbols* d = include(sc);
-        if (d)
-        {
-            Scope* sc2 = newScope(sc);
-            d.foreachDsymbol( s => s.addMember(sc2, sds) );
-            if (sc2 != sc)
-                sc2.pop();
-        }
-    }
-
     override void setScope(Scope* sc)
     {
         Dsymbols* d = include(sc);
@@ -295,34 +283,6 @@ extern (C++) class StorageClassDeclaration : AttribDeclaration
         return t;
     }
 
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        Dsymbols* d = include(sc);
-        if (d)
-        {
-            Scope* sc2 = newScope(sc);
-
-            d.foreachDsymbol( (s)
-            {
-                //printf("\taddMember %s to %s\n", s.toChars(), sds.toChars());
-                // STC.local needs to be attached before the member is added to the scope (because it influences the parent symbol)
-                if (auto decl = s.isDeclaration())
-                {
-                    decl.storage_class |= stc & STC.local;
-                    if (auto sdecl = s.isStorageClassDeclaration()) // TODO: why is this not enough to deal with the nested case?
-                    {
-                        sdecl.stc |= stc & STC.local;
-                    }
-                }
-                s.addMember(sc2, sds);
-            });
-
-            if (sc2 != sc)
-                sc2.pop();
-        }
-
-    }
-
     override inout(StorageClassDeclaration) isStorageClassDeclaration() inout
     {
         return this;
@@ -640,37 +600,6 @@ extern (C++) final class VisibilityDeclaration : AttribDeclaration
         return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, this.visibility, 1, sc.aligndecl, sc.inlining);
     }
 
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        if (pkg_identifiers)
-        {
-            Dsymbol tmp;
-            Package.resolve(pkg_identifiers, &tmp, null);
-            visibility.pkg = tmp ? tmp.isPackage() : null;
-            pkg_identifiers = null;
-        }
-        if (visibility.kind == Visibility.Kind.package_ && visibility.pkg && sc._module)
-        {
-            Module m = sc._module;
-
-            // https://issues.dlang.org/show_bug.cgi?id=17441
-            // While isAncestorPackageOf does an equality check, the fix for the issue adds a check to see if
-            // each package's .isModule() properites are equal.
-            //
-            // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null.
-            // This breaks package declarations of the package in question if they are declared in
-            // the same package.d file, which _do_ have a module associated with them, and hence a non-null
-            // isModule()
-            if (!m.isPackage() || !visibility.pkg.ident.equals(m.isPackage().ident))
-            {
-                Package pkg = m.parent ? m.parent.isPackage() : null;
-                if (!pkg || !visibility.pkg.isAncestorPackageOf(pkg))
-                    .error(loc, "%s `%s` does not bind to one of ancestor packages of module `%s`", kind(), toPrettyChars(false), m.toPrettyChars(true));
-            }
-        }
-        return AttribDeclaration.addMember(sc, sds);
-    }
-
     override const(char)* kind() const
     {
         return "visibility attribute";
@@ -1054,23 +983,6 @@ extern (C++) final class StaticIfDeclaration : ConditionalDeclaration
         }
     }
 
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        //printf("StaticIfDeclaration::addMember() '%s'\n", toChars());
-        /* This is deferred until the condition evaluated later (by the include() call),
-         * so that expressions in the condition can refer to declarations
-         * in the same scope, such as:
-         *
-         * template Foo(int i)
-         * {
-         *     const int j = i + 1;
-         *     static if (j == 3)
-         *         const int k;
-         * }
-         */
-        this.scopesym = sds;
-    }
-
     override void setScope(Scope* sc)
     {
         // do not evaluate condition before semantic pass
@@ -1186,12 +1098,6 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration
         return d;
     }
 
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        // used only for caching the enclosing symbol
-        this.scopesym = sds;
-    }
-
     override void addComment(const(char)* comment)
     {
         // do nothing
@@ -1266,15 +1172,6 @@ extern(C++) final class ForwardingAttribDeclaration : AttribDeclaration
         return sc.push(sym);
     }
 
-    /***************************************
-     * Lazily initializes the scope to forward to.
-     */
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        sym.parent = sds;
-        return super.addMember(sc, sym);
-    }
-
     override inout(ForwardingAttribDeclaration) isForwardingAttribDeclaration() inout
     {
         return this;
@@ -1312,12 +1209,6 @@ extern (C++) final class MixinDeclaration : AttribDeclaration
         return new MixinDeclaration(loc, Expression.arraySyntaxCopy(exps));
     }
 
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        //printf("MixinDeclaration::addMember(sc = %p, sds = %p, memnum = %d)\n", sc, sds, memnum);
-        this.scopesym = sds;
-    }
-
     override void setScope(Scope* sc)
     {
         Dsymbol.setScope(sc);
diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h
index f47a1f6f836..efea9af950c 100644
--- a/gcc/d/dmd/attrib.h
+++ b/gcc/d/dmd/attrib.h
@@ -26,7 +26,6 @@ public:
 
     virtual Dsymbols *include(Scope *sc);
     virtual Scope *newScope(Scope *sc);
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     void setScope(Scope *sc) override;
     void importAll(Scope *sc) override;
     void addComment(const utf8_t *comment) override;
@@ -49,7 +48,6 @@ public:
     StorageClassDeclaration *syntaxCopy(Dsymbol *s) override;
     Scope *newScope(Scope *sc) override;
     bool oneMember(Dsymbol **ps, Identifier *ident) override final;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     StorageClassDeclaration *isStorageClassDeclaration() override { return this; }
 
     void accept(Visitor *v) override { v->visit(this); }
@@ -110,7 +108,6 @@ public:
 
     VisibilityDeclaration *syntaxCopy(Dsymbol *s) override;
     Scope *newScope(Scope *sc) override;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     const char *kind() const override;
     const char *toPrettyChars(bool unused) override;
     VisibilityDeclaration *isVisibilityDeclaration() override { return this; }
@@ -179,7 +176,6 @@ public:
 
     StaticIfDeclaration *syntaxCopy(Dsymbol *s) override;
     Dsymbols *include(Scope *sc) override;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     void setScope(Scope *sc) override;
     void importAll(Scope *sc) override;
     StaticIfDeclaration *isStaticIfDeclaration() override { return this; }
@@ -199,7 +195,6 @@ public:
     StaticForeachDeclaration *syntaxCopy(Dsymbol *s) override;
     bool oneMember(Dsymbol **ps, Identifier *ident) override;
     Dsymbols *include(Scope *sc) override;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     void addComment(const utf8_t *comment) override;
     void setScope(Scope *sc) override;
     void importAll(Scope *sc) override;
@@ -213,7 +208,6 @@ public:
     ForwardingScopeDsymbol *sym;
 
     Scope *newScope(Scope *sc) override;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     ForwardingAttribDeclaration *isForwardingAttribDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
@@ -229,7 +223,6 @@ public:
     d_bool compiled;
 
     MixinDeclaration *syntaxCopy(Dsymbol *s) override;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     void setScope(Scope *sc) override;
     const char *kind() const override;
     void accept(Visitor *v) override { v->visit(this); }
diff --git a/gcc/d/dmd/common/outbuffer.d b/gcc/d/dmd/common/outbuffer.d
index b8ad7851e4d..4e7a82fb565 100644
--- a/gcc/d/dmd/common/outbuffer.d
+++ b/gcc/d/dmd/common/outbuffer.d
@@ -281,7 +281,7 @@ struct OutBuffer
         write(&v, v.sizeof);
     }
 
-    /// NOT zero-terminated
+    /// Buffer will NOT be zero-terminated
     extern (C++) void writestring(const(char)* s) pure nothrow @system
     {
         if (!s)
@@ -302,14 +302,14 @@ struct OutBuffer
         write(s);
     }
 
-    /// NOT zero-terminated, followed by newline
+    /// Buffer will NOT be zero-terminated, followed by newline
     void writestringln(const(char)[] s) pure nothrow @safe
     {
         writestring(s);
         writenl();
     }
 
-    /** Write string to buffer, ensure it is zero terminated
+    /** Write C string AND null byte
      */
     void writeStringz(const(char)* s) pure nothrow @system
     {
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index f0c834972d6..ed5f1f8b9a2 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -2168,6 +2168,7 @@ final class CParser(AST) : Parser!AST
      * C11 Initialization
      * initializer:
      *    assignment-expression
+     *    { }                       // C23 6.7.10 addition
      *    { initializer-list }
      *    { initializer-list , }
      *
@@ -2198,6 +2199,12 @@ final class CParser(AST) : Parser!AST
         nextToken();
         const loc = token.loc;
 
+        if (token.value == TOK.rightCurly)      // { }
+        {
+            nextToken();
+            return new AST.DefaultInitializer(loc);
+        }
+
         /* Collect one or more `designation (opt) initializer`
          * into ci.initializerList, but lazily create ci
          */
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index c93269fb321..43efc05b5d3 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -28,6 +28,7 @@ import dmd.func;
 import dmd.globals;
 import dmd.location;
 import dmd.mtype;
+import dmd.root.bitarray;
 import dmd.root.complex;
 import dmd.root.ctfloat;
 import dmd.root.port;
@@ -43,14 +44,14 @@ import dmd.visitor;
 extern (D) struct UnionExp
 {
     // yes, default constructor does nothing
-    extern (D) this(Expression e)
+    extern (D) this(Expression e) nothrow
     {
         memcpy(&this, cast(void*)e, e.size);
     }
 
     /* Extract pointer to Expression
      */
-    extern (D) Expression exp() return
+    extern (D) Expression exp() return nothrow
     {
         return cast(Expression)&u;
     }
@@ -109,7 +110,7 @@ void emplaceExp(T : Expression, Args...)(void* p, Args args)
     (cast(T)p).__ctor(args);
 }
 
-void emplaceExp(T : UnionExp)(T* p, Expression e)
+void emplaceExp(T : UnionExp)(T* p, Expression e) nothrow
 {
     memcpy(p, cast(void*)e, e.size);
 }
@@ -134,7 +135,7 @@ void generateUncaughtError(ThrownExceptionExp tee)
  * Returns:
  *    index of the field, or -1 if not found
  */
-int findFieldIndexByName(const StructDeclaration sd, const VarDeclaration v) pure @safe
+int findFieldIndexByName(const StructDeclaration sd, const VarDeclaration v) pure @safe nothrow
 {
     foreach (i, field; sd.fields)
     {
@@ -145,7 +146,7 @@ int findFieldIndexByName(const StructDeclaration sd, const VarDeclaration v) pur
 }
 
 // True if 'e' is CTFEExp::cantexp, or an exception
-bool exceptionOrCantInterpret(const Expression e) @safe
+bool exceptionOrCantInterpret(const Expression e) @safe nothrow
 {
     return e && (e.op == EXP.cantExpression || e.op == EXP.thrownException || e.op == EXP.showCtfeContext);
 }
@@ -153,7 +154,7 @@ bool exceptionOrCantInterpret(const Expression e) @safe
 /************** Aggregate literals (AA/string/array/struct) ******************/
 // Given expr, which evaluates to an array/AA/string literal,
 // return true if it needs to be copied
-bool needToCopyLiteral(const Expression expr)
+bool needToCopyLiteral(const Expression expr) nothrow
 {
     Expression e = cast()expr;
     for (;;)
@@ -593,7 +594,7 @@ TypeAArray toBuiltinAAType(Type t)
 
 /************** TypeInfo operations ************************************/
 // Return true if type is TypeInfo_Class
-bool isTypeInfo_Class(const Type type)
+bool isTypeInfo_Class(const Type type) nothrow
 {
     auto tc = cast()type.isTypeClass();
     return tc && (Type.dtypeinfo == tc.sym || Type.dtypeinfo.isBaseOf(tc.sym, null));
@@ -741,14 +742,14 @@ Expression pointerDifference(UnionExp* pue, const ref Loc loc, Type type, Expres
     Expression agg2 = getAggregateFromPointer(e2, &ofs2);
     if (agg1 == agg2)
     {
-        Type pointee = (cast(TypePointer)agg1.type).next;
+        Type pointee = agg1.type.nextOf();
         const sz = pointee.size();
         emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type);
     }
     else if (agg1.op == EXP.string_ && agg2.op == EXP.string_ &&
              agg1.isStringExp().peekString().ptr == agg2.isStringExp().peekString().ptr)
     {
-        Type pointee = (cast(TypePointer)agg1.type).next;
+        Type pointee = agg1.type.nextOf();
         const sz = pointee.size();
         emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type);
     }
@@ -794,14 +795,14 @@ Expression pointerArithmetic(UnionExp* pue, const ref Loc loc, EXP op, Type type
         goto Lcant;
     }
     dinteger_t ofs2 = e2.toInteger();
-    Type pointee = (cast(TypeNext)agg1.type.toBasetype()).next;
+    Type pointee = agg1.type.toBasetype().nextOf();
     dinteger_t sz = pointee.size();
     sinteger_t indx;
     dinteger_t len;
-    if (agg1.op == EXP.symbolOffset)
+    if (auto soe = agg1.isSymOffExp())
     {
         indx = ofs1 / sz;
-        len = (cast(TypeSArray)agg1.isSymOffExp().var.type).dim.toInteger();
+        len = soe.var.type.isTypeSArray().dim.toInteger();
     }
     else
     {
@@ -836,9 +837,9 @@ Expression pointerArithmetic(UnionExp* pue, const ref Loc loc, EXP op, Type type
         error(loc, "CTFE internal error: pointer arithmetic `%s`", agg1.toChars());
         goto Lcant;
     }
-    if (eptr.type.toBasetype().ty == Tsarray)
+    if (auto tsa = eptr.type.toBasetype().isTypeSArray())
     {
-        dinteger_t dim = (cast(TypeSArray)eptr.type.toBasetype()).dim.toInteger();
+        dinteger_t dim = tsa.dim.toInteger();
         // Create a CTFE pointer &agg1[indx .. indx+dim]
         auto se = ctfeEmplaceExp!SliceExp(loc, agg1,
                 ctfeEmplaceExp!IntegerExp(loc, indx, Type.tsize_t),
@@ -978,7 +979,7 @@ bool isCtfeComparable(Expression e)
 }
 
 /// Map EXP comparison ops
-private bool numCmp(N)(EXP op, N n1, N n2)
+private bool numCmp(N)(EXP op, N n1, N n2) nothrow
 {
     switch (op)
     {
@@ -997,25 +998,25 @@ private bool numCmp(N)(EXP op, N n1, N n2)
 }
 
 /// Returns cmp OP 0; where OP is ==, !=, <, >=, etc. Result is 0 or 1
-bool specificCmp(EXP op, int rawCmp) @safe
+bool specificCmp(EXP op, int rawCmp) @safe nothrow
 {
     return numCmp!int(op, rawCmp, 0);
 }
 
 /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
-bool intUnsignedCmp(EXP op, dinteger_t n1, dinteger_t n2) @safe
+bool intUnsignedCmp(EXP op, dinteger_t n1, dinteger_t n2) @safe nothrow
 {
     return numCmp!dinteger_t(op, n1, n2);
 }
 
 /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
-bool intSignedCmp(EXP op, sinteger_t n1, sinteger_t n2) @safe
+bool intSignedCmp(EXP op, sinteger_t n1, sinteger_t n2) @safe nothrow
 {
     return numCmp!sinteger_t(op, n1, n2);
 }
 
 /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
-bool realCmp(EXP op, real_t r1, real_t r2) @safe
+bool realCmp(EXP op, real_t r1, real_t r2) @safe nothrow
 {
     // Don't rely on compiler, handle NAN arguments separately
     if (CTFloat.isNaN(r1) || CTFloat.isNaN(r2)) // if unordered
@@ -1105,7 +1106,7 @@ private int ctfeCmpArrays(const ref Loc loc, Expression e1, Expression e2, uinte
 /* Given a delegate expression e, return .funcptr.
  * If e is NullExp, return NULL.
  */
-private FuncDeclaration funcptrOf(Expression e) @safe
+private FuncDeclaration funcptrOf(Expression e) @safe nothrow
 {
     assert(e.type.ty == Tdelegate);
     if (auto de = e.isDelegateExp())
@@ -1116,7 +1117,7 @@ private FuncDeclaration funcptrOf(Expression e) @safe
     return null;
 }
 
-private bool isArray(const Expression e) @safe
+private bool isArray(const Expression e) @safe nothrow
 {
     return e.op == EXP.arrayLiteral || e.op == EXP.string_ || e.op == EXP.slice || e.op == EXP.null_;
 }
@@ -1270,8 +1271,8 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
         size_t dim = es1.keys.length;
         if (es2.keys.length != dim)
             return 1;
-        bool* used = cast(bool*)mem.xmalloc(bool.sizeof * dim);
-        memset(used, 0, bool.sizeof * dim);
+        BitArray used;
+        used.length = dim;
         foreach (size_t i; 0 .. dim)
         {
             Expression k1 = (*es1.keys)[i];
@@ -1290,11 +1291,9 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
             }
             if (!v2 || ctfeRawCmp(loc, v1, v2, identity))
             {
-                mem.xfree(used);
                 return 1;
             }
         }
-        mem.xfree(used);
         return 0;
     }
     else if (e1.op == EXP.assocArrayLiteral && e2.op == EXP.null_)
@@ -2000,9 +1999,8 @@ void showCtfeExpr(Expression e, int level = 0)
 UnionExp voidInitLiteral(Type t, VarDeclaration var)
 {
     UnionExp ue;
-    if (t.ty == Tsarray)
+    if (auto tsa = t.isTypeSArray())
     {
-        TypeSArray tsa = cast(TypeSArray)t;
         Expression elem = voidInitLiteral(tsa.next, var).copy();
         // For aggregate value types (structs, static arrays) we must
         // create an a separate copy for each element.
@@ -2019,9 +2017,8 @@ UnionExp voidInitLiteral(Type t, VarDeclaration var)
         ArrayLiteralExp ae = ue.exp().isArrayLiteralExp();
         ae.ownedByCtfe = OwnedBy.ctfe;
     }
-    else if (t.ty == Tstruct)
+    else if (auto ts = t.isTypeStruct())
     {
-        TypeStruct ts = cast(TypeStruct)t;
         auto exps = new Expressions(ts.sym.fields.length);
         foreach (size_t i;  0 .. ts.sym.fields.length)
         {
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index eb3890bb58f..14c67f062a3 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -1631,6 +1631,13 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
         }
         else if (tob.ty == Tvector && t1b.ty != Tvector)
         {
+            if (t1b.ty == Tsarray)
+            {
+                // Casting static array to vector with same size, e.g. `cast(int4) int[4]`
+                if (t1b.size(e.loc) != tob.size(e.loc))
+                    goto Lfail;
+                return new VectorExp(e.loc, e, tob).expressionSemantic(sc);
+            }
             //printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars());
             TypeVector tv = tob.isTypeVector();
             Expression result = new CastExp(e.loc, e, tv.elementType());
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index bae942cbd97..72b85cfc64e 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -180,7 +180,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
     int cppDtorVtblIndex = -1;
 
     /// to prevent recursive attempts
-    private bool inuse;
+    bool inuse;
 
     ThreeState isabstract;
 
@@ -367,7 +367,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
         baseok = Baseok.none;
     }
 
-    extern (D) private void classError(const(char)* fmt, const(char)* arg)
+    extern (D) final void classError(const(char)* fmt, const(char)* arg)
     {
         .error(loc, fmt, kind, toPrettyChars, arg);
     }
@@ -468,67 +468,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
         return baseok >= Baseok.done;
     }
 
-    override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
-    {
-        //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", toChars(), ident.toChars(), flags);
-        //if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
-        if (_scope && baseok < Baseok.semanticdone)
-        {
-            if (!inuse)
-            {
-                // must semantic on base class/interfaces
-                inuse = true;
-                dsymbolSemantic(this, null);
-                inuse = false;
-            }
-        }
-
-        if (!members || !symtab) // opaque or addMember is not yet done
-        {
-            // .stringof is always defined (but may be hidden by some other symbol)
-            if (ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone)
-                classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars());
-            //*(char*)0=0;
-            return null;
-        }
-
-        auto s = ScopeDsymbol.search(loc, ident, flags);
-
-        // don't search imports of base classes
-        if (flags & SearchImportsOnly)
-            return s;
-
-        if (s)
-            return s;
-
-        // Search bases classes in depth-first, left to right order
-        foreach (b; (*baseclasses)[])
-        {
-            if (!b.sym)
-                continue;
-
-            if (!b.sym.symtab)
-            {
-                classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars());
-                continue;
-            }
-
-            import dmd.access : symbolIsVisible;
-
-            s = b.sym.search(loc, ident, flags);
-            if (!s)
-                continue;
-            else if (s == this) // happens if s is nested in this and derives from this
-                s = null;
-            else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(this, s))
-                s = null;
-            else
-                break;
-        }
-
-        return s;
-    }
-
     /************************************
      * Search base classes in depth-first, left-to-right order for
      * a class or interface named 'ident'.
@@ -675,7 +614,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
     final bool isFuncHidden(FuncDeclaration fd)
     {
         //printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toPrettyChars());
-        Dsymbol s = search(Loc.initial, fd.ident, IgnoreAmbiguous | IgnoreErrors);
+        Dsymbol s = this.search(Loc.initial, fd.ident, IgnoreAmbiguous | IgnoreErrors);
         if (!s)
         {
             //printf("not found\n");
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 76a31f4caf7..0e125fdd001 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -421,18 +421,6 @@ extern (C++) abstract class Declaration : Dsymbol
         return Modifiable.yes;
     }
 
-    override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
-    {
-        Dsymbol s = Dsymbol.search(loc, ident, flags);
-        if (!s && type)
-        {
-            s = type.toDsymbol(_scope);
-            if (s)
-                s = s.search(loc, ident, flags);
-        }
-        return s;
-    }
-
     final bool isStatic() const pure nothrow @nogc @safe
     {
         return (storage_class & STC.static_) != 0;
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 8cd295f1e06..a65fb4467e5 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -124,7 +124,6 @@ public:
     const char *kind() const override;
     uinteger_t size(const Loc &loc) override final;
 
-    Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final;
 
     bool isStatic() const { return (storage_class & STCstatic) != 0; }
     LINK resolvedLinkage() const; // returns the linkage, resolving the target-specific `System` one
diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index f33b5fd543e..797f6ee0a2d 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/dmd/denum.d
@@ -83,25 +83,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
         return ed;
     }
 
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        version (none)
-        {
-            printf("EnumDeclaration::addMember() %s\n", toChars());
-            for (size_t i = 0; i < members.length; i++)
-            {
-                EnumMember em = (*members)[i].isEnumMember();
-                printf("    member %s\n", em.toChars());
-            }
-        }
-        if (!isAnonymous())
-        {
-            ScopeDsymbol.addMember(sc, sds);
-        }
-
-        addEnumMembersToSymtab(this, sc, sds);
-    }
-
     override void setScope(Scope* sc)
     {
         if (semanticRun > PASS.initial)
@@ -126,19 +107,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
         return "enum";
     }
 
-    override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
-    {
-        //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident.toChars());
-        if (_scope)
-        {
-            // Try one last time to resolve this enum
-            dsymbolSemantic(this, _scope);
-        }
-
-        Dsymbol s = ScopeDsymbol.search(loc, ident, flags);
-        return s;
-    }
-
     // is Dsymbol deprecated?
     override bool isDeprecated() const
     {
diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d
index d74c8603420..0132e49cbed 100644
--- a/gcc/d/dmd/dimport.d
+++ b/gcc/d/dmd/dimport.d
@@ -305,33 +305,6 @@ extern (C++) final class Import : Dsymbol
         return this;
     }
 
-    /*****************************
-     * Add import to sd's symbol table.
-     */
-    override void addMember(Scope* sc, ScopeDsymbol sd)
-    {
-        //printf("Import.addMember(this=%s, sd=%s, sc=%p)\n", toChars(), sd.toChars(), sc);
-        if (names.length == 0)
-            return Dsymbol.addMember(sc, sd);
-        if (aliasId)
-            Dsymbol.addMember(sc, sd);
-        /* Instead of adding the import to sd's symbol table,
-         * add each of the alias=name pairs
-         */
-        for (size_t i = 0; i < names.length; i++)
-        {
-            Identifier name = names[i];
-            Identifier _alias = aliases[i];
-            if (!_alias)
-                _alias = name;
-            auto tname = new TypeIdentifier(loc, name);
-            auto ad = new AliasDeclaration(loc, _alias, tname);
-            ad._import = this;
-            ad.addMember(sc, sd);
-            aliasdecls.push(ad);
-        }
-    }
-
     override void setScope(Scope* sc)
     {
         Dsymbol.setScope(sc);
@@ -348,19 +321,6 @@ extern (C++) final class Import : Dsymbol
         }
     }
 
-    override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
-    {
-        //printf("%s.Import.search(ident = '%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
-        if (!pkg)
-        {
-            load(null);
-            mod.importAll(null);
-            mod.dsymbolSemantic(null);
-        }
-        // Forward it to the package/module
-        return pkg.search(loc, ident, flags);
-    }
-
     override bool overloadInsert(Dsymbol s)
     {
         /* Allow multiple imports with the same package base, but disallow
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index e6dde181fab..5f5de6390fb 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -268,22 +268,6 @@ extern (C++) class Package : ScopeDsymbol
         return isAncestorPackageOf(pkg.parent.isPackage());
     }
 
-    override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
-    {
-        //printf("%s Package.search('%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
-        flags &= ~SearchLocalsOnly;  // searching an import is always transitive
-        if (!isModule() && mod)
-        {
-            // Prefer full package name.
-            Dsymbol s = symtab ? symtab.lookup(ident) : null;
-            if (s)
-                return s;
-            //printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars());
-            return mod.search(loc, ident, flags);
-        }
-        return ScopeDsymbol.search(loc, ident, flags);
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -414,10 +398,10 @@ extern (C++) final class Module : Package
         return rootimports == ThreeState.yes;
     }
 
-    private Identifier searchCacheIdent;
-    private Dsymbol searchCacheSymbol;  // cached value of search
-    private int searchCacheFlags;       // cached flags
-    private bool insearch;
+    Identifier searchCacheIdent;
+    Dsymbol searchCacheSymbol;  // cached value of search
+    int searchCacheFlags;       // cached flags
+    bool insearch;
 
     /**
      * A root module is one that will be compiled all the way to
@@ -1036,47 +1020,6 @@ extern (C++) final class Module : Package
         }
     }
 
-    override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
-    {
-        /* Since modules can be circularly referenced,
-         * need to stop infinite recursive searches.
-         * This is done with the cache.
-         */
-        //printf("%s Module.search('%s', flags = x%x) insearch = %d\n", toChars(), ident.toChars(), flags, insearch);
-        if (insearch)
-            return null;
-
-        /* Qualified module searches always search their imports,
-         * even if SearchLocalsOnly
-         */
-        if (!(flags & SearchUnqualifiedModule))
-            flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly);
-
-        if (searchCacheIdent == ident && searchCacheFlags == flags)
-        {
-            //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n",
-            //        toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null");
-            return searchCacheSymbol;
-        }
-
-        uint errors = global.errors;
-
-        insearch = true;
-        Dsymbol s = ScopeDsymbol.search(loc, ident, flags);
-        insearch = false;
-
-        if (errors == global.errors)
-        {
-            // https://issues.dlang.org/show_bug.cgi?id=10752
-            // Can cache the result only when it does not cause
-            // access error so the side-effect should be reproduced in later search.
-            searchCacheIdent = ident;
-            searchCacheSymbol = s;
-            searchCacheFlags = flags;
-        }
-        return s;
-    }
-
     override bool isPackageAccessible(Package p, Visibility visibility, int flags = 0)
     {
         if (insearch) // don't follow import cycles
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 3853512005c..d68bcdaad40 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -66,13 +66,15 @@ enum SCOPE
 
     fullinst      = 0x10000,  /// fully instantiate templates
     ctfeBlock     = 0x20000,  /// inside a `if (__ctfe)` block
+    dip1000       = 0x40000,  /// dip1000 errors enabled for this scope
+    dip25         = 0x80000,  /// dip25 errors enabled for this scope
 }
 
 /// Flags that are carried along with a scope push()
 private enum PersistentFlags =
     SCOPE.contract | SCOPE.debug_ | SCOPE.ctfe | SCOPE.compile | SCOPE.constraint |
     SCOPE.noaccesscheck | SCOPE.ignoresymbolvisibility |
-    SCOPE.Cfile | SCOPE.ctfeBlock;
+    SCOPE.Cfile | SCOPE.ctfeBlock | SCOPE.dip1000 | SCOPE.dip25;
 
 extern (C++) struct Scope
 {
@@ -176,6 +178,10 @@ extern (C++) struct Scope
             m = m.parent;
         m.addMember(null, sc.scopesym);
         m.parent = null; // got changed by addMember()
+        if (global.params.useDIP1000 == FeatureState.enabled)
+            sc.flags |= SCOPE.dip1000;
+        if (global.params.useDIP25 == FeatureState.enabled)
+            sc.flags |= SCOPE.dip25;
         if (_module.filetype == FileType.c)
             sc.flags |= SCOPE.Cfile;
         // Create the module scope underneath the global scope
@@ -344,7 +350,7 @@ extern (C++) struct Scope
      * Returns:
      *  symbol if found, null if not
      */
-    extern (D) Dsymbol search(const ref Loc loc, Identifier ident, Dsymbol* pscopesym, int flags = IgnoreNone)
+    extern (C++) Dsymbol search(const ref Loc loc, Identifier ident, Dsymbol* pscopesym, int flags = IgnoreNone)
     {
         version (LOGSEARCH)
         {
@@ -821,4 +827,16 @@ extern (C++) struct Scope
     {
         return (flags & (SCOPE.ctfe | SCOPE.ctfeBlock | SCOPE.compile)) == 0;
     }
+
+    /// Returns: whether to raise DIP1000 warnings (FeatureStabe.default) or errors (FeatureState.enabled)
+    extern (D) FeatureState useDIP1000()
+    {
+        return (flags & SCOPE.dip1000) ? FeatureState.enabled : FeatureState.disabled;
+    }
+
+    /// Returns: whether to raise DIP25 warnings (FeatureStabe.default) or errors (FeatureState.enabled)
+    extern (D) FeatureState useDIP25()
+    {
+        return (flags & SCOPE.dip25) ? FeatureState.enabled : FeatureState.disabled;
+    }
 }
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index f77a263a894..36e847c3f88 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -263,23 +263,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration
         return sd;
     }
 
-    override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
-    {
-        //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
-        if (_scope && !symtab)
-            dsymbolSemantic(this, _scope);
-
-        if (!members || !symtab) // opaque or semantic() is not yet called
-        {
-            // .stringof is always defined (but may be hidden by some other symbol)
-            if(ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone)
-                .error(loc, "%s `%s` is forward referenced when looking for `%s`", kind, toPrettyChars, ident.toChars());
-            return null;
-        }
-
-        return ScopeDsymbol.search(loc, ident, flags);
-    }
-
     override const(char)* kind() const
     {
         return "struct";
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 914213c1e57..a52745fcc0e 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -35,7 +35,6 @@ import dmd.dsymbolsem;
 import dmd.dtemplate;
 import dmd.errors;
 import dmd.expression;
-import dmd.expressionsem;
 import dmd.func;
 import dmd.globals;
 import dmd.id;
@@ -750,67 +749,6 @@ extern (C++) class Dsymbol : ASTNode
         return toAlias();
     }
 
-    void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        //printf("Dsymbol::addMember('%s')\n", toChars());
-        //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds.toChars());
-        //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds.symtab = %p)\n", this, toChars(), sds, sds.symtab);
-        parent = sds;
-        if (isAnonymous()) // no name, so can't add it to symbol table
-            return;
-
-        if (!sds.symtabInsert(this)) // if name is already defined
-        {
-            if (isAliasDeclaration() && !_scope)
-                setScope(sc);
-            Dsymbol s2 = sds.symtabLookup(this,ident);
-            /* https://issues.dlang.org/show_bug.cgi?id=17434
-             *
-             * If we are trying to add an import to the symbol table
-             * that has already been introduced, then keep the one with
-             * larger visibility. This is fine for imports because if
-             * we have multiple imports of the same file, if a single one
-             * is public then the symbol is reachable.
-             */
-            if (auto i1 = isImport())
-            {
-                if (auto i2 = s2.isImport())
-                {
-                    if (sc.explicitVisibility && sc.visibility > i2.visibility)
-                        sds.symtab.update(this);
-                }
-            }
-
-            // If using C tag/prototype/forward declaration rules
-            if (sc.flags & SCOPE.Cfile && !this.isImport())
-            {
-                if (handleTagSymbols(*sc, this, s2, sds))
-                    return;
-                if (handleSymbolRedeclarations(*sc, this, s2, sds))
-                    return;
-
-                sds.multiplyDefined(Loc.initial, this, s2);  // ImportC doesn't allow overloading
-                errors = true;
-                return;
-            }
-
-            if (!s2.overloadInsert(this))
-            {
-                sds.multiplyDefined(Loc.initial, this, s2);
-                errors = true;
-            }
-        }
-        if (sds.isAggregateDeclaration() || sds.isEnumDeclaration())
-        {
-            if (ident == Id.__sizeof ||
-                !(sc && sc.flags & SCOPE.Cfile) && (ident == Id.__xalignof || ident == Id._mangleof))
-            {
-                .error(loc, "%s `%s` `.%s` property cannot be redefined", kind, toPrettyChars, ident.toChars());
-                errors = true;
-            }
-        }
-    }
-
     /*************************************
      * Set scope for future semantic analysis so we can
      * deal better with forward references.
@@ -831,21 +769,6 @@ extern (C++) class Dsymbol : ASTNode
     {
     }
 
-    /*********************************************
-     * Search for ident as member of s.
-     * Params:
-     *  loc = location to print for error messages
-     *  ident = identifier to search for
-     *  flags = IgnoreXXXX
-     * Returns:
-     *  null if not found
-     */
-    Dsymbol search(const ref Loc loc, Identifier ident, int flags = IgnoreNone)
-    {
-        //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars());
-        return null;
-    }
-
     extern (D) final Dsymbol search_correct(Identifier ident)
     {
         /***************************************************
@@ -870,7 +793,7 @@ extern (C++) class Dsymbol : ASTNode
         if (global.gag)
             return null; // don't do it for speculative compiles; too time consuming
         // search for exact name first
-        if (auto s = search(Loc.initial, ident, IgnoreErrors))
+        if (auto s = this.search(Loc.initial, ident, IgnoreErrors))
             return s;
         return speller!symbol_search_fp(ident.toString());
     }
@@ -1339,12 +1262,12 @@ extern (C++) class ScopeDsymbol : Dsymbol
     Dsymbols* members;          // all Dsymbol's in this scope
     DsymbolTable symtab;        // members[] sorted into table
     uint endlinnum;             // the linnumber of the statement after the scope (0 if unknown)
-
-private:
     /// symbols whose members have been imported, i.e. imported modules and template mixins
     Dsymbols* importedScopes;
     Visibility.Kind* visibilities; // array of Visibility.Kind, one for each import
 
+private:
+
     import dmd.root.bitarray;
     BitArray accessiblePackages, privateAccessiblePackages;// whitelists of accessible (imported) packages
 
@@ -1373,166 +1296,7 @@ public:
         return sds;
     }
 
-    /*****************************************
-     * This function is #1 on the list of functions that eat cpu time.
-     * Be very, very careful about slowing it down.
-     */
-    override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
-    {
-        //printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident.toChars(), flags);
-        //if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0;
-
-        // Look in symbols declared in this module
-        if (symtab && !(flags & SearchImportsOnly))
-        {
-            //printf(" look in locals\n");
-            auto s1 = symtab.lookup(ident);
-            if (s1)
-            {
-                //printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars());
-                return s1;
-            }
-        }
-        //printf(" not found in locals\n");
-
-        // Look in imported scopes
-        if (!importedScopes)
-            return null;
-
-        //printf(" look in imports\n");
-        Dsymbol s = null;
-        OverloadSet a = null;
-        // Look in imported modules
-        for (size_t i = 0; i < importedScopes.length; i++)
-        {
-            // If private import, don't search it
-            if ((flags & IgnorePrivateImports) && visibilities[i] == Visibility.Kind.private_)
-                continue;
-            int sflags = flags & (IgnoreErrors | IgnoreAmbiguous); // remember these in recursive searches
-            Dsymbol ss = (*importedScopes)[i];
-            //printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport());
-
-            if (ss.isModule())
-            {
-                if (flags & SearchLocalsOnly)
-                    continue;
-            }
-            else // mixin template
-            {
-                if (flags & SearchImportsOnly)
-                    continue;
-
-                sflags |= SearchLocalsOnly;
-            }
-
-            /* Don't find private members if ss is a module
-             */
-            Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? IgnorePrivateImports : IgnoreNone));
-            import dmd.access : symbolIsVisible;
-            if (!s2 || !(flags & IgnoreSymbolVisibility) && !symbolIsVisible(this, s2))
-                continue;
-            if (!s)
-            {
-                s = s2;
-                if (s && s.isOverloadSet())
-                    a = mergeOverloadSet(ident, a, s);
-            }
-            else if (s2 && s != s2)
-            {
-                if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType())
-                {
-                    /* After following aliases, we found the same
-                     * symbol, so it's not an ambiguity.  But if one
-                     * alias is deprecated or less accessible, prefer
-                     * the other.
-                     */
-                    if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none)
-                        s = s2;
-                }
-                else
-                {
-                    /* Two imports of the same module should be regarded as
-                     * the same.
-                     */
-                    Import i1 = s.isImport();
-                    Import i2 = s2.isImport();
-                    if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident)))))
-                    {
-                        /* https://issues.dlang.org/show_bug.cgi?id=8668
-                         * Public selective import adds AliasDeclaration in module.
-                         * To make an overload set, resolve aliases in here and
-                         * get actual overload roots which accessible via s and s2.
-                         */
-                        s = s.toAlias();
-                        s2 = s2.toAlias();
-                        /* If both s2 and s are overloadable (though we only
-                         * need to check s once)
-                         */
-
-                        auto so2 = s2.isOverloadSet();
-                        if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable()))
-                        {
-                            if (symbolIsVisible(this, s2))
-                            {
-                                a = mergeOverloadSet(ident, a, s2);
-                            }
-                            if (!symbolIsVisible(this, s))
-                                s = s2;
-                            continue;
-                        }
-
-                        /* Two different overflow sets can have the same members
-                         * https://issues.dlang.org/show_bug.cgi?id=16709
-                         */
-                        auto so = s.isOverloadSet();
-                        if (so && so2)
-                        {
-                            if (so.a.length == so2.a.length)
-                            {
-                                foreach (j; 0 .. so.a.length)
-                                {
-                                    if (so.a[j] !is so2.a[j])
-                                        goto L1;
-                                }
-                                continue;  // the same
-                              L1:
-                                {   } // different
-                            }
-                        }
-
-                        if (flags & IgnoreAmbiguous) // if return NULL on ambiguity
-                            return null;
-
-                        /* If two imports from C import files, pick first one, as C has global name space
-                         */
-                        if (s.isCsymbol() && s2.isCsymbol())
-                            continue;
-
-                        if (!(flags & IgnoreErrors))
-                            ScopeDsymbol.multiplyDefined(loc, s, s2);
-                        break;
-                    }
-                }
-            }
-        }
-        if (s)
-        {
-            /* Build special symbol if we had multiple finds
-             */
-            if (a)
-            {
-                if (!s.isOverloadSet())
-                    a = mergeOverloadSet(ident, a, s);
-                s = a;
-            }
-            //printf("\tfound in imports %s.%s\n", toChars(), s.toChars());
-            return s;
-        }
-        //printf(" not found in imports\n");
-        return null;
-    }
-
-    extern (D) private OverloadSet mergeOverloadSet(Identifier ident, OverloadSet os, Dsymbol s)
+    extern (D) final OverloadSet mergeOverloadSet(Identifier ident, OverloadSet os, Dsymbol s)
     {
         if (!os)
         {
@@ -1844,40 +1608,6 @@ extern (C++) final class WithScopeSymbol : ScopeDsymbol
         this.withstate = withstate;
     }
 
-    override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
-    {
-        //printf("WithScopeSymbol.search(%s)\n", ident.toChars());
-        if (flags & SearchImportsOnly)
-            return null;
-        // Acts as proxy to the with class declaration
-        Dsymbol s = null;
-        Expression eold = null;
-        for (Expression e = withstate.exp; e && e != eold; e = resolveAliasThis(_scope, e, true))
-        {
-            if (auto se = e.isScopeExp())
-            {
-                s = se.sds;
-            }
-            else if (e.isTypeExp())
-            {
-                s = e.type.toDsymbol(null);
-            }
-            else
-            {
-                Type t = e.type.toBasetype();
-                s = t.toDsymbol(null);
-            }
-            if (s)
-            {
-                s = s.search(loc, ident, flags);
-                if (s)
-                    return s;
-            }
-            eold = e;
-        }
-        return null;
-    }
-
     override inout(WithScopeSymbol) isWithScopeSymbol() inout
     {
         return this;
@@ -1896,217 +1626,28 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
 {
     // either a SliceExp, an IndexExp, an ArrayExp, a TypeTuple or a TupleDeclaration.
     // Discriminated using DYNCAST and, for expressions, also EXP
-    private RootObject arrayContent;
-    Scope* sc;
+    RootObject arrayContent;
 
     extern (D) this(Scope* sc, Expression exp) nothrow @safe
     {
         super(exp.loc, null);
         assert(exp.op == EXP.index || exp.op == EXP.slice || exp.op == EXP.array);
-        this.sc = sc;
+        this._scope = sc;
         this.arrayContent = exp;
     }
 
     extern (D) this(Scope* sc, TypeTuple type) nothrow @safe
     {
-        this.sc = sc;
+        this._scope = sc;
         this.arrayContent = type;
     }
 
     extern (D) this(Scope* sc, TupleDeclaration td) nothrow @safe
     {
-        this.sc = sc;
+        this._scope = sc;
         this.arrayContent = td;
     }
 
-    /// This override is used to solve `$`
-    override Dsymbol search(const ref Loc loc, Identifier ident, int flags = IgnoreNone)
-    {
-        //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags);
-        if (ident != Id.dollar)
-            return null;
-
-        VarDeclaration* pvar;
-        Expression ce;
-
-        static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc)
-        {
-
-            /* $ gives the number of type entries in the type tuple
-             */
-            auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
-            Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t);
-            v._init = new ExpInitializer(Loc.initial, e);
-            v.storage_class |= STC.temp | STC.static_ | STC.const_;
-            v.dsymbolSemantic(sc);
-            return v;
-        }
-
-        const DYNCAST kind = arrayContent.dyncast();
-        switch (kind) with (DYNCAST)
-        {
-        case dsymbol:
-            TupleDeclaration td = cast(TupleDeclaration) arrayContent;
-            /* $ gives the number of elements in the tuple
-             */
-            auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
-            Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t);
-            v._init = new ExpInitializer(Loc.initial, e);
-            v.storage_class |= STC.temp | STC.static_ | STC.const_;
-            v.dsymbolSemantic(sc);
-            return v;
-        case type:
-            return dollarFromTypeTuple(loc, cast(TypeTuple) arrayContent, sc);
-        default:
-            break;
-        }
-        Expression exp = cast(Expression) arrayContent;
-        if (auto ie = exp.isIndexExp())
-        {
-            /* array[index] where index is some function of $
-             */
-            pvar = &ie.lengthVar;
-            ce = ie.e1;
-        }
-        else if (auto se = exp.isSliceExp())
-        {
-            /* array[lwr .. upr] where lwr or upr is some function of $
-             */
-            pvar = &se.lengthVar;
-            ce = se.e1;
-        }
-        else if (auto ae = exp.isArrayExp())
-        {
-            /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $
-             * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...)
-             */
-            pvar = &ae.lengthVar;
-            ce = ae.e1;
-        }
-        else
-        {
-            /* Didn't find $, look in enclosing scope(s).
-             */
-            return null;
-        }
-        ce = ce.lastComma();
-        /* If we are indexing into an array that is really a type
-         * tuple, rewrite this as an index into a type tuple and
-         * try again.
-         */
-        if (auto te = ce.isTypeExp())
-        {
-            if (auto ttp = te.type.isTypeTuple())
-                return dollarFromTypeTuple(loc, ttp, sc);
-        }
-        /* *pvar is lazily initialized, so if we refer to $
-         * multiple times, it gets set only once.
-         */
-        if (!*pvar) // if not already initialized
-        {
-            /* Create variable v and set it to the value of $
-             */
-            VarDeclaration v;
-            Type t;
-            if (auto tupexp = ce.isTupleExp())
-            {
-                /* It is for an expression tuple, so the
-                 * length will be a const.
-                 */
-                Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t);
-                v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e));
-                v.storage_class |= STC.temp | STC.static_ | STC.const_;
-            }
-            else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass))
-            {
-                // Look for opDollar
-                assert(exp.op == EXP.array || exp.op == EXP.slice);
-                AggregateDeclaration ad = isAggregate(t);
-                assert(ad);
-                Dsymbol s = ad.search(loc, Id.opDollar);
-                if (!s) // no dollar exists -- search in higher scope
-                    return null;
-                s = s.toAlias();
-                Expression e = null;
-                // Check for multi-dimensional opDollar(dim) template.
-                if (TemplateDeclaration td = s.isTemplateDeclaration())
-                {
-                    dinteger_t dim = 0;
-                    if (auto ae = exp.isArrayExp())
-                    {
-                        dim = ae.currentDimension;
-                    }
-                    else if (exp.isSliceExp())
-                    {
-                        dim = 0; // slices are currently always one-dimensional
-                    }
-                    else
-                    {
-                        assert(0);
-                    }
-                    auto tiargs = new Objects();
-                    Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t);
-                    edim = edim.expressionSemantic(sc);
-                    tiargs.push(edim);
-                    e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs);
-                }
-                else
-                {
-                    /* opDollar exists, but it's not a template.
-                     * This is acceptable ONLY for single-dimension indexing.
-                     * Note that it's impossible to have both template & function opDollar,
-                     * because both take no arguments.
-                     */
-                    auto ae = exp.isArrayExp();
-                    if (ae && ae.arguments.length != 1)
-                    {
-                        error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars());
-                        return null;
-                    }
-                    Declaration d = s.isDeclaration();
-                    assert(d);
-                    e = new DotVarExp(loc, ce, d);
-                }
-                e = e.expressionSemantic(sc);
-                if (!e.type)
-                    error(exp.loc, "`%s` has no value", e.toChars());
-                t = e.type.toBasetype();
-                if (t && t.ty == Tfunction)
-                    e = new CallExp(e.loc, e);
-                v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e));
-                v.storage_class |= STC.temp | STC.ctfe | STC.rvalue;
-            }
-            else
-            {
-                /* For arrays, $ will either be a compile-time constant
-                 * (in which case its value in set during constant-folding),
-                 * or a variable (in which case an expression is created in
-                 * toir.c).
-                 */
-
-                // https://issues.dlang.org/show_bug.cgi?id=16213
-                // For static arrays $ is known at compile time,
-                // so declare it as a manifest constant.
-                auto tsa = ce.type ? ce.type.isTypeSArray() : null;
-                if (tsa)
-                {
-                    auto e = new ExpInitializer(loc, tsa.dim);
-                    v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest);
-                }
-                else
-                {
-                    auto e = new VoidInitializer(Loc.initial);
-                    e.type = Type.tsize_t;
-                    v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e);
-                    v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable
-                }
-            }
-            *pvar = v;
-        }
-        (*pvar).dsymbolSemantic(sc);
-        return (*pvar);
-    }
-
     override inout(ArrayScopeSymbol) isArrayScopeSymbol() inout
     {
         return this;
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 027897532d1..e0c2046bf90 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -228,10 +228,8 @@ public:
     virtual const char *kind() const;
     virtual Dsymbol *toAlias();                 // resolve real symbol
     virtual Dsymbol *toAlias2();
-    virtual void addMember(Scope *sc, ScopeDsymbol *sds);
     virtual void setScope(Scope *sc);
     virtual void importAll(Scope *sc);
-    virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone);
     virtual bool overloadInsert(Dsymbol *s);
     virtual uinteger_t size(const Loc &loc);
     virtual bool isforwardRef();
@@ -331,16 +329,14 @@ public:
     Dsymbols *members;          // all Dsymbol's in this scope
     DsymbolTable *symtab;       // members[] sorted into table
     unsigned endlinnum;         // the linnumber of the statement after the scope (0 if unknown)
-
-private:
     Dsymbols *importedScopes;   // imported Dsymbol's
     Visibility::Kind *visibilities;   // array of `Visibility.Kind`, one for each import
 
+private:
     BitArray accessiblePackages, privateAccessiblePackages;
 
 public:
     ScopeDsymbol *syntaxCopy(Dsymbol *s) override;
-    Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
     virtual void importScope(Dsymbol *s, Visibility visibility);
     virtual bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0);
     bool isforwardRef() override final;
@@ -362,7 +358,6 @@ class WithScopeSymbol final : public ScopeDsymbol
 public:
     WithStatement *withstate;
 
-    Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
 
     WithScopeSymbol *isWithScopeSymbol() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
@@ -372,12 +367,8 @@ public:
 
 class ArrayScopeSymbol final : public ScopeDsymbol
 {
-private:
-    RootObject *arrayContent;
 public:
-    Scope *sc;
-
-    Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone) override;
+    RootObject *arrayContent;
 
     ArrayScopeSymbol *isArrayScopeSymbol() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
@@ -437,3 +428,6 @@ public:
     // Number of symbols in symbol table
     size_t length() const;
 };
+
+void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds);
+Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 637edd7bf08..430377ff874 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -23,6 +23,7 @@ import dmd.astenums;
 import dmd.attrib;
 import dmd.blockexit;
 import dmd.clone;
+import dmd.cond;
 import dmd.compiler;
 import dmd.dcast;
 import dmd.dclass;
@@ -1141,7 +1142,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                         else if (auto ale = ex.isArrayLiteralExp())
                         {
                             // or an array literal assigned to a `scope` variable
-                            if (global.params.useDIP1000 == FeatureState.enabled
+                            if (sc.useDIP1000 == FeatureState.enabled
                                 && !dsym.type.nextOf().needsDestruction())
                                 ale.onstack = true;
                         }
@@ -1170,10 +1171,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     // https://issues.dlang.org/show_bug.cgi?id=14166
                     // Don't run CTFE for the temporary variables inside typeof
                     dsym._init = dsym._init.initializerSemantic(sc, dsym.type, sc.intypeof == 1 ? INITnointerpret : INITinterpret);
+                    import dmd.semantic2 : lowerStaticAAs;
+                    lowerStaticAAs(dsym, sc);
                     const init_err = dsym._init.isExpInitializer();
                     if (init_err && init_err.exp.op == EXP.showCtfeContext)
                     {
-                         errorSupplemental(dsym.loc, "compile time context created here");
+                        errorSupplemental(dsym.loc, "compile time context created here");
                     }
                 }
             }
@@ -1979,7 +1982,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         if (!cd.compiled)
         {
             cd.decl = compileIt(cd);
-            cd.AttribDeclaration.addMember(sc, cd.scopesym);
+            attribAddMember(cd, sc, cd.scopesym);
             cd.compiled = true;
 
             if (cd._scope && cd.decl)
@@ -3385,7 +3388,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
             if (!tf.isNaked() && !(funcdecl.isThis() || funcdecl.isNested()))
             {
-                import core.bitop;
+                import core.bitop : popcnt;
                 auto mods = MODtoChars(tf.mod);
                 .error(funcdecl.loc, "%s `%s` without `this` cannot be `%s`", funcdecl.kind, funcdecl.toPrettyChars, mods);
                 if (tf.next && tf.next.ty != Tvoid && popcnt(tf.mod) == 1)
@@ -5831,6 +5834,365 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
     }
 }
 
+/*
+Adds dsym as a member of scope sds.
+
+Params:
+    dsym = dsymbol to inserted
+    sc = scope where the dsymbol is declared
+    sds = ScopeDsymbol where dsym is inserted
+*/
+extern(C++) void addMember(Dsymbol dsym, Scope* sc, ScopeDsymbol sds)
+{
+    auto addMemberVisitor = new AddMemberVisitor(sc, sds);
+    dsym.accept(addMemberVisitor);
+}
+
+private void attribAddMember(AttribDeclaration atb, Scope* sc, ScopeDsymbol sds)
+{
+    Dsymbols* d = atb.include(sc);
+    if (d)
+    {
+        Scope* sc2 = atb.newScope(sc);
+        d.foreachDsymbol( s => s.addMember(sc2, sds) );
+        if (sc2 != sc)
+            sc2.pop();
+    }
+}
+
+private extern(C++) class AddMemberVisitor : Visitor
+{
+    alias visit = Visitor.visit;
+
+    Scope* sc;
+    ScopeDsymbol sds;
+
+    this(Scope* sc, ScopeDsymbol sds)
+    {
+        this.sc = sc;
+        this.sds = sds;
+    }
+
+    override void visit(Dsymbol dsym)
+    {
+        //printf("Dsymbol::addMember('%s')\n", toChars());
+        //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds.toChars());
+        //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds.symtab = %p)\n", this, toChars(), sds, sds.symtab);
+        dsym.parent = sds;
+        if (dsym.isAnonymous()) // no name, so can't add it to symbol table
+            return;
+
+        if (!sds.symtabInsert(dsym)) // if name is already defined
+        {
+            if (dsym.isAliasDeclaration() && !dsym._scope)
+                dsym.setScope(sc);
+            Dsymbol s2 = sds.symtabLookup(dsym, dsym.ident);
+            /* https://issues.dlang.org/show_bug.cgi?id=17434
+             *
+             * If we are trying to add an import to the symbol table
+             * that has already been introduced, then keep the one with
+             * larger visibility. This is fine for imports because if
+             * we have multiple imports of the same file, if a single one
+             * is public then the symbol is reachable.
+             */
+            if (auto i1 = dsym.isImport())
+            {
+                if (auto i2 = s2.isImport())
+                {
+                    if (sc.explicitVisibility && sc.visibility > i2.visibility)
+                        sds.symtab.update(dsym);
+                }
+            }
+
+            // If using C tag/prototype/forward declaration rules
+            if (sc.flags & SCOPE.Cfile && !dsym.isImport())
+            {
+                if (handleTagSymbols(*sc, dsym, s2, sds))
+                    return;
+                if (handleSymbolRedeclarations(*sc, dsym, s2, sds))
+                    return;
+
+                sds.multiplyDefined(Loc.initial, dsym, s2);  // ImportC doesn't allow overloading
+                dsym.errors = true;
+                return;
+            }
+
+            if (!s2.overloadInsert(dsym))
+            {
+                sds.multiplyDefined(Loc.initial, dsym, s2);
+                dsym.errors = true;
+            }
+        }
+        if (sds.isAggregateDeclaration() || sds.isEnumDeclaration())
+        {
+            if (dsym.ident == Id.__sizeof ||
+                !(sc && sc.flags & SCOPE.Cfile) && (dsym.ident == Id.__xalignof || dsym.ident == Id._mangleof))
+            {
+                .error(dsym.loc, "%s `%s` `.%s` property cannot be redefined", dsym.kind, dsym.toPrettyChars, dsym.ident.toChars());
+                dsym.errors = true;
+            }
+        }
+    }
+
+
+    override void visit(StaticAssert _)
+    {
+        // we didn't add anything
+    }
+
+    /*****************************
+     * Add import to sd's symbol table.
+     */
+    override void visit(Import imp)
+    {
+        //printf("Import.addMember(this=%s, sds=%s, sc=%p)\n", imp.toChars(), sds.toChars(), sc);
+        if (imp.names.length == 0)
+            return visit(cast(Dsymbol)imp);
+        if (imp.aliasId)
+            visit(cast(Dsymbol)imp);
+
+        /* Instead of adding the import to sds's symbol table,
+         * add each of the alias=name pairs
+         */
+        for (size_t i = 0; i < imp.names.length; i++)
+        {
+            Identifier name = imp.names[i];
+            Identifier _alias = imp.aliases[i];
+            if (!_alias)
+                _alias = name;
+            auto tname = new TypeIdentifier(imp.loc, name);
+            auto ad = new AliasDeclaration(imp.loc, _alias, tname);
+            ad._import = imp;
+            addMember(ad, sc, sds);
+            imp.aliasdecls.push(ad);
+        }
+    }
+
+    override void visit(AttribDeclaration atb)
+    {
+       attribAddMember(atb, sc, sds);
+    }
+
+    override void visit(StorageClassDeclaration stcd)
+    {
+        Dsymbols* d = stcd.include(sc);
+        if (d)
+        {
+            Scope* sc2 = stcd.newScope(sc);
+
+            d.foreachDsymbol( (s)
+            {
+                //printf("\taddMember %s to %s\n", s.toChars(), sds.toChars());
+                // STC.local needs to be attached before the member is added to the scope (because it influences the parent symbol)
+                if (auto decl = s.isDeclaration())
+                {
+                    decl.storage_class |= stcd.stc & STC.local;
+                    if (auto sdecl = s.isStorageClassDeclaration()) // TODO: why is this not enough to deal with the nested case?
+                    {
+                        sdecl.stc |= stcd.stc & STC.local;
+                    }
+                }
+                s.addMember(sc2, sds);
+            });
+
+            if (sc2 != sc)
+                sc2.pop();
+        }
+    }
+
+    override void visit(VisibilityDeclaration visd)
+    {
+        if (visd.pkg_identifiers)
+        {
+            Dsymbol tmp;
+            Package.resolve(visd.pkg_identifiers, &tmp, null);
+            visd.visibility.pkg = tmp ? tmp.isPackage() : null;
+            visd.pkg_identifiers = null;
+        }
+        if (visd.visibility.kind == Visibility.Kind.package_ && visd.visibility.pkg && sc._module)
+        {
+            Module m = sc._module;
+
+            // https://issues.dlang.org/show_bug.cgi?id=17441
+            // While isAncestorPackageOf does an equality check, the fix for the issue adds a check to see if
+            // each package's .isModule() properites are equal.
+            //
+            // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null.
+            // This breaks package declarations of the package in question if they are declared in
+            // the same package.d file, which _do_ have a module associated with them, and hence a non-null
+            // isModule()
+            if (!m.isPackage() || !visd.visibility.pkg.ident.equals(m.isPackage().ident))
+            {
+                Package pkg = m.parent ? m.parent.isPackage() : null;
+                if (!pkg || !visd.visibility.pkg.isAncestorPackageOf(pkg))
+                    .error(visd.loc, "%s `%s` does not bind to one of ancestor packages of module `%s`", visd.kind(), visd.toPrettyChars(false), m.toPrettyChars(true));
+            }
+        }
+        attribAddMember(visd, sc, sds);
+    }
+
+    override void visit(StaticIfDeclaration sid)
+    {
+        //printf("StaticIfDeclaration::addMember() '%s'\n", sid.toChars());
+        /* This is deferred until the condition evaluated later (by the include() call),
+         * so that expressions in the condition can refer to declarations
+         * in the same scope, such as:
+         *
+         * template Foo(int i)
+         * {
+         *     const int j = i + 1;
+         *     static if (j == 3)
+         *         const int k;
+         * }
+         */
+        sid.scopesym = sds;
+    }
+
+
+    override void visit(StaticForeachDeclaration sfd)
+    {
+        // used only for caching the enclosing symbol
+        sfd.scopesym = sds;
+    }
+
+    /***************************************
+     * Lazily initializes the scope to forward to.
+     */
+    override void visit(ForwardingAttribDeclaration fad)
+    {
+        fad.sym.parent = sds;
+        sds = fad.sym;
+        attribAddMember(fad, sc, fad.sym);
+    }
+
+    override void visit(MixinDeclaration md)
+    {
+        //printf("MixinDeclaration::addMember(sc = %p, sds = %p, memnum = %d)\n", sc, sds, md.memnum);
+        md.scopesym = sds;
+    }
+
+    override void visit(DebugSymbol ds)
+    {
+        //printf("DebugSymbol::addMember('%s') %s\n", sds.toChars(), ds.toChars());
+        Module m = sds.isModule();
+        // Do not add the member to the symbol table,
+        // just make sure subsequent debug declarations work.
+        if (ds.ident)
+        {
+            if (!m)
+            {
+                .error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars);
+                ds.errors = true;
+            }
+            else
+            {
+                if (findCondition(m.debugidsNot, ds.ident))
+                {
+                    .error(ds.loc, "%s `%s` defined after use", ds.kind, ds.toPrettyChars);
+                    ds.errors = true;
+                }
+                if (!m.debugids)
+                    m.debugids = new Identifiers();
+                m.debugids.push(ds.ident);
+            }
+        }
+        else
+        {
+            if (!m)
+            {
+                .error(ds.loc, "%s `%s` level declaration must be at module level", ds.kind, ds.toPrettyChars);
+                ds.errors = true;
+            }
+            else
+                m.debuglevel = ds.level;
+        }
+    }
+
+    override void visit(VersionSymbol vs)
+    {
+        //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), vs.toChars());
+        Module m = sds.isModule();
+        // Do not add the member to the symbol table,
+        // just make sure subsequent debug declarations work.
+        if (vs.ident)
+        {
+            VersionCondition.checkReserved(vs.loc, vs.ident.toString());
+            if (!m)
+            {
+                .error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars);
+                vs.errors = true;
+            }
+            else
+            {
+                if (findCondition(m.versionidsNot, vs.ident))
+                {
+                    .error(vs.loc, "%s `%s` defined after use", vs.kind, vs.toPrettyChars);
+                    vs.errors = true;
+                }
+                if (!m.versionids)
+                    m.versionids = new Identifiers();
+                m.versionids.push(vs.ident);
+            }
+        }
+        else
+        {
+            if (!m)
+            {
+                .error(vs.loc, "%s `%s` level declaration must be at module level", vs.kind, vs.toPrettyChars);
+                vs.errors = true;
+            }
+            else
+                m.versionlevel = vs.level;
+        }
+    }
+
+    override void visit(Nspace ns)
+    {
+        visit(cast(Dsymbol)ns);
+
+        if (ns.members)
+        {
+            if (!ns.symtab)
+                ns.symtab = new DsymbolTable();
+            // The namespace becomes 'imported' into the enclosing scope
+            for (Scope* sce = sc; 1; sce = sce.enclosing)
+            {
+                ScopeDsymbol sds2 = sce.scopesym;
+                if (sds2)
+                {
+                    sds2.importScope(ns, Visibility(Visibility.Kind.public_));
+                    break;
+                }
+            }
+            assert(sc);
+            sc = sc.push(ns);
+            sc.linkage = LINK.cpp; // namespaces default to C++ linkage
+            sc.parent = ns;
+            ns.members.foreachDsymbol(s => s.addMember(sc, ns));
+            sc.pop();
+        }
+    }
+
+    override void visit(EnumDeclaration ed)
+    {
+        version (none)
+        {
+            printf("EnumDeclaration::addMember() %s\n", ed.toChars());
+            for (size_t i = 0; i < ed.members.length; i++)
+            {
+                EnumMember em = (*ed.members)[i].isEnumMember();
+                printf("    member %s\n", em.toChars());
+            }
+        }
+        if (!ed.isAnonymous())
+        {
+            visit(cast(Dsymbol)ed);
+        }
+
+        addEnumMembersToSymtab(ed, sc, sds);
+    }
+}
+
 /*******************************************
  * Add members of EnumDeclaration to the symbol table(s).
  * Params:
@@ -5904,7 +6266,7 @@ private bool isDRuntimeHook(Identifier id)
         id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT ||
         id == Id._d_arraysetlengthTTrace ||
         id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace ||
-        id == Id._d_arrayappendcTXImpl;
+        id == Id._d_arrayappendcTX;
 }
 
 void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList argumentList)
@@ -7431,3 +7793,617 @@ void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, Scope*
             p, funcdecl.toChars());
     }
 }
+
+/*********************************************
+ * Search for ident as member of d.
+ * Params:
+ *  d = dsymbol where ident is searched for
+ *  loc = location to print for error messages
+ *  ident = identifier to search for
+ *  flags = IgnoreXXXX
+ * Returns:
+ *  null if not found
+ */
+extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, int flags = IgnoreNone)
+{
+    scope v = new SearchVisitor(loc, ident, flags);
+    d.accept(v);
+    return v.result;
+}
+
+private extern(C++) class SearchVisitor : Visitor
+{
+    alias visit = Visitor.visit;
+
+    const Loc loc;
+    Identifier ident;
+    int flags;
+    Dsymbol result;
+
+    this(const ref Loc loc, Identifier ident, int flags)
+    {
+        this.loc = loc;
+        this.ident = ident;
+        this.flags = flags;
+    }
+
+    void setResult(Dsymbol d)
+    {
+        result = d;
+    }
+
+    override void visit(Dsymbol d)
+    {
+        //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", d, d.toChars(), ident.toChars());
+        return setResult(null);
+    }
+
+    override void visit(ScopeDsymbol sds)
+    {
+        //printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", sds.toChars(), ident.toChars(), flags);
+        //if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0;
+
+        // Look in symbols declared in this module
+        if (sds.symtab && !(flags & SearchImportsOnly))
+        {
+            //printf(" look in locals\n");
+            auto s1 = sds.symtab.lookup(ident);
+            if (s1)
+            {
+                //printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars());
+                return setResult(s1);
+            }
+        }
+        //printf(" not found in locals\n");
+
+        // Look in imported scopes
+        if (!sds.importedScopes)
+            return setResult(null);
+
+        //printf(" look in imports\n");
+        Dsymbol s = null;
+        OverloadSet a = null;
+        // Look in imported modules
+        for (size_t i = 0; i < sds.importedScopes.length; i++)
+        {
+            // If private import, don't search it
+            if ((flags & IgnorePrivateImports) && sds.visibilities[i] == Visibility.Kind.private_)
+                continue;
+            int sflags = flags & (IgnoreErrors | IgnoreAmbiguous); // remember these in recursive searches
+            Dsymbol ss = (*sds.importedScopes)[i];
+            //printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport());
+
+            if (ss.isModule())
+            {
+                if (flags & SearchLocalsOnly)
+                    continue;
+            }
+            else // mixin template
+            {
+                if (flags & SearchImportsOnly)
+                    continue;
+
+                sflags |= SearchLocalsOnly;
+            }
+
+            /* Don't find private members if ss is a module
+             */
+            Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? IgnorePrivateImports : IgnoreNone));
+            import dmd.access : symbolIsVisible;
+            if (!s2 || !(flags & IgnoreSymbolVisibility) && !symbolIsVisible(sds, s2))
+                continue;
+            if (!s)
+            {
+                s = s2;
+                if (s && s.isOverloadSet())
+                    a = sds.mergeOverloadSet(ident, a, s);
+            }
+            else if (s2 && s != s2)
+            {
+                if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType())
+                {
+                    /* After following aliases, we found the same
+                     * symbol, so it's not an ambiguity.  But if one
+                     * alias is deprecated or less accessible, prefer
+                     * the other.
+                     */
+                    if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none)
+                        s = s2;
+                }
+                else
+                {
+                    /* Two imports of the same module should be regarded as
+                     * the same.
+                     */
+                    Import i1 = s.isImport();
+                    Import i2 = s2.isImport();
+                    if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident)))))
+                    {
+                        /* https://issues.dlang.org/show_bug.cgi?id=8668
+                         * Public selective import adds AliasDeclaration in module.
+                         * To make an overload set, resolve aliases in here and
+                         * get actual overload roots which accessible via s and s2.
+                         */
+                        s = s.toAlias();
+                        s2 = s2.toAlias();
+                        /* If both s2 and s are overloadable (though we only
+                         * need to check s once)
+                         */
+
+                        auto so2 = s2.isOverloadSet();
+                        if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable()))
+                        {
+                            if (symbolIsVisible(sds, s2))
+                            {
+                                a = sds.mergeOverloadSet(ident, a, s2);
+                            }
+                            if (!symbolIsVisible(sds, s))
+                                s = s2;
+                            continue;
+                        }
+
+                        /* Two different overflow sets can have the same members
+                         * https://issues.dlang.org/show_bug.cgi?id=16709
+                         */
+                        auto so = s.isOverloadSet();
+                        if (so && so2)
+                        {
+                            if (so.a.length == so2.a.length)
+                            {
+                                foreach (j; 0 .. so.a.length)
+                                {
+                                    if (so.a[j] !is so2.a[j])
+                                        goto L1;
+                                }
+                                continue;  // the same
+                              L1:
+                                {   } // different
+                            }
+                        }
+
+                        if (flags & IgnoreAmbiguous) // if return NULL on ambiguity
+                            return setResult(null);
+
+                        /* If two imports from C import files, pick first one, as C has global name space
+                         */
+                        if (s.isCsymbol() && s2.isCsymbol())
+                            continue;
+
+                        if (!(flags & IgnoreErrors))
+                            ScopeDsymbol.multiplyDefined(loc, s, s2);
+                        break;
+                    }
+                }
+            }
+        }
+        if (s)
+        {
+            /* Build special symbol if we had multiple finds
+             */
+            if (a)
+            {
+                if (!s.isOverloadSet())
+                    a = sds.mergeOverloadSet(ident, a, s);
+                s = a;
+            }
+            //printf("\tfound in imports %s.%s\n", toChars(), s.toChars());
+            return setResult(s);
+        }
+        //printf(" not found in imports\n");
+        return setResult(null);
+    }
+
+    override void visit(WithScopeSymbol ws)
+    {
+        //printf("WithScopeSymbol.search(%s)\n", ident.toChars());
+        if (flags & SearchImportsOnly)
+            return setResult(null);
+        // Acts as proxy to the with class declaration
+        Dsymbol s = null;
+        Expression eold = null;
+        for (Expression e = ws.withstate.exp; e && e != eold; e = resolveAliasThis(ws._scope, e, true))
+        {
+            if (auto se = e.isScopeExp())
+            {
+                s = se.sds;
+            }
+            else if (e.isTypeExp())
+            {
+                s = e.type.toDsymbol(null);
+            }
+            else
+            {
+                Type t = e.type.toBasetype();
+                s = t.toDsymbol(null);
+            }
+            if (s)
+            {
+                s = s.search(loc, ident, flags);
+                if (s)
+                    return setResult(s);
+            }
+            eold = e;
+        }
+        return setResult(null);
+    }
+
+    override void visit(ArrayScopeSymbol ass)
+    {
+        //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags);
+        if (ident != Id.dollar)
+            return setResult(null);
+
+        VarDeclaration* pvar;
+        Expression ce;
+
+        static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc)
+        {
+
+            /* $ gives the number of type entries in the type tuple
+             */
+            auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
+            Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t);
+            v._init = new ExpInitializer(Loc.initial, e);
+            v.storage_class |= STC.temp | STC.static_ | STC.const_;
+            v.dsymbolSemantic(sc);
+            return v;
+        }
+
+        const DYNCAST kind = ass.arrayContent.dyncast();
+        switch (kind) with (DYNCAST)
+        {
+        case dsymbol:
+            TupleDeclaration td = cast(TupleDeclaration) ass.arrayContent;
+            /* $ gives the number of elements in the tuple
+             */
+            auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
+            Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t);
+            v._init = new ExpInitializer(Loc.initial, e);
+            v.storage_class |= STC.temp | STC.static_ | STC.const_;
+            v.dsymbolSemantic(ass._scope);
+            return setResult(v);
+        case type:
+            return setResult(dollarFromTypeTuple(loc, cast(TypeTuple) ass.arrayContent, ass._scope));
+        default:
+            break;
+        }
+        Expression exp = cast(Expression) ass.arrayContent;
+        if (auto ie = exp.isIndexExp())
+        {
+            /* array[index] where index is some function of $
+             */
+            pvar = &ie.lengthVar;
+            ce = ie.e1;
+        }
+        else if (auto se = exp.isSliceExp())
+        {
+            /* array[lwr .. upr] where lwr or upr is some function of $
+             */
+            pvar = &se.lengthVar;
+            ce = se.e1;
+        }
+        else if (auto ae = exp.isArrayExp())
+        {
+            /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $
+             * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...)
+             */
+            pvar = &ae.lengthVar;
+            ce = ae.e1;
+        }
+        else
+        {
+            /* Didn't find $, look in enclosing scope(s).
+             */
+            return setResult(null);
+        }
+        ce = ce.lastComma();
+        /* If we are indexing into an array that is really a type
+         * tuple, rewrite this as an index into a type tuple and
+         * try again.
+         */
+        if (auto te = ce.isTypeExp())
+        {
+            if (auto ttp = te.type.isTypeTuple())
+                return setResult(dollarFromTypeTuple(loc, ttp, ass._scope));
+        }
+        /* *pvar is lazily initialized, so if we refer to $
+         * multiple times, it gets set only once.
+         */
+        if (!*pvar) // if not already initialized
+        {
+            /* Create variable v and set it to the value of $
+             */
+            VarDeclaration v;
+            Type t;
+            if (auto tupexp = ce.isTupleExp())
+            {
+                /* It is for an expression tuple, so the
+                 * length will be a const.
+                 */
+                Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t);
+                v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e));
+                v.storage_class |= STC.temp | STC.static_ | STC.const_;
+            }
+            else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass))
+            {
+                // Look for opDollar
+                assert(exp.op == EXP.array || exp.op == EXP.slice);
+                AggregateDeclaration ad = isAggregate(t);
+                assert(ad);
+                Dsymbol s = ad.search(loc, Id.opDollar);
+                if (!s) // no dollar exists -- search in higher scope
+                    return setResult(null);
+                s = s.toAlias();
+                Expression e = null;
+                // Check for multi-dimensional opDollar(dim) template.
+                if (TemplateDeclaration td = s.isTemplateDeclaration())
+                {
+                    dinteger_t dim = 0;
+                    if (auto ae = exp.isArrayExp())
+                    {
+                        dim = ae.currentDimension;
+                    }
+                    else if (exp.isSliceExp())
+                    {
+                        dim = 0; // slices are currently always one-dimensional
+                    }
+                    else
+                    {
+                        assert(0);
+                    }
+                    auto tiargs = new Objects();
+                    Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t);
+                    edim = edim.expressionSemantic(ass._scope);
+                    tiargs.push(edim);
+                    e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs);
+                }
+                else
+                {
+                    /* opDollar exists, but it's not a template.
+                     * This is acceptable ONLY for single-dimension indexing.
+                     * Note that it's impossible to have both template & function opDollar,
+                     * because both take no arguments.
+                     */
+                    auto ae = exp.isArrayExp();
+                    if (ae && ae.arguments.length != 1)
+                    {
+                        error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars());
+                        return setResult(null);
+                    }
+                    Declaration d = s.isDeclaration();
+                    assert(d);
+                    e = new DotVarExp(loc, ce, d);
+                }
+                e = e.expressionSemantic(ass._scope);
+                if (!e.type)
+                    error(exp.loc, "`%s` has no value", e.toChars());
+                t = e.type.toBasetype();
+                if (t && t.ty == Tfunction)
+                    e = new CallExp(e.loc, e);
+                v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e));
+                v.storage_class |= STC.temp | STC.ctfe | STC.rvalue;
+            }
+            else
+            {
+                /* For arrays, $ will either be a compile-time constant
+                 * (in which case its value in set during constant-folding),
+                 * or a variable (in which case an expression is created in
+                 * toir.c).
+                 */
+
+                // https://issues.dlang.org/show_bug.cgi?id=16213
+                // For static arrays $ is known at compile time,
+                // so declare it as a manifest constant.
+                auto tsa = ce.type ? ce.type.isTypeSArray() : null;
+                if (tsa)
+                {
+                    auto e = new ExpInitializer(loc, tsa.dim);
+                    v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest);
+                }
+                else
+                {
+                    auto e = new VoidInitializer(Loc.initial);
+                    e.type = Type.tsize_t;
+                    v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e);
+                    v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable
+                }
+            }
+            *pvar = v;
+        }
+        (*pvar).dsymbolSemantic(ass._scope);
+        return setResult((*pvar));
+
+    }
+
+    override void visit(Import imp)
+    {
+        //printf("%s.Import.search(ident = '%s', flags = x%x)\n", imp.toChars(), ident.toChars(), flags);
+        if (!imp.pkg)
+        {
+            imp.load(null);
+            imp.mod.importAll(null);
+            imp.mod.dsymbolSemantic(null);
+        }
+        // Forward it to the package/module
+        return setResult(imp.pkg.search(loc, ident, flags));
+
+    }
+
+    override void visit(Nspace ns)
+    {
+        //printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars());
+        if (ns._scope && !ns.symtab)
+            dsymbolSemantic(ns, ns._scope);
+
+        if (!ns.members || !ns.symtab) // opaque or semantic() is not yet called
+        {
+            if (!(flags & IgnoreErrors))
+                .error(loc, "%s `%s` is forward referenced when looking for `%s`", ns.kind, ns.toPrettyChars, ident.toChars());
+            return setResult(null);
+        }
+
+        visit(cast(ScopeDsymbol)ns);
+    }
+
+    override void visit(EnumDeclaration em)
+    {
+        //printf("%s.EnumDeclaration::search('%s')\n", em.toChars(), ident.toChars());
+        if (em._scope)
+        {
+            // Try one last time to resolve this enum
+            dsymbolSemantic(em, em._scope);
+        }
+
+        visit(cast(ScopeDsymbol)em);
+    }
+
+    override void visit(Package pkg)
+    {
+        //printf("%s Package.search('%s', flags = x%x)\n", pkg.toChars(), ident.toChars(), flags);
+        flags &= ~SearchLocalsOnly;  // searching an import is always transitive
+        if (!pkg.isModule() && pkg.mod)
+        {
+            // Prefer full package name.
+            Dsymbol s = pkg.symtab ? pkg.symtab.lookup(ident) : null;
+            if (s)
+                return setResult(s);
+            //printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars());
+            return setResult(pkg.mod.search(loc, ident, flags));
+        }
+
+        visit(cast(ScopeDsymbol)pkg);
+    }
+
+    override void visit(Module m)
+    {
+        /* Since modules can be circularly referenced,
+         * need to stop infinite recursive searches.
+         * This is done with the cache.
+         */
+        //printf("%s Module.search('%s', flags = x%x) insearch = %d\n", m.toChars(), ident.toChars(), flags, m.insearch);
+        if (m.insearch)
+            return setResult(null);
+
+        /* Qualified module searches always search their imports,
+         * even if SearchLocalsOnly
+         */
+        if (!(flags & SearchUnqualifiedModule))
+            flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly);
+
+        if (m.searchCacheIdent == ident && m.searchCacheFlags == flags)
+        {
+            //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n",
+            //        toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null");
+            return setResult(m.searchCacheSymbol);
+        }
+
+        uint errors = global.errors;
+
+        m.insearch = true;
+        visit(cast(ScopeDsymbol)m);
+        Dsymbol s = result;
+        m.insearch = false;
+
+        if (errors == global.errors)
+        {
+            // https://issues.dlang.org/show_bug.cgi?id=10752
+            // Can cache the result only when it does not cause
+            // access error so the side-effect should be reproduced in later search.
+            m.searchCacheIdent = ident;
+            m.searchCacheSymbol = s;
+            m.searchCacheFlags = flags;
+        }
+        return setResult(s);
+    }
+
+    override void visit(Declaration decl)
+    {
+        Dsymbol s = null;
+        if (decl.type)
+        {
+            s = decl.type.toDsymbol(decl._scope);
+            if (s)
+                s = s.search(loc, ident, flags);
+        }
+        return setResult(s);
+    }
+
+    override void visit(StructDeclaration sd)
+    {
+        //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", sd.toChars(), ident.toChars(), flags);
+        if (sd._scope && !sd.symtab)
+            dsymbolSemantic(sd, sd._scope);
+
+        if (!sd.members || !sd.symtab) // opaque or semantic() is not yet called
+        {
+            // .stringof is always defined (but may be hidden by some other symbol)
+            if(ident != Id.stringof && !(flags & IgnoreErrors) && sd.semanticRun < PASS.semanticdone)
+                .error(loc, "%s `%s` is forward referenced when looking for `%s`", sd.kind, sd.toPrettyChars, ident.toChars());
+            return setResult(null);
+        }
+
+        visit(cast(ScopeDsymbol)sd);
+    }
+
+    override void visit(ClassDeclaration cd)
+    {
+        //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", cd.toChars(), ident.toChars(), flags);
+        //if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
+        if (cd._scope && cd.baseok < Baseok.semanticdone)
+        {
+            if (!cd.inuse)
+            {
+                // must semantic on base class/interfaces
+                cd.inuse = true;
+                dsymbolSemantic(cd, null);
+                cd.inuse = false;
+            }
+        }
+
+        if (!cd.members || !cd.symtab) // opaque or addMember is not yet done
+        {
+            // .stringof is always defined (but may be hidden by some other symbol)
+            if (ident != Id.stringof && !(flags & IgnoreErrors) && cd.semanticRun < PASS.semanticdone)
+                cd.classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars());
+            //*(char*)0=0;
+            return setResult(null);
+        }
+
+        visit(cast(ScopeDsymbol)cd);
+        auto s = result;
+
+        // don't search imports of base classes
+        if (flags & SearchImportsOnly)
+            return setResult(s);
+
+        if (s)
+            return setResult(s);
+
+        // Search bases classes in depth-first, left to right order
+        foreach (b; (*cd.baseclasses)[])
+        {
+            if (!b.sym)
+                continue;
+
+            if (!b.sym.symtab)
+            {
+                cd.classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars());
+                continue;
+            }
+
+            import dmd.access : symbolIsVisible;
+
+            s = b.sym.search(loc, ident, flags);
+            if (!s)
+                continue;
+            else if (s == cd) // happens if s is nested in this and derives from this
+                s = null;
+            else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(cd, s))
+                s = null;
+            else
+                break;
+        }
+
+        return setResult(s);
+    }
+}
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 4cf1bae7537..037e0d01196 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -746,7 +746,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
         OutBuffer buf;
         HdrGenState hgs;
 
-        buf.writestring(ident.toString());
+        buf.writestring(ident == Id.ctor ? "this" : ident.toString());
         buf.writeByte('(');
         foreach (i, const tp; *parameters)
         {
@@ -763,6 +763,11 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
             {
                 TypeFunction tf = cast(TypeFunction)fd.type;
                 buf.writestring(parametersTypeToChars(tf.parameterList));
+                if (tf.mod)
+                {
+                    buf.writeByte(' ');
+                    buf.MODtoBuffer(tf.mod);
+                }
             }
         }
 
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 7c76da99d1b..9f855743ef9 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -20,6 +20,7 @@ import dmd.astenums;
 import dmd.arraytypes;
 import dmd.attrib;
 import dmd.dsymbol;
+import dmd.dsymbolsem;
 import dmd.errors;
 import dmd.globals;
 import dmd.hdrgen;
diff --git a/gcc/d/dmd/dversion.d b/gcc/d/dmd/dversion.d
index aa22532061e..31725c80b9b 100644
--- a/gcc/d/dmd/dversion.d
+++ b/gcc/d/dmd/dversion.d
@@ -68,43 +68,6 @@ extern (C++) final class DebugSymbol : Dsymbol
         }
     }
 
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        //printf("DebugSymbol::addMember('%s') %s\n", sds.toChars(), toChars());
-        Module m = sds.isModule();
-        // Do not add the member to the symbol table,
-        // just make sure subsequent debug declarations work.
-        if (ident)
-        {
-            if (!m)
-            {
-                .error(loc, "%s `%s` declaration must be at module level", kind, toPrettyChars);
-                errors = true;
-            }
-            else
-            {
-                if (findCondition(m.debugidsNot, ident))
-                {
-                    .error(loc, "%s `%s` defined after use", kind, toPrettyChars);
-                    errors = true;
-                }
-                if (!m.debugids)
-                    m.debugids = new Identifiers();
-                m.debugids.push(ident);
-            }
-        }
-        else
-        {
-            if (!m)
-            {
-                .error(loc, "%s `%s` level declaration must be at module level", kind, toPrettyChars);
-                errors = true;
-            }
-            else
-                m.debuglevel = level;
-        }
-    }
-
     override const(char)* kind() const nothrow
     {
         return "debug";
@@ -162,44 +125,6 @@ extern (C++) final class VersionSymbol : Dsymbol
         }
     }
 
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), toChars());
-        Module m = sds.isModule();
-        // Do not add the member to the symbol table,
-        // just make sure subsequent debug declarations work.
-        if (ident)
-        {
-            VersionCondition.checkReserved(loc, ident.toString());
-            if (!m)
-            {
-                .error(loc, "%s `%s` declaration must be at module level", kind, toPrettyChars);
-                errors = true;
-            }
-            else
-            {
-                if (findCondition(m.versionidsNot, ident))
-                {
-                    .error(loc, "%s `%s` defined after use", kind, toPrettyChars);
-                    errors = true;
-                }
-                if (!m.versionids)
-                    m.versionids = new Identifiers();
-                m.versionids.push(ident);
-            }
-        }
-        else
-        {
-            if (!m)
-            {
-                .error(loc, "%s `%s` level declaration must be at module level", kind, toPrettyChars);
-                errors = true;
-            }
-            else
-                m.versionlevel = level;
-        }
-    }
-
     override const(char)* kind() const nothrow
     {
         return "version";
diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h
index be12c65e6d6..e17e8cf5b0a 100644
--- a/gcc/d/dmd/enum.h
+++ b/gcc/d/dmd/enum.h
@@ -46,12 +46,10 @@ public:
     bool inuse(bool v);
 
     EnumDeclaration *syntaxCopy(Dsymbol *s) override;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     void setScope(Scope *sc) override;
     bool oneMember(Dsymbol **ps, Identifier *ident) override;
     Type *getType() override;
     const char *kind() const override;
-    Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
     bool isDeprecated() const override;       // is Dsymbol deprecated?
     Visibility visible() override;
     bool isSpecial() const;
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index 3f85ea08320..e25fc84234e 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -25,7 +25,7 @@ import dmd.dsymbol;
 import dmd.errors;
 import dmd.expression;
 import dmd.func;
-import dmd.globals;
+import dmd.globals : FeatureState;
 import dmd.id;
 import dmd.identifier;
 import dmd.init;
@@ -169,7 +169,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
         if (!(eb.isMutable || eb2.isMutable))
             return;
 
-        if (!tf.islive && !(global.params.useDIP1000 == FeatureState.enabled && sc.func && sc.func.setUnsafe()))
+        if (!tf.islive && !(sc.useDIP1000 == FeatureState.enabled && sc.func && sc.func.setUnsafe()))
             return;
 
         if (!gag)
@@ -377,7 +377,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
             sc.setUnsafeDIP1000(gag, arg.loc, msg, v, parId ? parId : fdc, fdc))
         {
             result = true;
-            printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), global.params.useDIP1000), vPar, 10);
+            printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), sc.useDIP1000), vPar, 10);
         }
     }
 
@@ -1094,7 +1094,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
         {
             if (p == sc.func)
             {
-                result |= escapingRef(v, global.params.useDIP1000);
+                result |= escapingRef(v, sc.useDIP1000);
                 continue;
             }
         }
@@ -1110,7 +1110,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
         {
             //printf("escaping reference to local ref variable %s\n", v.toChars());
             //printf("storage class = x%llx\n", v.storage_class);
-            result |= escapingRef(v, global.params.useDIP25);
+            result |= escapingRef(v, sc.useDIP25);
             continue;
         }
         // Don't need to be concerned if v's parent does not return a ref
@@ -1125,12 +1125,12 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
             const(char)* msg = "storing reference to outer local variable `%s` into allocated memory causes it to escape";
             if (!gag)
             {
-                previewErrorFunc(sc.isDeprecated(), global.params.useDIP25)(e.loc, msg, v.toChars());
+                previewErrorFunc(sc.isDeprecated(), sc.useDIP25)(e.loc, msg, v.toChars());
             }
 
             // If -preview=dip25 is used, the user wants an error
             // Otherwise, issue a deprecation
-            result |= (global.params.useDIP25 == FeatureState.enabled);
+            result |= (sc.useDIP25 == FeatureState.enabled);
         }
     }
 
@@ -1264,7 +1264,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
                     // https://issues.dlang.org/show_bug.cgi?id=23191
                     if (!gag)
                     {
-                        previewErrorFunc(sc.isDeprecated(), global.params.useDIP1000)(e.loc,
+                        previewErrorFunc(sc.isDeprecated(), sc.useDIP1000)(e.loc,
                             "scope parameter `%s` may not be returned", v.toChars()
                         );
                         result = true;
@@ -1403,7 +1403,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
                 {
                     //printf("escaping reference to local ref variable %s\n", v.toChars());
                     //printf("storage class = x%llx\n", v.storage_class);
-                    escapingRef(v, global.params.useDIP25);
+                    escapingRef(v, sc.useDIP25);
                     continue;
                 }
                 // Don't need to be concerned if v's parent does not return a ref
@@ -1415,7 +1415,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
                     {
                         const(char)* msg = "escaping reference to outer local variable `%s`";
                         if (!gag)
-                            previewErrorFunc(sc.isDeprecated(), global.params.useDIP25)(e.loc, msg, v.toChars());
+                            previewErrorFunc(sc.isDeprecated(), sc.useDIP25)(e.loc, msg, v.toChars());
                         result = true;
                         continue;
                     }
@@ -2588,7 +2588,7 @@ public
 bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg,
     RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
 {
-    return setUnsafePreview(sc, global.params.useDIP1000, gag, loc, msg, arg0, arg1, arg2);
+    return setUnsafePreview(sc, sc.useDIP1000, gag, loc, msg, arg0, arg1, arg2);
 }
 
 /***************************************
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 47902213504..cd93e54932c 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -4617,7 +4617,9 @@ extern (C++) final class UshrAssignExp : BinAssignExp
  */
 extern (C++) class CatAssignExp : BinAssignExp
 {
-    extern (D) this(const ref Loc loc, Expression e1, Expression e2) @safe
+    Expression lowering;    // lowered druntime hook `_d_arrayappend{cTX,T}`
+
+    extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
         super(loc, EXP.concatenateAssign, e1, e2);
     }
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 12ca6b4566c..b4ace74b496 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -52,7 +52,7 @@ void expandTuples(Expressions *exps, Identifiers *names = nullptr);
 StringExp *toUTF8(StringExp *se, Scope *sc);
 Expression *resolveLoc(Expression *exp, const Loc &loc, Scope *sc);
 MATCH implicitConvTo(Expression *e, Type *t);
-Expression *toLvalue(Expression *_this, Scope *sc);
+Expression *toLvalue(Expression *_this, Scope *sc, const char* action);
 Expression *modifiableLvalue(Expression* exp, Scope *sc);
 
 typedef unsigned char OwnedBy;
@@ -1114,6 +1114,8 @@ public:
 class CatAssignExp : public BinAssignExp
 {
 public:
+    Expression *lowering;   // lowered druntime hook `_d_arrayappend{cTX,T}`
+
     void accept(Visitor *v) override { v->visit(this); }
 };
 
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index d55ab3bcb26..e6b90183b51 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -2150,7 +2150,7 @@ private bool checkNogc(FuncDeclaration f, ref Loc loc, Scope* sc)
      * verified instead. This is to keep errors related to the original code
      * and not the lowering.
      */
-    if (f.ident == Id._d_newitemT || f.ident == Id._d_newarrayT)
+    if (f.ident == Id._d_newitemT || f.ident == Id._d_newarrayT || f.ident == Id._d_newarraymTX)
         return false;
 
     if (!f.isNogc())
@@ -3129,7 +3129,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
                     ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
                     arg = ev.expressionSemantic(sc);
                 }
-                arg = arg.toLvalue(sc);
+                arg = arg.toLvalue(sc, "create `in` parameter from");
 
                 // Look for mutable misaligned pointer, etc., in @safe mode
                 err |= checkUnsafeAccess(sc, arg, false, true);
@@ -3147,7 +3147,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
                     ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
                     arg = ev.expressionSemantic(sc);
                 }
-                arg = arg.toLvalue(sc);
+                arg = arg.toLvalue(sc, "create `ref` parameter from");
 
                 // Look for mutable misaligned pointer, etc., in @safe mode
                 err |= checkUnsafeAccess(sc, arg, false, true);
@@ -3166,7 +3166,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
                     err |= checkUnsafeAccess(sc, arg, false, true);
                     err |= checkDefCtor(arg.loc, t); // t must be default constructible
                 }
-                arg = arg.toLvalue(sc);
+                arg = arg.toLvalue(sc, "create `out` parameter from");
             }
             else if (p.isLazy())
             {
@@ -3209,7 +3209,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
             const explicitScope = p.isLazy() ||
                 ((p.storageClass & STC.scope_) && !(p.storageClass & STC.scopeinferred));
             if ((pStc & (STC.scope_ | STC.lazy_)) &&
-                ((global.params.useDIP1000 == FeatureState.enabled) || explicitScope) &&
+                ((sc.useDIP1000 == FeatureState.enabled) || explicitScope) &&
                 !(pStc & STC.return_))
             {
                 /* Argument value cannot escape from the called function.
@@ -5115,23 +5115,23 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 tb = tb.isTypeDArray().next.toBasetype();
             }
 
-            if (nargs == 1)
-            {
-                if (global.params.betterC || !sc.needsCodegen())
+            if (global.params.betterC || !sc.needsCodegen())
                     goto LskipNewArrayLowering;
 
-                /* Class types may inherit base classes that have errors.
-                 * This may leak errors from the base class to the derived one
-                 * and then to the hook. Semantic analysis is performed eagerly
-                 * to a void this.
-                 */
-                if (auto tc = exp.type.nextOf.isTypeClass())
-                {
-                    tc.sym.dsymbolSemantic(sc);
-                    if (tc.sym.errors)
-                        goto LskipNewArrayLowering;
-                }
+            /* Class types may inherit base classes that have errors.
+                * This may leak errors from the base class to the derived one
+                * and then to the hook. Semantic analysis is performed eagerly
+                * to a void this.
+                */
+            if (auto tc = exp.type.nextOf.isTypeClass())
+            {
+                tc.sym.dsymbolSemantic(sc);
+                if (tc.sym.errors)
+                    goto LskipNewArrayLowering;
+            }
 
+            if (nargs == 1)
+            {
                 auto hook = global.params.tracegc ? Id._d_newarrayTTrace : Id._d_newarrayT;
                 if (!verifyHookExist(exp.loc, *sc, hook, "new array"))
                     goto LskipNewArrayLowering;
@@ -5163,6 +5163,45 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 arguments.push((*exp.arguments)[0]);
                 arguments.push(new IntegerExp(exp.loc, isShared, Type.tbool));
 
+                lowering = new CallExp(exp.loc, lowering, arguments);
+                exp.lowering = lowering.expressionSemantic(sc);
+            }
+            else
+            {
+                auto hook = global.params.tracegc ? Id._d_newarraymTXTrace : Id._d_newarraymTX;
+                if (!verifyHookExist(exp.loc, *sc, hook, "new multi-dimensional array"))
+                    goto LskipNewArrayLowering;
+
+                /* Lower the memory allocation and initialization of `new T[][]...[](n1, n2, ...)`
+                 * to `_d_newarraymTX!(T[][]...[], T)([n1, n2, ...])`.
+                 */
+                Expression lowering = new IdentifierExp(exp.loc, Id.empty);
+                lowering = new DotIdExp(exp.loc, lowering, Id.object);
+
+                auto tbn = exp.type.nextOf();
+                while (tbn.ty == Tarray)
+                    tbn = tbn.nextOf();
+                auto unqualTbn = tbn.unqualify(MODFlags.wild | MODFlags.const_ |
+                    MODFlags.immutable_ | MODFlags.shared_);
+
+                auto tiargs = new Objects();
+                tiargs.push(exp.type);
+                tiargs.push(unqualTbn);
+                lowering = new DotTemplateInstanceExp(exp.loc, lowering, hook, tiargs);
+
+                auto arguments = new Expressions();
+                if (global.params.tracegc)
+                {
+                    auto funcname = (sc.callsc && sc.callsc.func) ?
+                        sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
+                    arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
+                    arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
+                    arguments.push(new StringExp(exp.loc, funcname.toDString()));
+                }
+
+                arguments.push(new ArrayLiteralExp(exp.loc, Type.tsize_t.sarrayOf(nargs), exp.arguments));
+                arguments.push(new IntegerExp(exp.loc, tbn.isShared(), Type.tbool));
+
                 lowering = new CallExp(exp.loc, lowering, arguments);
                 exp.lowering = lowering.expressionSemantic(sc);
             }
@@ -8295,7 +8334,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 else
                 {
                     // `toLvalue` call further below is upon exp.e1, omitting & from the error message
-                    exp.toLvalue(sc);
+                    exp.toLvalue(sc, "take address of");
                     return setError();
                 }
             }
@@ -8385,7 +8424,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
         }
 
-        exp.e1 = exp.e1.toLvalue(sc);
+        exp.e1 = exp.e1.toLvalue(sc, "take address of");
         if (exp.e1.op == EXP.error)
         {
             result = exp.e1;
@@ -9017,14 +9056,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 return setError();
         }
 
-        // Look for casting to a vector type
-        if (tob.ty == Tvector && t1b.ty != Tvector)
-        {
-            result = new VectorExp(exp.loc, exp.e1, exp.to);
-            result = result.expressionSemantic(sc);
-            return;
-        }
-
         Expression ex = exp.e1.castTo(sc, exp.to);
         if (ex.op == EXP.error)
         {
@@ -11727,8 +11758,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         result = res;
 
-        if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) &&
-            sc.needsCodegen())
+        if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) && sc.needsCodegen())
         {
             // if aa ordering is triggered, `res` will be a CommaExp
             // and `.e2` will be the rewritten original expression.
@@ -11772,7 +11802,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 arguments.push(exp.e1);
                 arguments.push(exp.e2);
                 Expression ce = new CallExp(exp.loc, id, arguments);
-                *output = ce.expressionSemantic(sc);
+
+                exp.lowering = ce.expressionSemantic(sc);
+                *output = exp;
             }
             else if (exp.op == EXP.concatenateElemAssign)
             {
@@ -11792,15 +11824,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 }
 
                 Identifier hook = global.params.tracegc ? Id._d_arrayappendcTXTrace : Id._d_arrayappendcTX;
-                if (!verifyHookExist(exp.loc, *sc, Id._d_arrayappendcTXImpl, "appending element to arrays", Id.object))
+                if (!verifyHookExist(exp.loc, *sc, hook, "appending element to arrays", Id.object))
                     return setError();
 
-                // Lower to object._d_arrayappendcTXImpl!(typeof(e1))._d_arrayappendcTX{,Trace}(e1, 1), e1[$-1]=e2
+                // Lower to object._d_arrayappendcTX{,Trace}(e1, 1), e1[$-1]=e2
                 Expression id = new IdentifierExp(exp.loc, Id.empty);
                 id = new DotIdExp(exp.loc, id, Id.object);
-                auto tiargs = new Objects();
-                tiargs.push(exp.e1.type);
-                id = new DotTemplateInstanceExp(exp.loc, id, Id._d_arrayappendcTXImpl, tiargs);
                 id = new DotIdExp(exp.loc, id, hook);
 
                 auto arguments = new Expressions();
@@ -11827,11 +11856,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 {
                     /* Before the template hook, this check was performed in e2ir.d
                      * for expressions like `a ~= a[$-1]`. Here, $ will be modified
-                     * by calling `_d_arrayappendcT`, so we need to save `a[$-1]` in
+                     * by calling `_d_arrayappendcTX`, so we need to save `a[$-1]` in
                      * a temporary variable.
                      */
                     value2 = extractSideEffect(sc, "__appendtmp", eValue2, value2, true);
-                    exp.e2 = value2;
 
                     // `__appendtmp*` will be destroyed together with the array `exp.e1`.
                     auto vd = eValue2.isDeclarationExp().declaration.isVarDeclaration();
@@ -11847,13 +11875,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 auto e0 = Expression.combine(ce, ae).expressionSemantic(sc);
                 e0 = Expression.combine(e0, value1);
                 e0 = Expression.combine(eValue1, e0);
-
                 e0 = Expression.combine(eValue2, e0);
 
-                *output = e0.expressionSemantic(sc);
+                exp.lowering = e0.expressionSemantic(sc);
+                *output = exp;
             }
         }
-
     }
 
     override void visit(AddExp exp)
@@ -15210,15 +15237,21 @@ Expression addDtorHook(Expression e, Scope* sc)
  * Params:
  *     _this = expression to convert
  *     sc = scope
+ *     action = for error messages, what the lvalue is needed for (e.g. take address of for `&x`, modify for `x++`)
  * Returns: converted expression, or `ErrorExp` on error
 */
-extern(C++) Expression toLvalue(Expression _this, Scope* sc)
+extern(C++) Expression toLvalue(Expression _this, Scope* sc, const(char)* action)
 {
-    return toLvalueImpl(_this, sc, _this);
+    return toLvalueImpl(_this, sc, action, _this);
 }
 
 // e = original un-lowered expression for error messages, in case of recursive calls
-private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) {
+private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action, Expression e)
+{
+    if (!action)
+        action = "create lvalue of";
+
+    assert(e);
     Expression visit(Expression _this)
     {
         // BinaryAssignExp does not have an EXP associated
@@ -15230,9 +15263,11 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) {
             _this.loc = e.loc;
 
         if (e.op == EXP.type)
-            error(_this.loc, "`%s` is a `%s` definition and cannot be modified", e.type.toChars(), e.type.kind());
+            error(_this.loc, "cannot %s type `%s`", action, e.type.toChars());
+        else if (e.op == EXP.template_)
+            error(_this.loc, "cannot %s template `%s`, perhaps instantiate it first", action, e.toChars());
         else
-            error(_this.loc, "`%s` is not an lvalue and cannot be modified", e.toChars());
+            error(_this.loc, "cannot %s expression `%s` because it is not an lvalue", action, e.toChars());
 
         return ErrorExp.get();
     }
@@ -15241,7 +15276,7 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) {
     {
         if (!_this.loc.isValid())
             _this.loc = e.loc;
-        error(e.loc, "cannot modify constant `%s`", e.toChars());
+        error(e.loc, "cannot %s constant `%s`", action, e.toChars());
         return ErrorExp.get();
     }
 
@@ -15285,22 +15320,22 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) {
         auto var = _this.var;
         if (var.storage_class & STC.manifest)
         {
-            error(_this.loc, "manifest constant `%s` cannot be modified", var.toChars());
+            error(_this.loc, "cannot %s manifest constant `%s`", action, var.toChars());
             return ErrorExp.get();
         }
         if (var.storage_class & STC.lazy_ && !_this.delegateWasExtracted)
         {
-            error(_this.loc, "lazy variable `%s` cannot be modified", var.toChars());
+            error(_this.loc, "cannot %s lazy variable `%s`", action, var.toChars());
             return ErrorExp.get();
         }
         if (var.ident == Id.ctfe)
         {
-            error(_this.loc, "cannot modify compiler-generated variable `__ctfe`");
+            error(_this.loc, "cannot %s compiler-generated variable `__ctfe`", action);
             return ErrorExp.get();
         }
         if (var.ident == Id.dollar) // https://issues.dlang.org/show_bug.cgi?id=13574
         {
-            error(_this.loc, "cannot modify operator `$`");
+            error(_this.loc, "cannot %s operator `$`", action);
             return ErrorExp.get();
         }
         return _this;
@@ -15370,7 +15405,7 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) {
 
     Expression visitVectorArray(VectorArrayExp _this)
     {
-        _this.e1 = _this.e1.toLvalueImpl(sc, e);
+        _this.e1 = _this.e1.toLvalueImpl(sc, action, e);
         return _this;
     }
 
@@ -15389,19 +15424,19 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) {
 
     Expression visitComma(CommaExp _this)
     {
-        _this.e2 = _this.e2.toLvalue(sc);
+        _this.e2 = _this.e2.toLvalue(sc, action);
         return _this;
     }
 
     Expression visitDelegatePointer(DelegatePtrExp _this)
     {
-        _this.e1 = _this.e1.toLvalueImpl(sc, e);
+        _this.e1 = _this.e1.toLvalueImpl(sc, action, e);
         return _this;
     }
 
     Expression visitDelegateFuncptr(DelegateFuncptrExp _this)
     {
-        _this.e1 = _this.e1.toLvalueImpl(sc, e);
+        _this.e1 = _this.e1.toLvalueImpl(sc, action, e);
         return _this;
     }
 
@@ -15430,8 +15465,8 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) {
     {
         // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
         CondExp e = cast(CondExp)(_this.copy());
-        e.e1 = _this.e1.toLvalue(sc).addressOf();
-        e.e2 = _this.e2.toLvalue(sc).addressOf();
+        e.e1 = _this.e1.toLvalue(sc, action).addressOf();
+        e.e2 = _this.e2.toLvalue(sc, action).addressOf();
         e.type = _this.type.pointerTo();
         return new PtrExp(_this.loc, e, _this.type);
 
@@ -15634,12 +15669,13 @@ extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc)
 // e = original / un-lowered expression to print in error messages
 private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression e)
 {
+    assert(e);
     Expression visit(Expression exp)
     {
         //printf("Expression::modifiableLvalue() %s, type = %s\n", exp.toChars(), exp.type.toChars());
         // See if this expression is a modifiable lvalue (i.e. not const)
         if (exp.isBinAssignExp())
-            return exp.toLvalue(sc);
+            return exp.toLvalue(sc, "modify");
 
         auto type = exp.type;
         if (checkModifiable(exp, sc) == Modifiable.yes)
@@ -15672,7 +15708,7 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression
                 return ErrorExp.get();
             }
         }
-        return exp.toLvalueImpl(sc, e);
+        return exp.toLvalueImpl(sc, "modify", e);
     }
 
     Expression visitString(StringExp exp)
@@ -15762,7 +15798,7 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression
         }
         exp.e1 = exp.e1.modifiableLvalue(sc);
         exp.e2 = exp.e2.modifiableLvalue(sc);
-        return exp.toLvalue(sc);
+        return exp.toLvalue(sc, "modify");
     }
 
     switch(_this.op)
@@ -15803,7 +15839,7 @@ bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
     }
     if (sc.func && !sc.intypeof && !v.isDataseg())
     {
-        if (global.params.useDIP1000 != FeatureState.enabled &&
+        if (sc.useDIP1000 != FeatureState.enabled &&
             !(v.storage_class & STC.temp) &&
             sc.setUnsafe(false, exp.loc, "cannot take address of local `%s` in `@safe` function `%s`", v, sc.func))
         {
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index edf113e2160..351faa471f2 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -3241,13 +3241,6 @@ unittest
     assert(mismatches.isMutable);
 }
 
-private const(char)* prependSpace(const(char)* str)
-{
-    if (!str || !*str) return "";
-
-    return (" " ~ str.toDString() ~ "\0").ptr;
-}
-
 /// Flag used by $(LREF resolveFuncCall).
 enum FuncResolveFlag : ubyte
 {
@@ -3361,14 +3354,11 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
         const(char)* lastprms = parametersTypeToChars(tf1.parameterList);
         const(char)* nextprms = parametersTypeToChars(tf2.parameterList);
 
-        const(char)* mod1 = prependSpace(MODtoChars(tf1.mod));
-        const(char)* mod2 = prependSpace(MODtoChars(tf2.mod));
-
         .error(loc, "`%s.%s` called with argument types `%s` matches both:\n%s:     `%s%s%s`\nand:\n%s:     `%s%s%s`",
             s.parent.toPrettyChars(), s.ident.toChars(),
             fargsBuf.peekChars(),
-            m.lastf.loc.toChars(), m.lastf.toPrettyChars(), lastprms, mod1,
-            m.nextf.loc.toChars(), m.nextf.toPrettyChars(), nextprms, mod2);
+            m.lastf.loc.toChars(), m.lastf.toPrettyChars(), lastprms, tf1.modToChars(),
+            m.nextf.loc.toChars(), m.nextf.toPrettyChars(), nextprms, tf2.modToChars());
         return null;
     }
 
@@ -3422,15 +3412,25 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
     if (!tf)
         tf = fd.originalType.toTypeFunction();
 
-    if (tthis && !MODimplicitConv(tthis.mod, tf.mod)) // modifier mismatch
+    // modifier mismatch
+    if (tthis && (fd.isCtorDeclaration() ?
+        !MODimplicitConv(tf.mod, tthis.mod) :
+        !MODimplicitConv(tthis.mod, tf.mod)))
     {
         OutBuffer thisBuf, funcBuf;
         MODMatchToBuffer(&thisBuf, tthis.mod, tf.mod);
         auto mismatches = MODMatchToBuffer(&funcBuf, tf.mod, tthis.mod);
         if (hasOverloads)
         {
-            .error(loc, "none of the overloads of `%s` are callable using a %sobject",
-                   fd.ident.toChars(), thisBuf.peekChars());
+            OutBuffer buf;
+            buf.argExpTypesToCBuffer(fargs);
+            if (fd.isCtorDeclaration())
+                .error(loc, "none of the overloads of `%s` can construct a %sobject with argument types `(%s)`",
+                    fd.toChars(), thisBuf.peekChars(), buf.peekChars());
+            else
+                .error(loc, "none of the overloads of `%s` are callable using a %sobject with argument types `(%s)`",
+                    fd.toChars(), thisBuf.peekChars(), buf.peekChars());
+
             if (!global.gag || global.params.v.showGaggedErrors)
                 printCandidates(loc, fd, sc.isDeprecated());
             return null;
@@ -3447,8 +3447,12 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
             return null;
         }
 
-        .error(loc, "%smethod `%s` is not callable using a %sobject",
-               funcBuf.peekChars(), fd.toPrettyChars(), thisBuf.peekChars());
+        if (fd.isCtorDeclaration())
+            .error(loc, "%s%s `%s` cannot construct a %sobject",
+                   funcBuf.peekChars(), fd.kind(), fd.toPrettyChars(), thisBuf.peekChars());
+        else
+            .error(loc, "%smethod `%s` is not callable using a %sobject",
+                   funcBuf.peekChars(), fd.toPrettyChars(), thisBuf.peekChars());
 
         if (mismatches.isNotShared)
             .errorSupplemental(fd.loc, "Consider adding `shared` here");
@@ -3535,11 +3539,17 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
             if (!print)
                 return true;
             auto tf = cast(TypeFunction) fd.type;
+            OutBuffer buf;
+            buf.writestring(fd.toPrettyChars());
+            buf.writestring(parametersTypeToChars(tf.parameterList));
+            if (tf.mod)
+            {
+                buf.writeByte(' ');
+                buf.MODtoBuffer(tf.mod);
+            }
             .errorSupplemental(fd.loc,
-                    printed ? "                `%s%s`" :
-                    single_candidate ? "Candidate is: `%s%s`" : "Candidates are: `%s%s`",
-                    fd.toPrettyChars(),
-                parametersTypeToChars(tf.parameterList));
+                printed ? "                `%s`" :
+                single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`", buf.peekChars());
         }
         else if (auto td = s.isTemplateDeclaration())
         {
@@ -4621,7 +4631,14 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)
       case default_:
         if (!sc.func)
             return false;
-        if (!sc.func.isSafeBypassingInference() && !sc.func.safetyViolation)
+        if (sc.func.isSafeBypassingInference())
+        {
+            if (!gag)
+            {
+                warning(loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
+            }
+        }
+        else if (!sc.func.safetyViolation)
         {
             import dmd.func : AttributeViolation;
             sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2);
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 8325081dbd2..ac2dda3e89f 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -1943,7 +1943,7 @@ private void visitTemplateParameters(TemplateParameters* parameters, ref OutBuff
     {
         if (i)
             buf.writestring(", ");
-        p.templateParameterToBuffer(buf, &hgs);
+        toCBuffer(p, buf, hgs);
     }
 }
 
@@ -2885,10 +2885,10 @@ void floatToBuffer(Type type, const real_t value, ref OutBuffer buf, const bool
     }
 }
 
-private void templateParameterToBuffer(TemplateParameter tp, ref OutBuffer buf, HdrGenState* hgs)
+void toCBuffer(const TemplateParameter tp, ref OutBuffer buf, ref HdrGenState hgs)
 {
-    scope v = new TemplateParameterPrettyPrintVisitor(&buf, hgs);
-    tp.accept(v);
+    scope v = new TemplateParameterPrettyPrintVisitor(&buf, &hgs);
+    (cast() tp).accept(v);
 }
 
 private extern (C++) final class TemplateParameterPrettyPrintVisitor : Visitor
@@ -3262,12 +3262,6 @@ void argExpTypesToCBuffer(ref OutBuffer buf, Expressions* arguments)
     }
 }
 
-void toCBuffer(const TemplateParameter tp, ref OutBuffer buf, ref HdrGenState hgs)
-{
-    scope v = new TemplateParameterPrettyPrintVisitor(&buf, &hgs);
-    (cast() tp).accept(v);
-}
-
 void arrayObjectsToBuffer(ref OutBuffer buf, Objects* objects)
 {
     if (!objects || !objects.length)
@@ -3837,7 +3831,7 @@ private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, Te
         {
             if (i)
                 buf.writestring(", ");
-            p.templateParameterToBuffer(buf, hgs);
+            toCBuffer(p, buf, *hgs);
         }
         buf.writeByte(')');
     }
@@ -3862,6 +3856,11 @@ private void initializerToBuffer(Initializer inx, ref OutBuffer buf, HdrGenState
         buf.writestring("void");
     }
 
+    void visitDefault(DefaultInitializer iz)
+    {
+        buf.writestring("{ }");
+    }
+
     void visitStruct(StructInitializer si)
     {
         //printf("StructInitializer::toCBuffer()\n");
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 5fcda91b435..32221d94744 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -323,6 +323,8 @@ immutable Msgtable[] msgtable =
     { "_d_newitemTTrace" },
     { "_d_newarrayT" },
     { "_d_newarrayTTrace" },
+    { "_d_newarraymTX" },
+    { "_d_newarraymTXTrace" },
     { "_d_assert_fail" },
     { "dup" },
     { "_aaApply" },
@@ -366,7 +368,6 @@ immutable Msgtable[] msgtable =
     { "_d_arraysetlengthTTrace"},
     { "_d_arrayappendT" },
     { "_d_arrayappendTTrace" },
-    { "_d_arrayappendcTXImpl" },
     { "_d_arrayappendcTX" },
     { "_d_arrayappendcTXTrace" },
     { "_d_arraycatnTX" },
diff --git a/gcc/d/dmd/import.h b/gcc/d/dmd/import.h
index 31ee61a65fb..aeb3621f1eb 100644
--- a/gcc/d/dmd/import.h
+++ b/gcc/d/dmd/import.h
@@ -43,9 +43,7 @@ public:
     Import *syntaxCopy(Dsymbol *s) override; // copy only syntax trees
     void importAll(Scope *sc) override;
     Dsymbol *toAlias() override;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     void setScope(Scope* sc) override;
-    Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
     bool overloadInsert(Dsymbol *s) override;
 
     Import *isImport() override { return this; }
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index 98ac9038a0a..2c7699b45ec 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/dmd/importc.d
@@ -20,6 +20,7 @@ import dmd.dcast;
 import dmd.declaration;
 import dmd.dscope;
 import dmd.dsymbol;
+import dmd.dsymbolsem;
 import dmd.errors;
 import dmd.expression;
 import dmd.expressionsem;
diff --git a/gcc/d/dmd/init.d b/gcc/d/dmd/init.d
index ebcd011f8a1..e48410082bd 100644
--- a/gcc/d/dmd/init.d
+++ b/gcc/d/dmd/init.d
@@ -68,6 +68,11 @@ extern (C++) class Initializer : ASTNode
         return kind == InitKind.void_ ? cast(inout VoidInitializer)cast(void*)this : null;
     }
 
+    final inout(DefaultInitializer) isDefaultInitializer() inout @nogc nothrow pure
+    {
+        return kind == InitKind.default_ ? cast(inout DefaultInitializer)cast(void*)this : null;
+    }
+
     final inout(StructInitializer) isStructInitializer() inout @nogc nothrow pure
     {
         return kind == InitKind.struct_ ? cast(inout StructInitializer)cast(void*)this : null;
@@ -111,6 +116,24 @@ extern (C++) final class VoidInitializer : Initializer
     }
 }
 
+/***********************************************************
+ * The C23 default initializer `{ }`
+ */
+extern (C++) final class DefaultInitializer : Initializer
+{
+    Type type;      // type that this will initialize to
+
+    extern (D) this(const ref Loc loc) @safe
+    {
+        super(loc, InitKind.default_);
+    }
+
+    override void accept(Visitor v)
+    {
+        v.visit(this);
+    }
+}
+
 /***********************************************************
  */
 extern (C++) final class ErrorInitializer : Initializer
@@ -266,6 +289,11 @@ Initializer syntaxCopy(Initializer inx)
         return new VoidInitializer(vi.loc);
     }
 
+    static Initializer visitDefault(DefaultInitializer vi)
+    {
+        return new DefaultInitializer(vi.loc);
+    }
+
     static Initializer visitError(ErrorInitializer vi)
     {
         return vi;
@@ -352,6 +380,7 @@ mixin template VisitInitializer(Result)
         final switch (init.kind)
         {
             case InitKind.void_:    mixin(visitCase("Void"));    break;
+            case InitKind.default_: mixin(visitCase("Default")); break;
             case InitKind.error:    mixin(visitCase("Error"));   break;
             case InitKind.struct_:  mixin(visitCase("Struct"));  break;
             case InitKind.array:    mixin(visitCase("Array"));   break;
diff --git a/gcc/d/dmd/init.h b/gcc/d/dmd/init.h
index 67d0527a3b2..21bd07f4f39 100644
--- a/gcc/d/dmd/init.h
+++ b/gcc/d/dmd/init.h
@@ -20,6 +20,7 @@ class Expression;
 class Type;
 class ErrorInitializer;
 class VoidInitializer;
+class DefaultInitializer;
 class StructInitializer;
 class ArrayInitializer;
 class ExpInitializer;
@@ -37,6 +38,7 @@ public:
 
     ErrorInitializer   *isErrorInitializer();
     VoidInitializer    *isVoidInitializer();
+    DefaultInitializer *isDefaultInitializer();
     StructInitializer  *isStructInitializer();
     ArrayInitializer   *isArrayInitializer();
     ExpInitializer     *isExpInitializer();
@@ -53,6 +55,14 @@ public:
     void accept(Visitor *v) override { v->visit(this); }
 };
 
+class DefaultInitializer final : public Initializer
+{
+public:
+    Type *type;         // type that this will initialize to
+
+    void accept(Visitor *v) override { v->visit(this); }
+};
+
 class ErrorInitializer final : public Initializer
 {
 public:
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index 139db0f59e9..76c2d8916b0 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -24,6 +24,7 @@ import dmd.dinterpret;
 import dmd.dscope;
 import dmd.dstruct;
 import dmd.dsymbol;
+import dmd.dsymbolsem;
 import dmd.dtemplate;
 import dmd.errors;
 import dmd.expression;
@@ -106,6 +107,7 @@ Expression toAssocArrayLiteral(ArrayInitializer ai)
  */
 extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret)
 {
+    //printf("initializerSemantic() tx: %p %s\n", tx, tx.toChars());
     Type t = tx;
 
     static Initializer err()
@@ -119,6 +121,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
         return i;
     }
 
+    Initializer visitDefault(DefaultInitializer i)
+    {
+        i.type = t;
+        return i;
+    }
+
     Initializer visitError(ErrorInitializer i)
     {
         return i;
@@ -1017,6 +1025,12 @@ Initializer inferType(Initializer init, Scope* sc)
         return new ErrorInitializer();
     }
 
+    Initializer visitDefault(DefaultInitializer i)
+    {
+        error(i.loc, "cannot infer type from default initializer");
+        return new ErrorInitializer();
+    }
+
     Initializer visitError(ErrorInitializer i)
     {
         return i;
@@ -1175,6 +1189,11 @@ extern (C++) Expression initializerToExpression(Initializer init, Type itype = n
         return null;
     }
 
+    Expression visitDefault(DefaultInitializer di)
+    {
+        return di.type ? di.type.defaultInit(Loc.initial, isCfile) : null;
+    }
+
     Expression visitError(ErrorInitializer)
     {
         return ErrorExp.get();
diff --git a/gcc/d/dmd/lambdacomp.d b/gcc/d/dmd/lambdacomp.d
index ec070d8ec0b..d19d435f240 100644
--- a/gcc/d/dmd/lambdacomp.d
+++ b/gcc/d/dmd/lambdacomp.d
@@ -22,6 +22,7 @@ import dmd.astenums;
 import dmd.declaration;
 import dmd.denum;
 import dmd.dsymbol;
+import dmd.dsymbolsem;
 import dmd.dtemplate;
 import dmd.expression;
 import dmd.func;
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index 6e8153d485a..92efc1656da 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -43,7 +43,6 @@ public:
 
     bool isAncestorPackageOf(const Package * const pkg) const;
 
-    Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
     void accept(Visitor *v) override { v->visit(this); }
 
     Module *isPackageMod();
@@ -124,7 +123,6 @@ public:
     Module *parse();    // syntactic parse
     void importAll(Scope *sc) override;
     int needModuleInfo();
-    Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
     bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0) override;
     Dsymbol *symtabInsert(Dsymbol *s) override;
     static void runDeferredSemantic();
diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index 59bf1d5d1d5..e59b01019f4 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -108,12 +108,6 @@ public:
                 return;
             f.printGCUsage(e.loc, "setting `length` may cause a GC allocation");
         }
-        else if (fd.ident == Id._d_arrayappendT || fd.ident == Id._d_arrayappendcTX)
-        {
-            if (setGC(e, "cannot use operator `~=` in `@nogc` %s `%s`"))
-                return;
-            f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation");
-        }
     }
 
     override void visit(ArrayLiteralExp e)
@@ -187,20 +181,14 @@ public:
 
     override void visit(CatAssignExp e)
     {
-        /* CatAssignExp will exist in `__traits(compiles, ...)` and in the `.e1` branch of a `__ctfe ? :` CondExp.
-         * The other branch will be `_d_arrayappendcTX(e1, 1), e1[$-1]=e2` which will generate the warning about
-         * GC usage. See visit(CallExp).
-         */
         if (checkOnly)
         {
             err = true;
             return;
         }
-        if (f.setGC(e.loc, null))
-        {
-            err = true;
+        if (setGC(e, "cannot use operator `~=` in `@nogc` %s `%s`"))
             return;
-        }
+        f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation");
     }
 
     override void visit(CatExp e)
diff --git a/gcc/d/dmd/nspace.d b/gcc/d/dmd/nspace.d
index 2d3367af804..a49e0bf0cc2 100644
--- a/gcc/d/dmd/nspace.d
+++ b/gcc/d/dmd/nspace.d
@@ -85,33 +85,6 @@ extern (C++) final class Nspace : ScopeDsymbol
         return ns;
     }
 
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        ScopeDsymbol.addMember(sc, sds);
-
-        if (members)
-        {
-            if (!symtab)
-                symtab = new DsymbolTable();
-            // The namespace becomes 'imported' into the enclosing scope
-            for (Scope* sce = sc; 1; sce = sce.enclosing)
-            {
-                ScopeDsymbol sds2 = sce.scopesym;
-                if (sds2)
-                {
-                    sds2.importScope(this, Visibility(Visibility.Kind.public_));
-                    break;
-                }
-            }
-            assert(sc);
-            sc = sc.push(this);
-            sc.linkage = LINK.cpp; // namespaces default to C++ linkage
-            sc.parent = this;
-            members.foreachDsymbol(s => s.addMember(sc, this));
-            sc.pop();
-        }
-    }
-
     override void setScope(Scope* sc)
     {
         ScopeDsymbol.setScope(sc);
@@ -126,22 +99,6 @@ extern (C++) final class Nspace : ScopeDsymbol
         }
     }
 
-    override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
-    {
-        //printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars());
-        if (_scope && !symtab)
-            dsymbolSemantic(this, _scope);
-
-        if (!members || !symtab) // opaque or semantic() is not yet called
-        {
-            if (!(flags & IgnoreErrors))
-                .error(loc, "%s `%s` is forward referenced when looking for `%s`", kind, toPrettyChars, ident.toChars());
-            return null;
-        }
-
-        return ScopeDsymbol.search(loc, ident, flags);
-    }
-
     override bool hasPointers()
     {
         //printf("Nspace::hasPointers() %s\n", toChars());
diff --git a/gcc/d/dmd/nspace.h b/gcc/d/dmd/nspace.h
index e9fb7bdc777..7d30402c595 100644
--- a/gcc/d/dmd/nspace.h
+++ b/gcc/d/dmd/nspace.h
@@ -21,9 +21,7 @@ class Nspace final : public ScopeDsymbol
   public:
     Expression *identExp;
     Nspace *syntaxCopy(Dsymbol *s) override;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     void setScope(Scope *sc) override;
-    Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
     bool hasPointers() override;
     void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override;
     const char *kind() const override;
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index b445b7b707b..b7bc9257b3e 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -23,6 +23,7 @@ import dmd.declaration;
 import dmd.dscope;
 import dmd.dstruct;
 import dmd.dsymbol;
+import dmd.dsymbolsem;
 import dmd.dtemplate;
 import dmd.errors;
 import dmd.expression;
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 69028fac21d..a9791684df4 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -928,6 +928,14 @@ Expression optimize(Expression e, int result, bool keepLvalue = false)
         }
     }
 
+    void visitCatAssign(CatAssignExp e)
+    {
+        if (auto lowering = e.lowering)
+            optimize(lowering, result, keepLvalue);
+        else
+            visitBinAssign(e);
+    }
+
     void visitBin(BinExp e)
     {
         //printf("BinExp::optimize(result = %d) %s\n", result, e.toChars());
@@ -1392,9 +1400,9 @@ Expression optimize(Expression e, int result, bool keepLvalue = false)
             case EXP.leftShiftAssign:
             case EXP.rightShiftAssign:
             case EXP.unsignedRightShiftAssign:
+            case EXP.concatenateDcharAssign: visitBinAssign(ex.isBinAssignExp()); break;
             case EXP.concatenateElemAssign:
-            case EXP.concatenateDcharAssign:
-            case EXP.concatenateAssign: visitBinAssign(ex.isBinAssignExp()); break;
+            case EXP.concatenateAssign:      visitCatAssign(cast(CatAssignExp) ex); break;
 
             case EXP.minusMinus:
             case EXP.plusPlus:
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 51e522d71e4..f9d174ab14f 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -4878,30 +4878,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 AST.Declaration v;
                 AST.Dsymbol s;
 
-                // try to parse function type:
-                // TypeCtors? BasicType ( Parameters ) MemberFunctionAttributes
                 bool attributesAppended;
                 const StorageClass funcStc = parseTypeCtor();
-                Token* tlu = &token;
                 Token* tk;
-                if (token.value != TOK.function_ &&
-                    token.value != TOK.delegate_ &&
-                    isBasicType(&tlu) && tlu &&
-                    tlu.value == TOK.leftParenthesis)
-                {
-                    AST.Type tret = parseBasicType();
-                    auto parameterList = parseParameterList(null);
-
-                    parseAttributes();
-                    if (udas)
-                        error("user-defined attributes not allowed for `alias` declarations");
-
-                    attributesAppended = true;
-                    storage_class = appendStorageClass(storage_class, funcStc);
-                    AST.Type tf = new AST.TypeFunction(parameterList, tret, link, storage_class);
-                    v = new AST.AliasDeclaration(loc, ident, tf);
-                }
-                else if (token.value == TOK.function_ ||
+                // function literal?
+                if (token.value == TOK.function_ ||
                     token.value == TOK.delegate_ ||
                     token.value == TOK.leftParenthesis &&
                         skipAttributes(peekPastParen(&token), &tk) &&
@@ -4911,10 +4892,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     token.value == TOK.ref_ && peekNext() == TOK.leftParenthesis &&
                         skipAttributes(peekPastParen(peek(&token)), &tk) &&
                         (tk.value == TOK.goesTo || tk.value == TOK.leftCurly) ||
-                    token.value == TOK.auto_ && peekNext() == TOK.ref_ &&
-                        peekNext2() == TOK.leftParenthesis &&
-                        skipAttributes(peekPastParen(peek(peek(&token))), &tk) &&
-                        (tk.value == TOK.goesTo || tk.value == TOK.leftCurly)
+                    token.value == TOK.auto_ &&
+                        (peekNext() == TOK.leftParenthesis || // for better error
+                            peekNext() == TOK.ref_ &&
+                            peekNext2() == TOK.leftParenthesis)
                    )
                 {
                     // function (parameters) { statements... }
@@ -4955,21 +4936,46 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 }
                 else
                 {
-                    parseAttributes();
                     // type
+                    parseAttributes();
                     if (udas)
                         error("user-defined attributes not allowed for `alias` declarations");
 
-                    auto t = parseType();
+                    auto t = parseBasicType();
+                    t = parseTypeSuffixes(t);
+                    if (token.value == TOK.identifier)
+                    {
+                        error("unexpected identifier `%s` after `%s`",
+                            token.ident.toChars(), t.toChars());
+                        nextToken();
+                    }
+                    else if (token.value == TOK.leftParenthesis)
+                    {
+                        // function type:
+                        // StorageClasses Type ( Parameters ) MemberFunctionAttributes
+                        auto parameterList = parseParameterList(null);
+                        udas = null;
+                        parseStorageClasses(storage_class, link, setAlignment, ealign, udas, linkloc);
+                        if (udas)
+                            error("user-defined attributes not allowed for `alias` declarations");
+
+                        attributesAppended = true;
+                        // Note: method types can have a TypeCtor attribute
+                        storage_class = appendStorageClass(storage_class, funcStc);
+                        t = new AST.TypeFunction(parameterList, t, link, storage_class);
+                    }
 
                     // Disallow meaningless storage classes on type aliases
                     if (storage_class)
                     {
                         // Don't raise errors for STC that are part of a function/delegate type, e.g.
                         // `alias F = ref pure nothrow @nogc @safe int function();`
-                        auto tp = t.isTypePointer;
-                        const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate;
-                        const remStc = isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class;
+                        const remStc = t.isTypeFunction ?
+                            storage_class & ~(STC.FUNCATTR | STC.TYPECTOR) : {
+                            auto tp = t.isTypePointer;
+                            const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate;
+                            return isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class;
+                        }();
 
                         if (remStc)
                         {
@@ -7217,6 +7223,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         return false;
     }
 
+    // pt = test token. If found, pt is set to the token after BasicType
     private bool isBasicType(Token** pt)
     {
         // This code parallels parseBasicType()
diff --git a/gcc/d/dmd/parsetimevisitor.d b/gcc/d/dmd/parsetimevisitor.d
index a4a9434334e..3d0a5854625 100644
--- a/gcc/d/dmd/parsetimevisitor.d
+++ b/gcc/d/dmd/parsetimevisitor.d
@@ -298,5 +298,6 @@ public:
     void visit(AST.StructInitializer i) { visit(cast(AST.Initializer)i); }
     void visit(AST.ArrayInitializer i) { visit(cast(AST.Initializer)i); }
     void visit(AST.VoidInitializer i) { visit(cast(AST.Initializer)i); }
+    void visit(AST.DefaultInitializer i) { visit(cast(AST.Initializer)i); }
     void visit(AST.CInitializer i) { visit(cast(AST.CInitializer)i); }
 }
diff --git a/gcc/d/dmd/scope.h b/gcc/d/dmd/scope.h
index 178542e37b0..2cac5f2941b 100644
--- a/gcc/d/dmd/scope.h
+++ b/gcc/d/dmd/scope.h
@@ -61,6 +61,9 @@ enum class SCOPE
     Cfile         = 0x0800,  // C semantics apply
     free          = 0x8000,  // is on free list
     fullinst      = 0x10000, // fully instantiate templates
+    ctfeBlock     = 0x20000, // inside a `if (__ctfe)` block
+    dip1000       = 0x40000, // dip1000 errors enabled for this scope
+    dip25         = 0x80000, // dip25 errors enabled for this scope
 };
 
 struct Scope
@@ -126,4 +129,6 @@ struct Scope
 
     AliasDeclaration *aliasAsg; // if set, then aliasAsg is being assigned a new value,
                                 // do not set wasRead for it
+
+    Dsymbol *search(const Loc &loc, Identifier *ident, Dsymbol **pscopesym, int flags = IgnoreNone);
 };
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index bf220f31d9b..c255701d767 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -918,7 +918,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                         if (f.isref)
                         {
                             // Function returns a reference
-                            exp = exp.toLvalue(sc2);
+                            exp = exp.toLvalue(sc2, "`ref` return");
                             checkReturnEscapeRef(sc2, exp, false);
                             exp = exp.optimize(WANTvalue, /*keepLvalue*/ true);
                         }
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index f8b2c26df7f..3873adc82ee 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -3801,7 +3801,7 @@ private extern(D) Expression applyOpApply(ForeachStatement fs, Expression flde,
 {
     version (none)
     {
-        if (global.params.useDIP1000 == FeatureState.enabled)
+        if (sc2.useDIP1000 == FeatureState.enabled)
         {
             message(loc, "To enforce `@safe`, the compiler allocates a closure unless `opApply()` uses `scope`");
         }
@@ -3809,7 +3809,7 @@ private extern(D) Expression applyOpApply(ForeachStatement fs, Expression flde,
     }
     else
     {
-        if (global.params.useDIP1000 == FeatureState.enabled)
+        if (sc2.useDIP1000 == FeatureState.enabled)
             ++(cast(FuncExp)flde).fd.tookAddressOf;  // allocate a closure unless the opApply() uses 'scope'
     }
     assert(tab.ty == Tstruct || tab.ty == Tclass);
diff --git a/gcc/d/dmd/staticassert.d b/gcc/d/dmd/staticassert.d
index 15c46b304ba..7f22c4c993a 100644
--- a/gcc/d/dmd/staticassert.d
+++ b/gcc/d/dmd/staticassert.d
@@ -52,11 +52,6 @@ extern (C++) final class StaticAssert : Dsymbol
         return new StaticAssert(loc, exp.syntaxCopy(), msgs ? Expression.arraySyntaxCopy(msgs) : null);
     }
 
-    override void addMember(Scope* sc, ScopeDsymbol sds)
-    {
-        // we didn't add anything
-    }
-
     override bool oneMember(Dsymbol* ps, Identifier ident)
     {
         //printf("StaticAssert::oneMember())\n");
diff --git a/gcc/d/dmd/staticassert.h b/gcc/d/dmd/staticassert.h
index 2b7d300f6af..c0d5363a414 100644
--- a/gcc/d/dmd/staticassert.h
+++ b/gcc/d/dmd/staticassert.h
@@ -21,7 +21,6 @@ public:
     Expressions *msg;
 
     StaticAssert *syntaxCopy(Dsymbol *s) override;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     bool oneMember(Dsymbol **ps, Identifier *ident) override;
     const char *kind() const override;
     StaticAssert *isStaticAssert() override { return this; }
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 79df7fde02b..0acadbb4604 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -32,6 +32,7 @@ import dmd.dsymbol;
 import dmd.dsymbolsem;
 import dmd.dtemplate;
 import dmd.errors;
+import dmd.errorsink;
 import dmd.expression;
 import dmd.expressionsem;
 import dmd.func;
@@ -92,43 +93,50 @@ private Dsymbol getDsymbolWithoutExpCtx(RootObject oarg)
 }
 
 /**
- * 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, ulong.max on error
+ * Fill an array of target size_t values that indicate possible pointer words in memory
+ *  if interpreted as the type given as argument.
+ *  One bit in the array per pointer-sized piece of memory
+ * Params:
+ *      loc = location for error messages
+ *      t = type to generate pointer bitmap from
+ *      data = array forming the bitmap
+ *      eSink = error message sink
+ * Returns:
+ *      size of the type `t` in bytes, ulong.max on error
  */
-ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data)
+ulong getTypePointerBitmap(Loc loc, Type t, ref Array!(ulong) data, ErrorSink eSink)
 {
-    ulong sz;
-    if (t.ty == Tclass && !(cast(TypeClass)t).sym.isInterfaceDeclaration())
-        sz = (cast(TypeClass)t).sym.AggregateDeclaration.size(loc);
-    else
-        sz = t.size(loc);
+    auto tc = t.isTypeClass();
+    const ulong sz = (tc && !tc.sym.isInterfaceDeclaration())
+        ? tc.sym.AggregateDeclaration.size(loc)
+        : t.size(loc);
     if (sz == SIZE_INVALID)
         return ulong.max;
 
-    const sz_size_t = Type.tsize_t.size(loc);
+    const sz_size_t = Type.tsize_t.size(loc); // size of target's size_t
+    assert(sz_size_t <= ulong.sizeof);
     if (sz > sz.max - sz_size_t)
     {
-        error(loc, "size overflow for type `%s`", t.toChars());
+        eSink.error(loc, "size overflow for type `%s`", t.toChars());
         return ulong.max;
     }
 
-    ulong bitsPerWord = sz_size_t * 8;
-    ulong cntptr = (sz + sz_size_t - 1) / sz_size_t;
-    ulong cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord;
+    const ulong bitsPerElement = sz_size_t * 8;  // bits used in each array element
+    const ulong cntptr = (sz + sz_size_t - 1) / sz_size_t; // pointers have same size as sz_size_t
+    const ulong length = (cntptr + bitsPerElement - 1) / bitsPerElement; // a bit per pointer
 
-    data.setDim(cast(size_t)cntdata);
+    data.setDim(cast(size_t)length);
     data.zero();
 
     ulong offset;
-    bool error;
+    bool error;    // sticky error indicator
 
     void visit(Type t)
     {
         void setpointer(ulong off)
         {
             ulong ptroff = off / sz_size_t;
-            (*data)[cast(size_t)(ptroff / (8 * sz_size_t))] |= 1L << (ptroff % (8 * sz_size_t));
+            data[cast(size_t)(ptroff / bitsPerElement)] |= 1L << (ptroff % bitsPerElement);
         }
 
         void visitType(Type t)
@@ -247,7 +255,7 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data)
         visit.VisitType(t);
     }
 
-    if (auto tc = t.isTypeClass())
+    if (auto tcx = t.isTypeClass())
     {
         // a "toplevel" class is treated as an instance, while TypeClass fields are treated as references
         void visitTopLevelClass(TypeClass t)
@@ -264,7 +272,7 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data)
             offset = classoff;
         }
 
-        visitTopLevelClass(tc);
+        visitTopLevelClass(tcx);
     }
     else
         visit(t);
@@ -281,28 +289,28 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data)
  *
  *  Returns: [T.sizeof, pointerbit0-31/63, pointerbit32/64-63/128, ...]
  */
-private Expression pointerBitmap(TraitsExp e)
+private Expression pointerBitmap(TraitsExp e, ErrorSink eSink)
 {
     if (!e.args || e.args.length != 1)
     {
-        error(e.loc, "a single type expected for trait pointerBitmap");
+        eSink.error(e.loc, "a single type expected for trait pointerBitmap");
         return ErrorExp.get();
     }
 
     Type t = getType((*e.args)[0]);
     if (!t)
     {
-        error(e.loc, "`%s` is not a type", (*e.args)[0].toChars());
+        eSink.error(e.loc, "`%s` is not a type", (*e.args)[0].toChars());
         return ErrorExp.get();
     }
 
     Array!(ulong) data;
-    ulong sz = getTypePointerBitmap(e.loc, t, &data);
+    const ulong sz = getTypePointerBitmap(e.loc, t, data, eSink);
     if (sz == ulong.max)
         return ErrorExp.get();
 
     auto exps = new Expressions(data.length + 1);
-    (*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t);
+    (*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t);       // [0] is size in bytes of t
     foreach (size_t i; 1 .. exps.length)
         (*exps)[i] = new IntegerExp(e.loc, data[cast(size_t) (i - 1)], Type.tsize_t);
 
@@ -472,13 +480,13 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
     }
     if (e.ident == Id.isAbstractClass)
     {
-        return isTypeX(t => t.toBasetype().ty == Tclass &&
-                            (cast(TypeClass)t.toBasetype()).sym.isAbstract());
+        return isTypeX(t => t.toBasetype().isTypeClass() &&
+                            t.toBasetype().isTypeClass().sym.isAbstract());
     }
     if (e.ident == Id.isFinalClass)
     {
-        return isTypeX(t => t.toBasetype().ty == Tclass &&
-                            ((cast(TypeClass)t.toBasetype()).sym.storage_class & STC.final_) != 0);
+        return isTypeX(t => t.toBasetype().isTypeClass() &&
+                            (t.toBasetype().isTypeClass().sym.storage_class & STC.final_) != 0);
     }
     if (e.ident == Id.isTemplate)
     {
@@ -508,7 +516,8 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         }
 
         Type tb = t.baseElemOf();
-        if (auto sd = tb.ty == Tstruct ? (cast(TypeStruct)tb).sym : null)
+        auto ts = tb.isTypeStruct();
+        if (auto sd = ts ? ts.sym : null)
         {
             return sd.isPOD() ? True() : False();
         }
@@ -529,7 +538,8 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         }
 
         Type tb = t.baseElemOf();
-        if (auto sd = tb.ty == Tstruct ? (cast(TypeStruct)tb).sym : null)
+        auto ts = tb.isTypeStruct();
+        if (auto sd = ts ? ts.sym : null)
         {
             return (e.ident == Id.hasPostblit) ? (sd.postblit ? True() : False())
                  : (sd.hasCopyCtor ? True() : False());
@@ -793,10 +803,10 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
                 {
                     if (auto p = s.toParent())         // `C`'s parent is `C!2`, believe it or not
                     {
-                        if (p.isTemplateInstance())    // `C!2` is a template instance
+                        if (auto ti = p.isTemplateInstance())    // `C!2` is a template instance
                         {
                             s = p;                     // `C!2`'s parent is `T1`
-                            auto td = (cast(TemplateInstance)p).tempdecl;
+                            auto td = ti.tempdecl;
                             if (td)
                                 s = td;                // get the declaration context just in case there's two contexts
                         }
@@ -1297,7 +1307,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
         if (fd && fd.parent && fd.parent.isTemplateInstance)
         {
             fd.functionSemantic3();
-            tf = cast(TypeFunction)fd.type;
+            tf = fd.type.isTypeFunction();
         }
 
         auto mods = new Expressions();
@@ -1738,9 +1748,9 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
                 ex = ex.expressionSemantic(sc2);
                 ex = resolvePropertiesOnly(sc2, ex);
                 ex = ex.optimize(WANTvalue);
-                if (sc2.func && sc2.func.type.ty == Tfunction)
+                if (sc2.func && sc2.func.type.isTypeFunction())
                 {
-                    const tf = cast(TypeFunction)sc2.func.type;
+                    const tf = sc2.func.type.isTypeFunction();
                     err |= tf.isnothrow && canThrow(ex, sc2.func, null);
                 }
                 ex = checkGC(sc2, ex);
@@ -1868,7 +1878,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
     }
     if (e.ident == Id.getPointerBitmap)
     {
-        return pointerBitmap(e);
+        return pointerBitmap(e, global.errorSink);
     }
     if (e.ident == Id.initSymbol)
     {
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 4a4c5d4f7f0..8795002cd15 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -1099,7 +1099,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
             if (isRefOrOut && !isAuto &&
                 !(global.params.previewIn && (fparam.storageClass & STC.in_)) &&
                 global.params.rvalueRefParam != FeatureState.enabled)
-                e = e.toLvalue(sc);
+                e = e.toLvalue(sc, "create default argument for `ref` / `out` parameter from");
 
             fparam.defaultArg = e;
             return (e.op != EXP.error);
diff --git a/gcc/d/dmd/version.h b/gcc/d/dmd/version.h
index 697d46ee211..c268bc9b8cf 100644
--- a/gcc/d/dmd/version.h
+++ b/gcc/d/dmd/version.h
@@ -20,7 +20,6 @@ public:
     DebugSymbol *syntaxCopy(Dsymbol *) override;
 
     const char *toChars() const override;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     const char *kind() const override;
     DebugSymbol *isDebugSymbol() override;
     void accept(Visitor *v) override { v->visit(this); }
@@ -34,7 +33,6 @@ public:
     VersionSymbol *syntaxCopy(Dsymbol *) override;
 
     const char *toChars() const override;
-    void addMember(Scope *sc, ScopeDsymbol *sds) override;
     const char *kind() const override;
     VersionSymbol *isVersionSymbol() override;
     void accept(Visitor *v) override { v->visit(this); }
diff --git a/gcc/d/dmd/visitor.h b/gcc/d/dmd/visitor.h
index 3d8c3e60220..360784a1076 100644
--- a/gcc/d/dmd/visitor.h
+++ b/gcc/d/dmd/visitor.h
@@ -176,6 +176,7 @@ class NewDeclaration;
 
 class Initializer;
 class VoidInitializer;
+class DefaultInitializer;
 class ErrorInitializer;
 class StructInitializer;
 class ArrayInitializer;
@@ -591,6 +592,7 @@ public:
     virtual void visit(StructInitializer *i) { visit((Initializer *)i); }
     virtual void visit(ArrayInitializer *i) { visit((Initializer *)i); }
     virtual void visit(VoidInitializer *i) { visit((Initializer *)i); }
+    virtual void visit(DefaultInitializer *i) { visit((Initializer *)i); }
     virtual void visit(CInitializer *i) { visit((Initializer *)i); }
 };
 
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 17801a3bd1e..a907979ba04 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -789,42 +789,58 @@ public:
 
   void visit (CatAssignExp *e) final override
   {
+    if (!global.params.useGC)
+      {
+	error_at (make_location_t (e->loc),
+		  "appending to array in %qs requires the GC and cannot be "
+		  "used with %<-fno-druntime%>", e->toChars ());
+	this->result_ = error_mark_node;
+	return;
+      }
+
     Type *tb1 = e->e1->type->toBasetype ();
     Type *tb2 = e->e2->type->toBasetype ();
-    Type *etype = tb1->nextOf ()->toBasetype ();
-
-    /* Save the address of `e1', so it can be evaluated first.
-       As all D run-time library functions for concat assignments update `e1'
-       in-place and then return its value, the saved address can also be used as
-       the result of this expression as well.  */
-    tree lhs = build_expr (e->e1);
-    tree lexpr = stabilize_expr (&lhs);
-    tree ptr = d_save_expr (build_address (lhs));
-    tree result = NULL_TREE;
 
-    if (tb1->ty == TY::Tarray && tb2->ty == TY::Tdchar
-	&& (etype->ty == TY::Tchar || etype->ty == TY::Twchar))
+    if (e->op == EXP::concatenateDcharAssign)
       {
 	/* Append a dchar to a char[] or wchar[]:
 	   The assignment is handled by the D run-time library, so only
 	   need to call `_d_arrayappend[cw]d(&e1, e2)'  */
+	Type *etype = tb1->nextOf ()->toBasetype ();
+
+	/* Save the address of `e1', so it can be evaluated first.
+	   As all D run-time library functions for concat assignments update
+	   `e1' in-place and then return its value, the saved address can also
+	   be used as the result of this expression as well.  */
+	tree lhs = build_expr (e->e1);
+	tree lexpr = stabilize_expr (&lhs);
+	tree ptr = d_save_expr (build_address (lhs));
+	tree result = NULL_TREE;
+
+	gcc_assert (tb1->ty == TY::Tarray && tb2->ty == TY::Tdchar
+		    && (etype->ty == TY::Tchar || etype->ty == TY::Twchar));
+
 	libcall_fn libcall = (etype->ty == TY::Tchar)
 	  ? LIBCALL_ARRAYAPPENDCD : LIBCALL_ARRAYAPPENDWD;
 
 	result = build_libcall (libcall, e->type, 2,
 				ptr, build_expr (e->e2));
+
+	/* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr;  */
+	result = compound_expr (compound_expr (lexpr, ptr), result);
+	this->result_ = compound_expr (result, build_deref (ptr));
       }
     else
       {
+	gcc_assert (e->op == EXP::concatenateAssign
+		    || e->op == EXP::concatenateElemAssign);
+	gcc_assert (tb1->ty == TY::Tarray || tb2->ty == TY::Tsarray);
 	/* Appending an element or array to another array has already been
 	   handled by the front-end.  */
-	gcc_assert (tb1->ty == TY::Tarray || tb2->ty == TY::Tsarray);
-	gcc_unreachable ();
-      }
+	gcc_assert (e->lowering);
 
-    /* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr;  */
-    result = compound_expr (compound_expr (lexpr, ptr), result);
-    this->result_ = compound_expr (result, build_deref (ptr));
+	this->result_ = build_expr (e->lowering);
+      }
   }
 
   /* Build an assignment expression.  The right operand is implicitly
@@ -2359,50 +2375,9 @@ public:
 	/* Allocating memory for a new D array.  */
 	gcc_assert (e->arguments && e->arguments->length >= 1);
 
-	if (e->arguments->length == 1)
-	  {
-	    /* Single dimension array allocations has already been handled by
-	       the front-end.  */
-	    gcc_assert (e->lowering);
-	    result = build_expr (e->lowering);
-	  }
-	else
-	  {
-	    /* Multidimensional array allocations.  */
-	    tree tarray = make_array_type (Type::tsize_t, e->arguments->length);
-	    tree var = build_local_temp (tarray);
-	    vec <constructor_elt, va_gc> *elms = NULL;
-
-	    /* Get the base element type for the array, generating the
-	       initializer for the dims parameter along the way.  */
-	    Type *telem = e->newtype->toBasetype ();
-	    for (size_t i = 0; i < e->arguments->length; i++)
-	      {
-		Expression *arg = (*e->arguments)[i];
-		CONSTRUCTOR_APPEND_ELT (elms, size_int (i), build_expr (arg));
-
-		gcc_assert (telem->ty == TY::Tarray);
-		telem = telem->toBasetype ()->nextOf ();
-		gcc_assert (telem);
-	      }
-
-	    /* Initialize the temporary.  */
-	    tree init = modify_expr (var, build_constructor (tarray, elms));
-	    var = compound_expr (init, var);
-
-	    /* Generate: _d_newarraymTX(ti, dims)
-		     or: _d_newarraymiTX(ti, dims)  */
-	    libcall_fn libcall = telem->isZeroInit ()
-	      ? LIBCALL_NEWARRAYMTX : LIBCALL_NEWARRAYMITX;
-
-	    tree tinfo = build_typeinfo (e, e->type);
-	    tree dims = d_array_value (build_ctype (Type::tsize_t->arrayOf ()),
-				       size_int (e->arguments->length),
-				       build_address (var));
-
-	    result = build_libcall (libcall, e->newtype->toBasetype (), 2,
-				    tinfo, dims);
-	  }
+	/* Array allocations have already been handled by the front-end.  */
+	gcc_assert (e->lowering != NULL);
+	result = build_expr (e->lowering);
 
 	if (e->argprefix)
 	  result = compound_expr (build_expr (e->argprefix), result);
diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def
index f7887e1548f..3307b3b8244 100644
--- a/gcc/d/runtime.def
+++ b/gcc/d/runtime.def
@@ -70,13 +70,6 @@ DEF_D_RUNTIME (DYNAMIC_CAST, "_d_dynamic_cast", RT(OBJECT),
 DEF_D_RUNTIME (INTERFACE_CAST, "_d_interface_cast", RT(OBJECT),
 	       P2(OBJECT, CLASSINFO), 0)
 
-/* Used when calling `new' on a multi-dimensional array.
-   The `i' variant is for when the initializer is nonzero.  */
-DEF_D_RUNTIME (NEWARRAYMTX, "_d_newarraymTX", RT(ARRAY_VOID),
-	       P2(CONST_TYPEINFO, ARRAY_SIZE_T), 0)
-DEF_D_RUNTIME (NEWARRAYMITX, "_d_newarraymiTX", RT(ARRAY_VOID),
-	       P2(CONST_TYPEINFO, ARRAY_SIZE_T), 0)
-
 /* Used for allocating an array literal on the GC heap.  */
 DEF_D_RUNTIME (ARRAYLITERALTX, "_d_arrayliteralTX", RT(VOIDPTR),
 	       P2(CONST_TYPEINFO, SIZE_T), 0)
diff --git a/gcc/testsuite/gdc.dg/asm1.d b/gcc/testsuite/gdc.dg/asm1.d
index 1b249ee7b35..1593eb6acd3 100644
--- a/gcc/testsuite/gdc.dg/asm1.d
+++ b/gcc/testsuite/gdc.dg/asm1.d
@@ -58,7 +58,7 @@ void semantic1()
 void semantic2a(X...)(X expr)
 {
     alias X[0] var1;
-    asm { "%0" : "=m" (var1); } // { dg-error "double' is a 'double' definition and cannot be modified" }
+    asm { "%0" : "=m" (var1); } // { dg-error "cannot modify type 'double'" }
 }
 
 void semantic2()
diff --git a/gcc/testsuite/gdc.test/compilable/issue16020.d b/gcc/testsuite/gdc.test/compilable/issue16020.d
index cfd078cdcd1..38a5d624320 100644
--- a/gcc/testsuite/gdc.test/compilable/issue16020.d
+++ b/gcc/testsuite/gdc.test/compilable/issue16020.d
@@ -1,3 +1,4 @@
+// function type aliases
 module issue16020;
 
 alias F1 = const(int)(); const(int) f1(){return 42;}
@@ -36,4 +37,8 @@ alias Specialized = FunTemplate!int;
 alias Compared = void(int);
 static assert(is(Specialized == Compared));
 
-void main() {}
+// type suffixes
+alias FT = const(int)*();
+static assert(is(FT* == const(int)* function()));
+alias FT2 = int*[2]() pure;
+static assert(is(FT2* == int*[2] function() pure));
diff --git a/gcc/testsuite/gdc.test/compilable/nogc.d b/gcc/testsuite/gdc.test/compilable/nogc.d
index 88cf1229d4d..959adc499cc 100644
--- a/gcc/testsuite/gdc.test/compilable/nogc.d
+++ b/gcc/testsuite/gdc.test/compilable/nogc.d
@@ -119,3 +119,12 @@ void f(bool cond, string s) @nogc {
     alias Unused2 = typeof(&inner); // (Does not) INFERS GC (anymore)
     enum Unused3 = __traits(compiles , &inner);
 }
+
+// https://issues.dlang.org/show_bug.cgi?id=24072
+
+version (D_SIMD) void f24072() @nogc
+{
+    alias int4 = __vector(int[4]);
+    int4 b = cast(int4)[1, 2, 3, 4];
+    int4 c = cast(int4)[1, 2];
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b20011.d b/gcc/testsuite/gdc.test/fail_compilation/b20011.d
index 7baad47f378..3ddcdaaf76b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/b20011.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/b20011.d
@@ -1,10 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/b20011.d(25): Error: `S1(cast(ubyte)0u).member` is not an lvalue and cannot be modified
-fail_compilation/b20011.d(28): Error: `S2(null).member` is not an lvalue and cannot be modified
-fail_compilation/b20011.d(29): Error: `S2(null).member` is not an lvalue and cannot be modified
-fail_compilation/b20011.d(32): Error: `U1(cast(ubyte)0u, ).m2` is not an lvalue and cannot be modified
+fail_compilation/b20011.d(25): Error: cannot modify expression `S1(cast(ubyte)0u).member` because it is not an lvalue
+fail_compilation/b20011.d(28): Error: cannot modify expression `S2(null).member` because it is not an lvalue
+fail_compilation/b20011.d(29): Error: cannot modify expression `S2(null).member` because it is not an lvalue
+fail_compilation/b20011.d(32): Error: cannot modify expression `U1(cast(ubyte)0u, ).m2` because it is not an lvalue
 fail_compilation/b20011.d(37): Error: function `b20011.main.assignableByRef(ref ubyte p)` is not callable using argument types `(ubyte)`
 fail_compilation/b20011.d(37):        cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref ubyte p`
 fail_compilation/b20011.d(38): Error: function `b20011.main.assignableByOut(out ubyte p)` is not callable using argument types `(ubyte)`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/const_ctor.d b/gcc/testsuite/gdc.test/fail_compilation/const_ctor.d
new file mode 100644
index 00000000000..ae37023f0a1
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/const_ctor.d
@@ -0,0 +1,26 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/const_ctor.d(23): Error: `const` copy constructor `const_ctor.S1.this` cannot construct a mutable object
+fail_compilation/const_ctor.d(25): Error: `const` constructor `const_ctor.S2.this` cannot construct a mutable object
+---
+*/
+
+struct S1
+{
+    this(ref const S1 s) const {}
+    int* i;
+}
+struct S2
+{
+    this(int) const {}
+    int* i;
+}
+
+void main()
+{
+    const(S1) s1;
+    S1 m1 = s1;
+
+    S2 s2 = S2(5);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ctor_attr.d b/gcc/testsuite/gdc.test/fail_compilation/ctor_attr.d
new file mode 100644
index 00000000000..337ded09fd2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/ctor_attr.d
@@ -0,0 +1,29 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/ctor_attr.d(26): Error: none of the overloads of `this` can construct a mutable object with argument types `(int)`
+fail_compilation/ctor_attr.d(16):        Candidates are: `ctor_attr.S.this(int x) const`
+fail_compilation/ctor_attr.d(18):                        `ctor_attr.S.this(string x)`
+fail_compilation/ctor_attr.d(17):                        `this()(int x) shared`
+fail_compilation/ctor_attr.d(28): Error: none of the overloads of `foo` are callable using a mutable object with argument types `(int)`
+fail_compilation/ctor_attr.d(20):        Candidates are: `ctor_attr.S.foo(int x) immutable`
+fail_compilation/ctor_attr.d(21):                        `ctor_attr.S.foo(string x)`
+---
+*/
+
+struct S
+{
+    this(int x) const {}
+    this()(int x) shared {}
+    this(string x) {}
+
+    void foo(int x) immutable  {}
+    void foo(string x) {}
+}
+
+void f()
+{
+   auto s = S(1);
+   S t;
+   t.foo(1);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10415.d b/gcc/testsuite/gdc.test/fail_compilation/diag10415.d
index 207f6a4aa15..74444327ecb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10415.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10415.d
@@ -2,7 +2,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/diag10415.d(36): Error: none of the overloads of `x` are callable using argument types `(int) const`
-fail_compilation/diag10415.d(13):        Candidates are: `diag10415.C.x()`
+fail_compilation/diag10415.d(13):        Candidates are: `diag10415.C.x() const`
 fail_compilation/diag10415.d(18):                        `diag10415.C.x(int __param_0)`
 fail_compilation/diag10415.d(39): Error: d.x is not an lvalue
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10862.d b/gcc/testsuite/gdc.test/fail_compilation/diag10862.d
index 3e154979e8c..2c9384159ff 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10862.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10862.d
@@ -26,10 +26,10 @@ fail_compilation/diag10862.d-mixin-78(78): Error: assignment cannot be used as a
 fail_compilation/diag10862.d-mixin-79(79): Error: assignment cannot be used as a condition, perhaps `==` was meant?
 fail_compilation/diag10862.d-mixin-80(80): Error: using the result of a comma expression is not allowed
 fail_compilation/diag10862.d-mixin-80(80): Error: assignment cannot be used as a condition, perhaps `==` was meant?
-fail_compilation/diag10862.d-mixin-83(83): Error: `a + b` is not an lvalue and cannot be modified
+fail_compilation/diag10862.d-mixin-83(83): Error: cannot modify expression `a + b` because it is not an lvalue
 fail_compilation/diag10862.d-mixin-84(84): Error: undefined identifier `c`
 fail_compilation/diag10862.d(86): Error: undefined identifier `semanticError`
-fail_compilation/diag10862.d(93): Error: lazy variable `bar` cannot be modified
+fail_compilation/diag10862.d(93): Error: cannot modify lazy variable `bar`
 fail_compilation/diag10862.d(95): Error: template instance `diag10862.test3.foo!int` error instantiating
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10926.d b/gcc/testsuite/gdc.test/fail_compilation/diag10926.d
index f98a5b27dea..9bad6336d18 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10926.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10926.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag10926.d(11): Error: `cast(const(int)[])c` is not an lvalue and cannot be modified
+fail_compilation/diag10926.d(11): Error: cannot modify expression `cast(const(int)[])c` because it is not an lvalue
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag14102.d b/gcc/testsuite/gdc.test/fail_compilation/diag14102.d
index e93d40b224e..b88dd7803cf 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag14102.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag14102.d
@@ -1,10 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag14102.d(14): Error: `-x` is not an lvalue and cannot be modified
-fail_compilation/diag14102.d(15): Error: `-(x -= 1)` is not an lvalue and cannot be modified
-fail_compilation/diag14102.d(16): Error: `-(x -= 1 -= 1)` is not an lvalue and cannot be modified
-fail_compilation/diag14102.d(17): Error: `-(x -= 1 -= 1 -= 1)` is not an lvalue and cannot be modified
+fail_compilation/diag14102.d(14): Error: cannot modify expression `-x` because it is not an lvalue
+fail_compilation/diag14102.d(15): Error: cannot modify expression `-(x -= 1)` because it is not an lvalue
+fail_compilation/diag14102.d(16): Error: cannot modify expression `-(x -= 1 -= 1)` because it is not an lvalue
+fail_compilation/diag14102.d(17): Error: cannot modify expression `-(x -= 1 -= 1 -= 1)` because it is not an lvalue
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag4596.d b/gcc/testsuite/gdc.test/fail_compilation/diag4596.d
index f6b49d6bd13..d43342bdc58 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag4596.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag4596.d
@@ -1,9 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag4596.d(15): Error: `this` is not an lvalue and cannot be modified
+fail_compilation/diag4596.d(15): Error: cannot modify expression `this` because it is not an lvalue
 fail_compilation/diag4596.d(16): Error: conditional expression `1 ? this : this` is not a modifiable lvalue
-fail_compilation/diag4596.d(18): Error: `super` is not an lvalue and cannot be modified
+fail_compilation/diag4596.d(18): Error: cannot modify expression `super` because it is not an lvalue
 fail_compilation/diag4596.d(19): Error: conditional expression `1 ? super : super` is not a modifiable lvalue
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d b/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d
index a55ef731ad2..626fb827878 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d
@@ -6,7 +6,7 @@ fail_compilation/diag8101b.d(19):        Candidates are: `diag8101b.S.foo(int __
 fail_compilation/diag8101b.d(20):                        `diag8101b.S.foo(int __param_0, int __param_1)`
 fail_compilation/diag8101b.d(30): Error: function `diag8101b.S.bar(int __param_0)` is not callable using argument types `(double)`
 fail_compilation/diag8101b.d(30):        cannot pass argument `1.0` of type `double` to parameter `int __param_0`
-fail_compilation/diag8101b.d(33): Error: none of the overloads of `foo` are callable using a `const` object
+fail_compilation/diag8101b.d(33): Error: none of the overloads of `foo` are callable using a `const` object with argument types `(int)`
 fail_compilation/diag8101b.d(19):        Candidates are: `diag8101b.S.foo(int __param_0)`
 fail_compilation/diag8101b.d(20):                        `diag8101b.S.foo(int __param_0, int __param_1)`
 fail_compilation/diag8101b.d(35): Error: mutable method `diag8101b.S.bar` is not callable using a `const` object
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d b/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d
deleted file mode 100644
index 77ab52046fc..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-REQUIRED_ARGS: -de
-TEST_OUTPUT:
----
-fail_compilation/dip1000_deprecation.d(17): Deprecation: `@safe` function `main` calling `inferred`
-fail_compilation/dip1000_deprecation.d(25):        which wouldn't be `@safe` because of:
-fail_compilation/dip1000_deprecation.d(25):        scope variable `x0` may not be returned
-fail_compilation/dip1000_deprecation.d(19): Deprecation: `@safe` function `main` calling `inferredC`
-fail_compilation/dip1000_deprecation.d(36):        which calls `dip1000_deprecation.inferred`
-fail_compilation/dip1000_deprecation.d(25):        which wouldn't be `@safe` because of:
-fail_compilation/dip1000_deprecation.d(25):        scope variable `x0` may not be returned
----
-*/
-
-void main() @safe
-{
-    cast(void)inferred();
-    cast(void)inferredB(); // no deprecation, trusted
-    cast(void)inferredC(); // nested deprecation
-}
-
-auto inferred()
-{
-    scope int* x0;
-    return x0;
-}
-
-auto inferredB() @trusted
-{
-    scope int* x1;
-    return x1;
-}
-
-auto inferredC()
-{
-    return inferred(); // no deprecation, inferredC is not explicit `@safe`
-}
-
-@safe:
-
-struct S
-{
-    int* ptr;
-    int* incorrectReturnRef() scope return @trusted {return ptr;}
-}
-
-S createS() { return S.init; }
-
-int* escape(int i)
-{
-    if (i) return S().incorrectReturnRef();
-    if (i) return createS().incorrectReturnRef();
-
-    S s;
-    return s.incorrectReturnRef();
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10299.d b/gcc/testsuite/gdc.test/fail_compilation/fail10299.d
index f0eaeba821a..d9cfb047724 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail10299.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail10299.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail10299.d(11): Error: `foo!string` is not an lvalue and cannot be modified
+fail_compilation/fail10299.d(11): Error: cannot take address of expression `foo!string` because it is not an lvalue
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13116.d b/gcc/testsuite/gdc.test/fail_compilation/fail13116.d
index ac520d79997..156da435c7b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail13116.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail13116.d
@@ -1,8 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail13116.d(14): Error: `this` is not an lvalue and cannot be modified
-fail_compilation/fail13116.d(23): Error: `super` is not an lvalue and cannot be modified
+fail_compilation/fail13116.d(14): Error: cannot `ref` return expression `this` because it is not an lvalue
+fail_compilation/fail13116.d(23): Error: cannot `ref` return expression `super` because it is not an lvalue
 ---
 */
 struct S
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13336a.d b/gcc/testsuite/gdc.test/fail_compilation/fail13336a.d
index e3f990c2fdf..6307e902551 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail13336a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail13336a.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail13336a.d(28): Error: `choose(true)` is not an lvalue and cannot be modified
+fail_compilation/fail13336a.d(28): Error: cannot modify expression `choose(true)` because it is not an lvalue
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13336b.d b/gcc/testsuite/gdc.test/fail_compilation/fail13336b.d
index b8fb12d1427..f8959a2183c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail13336b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail13336b.d
@@ -6,8 +6,8 @@ double sy;
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail13336b.d(16): Error: `cast(double)sx` is not an lvalue and cannot be modified
-fail_compilation/fail13336b.d(24): Error: `cast(double)sx` is not an lvalue and cannot be modified
+fail_compilation/fail13336b.d(16): Error: cannot `ref` return expression `cast(double)sx` because it is not an lvalue
+fail_compilation/fail13336b.d(24): Error: cannot `ref` return expression `cast(double)sx` because it is not an lvalue
 ---
 */
 ref f1(bool f)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17491.d b/gcc/testsuite/gdc.test/fail_compilation/fail17491.d
index 0fb9708b430..718948c2832 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail17491.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail17491.d
@@ -1,13 +1,13 @@
 /* TEST_OUTPUT:
 ---
-fail_compilation/fail17491.d(22): Error: `(S17491).init` is not an lvalue and cannot be modified
-fail_compilation/fail17491.d(23): Error: `S17491(0)` is not an lvalue and cannot be modified
-fail_compilation/fail17491.d(25): Error: `S17491(0).field` is not an lvalue and cannot be modified
-fail_compilation/fail17491.d(26): Error: `S17491(0).field` is not an lvalue and cannot be modified
-fail_compilation/fail17491.d(31): Error: `S17491(0)` is not an lvalue and cannot be modified
-fail_compilation/fail17491.d(32): Error: `S17491(0)` is not an lvalue and cannot be modified
-fail_compilation/fail17491.d(34): Error: `S17491(0).field` is not an lvalue and cannot be modified
-fail_compilation/fail17491.d(35): Error: `S17491(0).field` is not an lvalue and cannot be modified
+fail_compilation/fail17491.d(22): Error: cannot modify expression `(S17491).init` because it is not an lvalue
+fail_compilation/fail17491.d(23): Error: cannot take address of expression `S17491(0)` because it is not an lvalue
+fail_compilation/fail17491.d(25): Error: cannot modify expression `S17491(0).field` because it is not an lvalue
+fail_compilation/fail17491.d(26): Error: cannot take address of expression `S17491(0).field` because it is not an lvalue
+fail_compilation/fail17491.d(31): Error: cannot modify expression `S17491(0)` because it is not an lvalue
+fail_compilation/fail17491.d(32): Error: cannot take address of expression `S17491(0)` because it is not an lvalue
+fail_compilation/fail17491.d(34): Error: cannot modify expression `S17491(0).field` because it is not an lvalue
+fail_compilation/fail17491.d(35): Error: cannot take address of expression `S17491(0).field` because it is not an lvalue
 ---
 */
 // https://issues.dlang.org/show_bug.cgi?id=17491
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21243.d b/gcc/testsuite/gdc.test/fail_compilation/fail21243.d
index 2e170d096c5..0b4117d5bc6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21243.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21243.d
@@ -1,16 +1,12 @@
 /+ TEST_OUTPUT:
 ---
-fail_compilation/fail21243.d(16): Error: found `(` when expecting `ref` and function literal following `auto`
-fail_compilation/fail21243.d(16): Error: semicolon expected following auto declaration, not `int`
-fail_compilation/fail21243.d(16): Error: semicolon needed to end declaration of `x` instead of `)`
-fail_compilation/fail21243.d(16): Error: declaration expected, not `)`
-fail_compilation/fail21243.d(17): Error: `auto` can only be used as part of `auto ref` for function literal return values
-fail_compilation/fail21243.d(18): Error: basic type expected, not `(`
-fail_compilation/fail21243.d(18): Error: function declaration without return type. (Note that constructors are always named `this`)
-fail_compilation/fail21243.d(18): Deprecation: storage class `auto` has no effect in type aliases
-fail_compilation/fail21243.d(18): Error: semicolon expected to close `alias` declaration, not `=>`
-fail_compilation/fail21243.d(18): Error: declaration expected, not `=>`
-fail_compilation/fail21243.d(19): Error: `auto` can only be used as part of `auto ref` for function literal return values
+fail_compilation/fail21243.d(12): Error: found `(` when expecting `ref` and function literal following `auto`
+fail_compilation/fail21243.d(12): Error: semicolon expected following auto declaration, not `int`
+fail_compilation/fail21243.d(12): Error: semicolon needed to end declaration of `x` instead of `)`
+fail_compilation/fail21243.d(12): Error: declaration expected, not `)`
+fail_compilation/fail21243.d(13): Error: `auto` can only be used as part of `auto ref` for function literal return values
+fail_compilation/fail21243.d(14): Error: `auto` can only be used as part of `auto ref` for function literal return values
+fail_compilation/fail21243.d(15): Error: `auto` can only be used as part of `auto ref` for function literal return values
 ---
 +/
 auto a = auto (int x) => x;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail217.d b/gcc/testsuite/gdc.test/fail_compilation/fail217.d
index 11ad76fabdc..ecae1a38e6d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail217.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail217.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail217.d(22): Error: mutable method `fail217.Message.this` is not callable using a `immutable` object
+fail_compilation/fail217.d(22): Error: mutable constructor `fail217.Message.this` cannot construct a `immutable` object
 fail_compilation/fail217.d(13):        Consider adding `const` or `inout` here
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail24224.d b/gcc/testsuite/gdc.test/fail_compilation/fail24224.d
new file mode 100644
index 00000000000..db87f5305d7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail24224.d
@@ -0,0 +1,22 @@
+/+
+TEST_OUTPUT:
+---
+fail_compilation/fail24224.d(19): Error: struct / class type expected as argument to __traits(initSymbol) instead of `ES`
+fail_compilation/fail24224.d(20): Error: struct / class type expected as argument to __traits(initSymbol) instead of `EU`
+fail_compilation/fail24224.d(21): Error: struct / class type expected as argument to __traits(initSymbol) instead of `EC`
+---
++/
+struct S {}
+union U {}
+class C {}
+
+enum ES : S { a = S.init }
+enum EU : U { a = U.init }
+enum EC : C { a = C.init }
+
+void test()
+{
+    auto init1 = __traits(initSymbol, ES);
+    auto init2 = __traits(initSymbol, EU);
+    auto init3 = __traits(initSymbol, EC);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail6795.d b/gcc/testsuite/gdc.test/fail_compilation/fail6795.d
index 584a4679ccd..26d44296498 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail6795.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail6795.d
@@ -2,12 +2,12 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail6795.d(19): Error: `[0][0]` is not an lvalue and cannot be modified
-fail_compilation/fail6795.d(20): Error: `[0:0][0]` is not an lvalue and cannot be modified
-fail_compilation/fail6795.d(22): Error: `[0][0]` is not an lvalue and cannot be modified
-fail_compilation/fail6795.d(23): Error: `[0:0][0]` is not an lvalue and cannot be modified
-fail_compilation/fail6795.d(25): Error: `[0][0]` is not an lvalue and cannot be modified
-fail_compilation/fail6795.d(26): Error: `[0:0][0]` is not an lvalue and cannot be modified
+fail_compilation/fail6795.d(19): Error: cannot modify expression `[0][0]` because it is not an lvalue
+fail_compilation/fail6795.d(20): Error: cannot modify expression `[0:0][0]` because it is not an lvalue
+fail_compilation/fail6795.d(22): Error: cannot modify expression `[0][0]` because it is not an lvalue
+fail_compilation/fail6795.d(23): Error: cannot modify expression `[0:0][0]` because it is not an lvalue
+fail_compilation/fail6795.d(25): Error: cannot take address of expression `[0][0]` because it is not an lvalue
+fail_compilation/fail6795.d(26): Error: cannot take address of expression `[0:0][0]` because it is not an lvalue
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7424d.d b/gcc/testsuite/gdc.test/fail_compilation/fail7424d.d
index 38f47ba0913..920956bf2f9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7424d.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7424d.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail7424d.d(10): Error: template `this.g()()` has no value
+fail_compilation/fail7424d.d(10): Error: template `this.g()() immutable` has no value
 ---
 */
 struct S7424d
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7424e.d b/gcc/testsuite/gdc.test/fail_compilation/fail7424e.d
index e92b4693d51..ddf9d1a89b3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7424e.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7424e.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail7424e.d(10): Error: template `this.g()()` has no value
+fail_compilation/fail7424e.d(10): Error: template `this.g()() immutable` has no value
 ---
 */
 struct S7424e
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7424f.d b/gcc/testsuite/gdc.test/fail_compilation/fail7424f.d
index 1af14f83d7e..2f7f8f36153 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7424f.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7424f.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail7424f.d(10): Error: template `this.g()()` has no value
+fail_compilation/fail7424f.d(10): Error: template `this.g()() shared` has no value
 ---
 */
 struct S7424f
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7424i.d b/gcc/testsuite/gdc.test/fail_compilation/fail7424i.d
index 6352166add5..4e922d6f5be 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7424i.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7424i.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail7424i.d(10): Error: template `this.g()()` has no value
+fail_compilation/fail7424i.d(10): Error: template `this.g()() immutable` has no value
 ---
 */
 struct S7424g
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7603a.d b/gcc/testsuite/gdc.test/fail_compilation/fail7603a.d
index 76a92c2b193..a106a566a5c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7603a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7603a.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail7603a.d(7): Error: cannot modify constant `true`
+fail_compilation/fail7603a.d(7): Error: cannot create default argument for `ref` / `out` parameter from constant `true`
 ---
 */
 void test(ref bool val = true) { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7603b.d b/gcc/testsuite/gdc.test/fail_compilation/fail7603b.d
index 9b84d3f6a4d..a6524221afd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7603b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7603b.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail7603b.d(7): Error: cannot modify constant `true`
+fail_compilation/fail7603b.d(7): Error: cannot create default argument for `ref` / `out` parameter from constant `true`
 ---
 */
 void test(out bool val = true) { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7603c.d b/gcc/testsuite/gdc.test/fail_compilation/fail7603c.d
index 25a7399dd7a..3d030fc9668 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7603c.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7603c.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail7603c.d(8): Error: cannot modify constant `3`
+fail_compilation/fail7603c.d(8): Error: cannot create default argument for `ref` / `out` parameter from constant `3`
 ---
 */
 enum x = 3;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail9537.d b/gcc/testsuite/gdc.test/fail_compilation/fail9537.d
index e08badf34a9..4d593e39ddb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail9537.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail9537.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail9537.d(26): Error: `foo(tuple(1, 2))` is not an lvalue and cannot be modified
+fail_compilation/fail9537.d(26): Error: cannot take address of expression `foo(tuple(1, 2))` because it is not an lvalue
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail9773.d b/gcc/testsuite/gdc.test/fail_compilation/fail9773.d
index b49ffe13dfc..26447a73914 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail9773.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail9773.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail9773.d(7): Error: `""` is not an lvalue and cannot be modified
+fail_compilation/fail9773.d(7): Error: cannot create default argument for `ref` / `out` parameter from expression `""` because it is not an lvalue
 ---
 */
 void f(ref string a = "")
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail9891.d b/gcc/testsuite/gdc.test/fail_compilation/fail9891.d
index 791e734349f..0c2384fccfa 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail9891.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail9891.d
@@ -3,7 +3,7 @@ TEST_OUTPUT:
 ---
 fail_compilation/fail9891.d(13): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `ref int` of parameter `n`
 fail_compilation/fail9891.d(18): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `out int` of parameter `n`
-fail_compilation/fail9891.d(23): Error: `prop()` is not an lvalue and cannot be modified
+fail_compilation/fail9891.d(23): Error: cannot create default argument for `ref` / `out` parameter from expression `prop()` because it is not an lvalue
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d b/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d
index c3c735ed552..0db6a45c9a2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d
@@ -207,21 +207,21 @@ fail_compilation/fail_arrayop2.d(265): Error: array operation `[1] * 6` without
 fail_compilation/fail_arrayop2.d(268): Error: array operation `[1] * 6` without destination memory not allowed
 fail_compilation/fail_arrayop2.d(269): Error: array operation `"abc"[] + '\x01'` without destination memory not allowed
 fail_compilation/fail_arrayop2.d(272): Error: array operation `[1] * 6` without destination memory not allowed
-fail_compilation/fail_arrayop2.d(275): Error: `([1] * 6)[0..2]` is not an lvalue and cannot be modified
+fail_compilation/fail_arrayop2.d(275): Error: cannot take address of expression `([1] * 6)[0..2]` because it is not an lvalue
 fail_compilation/fail_arrayop2.d(278): Error: can only `*` a pointer, not a `int[]`
 fail_compilation/fail_arrayop2.d(281): Error: the `delete` keyword is obsolete
 fail_compilation/fail_arrayop2.d(281):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
 fail_compilation/fail_arrayop2.d(284): Error: array operation `da[] * 6` without destination memory not allowed
 fail_compilation/fail_arrayop2.d(287): Error: array operation `da[] * 6` without destination memory not allowed
-fail_compilation/fail_arrayop2.d(290): Error: `[1] * 6` is not an lvalue and cannot be modified
+fail_compilation/fail_arrayop2.d(290): Error: cannot modify expression `[1] * 6` because it is not an lvalue
 fail_compilation/fail_arrayop2.d(291): Error: array operation `[1] * 6` without destination memory not allowed
-fail_compilation/fail_arrayop2.d(294): Error: `[1] * 6` is not an lvalue and cannot be modified
-fail_compilation/fail_arrayop2.d(295): Error: `([1] * 6)[]` is not an lvalue and cannot be modified
+fail_compilation/fail_arrayop2.d(294): Error: cannot modify expression `[1] * 6` because it is not an lvalue
+fail_compilation/fail_arrayop2.d(295): Error: cannot modify expression `([1] * 6)[]` because it is not an lvalue
 fail_compilation/fail_arrayop2.d(298): Error: array operation `[1] * 6` without destination memory not allowed
 fail_compilation/fail_arrayop2.d(299): Error: array operation `[1] * 6` without destination memory not allowed
 fail_compilation/fail_arrayop2.d(300): Error: array operation `[1] * 6` without destination memory not allowed
-fail_compilation/fail_arrayop2.d(303): Error: `[1] * 6` is not an lvalue and cannot be modified
-fail_compilation/fail_arrayop2.d(304): Error: `[1] * 6` is not an lvalue and cannot be modified
+fail_compilation/fail_arrayop2.d(303): Error: cannot modify expression `[1] * 6` because it is not an lvalue
+fail_compilation/fail_arrayop2.d(304): Error: cannot modify expression `[1] * 6` because it is not an lvalue
 fail_compilation/fail_arrayop2.d(307): Error: `[1] * 6` is not of integral type, it is a `int[]`
 fail_compilation/fail_arrayop2.d(308): Error: `[1] * 6` is not of integral type, it is a `int[]`
 fail_compilation/fail_arrayop2.d(309): Error: `[1] * 6` is not of integral type, it is a `int[]`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d
index a9e5429366a..9851ffc1c74 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d
@@ -1,10 +1,6 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail_scope.d(28): Deprecation: scope parameter `da` may not be returned
-fail_compilation/fail_scope.d(30): Deprecation: scope parameter `o` may not be returned
-fail_compilation/fail_scope.d(31): Deprecation: scope parameter `dg` may not be returned
-fail_compilation/fail_scope.d(38): Deprecation: scope parameter `p` may not be returned
 fail_compilation/fail_scope.d(43): Error: returning `cast(char[])string` escapes a reference to local variable `string`
 fail_compilation/fail_scope.d(61): Error: returning `s.bar()` escapes a reference to local variable `s`
 fail_compilation/fail_scope.d(72): Error: `fail_scope.foo8` called with argument types `(int)` matches both:
@@ -23,6 +19,10 @@ fail_compilation/fail_scope.d(135): Error: returning `foo16226(i)` escapes a ref
 //fail_compilation/fail_scope.d(40): Error: scope variable `p` may not be returned
 */
 
+
+
+
+
 alias int delegate() dg_t;
 
 int[]  checkEscapeScope1(scope int[]  da) { return da; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10419.d b/gcc/testsuite/gdc.test/fail_compilation/ice10419.d
index 827f0451824..fed8c608569 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10419.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10419.d
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice10419.d(12): Error: `arr().length` is not an lvalue and cannot be modified
+fail_compilation/ice10419.d(12): Error: cannot modify expression `arr().length` because it is not an lvalue
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12841.d b/gcc/testsuite/gdc.test/fail_compilation/ice12841.d
index c5894d2c7ee..343624dbc39 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice12841.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice12841.d
@@ -1,8 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice12841.d(23): Error: `taskPool().amap(Args...)(Args args)` is not an lvalue and cannot be modified
-fail_compilation/ice12841.d(24): Error: `amap(Args...)(Args args)` is not an lvalue and cannot be modified
+fail_compilation/ice12841.d(23): Error: cannot take address of expression `taskPool().amap(Args...)(Args args)` because it is not an lvalue
+fail_compilation/ice12841.d(24): Error: cannot take address of template `amap(Args...)(Args args)`, perhaps instantiate it first
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice13459.d b/gcc/testsuite/gdc.test/fail_compilation/ice13459.d
index d34fc60db6a..6998e685a75 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice13459.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice13459.d
@@ -3,7 +3,7 @@ TEST_OUTPUT:
 ---
 fail_compilation/ice13459.d(12): Error: undefined identifier `B`
 fail_compilation/ice13459.d(18): Error: none of the overloads of `opSlice` are callable using argument types `(int, int)`
-fail_compilation/ice13459.d(11):        Candidate is: `ice13459.A.opSlice()`
+fail_compilation/ice13459.d(11):        Candidate is: `ice13459.A.opSlice() const`
 ---
 */
 struct A
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice20264.d b/gcc/testsuite/gdc.test/fail_compilation/ice20264.d
index 0d697e22c9f..df6667d9e4b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice20264.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice20264.d
@@ -2,7 +2,7 @@
 DISABLED: freebsd32 linux32 osx32 win32
 TEST_OUTPUT:
 ---
-fail_compilation/ice20264.d(12): Error: `cast(__vector(float[4]))a` is not an lvalue and cannot be modified
+fail_compilation/ice20264.d(12): Error: cannot modify expression `cast(__vector(float[4]))a` because it is not an lvalue
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice9284.d b/gcc/testsuite/gdc.test/fail_compilation/ice9284.d
index 47fd44c6b01..c9ab014b6e6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice9284.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice9284.d
@@ -2,7 +2,7 @@
 TEST_OUTPUT:
 ---
 fail_compilation/ice9284.d(14): Error: template `ice9284.C.__ctor` is not callable using argument types `!()(int)`
-fail_compilation/ice9284.d(12):        Candidate is: `__ctor()(string)`
+fail_compilation/ice9284.d(12):        Candidate is: `this()(string)`
 fail_compilation/ice9284.d(20): Error: template instance `ice9284.C.__ctor!()` error instantiating
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/immutable_ctor.d b/gcc/testsuite/gdc.test/fail_compilation/immutable_ctor.d
new file mode 100644
index 00000000000..408e4027fd6
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/immutable_ctor.d
@@ -0,0 +1,19 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/immutable_ctor.d(18): Error: `immutable` copy constructor `immutable_ctor.S1.this` cannot construct a mutable object
+---
+*/
+
+struct S1
+{
+    this(ref const S1 s) immutable {
+    }
+    int i;
+}
+
+void main()
+{
+    const(S1) s1;
+    S1 ms1 = s1;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue16020.d b/gcc/testsuite/gdc.test/fail_compilation/issue16020.d
index fe4ad78f1ac..79eda2ea08c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/issue16020.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/issue16020.d
@@ -1,9 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/issue16020.d(12): Error: user-defined attributes not allowed for `alias` declarations
-fail_compilation/issue16020.d(13): Error: semicolon expected to close `alias` declaration, not `(`
-fail_compilation/issue16020.d(13): Error: declaration expected, not `(`
+fail_compilation/issue16020.d(13): Error: user-defined attributes not allowed for `alias` declarations
+fail_compilation/issue16020.d(14): Error: semicolon expected to close `alias` declaration, not `(`
+fail_compilation/issue16020.d(14): Error: declaration expected, not `(`
+fail_compilation/issue16020.d(15): Deprecation: storage class `final` has no effect in type aliases
 ---
 */
 module issue16020;
@@ -11,3 +12,4 @@ module issue16020;
 struct UDA{}
 alias Fun = @UDA void();
 alias FunTemplate = void(T)(T t);
+alias F2 = final int();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue20704.d b/gcc/testsuite/gdc.test/fail_compilation/issue20704.d
index 1e1f2e6f34b..ba91b063572 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/issue20704.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/issue20704.d
@@ -1,12 +1,12 @@
 /* TEST_OUTPUT:
 ---
-fail_compilation/issue20704.d(17): Error: cannot modify constant `0`
+fail_compilation/issue20704.d(17): Error: cannot create default argument for `ref` / `out` parameter from constant `0`
 fail_compilation/issue20704.d(28): Error: template instance `issue20704.f2!int` error instantiating
-fail_compilation/issue20704.d(19): Error: cannot modify constant `0`
+fail_compilation/issue20704.d(19): Error: cannot create default argument for `ref` / `out` parameter from constant `0`
 fail_compilation/issue20704.d(30): Error: template instance `issue20704.f4!int` error instantiating
-fail_compilation/issue20704.d(17): Error: `S(0)` is not an lvalue and cannot be modified
+fail_compilation/issue20704.d(17): Error: cannot create default argument for `ref` / `out` parameter from expression `S(0)` because it is not an lvalue
 fail_compilation/issue20704.d(36): Error: template instance `issue20704.f2!(S)` error instantiating
-fail_compilation/issue20704.d(17): Error: `null` is not an lvalue and cannot be modified
+fail_compilation/issue20704.d(17): Error: cannot create default argument for `ref` / `out` parameter from expression `null` because it is not an lvalue
 fail_compilation/issue20704.d(38): Error: template instance `issue20704.f2!(C)` error instantiating
 ---
 */
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16381.d b/gcc/testsuite/gdc.test/fail_compilation/test16381.d
index fd92798366c..5847e0459b6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16381.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16381.d
@@ -2,7 +2,7 @@
 REQUIRED_ARGS: -m64
 TEST_OUTPUT:
 ---
-fail_compilation/test16381.d(15): Error: `foo()` is not an lvalue and cannot be modified
+fail_compilation/test16381.d(15): Error: cannot take address of expression `foo()` because it is not an lvalue
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22048.d b/gcc/testsuite/gdc.test/fail_compilation/test22048.d
index e0560689f8d..72b91546a2b 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test22048.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22048.d
@@ -3,7 +3,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/test22048.d(10): Error: unexpected identifier `p` in declarator
+fail_compilation/test22048.d(10): Error: unexpected identifier `p` after `int`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24157.d b/gcc/testsuite/gdc.test/fail_compilation/test24157.d
index 5022014a9a1..d78c9b628ef 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test24157.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test24157.d
@@ -3,8 +3,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/test24157.d(23): Error: `p.self()` is not an lvalue and cannot be modified
-fail_compilation/test24157.d(27): Error: `p.unshared()` is not an lvalue and cannot be modified
+fail_compilation/test24157.d(23): Error: cannot take address of expression `p.self()` because it is not an lvalue
+fail_compilation/test24157.d(27): Error: cannot take address of expression `p.unshared()` because it is not an lvalue
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24159.d b/gcc/testsuite/gdc.test/fail_compilation/test24159.d
new file mode 100644
index 00000000000..35c7f364168
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test24159.d
@@ -0,0 +1,14 @@
+// https://issues.dlang.org/show_bug.cgi?id=24159
+// REQUIRED_ARGS: -betterC
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test24159.d(13): Error: appending to array in `x ~= 3` requires the GC which is not available with -betterC
+---
+*/
+
+extern(C) void main()
+{
+    int[] x = null;
+    x ~= 3;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d b/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d
index 50cebabfda4..1173d14480d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d
@@ -5,9 +5,9 @@ TEST_OUTPUT:
 ---
 fail_compilation/testrvaluecpctor.d(16): Error: cannot define both an rvalue constructor and a copy constructor for `struct Foo`
 fail_compilation/testrvaluecpctor.d(24):        Template instance `testrvaluecpctor.Foo!int.Foo.__ctor!(immutable(Foo!int), immutable(Foo!int))` creates an rvalue constructor for `struct Foo`
-fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `__ctor` are callable using a `immutable` object
+fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `this` can construct a `immutable` object with argument types `(immutable(Foo!int))`
 fail_compilation/testrvaluecpctor.d(18):        Candidates are: `testrvaluecpctor.Foo!int.Foo.this(ref scope Foo!int rhs)`
-fail_compilation/testrvaluecpctor.d(16):                        `__ctor(Rhs, this This)(scope Rhs rhs)`
+fail_compilation/testrvaluecpctor.d(16):                        `this(Rhs, this This)(scope Rhs rhs)`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/tolvalue.d b/gcc/testsuite/gdc.test/fail_compilation/tolvalue.d
new file mode 100644
index 00000000000..e911dff7729
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/tolvalue.d
@@ -0,0 +1,48 @@
+/**
+TEST_OUTPUT:
+---
+fail_compilation/tolvalue.d(28): Error: cannot take address of template `templateFunc(T)()`, perhaps instantiate it first
+fail_compilation/tolvalue.d(29): Error: cannot take address of type `int`
+fail_compilation/tolvalue.d(30): Error: cannot take address of constant `3`
+fail_compilation/tolvalue.d(31): Error: cannot take address of operator `$`
+fail_compilation/tolvalue.d(32): Error: cannot take address of compiler-generated variable `__ctfe`
+fail_compilation/tolvalue.d(33): Error: cannot take address of manifest constant `f`
+fail_compilation/tolvalue.d(38): Error: cannot create default argument for `ref` / `out` parameter from constant `3`
+fail_compilation/tolvalue.d(39): Error: cannot create default argument for `ref` / `out` parameter from compiler-generated variable `__ctfe`
+fail_compilation/tolvalue.d(40): Error: cannot create default argument for `ref` / `out` parameter from manifest constant `f`
+fail_compilation/tolvalue.d(45): Error: cannot modify constant `3`
+fail_compilation/tolvalue.d(46): Error: cannot modify compiler-generated variable `__ctfe`
+fail_compilation/tolvalue.d(47): Error: cannot modify manifest constant `f`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=24238
+
+void templateFunc(T)() {}
+alias intAlias = int;
+enum E { f }
+
+void addr()
+{
+    int[] a;
+    auto x0 = &templateFunc;
+    auto x1 = &intAlias;
+    auto x2 = &3;
+    auto x3 = a[&$];
+    auto x4 = &__ctfe;
+    auto x6 = &E.f;
+}
+
+void refArg()
+{
+    void f0(ref int = 3) {}
+    void f1(ref bool = __ctfe) {}
+    void f3(ref E = E.f) {}
+}
+
+void inc(int lz)
+{
+    3++;
+    __ctfe++;
+    E.f++;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/vector_cast.d b/gcc/testsuite/gdc.test/fail_compilation/vector_cast.d
new file mode 100644
index 00000000000..e8a8d48c790
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/vector_cast.d
@@ -0,0 +1,13 @@
+/**
+REQUIRED_ARGS: -m64
+TEST_OUTPUT:
+---
+fail_compilation/vector_cast.d(11): Error: cannot cast expression `a` of type `int[3]` to `__vector(int[4])`
+fail_compilation/vector_cast.d(13): Error: cannot cast expression `a` of type `int[5]` to `__vector(int[4])`
+---
+*/
+
+alias int4 = __vector(int[4]);
+int4 convtest3(int[3] a) { return cast(int4) a; }
+int4 convtest4(int[4] a) { return cast(int4) a; }
+int4 convtest5(int[5] a) { return cast(int4) a; }
diff --git a/gcc/testsuite/gdc.test/runnable/staticaa.d b/gcc/testsuite/gdc.test/runnable/staticaa.d
index 17a2ecb5ec7..606b70e908a 100644
--- a/gcc/testsuite/gdc.test/runnable/staticaa.d
+++ b/gcc/testsuite/gdc.test/runnable/staticaa.d
@@ -56,7 +56,7 @@ struct Key
 {
     int v;
     bool opEquals(ref const Key o) const { return v == o.v; }
-    size_t toHash() const { return v; }
+    size_t toHash() const nothrow { return v; }
 }
 
 Destructing[Key] dAa = [Key(1): Destructing(10), Key(2): Destructing(20)];
@@ -142,6 +142,18 @@ void testImmutable()
 
 /////////////////////////////////////////////
 
+// https://issues.dlang.org/show_bug.cgi?id=24209
+void testLocalStatic() @trusted
+{
+    static int[int] aa0 = [1: 2];
+    __gshared string[string] aa1 = null;
+
+    assert(aa0[1] == 2);
+    assert(aa1.length == 0);
+}
+
+/////////////////////////////////////////////
+
 void main()
 {
     testSimple();
@@ -150,4 +162,5 @@ void main()
     testStructInit();
     testClassInit();
     testImmutable();
+    testLocalStatic();
 }
diff --git a/gcc/testsuite/gdc.test/runnable/test24184.d b/gcc/testsuite/gdc.test/runnable/test24184.d
new file mode 100644
index 00000000000..736824fce86
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test24184.d
@@ -0,0 +1,30 @@
+// https://issues.dlang.org/show_bug.cgi?id=24184
+
+void stage3(alias abc)(ubyte[])
+{
+    bool skipSpaces()
+    {
+        abc();
+        return false;
+    }
+    skipSpaces;
+}
+ubyte[] singleThreadJsonImpl(alias xxx)(ubyte[] table)
+{
+    align(64) ubyte[] vector;
+
+    ubyte[] abc() { return vector; }
+
+    stage3!(abc)(table);
+
+    return table;
+}
+ubyte[] singleThreadJsonText()
+{
+    bool xxx() { return true; }
+
+    return singleThreadJsonImpl!(xxx)([]);
+}
+void deserializeJson() { singleThreadJsonText(); }
+
+void main() { deserializeJson(); }
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 235db4b2ef1..aa0062c10eb 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-643b1261bba0757d97efa3ff1f63e461271eb000
+ff57fec51558013b25cadb7e83da9f4675915d56
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/core/cpuid.d b/libphobos/libdruntime/core/cpuid.d
index b79bd1df9c4..9c5735728b5 100644
--- a/libphobos/libdruntime/core/cpuid.d
+++ b/libphobos/libdruntime/core/cpuid.d
@@ -666,10 +666,12 @@ void getAMDcacheinfo()
 // to determine number of processors.
 void getCpuInfo0B()
 {
-    int level=0;
     int threadsPerCore;
     uint a, b, c, d;
-    do {
+    // I'm not sure about this. The docs state that there
+    // are 2 hyperthreads per core if HT is factory enabled.
+    for (int level = 0; level < 2; level++)
+    {
         version (GNU_OR_LDC) asm pure nothrow @nogc {
             "cpuid" : "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (0x0B), "c" (level);
         } else asm pure nothrow @nogc {
@@ -681,19 +683,20 @@ void getCpuInfo0B()
             mov c, ECX;
             mov d, EDX;
         }
-        if (b!=0) {
-           // I'm not sure about this. The docs state that there
-           // are 2 hyperthreads per core if HT is factory enabled.
-            if (level==0)
+        if (b != 0)
+        {
+            if (level == 0)
                 threadsPerCore = b & 0xFFFF;
-            else if (level==1) {
+            else if (level == 1)
+            {
                 cpuFeatures.maxThreads = b & 0xFFFF;
                 cpuFeatures.maxCores = cpuFeatures.maxThreads / threadsPerCore;
             }
-
         }
-        ++level;
-    } while (a!=0 || b!=0);
+        // Got "invalid domain" returned from cpuid
+        if (a == 0 && b == 0)
+            break;
+    }
 }
 
 void cpuidX86()
diff --git a/libphobos/libdruntime/core/internal/array/appending.d b/libphobos/libdruntime/core/internal/array/appending.d
index bb24813ae9e..ba34727a305 100644
--- a/libphobos/libdruntime/core/internal/array/appending.d
+++ b/libphobos/libdruntime/core/internal/array/appending.d
@@ -14,56 +14,55 @@ private extern (C) byte[] _d_arrayappendcTX(const TypeInfo ti, ref return scope
 
 private enum isCopyingNothrow(T) = __traits(compiles, (ref T rhs) nothrow { T lhs = rhs; });
 
-/// Implementation of `_d_arrayappendcTX` and `_d_arrayappendcTXTrace`
-template _d_arrayappendcTXImpl(Tarr : T[], T)
+/**
+ * Extend an array `px` by `n` elements.
+ * Caller must initialize those elements.
+ * Params:
+ *  px = the array that will be extended, taken as a reference
+ *  n = how many new elements to extend it with
+ * Returns:
+ *  The new value of `px`
+ * Bugs:
+ *  This function template was ported from a much older runtime hook that bypassed safety,
+ *  purity, and throwabilty checks. To prevent breaking existing code, this function template
+ *  is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
+ */
+ref Tarr _d_arrayappendcTX(Tarr : T[], T)(return ref scope Tarr px, size_t n) @trusted
 {
-    private enum errorMessage = "Cannot append to array if compiling without support for runtime type information!";
+    // needed for CTFE: https://github.com/dlang/druntime/pull/3870#issuecomment-1178800718
+    version (DigitalMars) pragma(inline, false);
+    version (D_TypeInfo)
+    {
+        auto ti = typeid(Tarr);
+
+        // _d_arrayappendcTX takes the `px` as a ref byte[], but its length
+        // should still be the original length
+        auto pxx = (cast(byte*)px.ptr)[0 .. px.length];
+        ._d_arrayappendcTX(ti, pxx, n);
+        px = (cast(T*)pxx.ptr)[0 .. pxx.length];
+
+        return px;
+    }
+    else
+        assert(0, "Cannot append to array if compiling without support for runtime type information!");
+}
 
+version (D_ProfileGC)
+{
     /**
-     * Extend an array `px` by `n` elements.
-     * Caller must initialize those elements.
-     * Params:
-     *  px = the array that will be extended, taken as a reference
-     *  n = how many new elements to extend it with
-     * Returns:
-     *  The new value of `px`
-     * Bugs:
-     *  This function template was ported from a much older runtime hook that bypassed safety,
-     *  purity, and throwabilty checks. To prevent breaking existing code, this function template
-     *  is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
+     * TraceGC wrapper around $(REF _d_arrayappendT, core,internal,array,appending).
      */
-    ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
+    ref Tarr _d_arrayappendcTXTrace(Tarr : T[], T)(string file, int line, string funcname, return ref scope Tarr px, size_t n) @trusted
     {
-        // needed for CTFE: https://github.com/dlang/druntime/pull/3870#issuecomment-1178800718
-        version (DigitalMars) pragma(inline, false);
         version (D_TypeInfo)
         {
-            auto ti = typeid(Tarr);
-
-            // _d_arrayappendcTX takes the `px` as a ref byte[], but its length
-            // should still be the original length
-            auto pxx = (cast(byte*)px.ptr)[0 .. px.length];
-            ._d_arrayappendcTX(ti, pxx, n);
-            px = (cast(T*)pxx.ptr)[0 .. pxx.length];
+            import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure;
+            mixin(TraceHook!(Tarr.stringof, "_d_arrayappendcTX"));
 
-            return px;
+            return _d_arrayappendcTX(px, n);
         }
         else
-            assert(0, errorMessage);
-    }
-
-    version (D_ProfileGC)
-    {
-        import core.internal.array.utils : _d_HookTraceImpl;
-
-        /**
-         * TraceGC wrapper around $(REF _d_arrayappendcTX, rt,array,appending,_d_arrayappendcTXImpl).
-         * Bugs:
-         *  This function template was ported from a much older runtime hook that bypassed safety,
-         *  purity, and throwabilty checks. To prevent breaking existing code, this function template
-         *  is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
-         */
-        alias _d_arrayappendcTXTrace = _d_HookTraceImpl!(Tarr, _d_arrayappendcTX, errorMessage);
+            static assert(0, "Cannot append to array if compiling without support for runtime type information!");
     }
 }
 
@@ -78,7 +77,7 @@ ref Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y) @
     enum hasPostblit = __traits(hasPostblit, T);
     auto length = x.length;
 
-    _d_arrayappendcTXImpl!Tarr._d_arrayappendcTX(x, y.length);
+    _d_arrayappendcTX(x, y.length);
 
     // Only call `copyEmplace` if `T` has a copy ctor and no postblit.
     static if (hasElaborateCopyConstructor!T && !hasPostblit)
@@ -126,7 +125,7 @@ version (D_ProfileGC)
             return _d_arrayappendT(x, y);
         }
         else
-            assert(0, "Cannot append to array if compiling without support for runtime type information!");
+            static assert(0, "Cannot append to array if compiling without support for runtime type information!");
     }
 }
 
diff --git a/libphobos/libdruntime/core/internal/array/construction.d b/libphobos/libdruntime/core/internal/array/construction.d
index 54f8767139c..655acc8db57 100644
--- a/libphobos/libdruntime/core/internal/array/construction.d
+++ b/libphobos/libdruntime/core/internal/array/construction.d
@@ -486,3 +486,111 @@ version (D_ProfileGC)
             assert(0, "Cannot create new array if compiling without support for runtime type information!");
     }
 }
+
+/**
+ * Create a new multi-dimensional array. Also initalize elements if their type has an initializer.
+ * Otherwise, not zero-initialize the array.
+ *
+ * ---
+ * void main()
+ * {
+ *     S[][] s = new S[][](2, 3)
+ *
+ *     // lowering:
+ *     S[] s = _d_newarraymTX!(S[][], S)([2, 3]);
+ * }
+ * ---
+ *
+ * Params:
+ *    dims = array length values for each dimension
+ *    isShared = whether the array should be shared
+ *
+ * Returns:
+ *    newly allocated array
+ */
+Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trusted
+{
+    debug(PRINTF) printf("_d_newarraymTX(dims.length = %d)\n", dims.length);
+
+    if (dims.length == 0)
+        return null;
+
+    alias UnqT = Unqual!(T);
+
+    void[] __allocateInnerArray(size_t[] dims)
+    {
+        import core.internal.array.utils : __arrayStart, __setArrayAllocLength, __arrayAlloc;
+
+        auto dim = dims[0];
+
+        debug(PRINTF) printf("__allocateInnerArray(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, dims.length);
+        if (dims.length == 1)
+        {
+            auto r = _d_newarrayT!UnqT(dim, isShared);
+            return *cast(void[]*)(&r);
+        }
+
+        auto allocSize = (void[]).sizeof * dim;
+        auto info = __arrayAlloc!UnqT(allocSize);
+        __setArrayAllocLength!UnqT(info, allocSize, isShared);
+        auto p = __arrayStart(info)[0 .. dim];
+
+        foreach (i; 0..dim)
+        {
+            (cast(void[]*)p.ptr)[i] = __allocateInnerArray(dims[1..$]);
+        }
+        return p;
+    }
+
+    auto result = __allocateInnerArray(dims);
+    debug(PRINTF) printf("result = %llx\n", result.ptr);
+
+    return (cast(U*) result.ptr)[0 .. dims[0]];
+}
+
+unittest
+{
+    int[][] a = _d_newarraymTX!(int[][], int)([2, 3]);
+
+    assert(a.length == 2);
+    for (size_t i = 0; i < a.length; i++)
+    {
+        assert(a[i].length == 3);
+        for (size_t j = 0; j < a[i].length; j++)
+            assert(a[i][j] == 0);
+    }
+}
+
+unittest
+{
+    struct S { int x = 1; }
+
+    S[][] a = _d_newarraymTX!(S[][], S)([2, 3]);
+
+    assert(a.length == 2);
+    for (size_t i = 0; i < a.length; i++)
+    {
+        assert(a[i].length == 3);
+        for (size_t j = 0; j < a[i].length; j++)
+            assert(a[i][j].x == 1);
+    }
+}
+
+version (D_ProfileGC)
+{
+    /**
+    * TraceGC wrapper around $(REF _d_newarraymT, core,internal,array,construction).
+    */
+    Tarr _d_newarraymTXTrace(Tarr : U[], T, U)(string file, int line, string funcname, size_t[] dims, bool isShared=false) @trusted
+    {
+        version (D_TypeInfo)
+        {
+            import core.internal.array.utils : TraceHook, gcStatsPure, accumulatePure;
+            mixin(TraceHook!(T.stringof, "_d_newarraymTX"));
+
+            return _d_newarraymTX!(Tarr, T)(dims, isShared);
+        }
+        else
+            assert(0, "Cannot create new multi-dimensional array if compiling without support for runtime type information!");
+    }
+}
diff --git a/libphobos/libdruntime/core/internal/atomic.d b/libphobos/libdruntime/core/internal/atomic.d
index 5daab89a387..eebf94ee29d 100644
--- a/libphobos/libdruntime/core/internal/atomic.d
+++ b/libphobos/libdruntime/core/internal/atomic.d
@@ -656,7 +656,7 @@ version (DigitalMars)
             asm pure nothrow @nogc @trusted
             {
                 naked;
-                rep; nop;
+                pause;
                 ret;
             }
         }
@@ -665,8 +665,7 @@ version (DigitalMars)
             asm pure nothrow @nogc @trusted
             {
                 naked;
-    //            pause; // TODO: DMD should add this opcode to its inline asm
-                rep; nop;
+                pause;
                 ret;
             }
         }
diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
index 39cd30aee16..6f194126e7e 100644
--- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
+++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
@@ -3336,7 +3336,7 @@ Lmark:
 
         busyThreads.atomicOp!"+="(1); // main thread is busy
 
-        evStart.set();
+        evStart.setIfInitialized();
 
         debug(PARALLEL_PRINTF) printf("mark %lld roots\n", cast(ulong)(ptop - pbot));
 
@@ -3438,7 +3438,7 @@ Lmark:
         stopGC = true;
         while (atomicLoad(stoppedThreads) < startedThreads && !allThreadsDead)
         {
-            evStart.set();
+            evStart.setIfInitialized();
             evDone.wait(dur!"msecs"(1));
         }
 
@@ -3467,7 +3467,7 @@ Lmark:
         {
             evStart.wait();
             pullFromScanStack();
-            evDone.set();
+            evDone.setIfInitialized();
         }
         stoppedThreads.atomicOp!"+="(1);
     }
diff --git a/libphobos/libdruntime/core/internal/newaa.d b/libphobos/libdruntime/core/internal/newaa.d
index 314f2554103..2fd93651a22 100644
--- a/libphobos/libdruntime/core/internal/newaa.d
+++ b/libphobos/libdruntime/core/internal/newaa.d
@@ -50,6 +50,7 @@ struct Impl
     immutable uint valsz;
     immutable uint valoff;
     Flags flags;
+    size_t delegate(scope const void*) nothrow hashFn;
 
     enum Flags : ubyte
     {
@@ -76,15 +77,19 @@ private size_t mix(size_t h) @safe pure nothrow @nogc
 
 struct Entry(K, V)
 {
-    /*const*/ K key; // this really should be const, but legacy issues.
+    // can make this const, because we aren't really going to use it aside from
+    // construction.
+    const K key;
     V value;
 }
 
 
 // create a binary-compatible AA structure that can be used directly as an
 // associative array.
-AAShell makeAA(K, V)(V[K] src)
+// NOTE: this must only be called during CTFE
+AAShell makeAA(K, V)(V[K] src) @trusted
 {
+    assert(__ctfe, "makeAA Must only be called at compile time");
     immutable srclen = src.length;
     assert(srclen <= uint.max);
     alias E = Entry!(K, V);
@@ -96,6 +101,12 @@ AAShell makeAA(K, V)(V[K] src)
     while (srclen * GROW_DEN > dim * GROW_NUM)
         dim = dim * GROW_FAC;
 
+    // used during runtime.
+    size_t delegate(scope const void *) nothrow hashFn = (scope const void* val) {
+        auto x = cast(K*)val;
+        return hashOf(*x);
+    };
+
     Bucket[] buckets;
     // Allocate and fill the buckets
     if (__ctfe)
@@ -140,5 +151,19 @@ AAShell makeAA(K, V)(V[K] src)
     } ();
     // return the new implementation
     return AAShell(new Impl(buckets, cast(uint)srclen, 0, typeid(E), firstUsed,
-            K.sizeof, V.sizeof, E.value.offsetof, flags));
+            K.sizeof, V.sizeof, E.value.offsetof, flags, hashFn));
+}
+
+unittest
+{
+    static struct Foo
+    {
+        ubyte x;
+        double d;
+    }
+    static int[Foo] utaa = [Foo(1, 2.0) : 5];
+    auto k = Foo(1, 2.0);
+    // verify that getHash doesn't match hashOf for Foo
+    assert(typeid(Foo).getHash(&k) != hashOf(k));
+    assert(utaa[Foo(1, 2.0)] == 5);
 }
diff --git a/libphobos/libdruntime/core/stdc/fenv.d b/libphobos/libdruntime/core/stdc/fenv.d
index 288f9c25dc6..0051ecdb7c9 100644
--- a/libphobos/libdruntime/core/stdc/fenv.d
+++ b/libphobos/libdruntime/core/stdc/fenv.d
@@ -797,7 +797,7 @@ else
     }
     else version (LoongArch64)
     {
-        // Define bits representing exceptions in the FPSR status word.
+        // Define bits representing exceptions in the Flags field in FCSR{0,2}.
         enum
         {
             FE_INEXACT      = 0x010000, ///
@@ -808,13 +808,13 @@ else
             FE_ALL_EXCEPT   = 0x1f0000, ///
         }
 
-        // Define bits representing rounding modes in the FPCR Rmode field.
+        // Define bits representing rounding modes in the RM field in FCSR{0,3}.
         enum
         {
             FE_TONEAREST    = 0x000, ///
             FE_TOWARDZERO   = 0x100, ///
-            FE_DOWNWARD     = 0x200, ///
-            FE_UPWARD       = 0x300, ///
+            FE_UPWARD       = 0x200, ///
+            FE_DOWNWARD     = 0x300, ///
         }
     }
     else
diff --git a/libphobos/libdruntime/core/stdc/stdarg.d b/libphobos/libdruntime/core/stdc/stdarg.d
index 5b79813ae1b..0ba1ebe34e3 100644
--- a/libphobos/libdruntime/core/stdc/stdarg.d
+++ b/libphobos/libdruntime/core/stdc/stdarg.d
@@ -257,6 +257,12 @@ T va_arg(T)(ref va_list ap)
         ap += T.sizeof.alignUp;
         return *p;
     }
+    else version (LoongArch64)
+    {
+        auto p = cast(T*) ap;
+        ap += T.sizeof.alignUp;
+        return *p;
+    }
     else version (MIPS_Any)
     {
         auto p = cast(T*) ap;
diff --git a/libphobos/libdruntime/core/sync/event.d b/libphobos/libdruntime/core/sync/event.d
index 37951061d93..048607f6ed2 100644
--- a/libphobos/libdruntime/core/sync/event.d
+++ b/libphobos/libdruntime/core/sync/event.d
@@ -61,7 +61,7 @@ struct ProcessFile
             group.create(&doProcess);
 
         buffer = std.file.read(filename);
-        event.set();
+        event.setIfInitialized();
         group.joinAll();
         event.terminate();
     }
@@ -162,9 +162,13 @@ nothrow @nogc:
         }
     }
 
+    deprecated ("Use setIfInitialized() instead") void set()
+    {
+        setIfInitialized();
+    }
 
     /// Set the event to "signaled", so that waiting clients are resumed
-    void set()
+    void setIfInitialized()
     {
         version (Windows)
         {
@@ -302,7 +306,7 @@ private:
     // auto-reset, initial state false
     Event ev1 = Event(false, false);
     assert(!ev1.wait(1.dur!"msecs"));
-    ev1.set();
+    ev1.setIfInitialized();
     assert(ev1.wait());
     assert(!ev1.wait(1.dur!"msecs"));
 
@@ -336,7 +340,7 @@ unittest
     auto start = MonoTime.currTime;
     assert(numRunning == 0);
 
-    event.set();
+    event.setIfInitialized();
     group.joinAll();
 
     assert(numRunning == numThreads);
diff --git a/libphobos/libdruntime/core/sys/elf/package.d b/libphobos/libdruntime/core/sys/elf/package.d
index b120ee58f69..60e05d97036 100644
--- a/libphobos/libdruntime/core/sys/elf/package.d
+++ b/libphobos/libdruntime/core/sys/elf/package.d
@@ -339,6 +339,8 @@ enum EM_CSKY =        252;
 
 enum EM_NUM =         253;
 
+enum EM_LOONGARCH =   258;
+
 enum EM_ALPHA =        0x9026;
 
 enum EV_NONE =         0;
diff --git a/libphobos/libdruntime/core/sys/linux/sys/auxv.d b/libphobos/libdruntime/core/sys/linux/sys/auxv.d
index 5f098e98e02..1099fae497f 100644
--- a/libphobos/libdruntime/core/sys/linux/sys/auxv.d
+++ b/libphobos/libdruntime/core/sys/linux/sys/auxv.d
@@ -13,6 +13,7 @@ extern (C):
 
 version (MIPS32)  version = MIPS_Any;
 version (MIPS64)  version = MIPS_Any;
+version (LoongArch64) version = LoongArch_Any;
 version (PPC)     version = PPC_Any;
 version (PPC64)   version = PPC_Any;
 version (S390)    version = IBMZ_Any;
@@ -156,3 +157,19 @@ else version (IBMZ_Any)
   enum HWCAP_S390_TE                      = 1024;
   enum HWCAP_S390_VX                      = 2048;
 }
+else version (LoongArch_Any)
+{
+  enum HWCAP_LOONGARCH_CPUCFG             = 0x00000001;
+  enum HWCAP_LOONGARCH_LAM                = 0x00000002;
+  enum HWCAP_LOONGARCH_UAL                = 0x00000004;
+  enum HWCAP_LOONGARCH_FPU                = 0x00000008;
+  enum HWCAP_LOONGARCH_LSX                = 0x00000010;
+  enum HWCAP_LOONGARCH_LASX               = 0x00000020;
+  enum HWCAP_LOONGARCH_CRC32              = 0x00000040;
+  enum HWCAP_LOONGARCH_COMPLEX            = 0x00000080;
+  enum HWCAP_LOONGARCH_CRYPTO             = 0x00000100;
+  enum HWCAP_LOONGARCH_LVZ                = 0x00000200;
+  enum HWCAP_LOONGARCH_LBT_X86            = 0x00000400;
+  enum HWCAP_LOONGARCH_LBT_ARM            = 0x00000800;
+  enum HWCAP_LOONGARCH_LBT_MIPS           = 0x00001000;
+}
diff --git a/libphobos/libdruntime/core/sys/linux/sys/mman.d b/libphobos/libdruntime/core/sys/linux/sys/mman.d
index 7ed78ef6436..e4765af1490 100644
--- a/libphobos/libdruntime/core/sys/linux/sys/mman.d
+++ b/libphobos/libdruntime/core/sys/linux/sys/mman.d
@@ -432,6 +432,7 @@ else version (MIPS_Any)
         MAP_HUGETLB = 0x80000,
     }
 }
+// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/bits/mman-map-flags-generic.h
 else version (LoongArch64)
 {
     static if (_DEFAULT_SOURCE) enum
diff --git a/libphobos/libdruntime/core/thread/fiber.d b/libphobos/libdruntime/core/thread/fiber.d
index 65878bc1c66..8bbd6e15c4e 100644
--- a/libphobos/libdruntime/core/thread/fiber.d
+++ b/libphobos/libdruntime/core/thread/fiber.d
@@ -178,8 +178,12 @@ private
     }
     else version (LoongArch64)
     {
-        version = AsmLoongArch64_Posix;
-        version = AsmExternal;
+        version (Posix)
+        {
+            version = AsmLoongArch64_Posix;
+            version = AsmExternal;
+            version = AlignFiberStackTo16Byte;
+        }
     }
 
     version (Posix)
@@ -1444,24 +1448,28 @@ private:
         }
         else version (AsmLoongArch64_Posix)
         {
+            // Like others, FP registers and return address ($r1) are kept
+            // below the saved stack top (tstack) to hide from GC scanning.
+            // fiber_switchContext expects newp sp to look like this:
+            //   10: $r21 (reserved)
+            //    9: $r22 (frame pointer)
+            //    8: $r23
+            //   ...
+            //    0: $r31 <-- newp tstack
+            //   -1: $r1  (return address)  [&fiber_entryPoint]
+            //   -2: $f24
+            //   ...
+            //   -9: $f31
+
             version (StackGrowsDown) {}
-            else static assert(0);
+            else
+                static assert(false, "Only full descending stacks supported on LoongArch64");
 
-            // Like others, FP registers and return address (ra) are kept
-            // below the saved stack top (tstack) to hide from GC scanning.
-            // The newp stack should look like this on LoongArch64:
-            // 18: fp     <- pstack
-            // ...
-            //  9: s0     <- newp tstack
-            //  8: ra     [&fiber_entryPoint]
-            //  7: fs7
-            // ...
-            //  1: fs1
-            //  0: fs0
-            pstack -= 10 * size_t.sizeof; // skip s0-s8 and fp
-            // set $ra
-            push( cast(size_t) &fiber_entryPoint );
-            pstack += size_t.sizeof;
+            // Only need to set return address ($r1).  Everything else is fine
+            // zero initialized.
+            pstack -= size_t.sizeof * 11;    // skip past space reserved for $r21-$r31
+            push (cast(size_t) &fiber_entryPoint);
+            pstack += size_t.sizeof;         // adjust sp (newp) above lr
         }
         else version (AsmAArch64_Posix)
         {
diff --git a/libphobos/libdruntime/core/vararg.d b/libphobos/libdruntime/core/vararg.d
index 2c3e9659fb6..e6dd47d06d3 100644
--- a/libphobos/libdruntime/core/vararg.d
+++ b/libphobos/libdruntime/core/vararg.d
@@ -129,6 +129,13 @@ void va_arg()(ref va_list ap, TypeInfo ti, void* parmn)
         ap += tsize.alignUp;
         parmn[0..tsize] = p[0..tsize];
     }
+    else version (LoongArch64)
+    {
+        const tsize = ti.tsize;
+        auto p = cast(void*) ap;
+        ap += tsize.alignUp;
+        parmn[0..tsize] = p[0..tsize];
+    }
     else version (MIPS_Any)
     {
         const tsize = ti.tsize;
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index 0111be0b617..5589c0a884f 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -642,7 +642,8 @@ class TypeInfo
      */
     size_t getHash(scope const void* p) @trusted nothrow const
     {
-        return hashOf(p);
+        // by default, do not assume anything about the type
+        return 0;
     }
 
     /// Compares two instances for equality.
@@ -2918,19 +2919,19 @@ alias AssociativeArray(Key, Value) = Value[Key];
  * Params:
  *      aa =     The associative array.
  */
-void clear(Value, Key)(Value[Key] aa)
+void clear(Value, Key)(Value[Key] aa) @trusted
 {
     _aaClear(*cast(AA *) &aa);
 }
 
 /** ditto */
-void clear(Value, Key)(Value[Key]* aa)
+void clear(Value, Key)(Value[Key]* aa) @trusted
 {
     _aaClear(*cast(AA *) aa);
 }
 
 ///
-@system unittest
+@safe unittest
 {
     auto aa = ["k1": 2];
     aa.clear;
@@ -4666,11 +4667,13 @@ public import core.internal.array.appending : _d_arrayappendT;
 version (D_ProfileGC)
 {
     public import core.internal.array.appending : _d_arrayappendTTrace;
+    public import core.internal.array.appending : _d_arrayappendcTXTrace;
     public import core.internal.array.concatenation : _d_arraycatnTXTrace;
     public import core.lifetime : _d_newitemTTrace;
     public import core.internal.array.construction : _d_newarrayTTrace;
+    public import core.internal.array.construction : _d_newarraymTXTrace;
 }
-public import core.internal.array.appending : _d_arrayappendcTXImpl;
+public import core.internal.array.appending : _d_arrayappendcTX;
 public import core.internal.array.comparison : __cmp;
 public import core.internal.array.equality : __equals;
 public import core.internal.array.casting: __ArrayCast;
@@ -4678,6 +4681,7 @@ public import core.internal.array.concatenation : _d_arraycatnTX;
 public import core.internal.array.construction : _d_arrayctor;
 public import core.internal.array.construction : _d_arraysetctor;
 public import core.internal.array.construction : _d_newarrayT;
+public import core.internal.array.construction : _d_newarraymTX;
 public import core.internal.array.arrayassign : _d_arrayassign_l;
 public import core.internal.array.arrayassign : _d_arrayassign_r;
 public import core.internal.array.arrayassign : _d_arraysetassign;
diff --git a/libphobos/libdruntime/rt/aaA.d b/libphobos/libdruntime/rt/aaA.d
index 4014862b4e4..36f25554db3 100644
--- a/libphobos/libdruntime/rt/aaA.d
+++ b/libphobos/libdruntime/rt/aaA.d
@@ -41,7 +41,7 @@ struct AA
     Impl* impl;
     alias impl this;
 
-    private @property bool empty() const pure nothrow @nogc
+    private @property bool empty() const pure nothrow @nogc @safe
     {
         return impl is null || !impl.length;
     }
@@ -57,6 +57,7 @@ private:
         buckets = allocBuckets(sz);
         firstUsed = cast(uint) buckets.length;
         valoff = cast(uint) talign(keysz, ti.value.talign);
+        hashFn = &ti.key.getHash;
 
         import rt.lifetime : hasPostblit, unqualify;
 
@@ -78,6 +79,10 @@ private:
     immutable uint valoff;
     Flags flags;
 
+    // function that calculates hash of a key. Set on creation
+    // the parameter is a pointer to the key.
+    size_t delegate(scope const void*) nothrow hashFn;
+
     enum Flags : ubyte
     {
         none = 0x0,
@@ -85,7 +90,7 @@ private:
         hasPointers = 0x2,
     }
 
-    @property size_t length() const pure nothrow @nogc
+    @property size_t length() const pure nothrow @nogc @safe
     {
         assert(used >= deleted);
         return used - deleted;
@@ -156,7 +161,7 @@ private:
         GC.free(obuckets.ptr); // safe to free b/c impossible to reference
     }
 
-    void clear() pure nothrow
+    void clear() pure nothrow @trusted
     {
         import core.stdc.string : memset;
         // clear all data, but don't change bucket array length
@@ -457,9 +462,9 @@ private size_t mix(size_t h) @safe pure nothrow @nogc
     return h;
 }
 
-private size_t calcHash(scope const void* pkey, scope const TypeInfo keyti) nothrow
+private size_t calcHash(scope const void *pkey, scope const Impl* impl) nothrow
 {
-    immutable hash = keyti.getHash(pkey);
+    immutable hash = impl.hashFn(pkey);
     // highest bit is set to distinguish empty/deleted from filled buckets
     return mix(hash) | HASH_FILLED_MARK;
 }
@@ -550,7 +555,7 @@ extern (C) void* _aaGetX(scope AA* paa, const TypeInfo_AssociativeArray ti,
     }
 
     // get hash and bucket for key
-    immutable hash = calcHash(pkey, ti.key);
+    immutable hash = calcHash(pkey, aa);
 
     // found a value => return it
     if (auto p = aa.findSlotLookup(hash, pkey, ti.key))
@@ -617,7 +622,7 @@ extern (C) inout(void)* _aaInX(inout AA aa, scope const TypeInfo keyti, scope co
     if (aa.empty)
         return null;
 
-    immutable hash = calcHash(pkey, keyti);
+    immutable hash = calcHash(pkey, aa);
     if (auto p = aa.findSlotLookup(hash, pkey, keyti))
         return p.entry + aa.valoff;
     return null;
@@ -629,7 +634,7 @@ extern (C) bool _aaDelX(AA aa, scope const TypeInfo keyti, scope const void* pke
     if (aa.empty)
         return false;
 
-    immutable hash = calcHash(pkey, keyti);
+    immutable hash = calcHash(pkey, aa);
     if (auto p = aa.findSlotLookup(hash, pkey, keyti))
     {
         // clear entry
@@ -648,7 +653,7 @@ extern (C) bool _aaDelX(AA aa, scope const TypeInfo keyti, scope const void* pke
 }
 
 /// Remove all elements from AA.
-extern (C) void _aaClear(AA aa) pure nothrow
+extern (C) void _aaClear(AA aa) pure nothrow @safe
 {
     if (!aa.empty)
     {
@@ -778,7 +783,7 @@ extern (C) Impl* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void
     uint actualLength = 0;
     foreach (_; 0 .. length)
     {
-        immutable hash = calcHash(pkey, ti.key);
+        immutable hash = calcHash(pkey, aa);
 
         auto p = aa.findSlotLookup(hash, pkey, ti.key);
         if (p is null)
diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d
index af3c6bb1296..8ce2d564bd6 100644
--- a/libphobos/libdruntime/rt/lifetime.d
+++ b/libphobos/libdruntime/rt/lifetime.d
@@ -1041,98 +1041,6 @@ extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length) pure nothrow @
     }
 }
 
-
-/*
- * Helper for creating multi-dimensional arrays
- */
-private void[] _d_newarrayOpT(alias op)(const TypeInfo ti, size_t[] dims)
-{
-    debug(PRINTF) printf("_d_newarrayOpT(ndims = %d)\n", dims.length);
-    if (dims.length == 0)
-        return null;
-
-    void[] foo(const TypeInfo ti, size_t[] dims)
-    {
-        auto tinext = unqualify(ti.next);
-        auto dim = dims[0];
-
-        debug(PRINTF) printf("foo(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, dims.length);
-        if (dims.length == 1)
-        {
-            auto r = op(ti, dim);
-            return *cast(void[]*)(&r);
-        }
-
-        auto allocsize = (void[]).sizeof * dim;
-        auto info = __arrayAlloc(allocsize, ti, tinext);
-        auto isshared = typeid(ti) is typeid(TypeInfo_Shared);
-        __setArrayAllocLength(info, allocsize, isshared, tinext);
-        auto p = __arrayStart(info)[0 .. dim];
-
-        foreach (i; 0..dim)
-        {
-            (cast(void[]*)p.ptr)[i] = foo(tinext, dims[1..$]);
-        }
-        return p;
-    }
-
-    auto result = foo(ti, dims);
-    debug(PRINTF) printf("result = %llx\n", result.ptr);
-
-    return result;
-}
-
-
-/**
-Create a new multi-dimensional array
-
-Has two variants:
-- `_d_newarraymTX` which initializes to 0
-- `_d_newarraymiTX` which initializes elements based on `TypeInfo`
-
----
-void main()
-{
-    new int[][](10, 20);
-    // _d_newarraymTX(typeid(float), [10, 20]);
-
-    new float[][][](10, 20, 30);
-    // _d_newarraymiTX(typeid(float), [10, 20, 30]);
-}
----
-
-Params:
-    ti = `TypeInfo` of the array type
-    dims = array length values for each dimension
-
-Returns:
-    newly allocated array
-*/
-extern (C) void[] _d_newarraymTX(const TypeInfo ti, size_t[] dims) @weak
-{
-    debug(PRINTF) printf("_d_newarraymT(dims.length = %d)\n", dims.length);
-
-    if (dims.length == 0)
-        return null;
-    else
-    {
-        return _d_newarrayOpT!(_d_newarrayT)(ti, dims);
-    }
-}
-
-/// ditto
-extern (C) void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims) @weak
-{
-    debug(PRINTF) printf("_d_newarraymiT(dims.length = %d)\n", dims.length);
-
-    if (dims.length == 0)
-        return null;
-    else
-    {
-        return _d_newarrayOpT!(_d_newarrayiT)(ti, dims);
-    }
-}
-
 /**
 Non-template version of $(REF _d_newitemT, core,lifetime) that does not perform
 initialization. Needed for $(REF allocEntry, rt,aaA).
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 95b2778d141..1b20d58c1e2 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-fc06c514a8c4492f60fc89b8c4f857e6932fbcbd
+17bafda797296e04f40f16a9660e5a9685392db4
 
 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/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d
index 0adb88b2210..ef1170600b3 100644
--- a/libphobos/src/std/algorithm/iteration.d
+++ b/libphobos/src/std/algorithm/iteration.d
@@ -4809,26 +4809,41 @@ private template ReduceSeedType(E)
 /++
 Implements the homonym function (also known as `accumulate`, $(D
 compress), `inject`, or `foldl`) present in various programming
-languages of functional flavor. The call `fold!(fun)(range, seed)`
-first assigns `seed` to an internal variable `result`,
-also called the accumulator. Then, for each element `x` in $(D
-range), `result = fun(result, x)` gets evaluated. Finally, $(D
-result) is returned. The one-argument version `fold!(fun)(range)`
+languages of functional flavor, iteratively calling one or more predicates.
+
+$(P Each predicate in `fun` must take two arguments:)
+* An accumulator value
+* An element of the range `r`
+$(P Each predicate must return a value which implicitly converts to the
+type of the accumulator.)
+
+$(P For a single predicate,
+the call `fold!(fun)(range, seed)` will:)
+
+* Use `seed` to initialize an internal variable `result` (also called
+  the accumulator).
+* For each element `e` in $(D range), evaluate `result = fun(result, e)`.
+* Return $(D result).
+
+$(P The one-argument version `fold!(fun)(range)`
 works similarly, but it uses the first element of the range as the
-seed (the range must be non-empty).
+seed (the range must be non-empty) and iterates over the remaining
+elements.)
+
+Multiple results are produced when using multiple predicates.
 
 Params:
     fun = the predicate function(s) to apply to the elements
 
 See_Also:
-    $(HTTP en.wikipedia.org/wiki/Fold_(higher-order_function), Fold (higher-order function))
+    * $(HTTP en.wikipedia.org/wiki/Fold_(higher-order_function), Fold (higher-order function))
 
-    $(LREF sum) is similar to `fold!((a, b) => a + b)` that offers
-    precise summing of floating point numbers.
+    * $(LREF sum) is similar to `fold!((a, b) => a + b)` that offers
+      precise summing of floating point numbers.
 
-    This is functionally equivalent to $(LREF reduce) with the argument order
-    reversed, and without the need to use $(REF_ALTTEXT `tuple`,tuple,std,typecons)
-    for multiple seeds.
+    * `fold` is functionally equivalent to $(LREF reduce) with the argument order
+      reversed, and without the need to use $(REF_ALTTEXT `tuple`,tuple,std,typecons)
+      for multiple seeds.
 +/
 template fold(fun...)
 if (fun.length >= 1)
@@ -4836,20 +4851,21 @@ if (fun.length >= 1)
     /**
     Params:
         r = the $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to fold
-        seed = the initial value of the accumulator
+        seeds = the initial values of each accumulator (optional), one for each predicate
     Returns:
-        the accumulated `result`
+        Either the accumulated result for a single predicate, or a
+        $(REF_ALTTEXT `Tuple`,Tuple,std,typecons) of results.
      */
-    auto fold(R, S...)(R r, S seed)
+    auto fold(R, S...)(R r, S seeds)
     {
         static if (S.length < 2)
         {
-            return reduce!fun(seed, r);
+            return reduce!fun(seeds, r);
         }
         else
         {
             import std.typecons : tuple;
-            return reduce!fun(tuple(seed), r);
+            return reduce!fun(tuple(seeds), r);
         }
     }
 }
@@ -4860,10 +4876,10 @@ if (fun.length >= 1)
     immutable arr = [1, 2, 3, 4, 5];
 
     // Sum all elements
-    assert(arr.fold!((a, b) => a + b) == 15);
+    assert(arr.fold!((a, e) => a + e) == 15);
 
     // Sum all elements with explicit seed
-    assert(arr.fold!((a, b) => a + b)(6) == 21);
+    assert(arr.fold!((a, e) => a + e)(6) == 21);
 
     import std.algorithm.comparison : min, max;
     import std.typecons : tuple;
@@ -4875,10 +4891,10 @@ if (fun.length >= 1)
     assert(arr.fold!(min, max)(0, 7) == tuple(0, 7));
 
     // Can be used in a UFCS chain
-    assert(arr.map!(a => a + 1).fold!((a, b) => a + b) == 20);
+    assert(arr.map!(a => a + 1).fold!((a, e) => a + e) == 20);
 
     // Return the last element of any range
-    assert(arr.fold!((a, b) => b) == 5);
+    assert(arr.fold!((a, e) => e) == 5);
 }
 
 @safe @nogc pure nothrow unittest
diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d
index 37a08de7a8f..68979057f54 100644
--- a/libphobos/src/std/algorithm/searching.d
+++ b/libphobos/src/std/algorithm/searching.d
@@ -1546,28 +1546,96 @@ if (isInputRange!Range && !isInfinite!Range &&
 }
 
 // find
+/**
+Finds an element `e` of an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+where `pred(e)` is `true`.
+$(P
+$(PANEL
+$(UL
+$(LI `find` behaves similarly to `dropWhile` in other languages.)
+$(LI To _find the *last* matching element in a
+$(REF_ALTTEXT bidirectional, isBidirectionalRange, std,range,primitives) `haystack`,
+call `find!pred(retro(haystack))`. See $(REF retro, std,range).)
+)))
+
+Complexity:
+    `find` performs $(BIGOH walkLength(haystack)) evaluations of `pred`.
+
+Params:
+
+    pred = The predicate to match an element.
+    haystack = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
+               searched in.
+
+Returns:
+    `haystack` advanced such that the front element satisfies `pred`.
+    If no such element exists, returns an empty `haystack`.
+*/
+InputRange find(alias pred, InputRange)(InputRange haystack)
+if (isInputRange!InputRange)
+{
+    alias R = InputRange;
+    alias predFun = unaryFun!pred;
+    static if (isNarrowString!R)
+    {
+        import std.utf : decode;
+
+        immutable len = haystack.length;
+        size_t i = 0, next = 0;
+        while (next < len)
+        {
+            if (predFun(decode(haystack, next)))
+                return haystack[i .. $];
+            i = next;
+        }
+        return haystack[$ .. $];
+    }
+    else
+    {
+        //standard range
+        for ( ; !haystack.empty; haystack.popFront() )
+        {
+            if (predFun(haystack.front))
+                break;
+        }
+        return haystack;
+    }
+}
+
+///
+@safe unittest
+{
+    auto arr = [ 1, 2, 3, 4, 1 ];
+    assert(find!("a > 2")(arr) == [ 3, 4, 1 ]);
+
+    // with predicate alias
+    bool pred(int e) => e + 1 > 1.5;
+    assert(find!(pred)(arr) == arr);
+}
+
+@safe pure unittest
+{
+    int[] r = [ 1, 2, 3 ];
+    assert(find!(a=>a > 2)(r) == [3]);
+    bool pred(int x) { return x + 1 > 1.5; }
+    assert(find!(pred)(r) == r);
+
+    assert(find!(a=>a > 'v')("hello world") == "world");
+    assert(find!(a=>a%4 == 0)("日本語") == "本語");
+}
+
 /**
 Finds an individual element in an $(REF_ALTTEXT input range, isInputRange, std,range,primitives).
 Elements of `haystack` are compared with `needle` by using predicate
 `pred` with `pred(haystack.front, needle)`.
-`find` performs $(BIGOH walkLength(haystack)) evaluations of `pred`.
-
 The predicate is passed to $(REF binaryFun, std, functional), and can either accept a
 string, or any callable that can be executed via `pred(element, element)`.
 
-To _find the last occurrence of `needle` in a
-$(REF_ALTTEXT bidirectional, isBidirectionalRange, std,range,primitives) `haystack`,
-call `find(retro(haystack), needle)`. See $(REF retro, std,range).
-
-If no `needle` is provided, `pred(haystack.front)` will be evaluated on each
-element of the input range.
-
-If `input` is a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives),
+If `haystack` is a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives),
 `needle` can be a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) too.
 In this case `startsWith!pred(haystack, needle)` is evaluated on each evaluation.
 
-Note:
-    `find` behaves similar to `dropWhile` in other languages.
+$(NOTE To find the first element $(I not) matching the needle, use predicate `"a != b"`.)
 
 Complexity:
     `find` performs $(BIGOH walkLength(haystack)) evaluations of `pred`.
@@ -1579,21 +1647,16 @@ Complexity:
 Params:
 
     pred = The predicate for comparing each element with the needle, defaulting to equality `"a == b"`.
-           The negated predicate `"a != b"` can be used to search instead for the first
-           element $(I not) matching the needle.
-
     haystack = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
                searched in.
-
     needle = The element searched for.
 
 Returns:
-
     `haystack` advanced such that the front element is the one searched for;
     that is, until `binaryFun!pred(haystack.front, needle)` is `true`. If no
     such position exists, returns an empty `haystack`.
 
-See_ALso: $(LREF findAdjacent), $(LREF findAmong), $(LREF findSkip), $(LREF findSplit), $(LREF startsWith)
+See_Also: $(LREF findAdjacent), $(LREF findAmong), $(LREF findSkip), $(LREF findSplit), $(LREF startsWith)
 */
 InputRange find(alias pred = "a == b", InputRange, Element)(InputRange haystack, scope Element needle)
 if (isInputRange!InputRange &&
@@ -1754,8 +1817,8 @@ if (isInputRange!InputRange &&
     assert(arr.find(4) == [4, 4, 4, 4, 5, 6, 9]);
     assert(arr.find(1) == arr);
     assert(arr.find(9) == [9]);
-    assert(arr.find!((a, b) => a > b)(4) == [5, 6, 9]);
-    assert(arr.find!((a, b) => a < b)(4) == arr);
+    assert(arr.find!((e, n) => e > n)(4) == [5, 6, 9]);
+    assert(arr.find!((e, n) => e < n)(4) == arr);
     assert(arr.find(0).empty);
     assert(arr.find(10).empty);
     assert(arr.find(8).empty);
@@ -1770,7 +1833,7 @@ if (isInputRange!InputRange &&
     import std.uni : toLower;
 
     string[] s = ["Hello", "world", "!"];
-    assert(s.find!((a, b) => toLower(a) == b)("hello") == s);
+    assert(s.find!((e, n) => toLower(e) == n)("hello") == s);
 }
 
 @safe unittest
@@ -1862,60 +1925,6 @@ if (isInputRange!InputRange &&
     assert([x].find(x).empty == false);
 }
 
-/// ditto
-InputRange find(alias pred, InputRange)(InputRange haystack)
-if (isInputRange!InputRange)
-{
-    alias R = InputRange;
-    alias predFun = unaryFun!pred;
-    static if (isNarrowString!R)
-    {
-        import std.utf : decode;
-
-        immutable len = haystack.length;
-        size_t i = 0, next = 0;
-        while (next < len)
-        {
-            if (predFun(decode(haystack, next)))
-                return haystack[i .. $];
-            i = next;
-        }
-        return haystack[$ .. $];
-    }
-    else
-    {
-        //standard range
-        for ( ; !haystack.empty; haystack.popFront() )
-        {
-            if (predFun(haystack.front))
-                break;
-        }
-        return haystack;
-    }
-}
-
-///
-@safe unittest
-{
-    auto arr = [ 1, 2, 3, 4, 1 ];
-    assert(find!("a > 2")(arr) == [ 3, 4, 1 ]);
-
-    // with predicate alias
-    bool pred(int x) { return x + 1 > 1.5; }
-    assert(find!(pred)(arr) == arr);
-}
-
-@safe pure unittest
-{
-    int[] r = [ 1, 2, 3 ];
-    assert(find!(a=>a > 2)(r) == [3]);
-    bool pred(int x) { return x + 1 > 1.5; }
-    assert(find!(pred)(r) == r);
-
-    assert(find!(a=>a > 'v')("hello world") == "world");
-    assert(find!(a=>a%4 == 0)("日本語") == "本語");
-}
-
 /// ditto
 R1 find(alias pred = "a == b", R1, R2)(R1 haystack, scope R2 needle)
 if (isForwardRange!R1 && isForwardRange!R2
@@ -2376,9 +2385,9 @@ is considered to be 1.) The strategy used in searching several
 subranges at once maximizes cache usage by moving in `haystack` as
 few times as possible.
  */
-Tuple!(Range, size_t) find(alias pred = "a == b", Range, Ranges...)
-(Range haystack, Ranges needles)
-if (Ranges.length > 1 && is(typeof(startsWith!pred(haystack, needles))))
+Tuple!(Range, size_t) find(alias pred = "a == b", Range, Needles...)
+(Range haystack, Needles needles)
+if (Needles.length > 1 && is(typeof(startsWith!pred(haystack, needles))))
 {
     for (;; haystack.popFront())
     {
@@ -2536,13 +2545,13 @@ was successful.
 For more information about `pred` see $(LREF find).
 
 See_Also:
-$(REF among, std,algorithm,comparison) for checking a value against multiple possibilities.
+$(REF among, std,algorithm,comparison) for checking a value against multiple arguments.
  +/
 template canFind(alias pred="a == b")
 {
     /++
-    Returns `true` if and only if any value `v` found in the
-    input range `range` satisfies the predicate `pred`.
+    Returns `true` if and only if `pred(e)` is true for any value `e` in the
+    input range `range`.
     Performs (at most) $(BIGOH haystack.length) evaluations of `pred`.
      +/
     bool canFind(Range)(Range haystack)
@@ -2565,16 +2574,15 @@ template canFind(alias pred="a == b")
     Returns the 1-based index of the first needle found in `haystack`. If no
     needle is found, then `0` is returned.
 
-    So, if used directly in the condition of an if statement or loop, the result
+    So, if used directly in the condition of an `if` statement or loop, the result
     will be `true` if one of the needles is found and `false` if none are
     found, whereas if the result is used elsewhere, it can either be cast to
     `bool` for the same effect or used to get which needle was found first
-    without having to deal with the tuple that `LREF find` returns for the
+    without having to deal with the tuple that $(LREF find) returns for the
     same operation.
      +/
-    size_t canFind(Range, Ranges...)(Range haystack, scope Ranges needles)
-    if (Ranges.length > 1 &&
-        allSatisfy!(isForwardRange, Ranges) &&
+    size_t canFind(Range, Needles...)(Range haystack, scope Needles needles)
+    if (Needles.length > 1 &&
         is(typeof(find!pred(haystack, needles))))
     {
         return find!pred(haystack, needles)[1];
@@ -2584,15 +2592,21 @@ template canFind(alias pred="a == b")
 ///
 @safe unittest
 {
-    assert(canFind([0, 1, 2, 3], 2) == true);
-    assert(canFind([0, 1, 2, 3], [1, 2], [2, 3]));
-    assert(canFind([0, 1, 2, 3], [1, 2], [2, 3]) == 1);
-    assert(canFind([0, 1, 2, 3], [1, 7], [2, 3]));
-    assert(canFind([0, 1, 2, 3], [1, 7], [2, 3]) == 2);
+    const arr = [0, 1, 2, 3];
+    assert(canFind(arr, 2));
+    assert(!canFind(arr, 4));
+
+    // find one of several needles
+    assert(arr.canFind(3, 2));
+    assert(arr.canFind(3, 2) == 2); // second needle found
+    assert(arr.canFind([1, 3], 2) == 2);
 
-    assert(canFind([0, 1, 2, 3], 4) == false);
-    assert(!canFind([0, 1, 2, 3], [1, 3], [2, 4]));
-    assert(canFind([0, 1, 2, 3], [1, 3], [2, 4]) == 0);
+    assert(canFind(arr, [1, 2], [2, 3]));
+    assert(canFind(arr, [1, 2], [2, 3]) == 1);
+    assert(canFind(arr, [1, 7], [2, 3]));
+    assert(canFind(arr, [1, 7], [2, 3]) == 2);
+    assert(!canFind(arr, [1, 3], [2, 4]));
+    assert(canFind(arr, [1, 3], [2, 4]) == 0);
 }
 
 /**
@@ -2607,10 +2621,10 @@ template canFind(alias pred="a == b")
         "cardboard"
     ];
     assert(!canFind(words, "bees"));
-    assert( canFind!((string a, string b) => a.startsWith(b))(words, "bees"));
+    assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));
 }
 
-/// Search for mutliple items in an array of items (search for needles in an array of hay stacks)
+/// Search for multiple items in an array of items (search for needles in an array of haystacks)
 @safe unittest
 {
     string s1 = "aaa111aaa";
@@ -2618,7 +2632,7 @@ template canFind(alias pred="a == b")
     string s3 = "aaa333aaa";
     string s4 = "aaa444aaa";
     const hay = [s1, s2, s3, s4];
-    assert(hay.canFind!(e => (e.canFind("111", "222"))));
+    assert(hay.canFind!(e => e.canFind("111", "222")));
 }
 
 @safe unittest
@@ -2736,7 +2750,7 @@ Returns:
 `seq` advanced to the first matching element, or until empty if there are no
 matching elements.
 
-See_Also: $(LREF find), $(REF std,algorithm,comparison,among)
+See_Also: $(LREF find), $(REF among, std,algorithm,comparison)
 */
 InputRange findAmong(alias pred = "a == b", InputRange, ForwardRange)(
     InputRange seq, ForwardRange choices)
diff --git a/libphobos/src/std/array.d b/libphobos/src/std/array.d
index a613a8d9e4a..494fa297b4b 100644
--- a/libphobos/src/std/array.d
+++ b/libphobos/src/std/array.d
@@ -1201,7 +1201,7 @@ private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow
     auto a2 = minimallyInitializedArray!(S2[][])(2, 2);
     assert(a2);
     enum b2 = minimallyInitializedArray!(S2[][])(2, 2);
-    assert(b2);
+    assert(b2 !is null);
     static struct S3
     {
         //this() @disable;
@@ -1210,7 +1210,7 @@ private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow
     auto a3 = minimallyInitializedArray!(S3[][])(2, 2);
     assert(a3);
     enum b3 = minimallyInitializedArray!(S3[][])(2, 2);
-    assert(b3);
+    assert(b3 !is null);
 }
 
 /++
diff --git a/libphobos/src/std/logger/package.d b/libphobos/src/std/logger/package.d
index 330ef88aa06..14a439486db 100644
--- a/libphobos/src/std/logger/package.d
+++ b/libphobos/src/std/logger/package.d
@@ -54,7 +54,7 @@ $(UL
     $(LI `trace`)
     $(LI `info`)
     $(LI `warning`)
-    #(LI `error`)
+    $(LI `error`)
     $(LI `critical`)
     $(LI `fatal`)
 )
diff --git a/libphobos/src/std/math/hardware.d b/libphobos/src/std/math/hardware.d
index 81c7302b4c1..cb6cb87845c 100644
--- a/libphobos/src/std/math/hardware.d
+++ b/libphobos/src/std/math/hardware.d
@@ -33,6 +33,7 @@ version (SPARC64)   version = SPARC_Any;
 version (SystemZ)   version = IBMZ_Any;
 version (RISCV32)   version = RISCV_Any;
 version (RISCV64)   version = RISCV_Any;
+version (LoongArch64)   version = LoongArch_Any;
 
 version (D_InlineAsm_X86)    version = InlineAsm_X86_Any;
 version (D_InlineAsm_X86_64) version = InlineAsm_X86_Any;
@@ -60,6 +61,7 @@ else version (X86_Any)   version = IeeeFlagsSupport;
 else version (PPC_Any)   version = IeeeFlagsSupport;
 else version (RISCV_Any) version = IeeeFlagsSupport;
 else version (MIPS_Any)  version = IeeeFlagsSupport;
+else version (LoongArch_Any) version = IeeeFlagsSupport;
 else version (ARM_Any)   version = IeeeFlagsSupport;
 
 // Struct FloatingPointControl is only available if hardware FP units are available.
@@ -90,6 +92,7 @@ private:
     // The ARM and PowerPC FPSCR is a 32-bit register.
     // The SPARC FSR is a 32bit register (64 bits for SPARC 7 & 8, but high bits are uninteresting).
     // The RISC-V (32 & 64 bit) fcsr is 32-bit register.
+    // THe LoongArch fcsr (fcsr0) is a 32-bit register.
     uint flags;
 
     version (CRuntime_Microsoft)
@@ -216,6 +219,15 @@ private:
             return result;
             `);
         }
+        else version (LoongArch_Any)
+        {
+            uint result = void;
+            asm pure nothrow @nogc
+            {
+                "movfcsr2gr %0,$r2" : "=r" (result);
+            }
+            return result & EXCEPTIONS_MASK;
+        }
         else
             assert(0, "Not yet supported");
     }
@@ -303,6 +315,13 @@ private:
             }
             `);
         }
+        else version (LoongArch_Any)
+        {
+            asm nothrow @nogc
+            {
+                "movgr2fcsr $r2,$r0";
+            }
+        }
         else
         {
             /* SPARC:
@@ -725,6 +744,21 @@ nothrow @nogc:
                                  | inexactException,
         }
     }
+    else version (LoongArch_Any)
+    {
+        enum : ExceptionMask
+        {
+            inexactException      = 0x00,
+            divByZeroException    = 0x01,
+            overflowException     = 0x02,
+            underflowException    = 0x04,
+            invalidException      = 0x08,
+            severeExceptions   = overflowException | divByZeroException
+                                 | invalidException,
+            allExceptions      = severeExceptions | underflowException
+                                 | inexactException,
+        }
+    }
     else version (MIPS_Any)
     {
         enum : ExceptionMask
@@ -812,6 +846,8 @@ nothrow @nogc:
             return true;
         else version (MIPS_Any)
             return true;
+        else version (LoongArch_Any)
+            return true;
         else version (ARM_Any)
         {
             // The hasExceptionTraps_impl function is basically pure,
@@ -885,6 +921,10 @@ private:
     {
         alias ControlState = uint;
     }
+    else version (LoongArch_Any)
+    {
+        alias ControlState = uint;
+    }
     else version (MIPS_Any)
     {
         alias ControlState = uint;
@@ -1008,6 +1048,16 @@ private:
             return cont;
             `);
         }
+        else version (LoongArch_Any)
+        {
+            ControlState cont;
+            asm pure nothrow @nogc
+            {
+                "movfcsr2gr %0,$r0" : "=r" (cont);
+            }
+            cont &= (roundingMask | allExceptions);
+            return cont;
+        }
         else
             assert(0, "Not yet supported");
     }
@@ -1120,6 +1170,14 @@ private:
             }
             `);
         }
+        else version (LoongArch_Any)
+        {
+            asm nothrow @nogc
+            {
+                "movgr2fcsr $r0,%0" :
+                : "r" (newState & (roundingMask | allExceptions));
+            }
+        }
         else
             assert(0, "Not yet supported");
     }
