diff mbox series

[committed] d: Merge upstream dmd, druntime 603225372b

Message ID 20250316205239.613598-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Merge upstream dmd, druntime 603225372b | expand

Commit Message

Iain Buclaw March 16, 2025, 8:52 p.m. UTC
Hi,

This patch merges the D front-end and runtime library with upstream dmd
603225372b.  Synchronizing with the release of v2.111.0-beta.1.

D front-end changes:

	- Import dmd v2.111.0-beta.1.
	- Added placement `new' expressions.

D runtime changes:

	- Import druntime v2.111.0-beta.1.

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

Regards,
Iain.

---
gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 603225372b.
	* dmd/VERSION: Bump version to v2.111.0-beta.1.
	* d-builtins.cc (build_frontend_type): Update for new front-end
	interface.
	* decl.cc (Class DeclVisitor): Likewise.
	(maybe_build_decl_tree): Likewise.
	(get_vtable_decl): Likewise.
	(layout_class_initializer): Likewise.
	* expr.cc (class ExprVisitor): Likewise.
	(ExprVisitor::visit (NewExp *)): Implement placement new for class,
	struct, and pointer types.
	* modules.cc (get_internal_fn): Update for new front-end interface.

libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime 603225372b.
---
 gcc/d/d-builtins.cc                           |   2 +-
 gcc/d/decl.cc                                 |  52 +--
 gcc/d/dmd/MERGE                               |   2 +-
 gcc/d/dmd/VERSION                             |   2 +-
 gcc/d/dmd/aggregate.d                         |   7 +-
 gcc/d/dmd/aggregate.h                         |   9 +-
 gcc/d/dmd/aliasthis.d                         |   2 +-
 gcc/d/dmd/astenums.d                          |   5 +-
 gcc/d/dmd/attrib.d                            | 139 ++----
 gcc/d/dmd/attrib.h                            |  12 -
 gcc/d/dmd/clone.d                             |  38 +-
 gcc/d/dmd/cond.d                              | 253 +----------
 gcc/d/dmd/cond.h                              |   2 -
 gcc/d/dmd/cparse.d                            |  34 +-
 gcc/d/dmd/cxxfrontend.d                       |  30 +-
 gcc/d/dmd/dcast.d                             |   6 +
 gcc/d/dmd/dclass.d                            |  63 +--
 gcc/d/dmd/declaration.d                       |  81 +---
 gcc/d/dmd/declaration.h                       |  30 +-
 gcc/d/dmd/denum.d                             |  21 +-
 gcc/d/dmd/dimport.d                           |   7 +-
 gcc/d/dmd/dinterpret.d                        |   9 +-
 gcc/d/dmd/dmodule.d                           |  12 +-
 gcc/d/dmd/dscope.d                            |   2 +-
 gcc/d/dmd/dstruct.d                           |  12 +-
 gcc/d/dmd/dsymbol.d                           | 421 +++++++++++-------
 gcc/d/dmd/dsymbol.h                           | 132 +++---
 gcc/d/dmd/dsymbolsem.d                        | 277 +++++++++++-
 gcc/d/dmd/dtemplate.d                         |  39 +-
 gcc/d/dmd/dversion.d                          |  18 +-
 gcc/d/dmd/enum.h                              |   3 -
 gcc/d/dmd/escape.d                            |   7 +-
 gcc/d/dmd/expression.d                        |  21 +-
 gcc/d/dmd/expression.h                        |   6 +-
 gcc/d/dmd/expressionsem.d                     | 374 +++++++++++++++-
 gcc/d/dmd/func.d                              | 130 ++----
 gcc/d/dmd/funcsem.d                           |  11 +-
 gcc/d/dmd/hdrgen.d                            |  26 +-
 gcc/d/dmd/import.h                            |   1 -
 gcc/d/dmd/json.d                              |   2 +-
 gcc/d/dmd/mangle/package.d                    |   2 +-
 gcc/d/dmd/module.h                            |   3 -
 gcc/d/dmd/mtype.d                             |  52 ++-
 gcc/d/dmd/nogc.d                              |   2 +
 gcc/d/dmd/nspace.d                            |   6 +-
 gcc/d/dmd/nspace.h                            |   1 -
 gcc/d/dmd/ob.d                                |   5 +
 gcc/d/dmd/optimize.d                          |   1 +
 gcc/d/dmd/parse.d                             | 164 +++----
 gcc/d/dmd/pragmasem.d                         |   2 +-
 gcc/d/dmd/semantic3.d                         |  10 +-
 gcc/d/dmd/sideeffect.d                        |   4 +-
 gcc/d/dmd/statement.d                         |   8 +-
 gcc/d/dmd/statementsem.d                      |  54 ++-
 gcc/d/dmd/staticassert.d                      |  16 +-
 gcc/d/dmd/staticassert.h                      |   2 -
 gcc/d/dmd/template.h                          |   6 -
 gcc/d/dmd/templatesem.d                       |   8 +-
 gcc/d/dmd/traits.d                            |   2 +-
 gcc/d/dmd/typesem.d                           |  44 +-
 gcc/d/dmd/version.h                           |   2 -
 gcc/d/dmd/visitor/postorder.d                 |   4 +-
 gcc/d/dmd/visitor/transitive.d                |   4 +
 gcc/d/expr.cc                                 |  51 ++-
 gcc/d/modules.cc                              |   6 +-
 gcc/testsuite/gdc.test/compilable/bug11735.d  |   4 +
 .../gdc.test/compilable/placementnew.d        |   4 +
 gcc/testsuite/gdc.test/compilable/test21177.d |   1 +
 gcc/testsuite/gdc.test/compilable/test24017.d |  11 -
 .../gdc.test/fail_compilation/fail21849.d     |   4 +
 .../gdc.test/fail_compilation/fail22151.d     |  16 +-
 .../gdc.test/fail_compilation/placenew.d      |  80 ++++
 .../gdc.test/fail_compilation/test20859.d     |  11 +
 gcc/testsuite/gdc.test/runnable/literal.d     |   8 +
 gcc/testsuite/gdc.test/runnable/placenew.d    | 106 +++++
 gcc/testsuite/gdc.test/runnable/template3.d   |  11 +
 libphobos/libdruntime/MERGE                   |   2 +-
 77 files changed, 1722 insertions(+), 1295 deletions(-)
 create mode 100644 gcc/testsuite/gdc.test/compilable/placementnew.d
 delete mode 100644 gcc/testsuite/gdc.test/compilable/test24017.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/placenew.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test20859.d
 create mode 100644 gcc/testsuite/gdc.test/runnable/placenew.d
diff mbox series

Patch

diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index f7e7a801a00..9c146459d57 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -279,7 +279,7 @@  build_frontend_type (tree type)
 						       NULL);
 	  vd->parent = sdecl;
 	  vd->offset = tree_to_uhwi (byte_position (field));
-	  vd->semanticRun = PASS::semanticdone;
+	  vd->semanticRun (PASS::semanticdone);
 	  vd->csym = field;
 	  sdecl->members->push (vd);
 	  sdecl->fields.push (vd);
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index c05c30397b8..9fcfc5681f8 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -256,18 +256,18 @@  public:
 
   void visit (Module *d) final override
   {
-    if (d->semanticRun >= PASS::obj)
+    if (d->semanticRun () >= PASS::obj)
       return;
 
     build_module_tree (d);
-    d->semanticRun = PASS::obj;
+    d->semanticRun (PASS::obj);
   }
 
   /* Write the imported symbol to debug.  */
 
   void visit (Import *d) final override
   {
-    if (d->semanticRun >= PASS::obj)
+    if (d->semanticRun () >= PASS::obj)
       return;
 
     /* Implements import declarations by telling the debug back-end we are
@@ -320,7 +320,7 @@  public:
 					      false, false);
       }
 
-    d->semanticRun = PASS::obj;
+    d->semanticRun (PASS::obj);
   }
 
   /* Finish a top-level `asm` definition.  */
@@ -472,7 +472,7 @@  public:
 
   void visit (StructDeclaration *d) final override
   {
-    if (d->semanticRun >= PASS::obj)
+    if (d->semanticRun () >= PASS::obj)
       return;
 
     if (d->type->ty == TY::Terror)
@@ -520,7 +520,7 @@  public:
     if (d->xhash)
       this->build_dsymbol (d->xhash);
 
-    d->semanticRun = PASS::obj;
+    d->semanticRun (PASS::obj);
   }
 
   /* Finish semantic analysis of functions in vtbl for class CD.  */
@@ -542,7 +542,7 @@  public:
 	  has_errors = true;
 
 	/* No name hiding to check for.  */
-	if (!d->isFuncHidden (fd) || fd->isFuture ())
+	if (!dmd::isFuncHidden (d, fd) || fd->isFuture ())
 	  continue;
 
 	/* The function fd is hidden from the view of the class.
@@ -588,7 +588,7 @@  public:
 
   void visit (ClassDeclaration *d) final override
   {
-    if (d->semanticRun >= PASS::obj)
+    if (d->semanticRun () >= PASS::obj)
       return;
 
     if (d->type->ty == TY::Terror)
@@ -617,7 +617,7 @@  public:
 
     /* Generate C symbols.  */
     d->csym = get_classinfo_decl (d);
-    Dsymbol *vtblsym = d->vtblSymbol ();
+    Dsymbol *vtblsym = dmd::vtblSymbol (d);
     vtblsym->csym = get_vtable_decl (d);
     tree sinit = aggregate_initializer_decl (d);
 
@@ -654,7 +654,7 @@  public:
       = build_constructor (TREE_TYPE (vtblsym->csym), elms);
     d_finish_decl (vtblsym->csym);
 
-    d->semanticRun = PASS::obj;
+    d->semanticRun (PASS::obj);
   }
 
   /* Write out compiler generated TypeInfo and vtables for the given interface
@@ -662,7 +662,7 @@  public:
 
   void visit (InterfaceDeclaration *d) final override
   {
-    if (d->semanticRun >= PASS::obj)
+    if (d->semanticRun () >= PASS::obj)
       return;
 
     if (d->type->ty == TY::Terror)
@@ -697,7 +697,7 @@  public:
     DECL_INITIAL (d->csym) = layout_classinfo (d);
     d_finish_decl (d->csym);
 
-    d->semanticRun = PASS::obj;
+    d->semanticRun (PASS::obj);
   }
 
   /* Write out compiler generated TypeInfo and initializer for the given
@@ -705,10 +705,10 @@  public:
 
   void visit (EnumDeclaration *d) final override
   {
-    if (d->semanticRun >= PASS::obj)
+    if (d->semanticRun () >= PASS::obj)
       return;
 
-    if (d->errors || d->type->ty == TY::Terror)
+    if (d->errors () || d->type->ty == TY::Terror)
       {
 	error_at (make_location_t (d->loc),
 		  "had semantic errors when compiling");
@@ -736,7 +736,7 @@  public:
 	d_finish_decl (d->sinit);
       }
 
-    d->semanticRun = PASS::obj;
+    d->semanticRun (PASS::obj);
   }
 
   /* Finish up a variable declaration and push it into the current scope.
@@ -744,7 +744,7 @@  public:
 
   void visit (VarDeclaration *d) final override
   {
-    if (d->semanticRun >= PASS::obj)
+    if (d->semanticRun () >= PASS::obj)
       return;
 
     if (d->type->ty == TY::Terror)
@@ -889,7 +889,7 @@  public:
 	  }
       }
 
-    d->semanticRun = PASS::obj;
+    d->semanticRun (PASS::obj);
   }
 
   /* Generate and compile a static TypeInfo declaration, but only if it is
@@ -897,7 +897,7 @@  public:
 
   void visit (TypeInfoDeclaration *d) final override
   {
-    if (d->semanticRun >= PASS::obj)
+    if (d->semanticRun () >= PASS::obj)
       return;
 
     if (dmd::isSpeculativeType (d->tinfo))
@@ -906,7 +906,7 @@  public:
     tree t = get_typeinfo_decl (d);
     DECL_INITIAL (t) = layout_typeinfo (d);
     d_finish_decl (t);
-    d->semanticRun = PASS::obj;
+    d->semanticRun (PASS::obj);
   }
 
   /* Finish up a function declaration and compile it all the way
@@ -915,7 +915,7 @@  public:
   void visit (FuncDeclaration *d) final override
   {
     /* Already generated the function.  */
-    if (d->semanticRun >= PASS::obj)
+    if (d->semanticRun () >= PASS::obj)
       return;
 
     /* Don't emit any symbols from gcc.attributes module.  */
@@ -957,7 +957,7 @@  public:
       }
 
     /* Ensure all semantic passes have run.  */
-    if (d->semanticRun < PASS::semantic3)
+    if (d->semanticRun () < PASS::semantic3)
       {
 	gcc_assert (!doing_semantic_analysis_p);
 
@@ -971,8 +971,8 @@  public:
       return;
 
     /* Start generating code for this function.  */
-    gcc_assert (d->semanticRun == PASS::semantic3done);
-    d->semanticRun = PASS::obj;
+    gcc_assert (d->semanticRun () == PASS::semantic3done);
+    d->semanticRun (PASS::obj);
 
     /* Duplicated FuncDeclarations map to the same symbol.  Check if this
        is the one declaration which will be emitted.  */
@@ -1179,7 +1179,7 @@  maybe_build_decl_tree (Declaration *decl)
 
   /* Still running semantic analysis on declaration, or it has already had its
      code generated.  */
-  if (doing_semantic_analysis_p || decl->semanticRun >= PASS::obj)
+  if (doing_semantic_analysis_p || decl->semanticRun () >= PASS::obj)
     return decl->csym;
 
   if (error_operand_p (decl->csym))
@@ -2212,7 +2212,7 @@  get_vtable_decl (ClassDeclaration *decl)
      will have a different type.  However the back-end seems to accept this.  */
   tree type = build_ctype (dmd::sarrayOf (Type::tvoidptr, decl->vtbl.length));
 
-  Dsymbol *vtblsym = decl->vtblSymbol ();
+  Dsymbol *vtblsym = dmd::vtblSymbol (decl);
   vtblsym->csym = declare_extern_var (ident, type);
   DECL_LANG_SPECIFIC (vtblsym->csym) = build_lang_decl (NULL);
 
@@ -2403,7 +2403,7 @@  aggregate_initializer_decl (AggregateDeclaration *decl)
 tree
 layout_class_initializer (ClassDeclaration *cd)
 {
-  NewExp *ne = NewExp::create (cd->loc, NULL, cd->type, NULL);
+  NewExp *ne = NewExp::create (cd->loc, NULL, NULL, cd->type, NULL);
   ne->type = cd->type;
 
   Expression *e = dmd::ctfeInterpret (ne);
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 66cfdd6ad4a..070d9fec28b 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-53a1cc8d13e8db2cb1642219320a8dfc1b0cc6c5
+603225372b211bb66dd0ea1a939043ace5a650cf
 
 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 5aab7a2b62a..2f668e5056b 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@ 
-v2.110.0-rc.1
+v2.111.0-beta.1
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index a1938763c2f..4423653e908 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -96,7 +96,7 @@  struct MangleOverride
 extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
 {
     Type type;                  ///
-    StorageClass storage_class; ///
+    STC storage_class;          ///
     uint structsize;            /// size of struct
     uint alignsize;             /// size of struct for alignment purposes
     VarDeclarations fields;     /// VarDeclaration fields including flattened AnonDeclaration members
@@ -495,11 +495,6 @@  extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
     // Back end
     void* sinit;  /// initializer symbol
 
-    override final inout(AggregateDeclaration) isAggregateDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index 56f597bac79..b7424785fb5 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -46,6 +46,8 @@  namespace dmd
     FuncDeclaration *search_toString(StructDeclaration *sd);
     void semanticTypeInfoMembers(StructDeclaration *sd);
     bool fill(StructDeclaration* sd, Loc loc, Expressions &elements, bool ctorinit);
+    bool isFuncHidden(ClassDeclaration* cd, FuncDeclaration* fd);
+    Dsymbol* vtblSymbol(ClassDeclaration *cd);
 }
 
 enum class ClassKind : uint8_t
@@ -135,7 +137,6 @@  public:
     // Back end
     void *sinit;
 
-    AggregateDeclaration *isAggregateDeclaration() override final { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -191,7 +192,6 @@  public:
     bool requestTypeInfo() const;
     bool requestTypeInfo(bool v);
 
-    StructDeclaration *isStructDeclaration() override final { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 
     unsigned numArgTypes() const;
@@ -205,7 +205,6 @@  public:
     UnionDeclaration *syntaxCopy(Dsymbol *s) override;
     const char *kind() const override;
 
-    UnionDeclaration *isUnionDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -290,7 +289,6 @@  public:
     bool isBaseInfoComplete();
     void finalizeSize() override;
     bool hasMonitor();
-    bool isFuncHidden(FuncDeclaration *fd);
     bool isCOMclass() const;
     virtual bool isCOMinterface() const;
     bool isCPPclass() const;
@@ -303,9 +301,7 @@  public:
 
     // Back end
     Dsymbol *vtblsym;
-    Dsymbol *vtblSymbol();
 
-    ClassDeclaration *isClassDeclaration() override final { return (ClassDeclaration *)this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -320,6 +316,5 @@  public:
     bool isCPPinterface() const override;
     bool isCOMinterface() const override;
 
-    InterfaceDeclaration *isInterfaceDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
diff --git a/gcc/d/dmd/aliasthis.d b/gcc/d/dmd/aliasthis.d
index 620b016ac5a..b5c0399a93e 100644
--- a/gcc/d/dmd/aliasthis.d
+++ b/gcc/d/dmd/aliasthis.d
@@ -33,7 +33,7 @@  extern (C++) final class AliasThis : Dsymbol
 
     extern (D) this(Loc loc, Identifier ident) @safe
     {
-        super(loc, null);    // it's anonymous (no identifier)
+        super(DSYM.aliasThis, loc, null);    // it's anonymous (no identifier)
         this.ident = ident;
     }
 
diff --git a/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d
index 551b45317e2..bbe1f9f0202 100644
--- a/gcc/d/dmd/astenums.d
+++ b/gcc/d/dmd/astenums.d
@@ -50,7 +50,7 @@  alias MOD = ubyte;
 
 enum STC : ulong  // transfer changes to declaration.h
 {
-    undefined_          = 0,
+    none                = 0,
 
     static_             = 1,   /// `static`
     extern_             = 2,   /// `extern`
@@ -143,6 +143,9 @@  enum STC : ulong  // transfer changes to declaration.h
 
 }
 
+// Alias for C++ interface functions which use plain integer instead of enum class,
+// since C++ enum class doesn't support | & and conversion to bool. Maybe this can
+// be refactored to a struct with operator overloads or bit fields at some point.
 alias StorageClass = ulong;
 
 /********
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index df04ed1756d..80e8878fe93 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -57,18 +57,19 @@  extern (C++) abstract class AttribDeclaration : Dsymbol
 
     extern (D) this(Dsymbols* decl) @safe
     {
+        super(DSYM.attribDeclaration);
         this.decl = decl;
     }
 
     extern (D) this(Loc loc, Dsymbols* decl) @safe
     {
-        super(loc, null);
+        super(DSYM.attribDeclaration, loc, null);
         this.decl = decl;
     }
 
     extern (D) this(Loc loc, Identifier ident, Dsymbols* decl) @safe
     {
-        super(loc, ident);
+        super(DSYM.attribDeclaration, loc, ident);
         this.decl = decl;
     }
 
@@ -78,7 +79,7 @@  extern (C++) abstract class AttribDeclaration : Dsymbol
      * If the returned scope != sc, the caller should pop
      * the scope after it used.
      */
-    extern (D) static Scope* createNewScope(Scope* sc, StorageClass stc, LINK linkage,
+    extern (D) static Scope* createNewScope(Scope* sc, STC stc, LINK linkage,
         CPPMANGLE cppmangle, Visibility visibility, int explicitVisibility,
         AlignDeclaration aligndecl, PragmaDeclaration inlining)
     {
@@ -109,22 +110,11 @@  extern (C++) abstract class AttribDeclaration : Dsymbol
         return "attribute";
     }
 
-    override bool oneMember(out Dsymbol ps, Identifier ident)
-    {
-        Dsymbols* d = this.include(null);
-        return Dsymbol.oneMembers(d, ps, ident);
-    }
-
     override final bool hasPointers()
     {
         return this.include(null).foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
     }
 
-    override final bool hasStaticCtorOrDtor()
-    {
-        return this.include(null).foreachDsymbol( (s) { return s.hasStaticCtorOrDtor(); } ) != 0;
-    }
-
     /****************************************
      */
     override final void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories)
@@ -132,11 +122,6 @@  extern (C++) abstract class AttribDeclaration : Dsymbol
         objc.addSymbols(this, classes, categories);
     }
 
-    override inout(AttribDeclaration) isAttribDeclaration() inout pure @safe
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -150,18 +135,20 @@  extern (C++) abstract class AttribDeclaration : Dsymbol
  */
 extern (C++) class StorageClassDeclaration : AttribDeclaration
 {
-    StorageClass stc;
+    STC stc;
 
-    extern (D) this(StorageClass stc, Dsymbols* decl) @safe
+    extern (D) this(STC stc, Dsymbols* decl) @safe
     {
         super(decl);
         this.stc = stc;
+        this.dsym = DSYM.storageClassDeclaration;
     }
 
-    extern (D) this(Loc loc, StorageClass stc, Dsymbols* decl) @safe
+    extern (D) this(Loc loc, STC stc, Dsymbols* decl) @safe
     {
         super(loc, decl);
         this.stc = stc;
+        this.dsym = DSYM.storageClassDeclaration;
     }
 
     override StorageClassDeclaration syntaxCopy(Dsymbol s)
@@ -170,37 +157,6 @@  extern (C++) class StorageClassDeclaration : AttribDeclaration
         return new StorageClassDeclaration(stc, Dsymbol.arraySyntaxCopy(decl));
     }
 
-    override final bool oneMember(out Dsymbol ps, Identifier ident)
-    {
-        bool t = Dsymbol.oneMembers(decl, ps, ident);
-        if (t && ps)
-        {
-            /* This is to deal with the following case:
-             * struct Tick {
-             *   template to(T) { const T to() { ... } }
-             * }
-             * For eponymous function templates, the 'const' needs to get attached to 'to'
-             * before the semantic analysis of 'to', so that template overloading based on the
-             * 'this' pointer can be successful.
-             */
-            if (FuncDeclaration fd = ps.isFuncDeclaration())
-            {
-                /* Use storage_class2 instead of storage_class otherwise when we do .di generation
-                 * we'll wind up with 'const const' rather than 'const'.
-                 */
-                /* Don't think we need to worry about mutually exclusive storage classes here
-                 */
-                fd.storage_class2 |= stc;
-            }
-        }
-        return t;
-    }
-
-    override inout(StorageClassDeclaration) isStorageClassDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -253,6 +209,7 @@  extern (C++) final class LinkDeclaration : AttribDeclaration
         super(loc, null, decl);
         //printf("LinkDeclaration(linkage = %d, decl = %p)\n", linkage, decl);
         this.linkage = linkage;
+        this.dsym = DSYM.linkDeclaration;
     }
 
     static LinkDeclaration create(Loc loc, LINK p, Dsymbols* decl) @safe
@@ -289,6 +246,7 @@  extern (C++) final class CPPMangleDeclaration : AttribDeclaration
         super(loc, null, decl);
         //printf("CPPMangleDeclaration(cppmangle = %d, decl = %p)\n", cppmangle, decl);
         this.cppmangle = cppmangle;
+        this.dsym = DSYM.cppMangleDeclaration;
     }
 
     override CPPMangleDeclaration syntaxCopy(Dsymbol s)
@@ -334,11 +292,13 @@  extern (C++) final class CPPNamespaceDeclaration : AttribDeclaration
     extern (D) this(Loc loc, Identifier ident, Dsymbols* decl) @safe
     {
         super(loc, ident, decl);
+        this.dsym = DSYM.cppNamespaceDeclaration;
     }
 
     extern (D) this(Loc loc, Expression exp, Dsymbols* decl) @safe
     {
         super(loc, null, decl);
+        this.dsym = DSYM.cppNamespaceDeclaration;
         this.exp = exp;
     }
 
@@ -346,6 +306,7 @@  extern (C++) final class CPPNamespaceDeclaration : AttribDeclaration
                     CPPNamespaceDeclaration parent) @safe
     {
         super(loc, ident, decl);
+        this.dsym = DSYM.cppNamespaceDeclaration;
         this.exp = exp;
         this.cppnamespace = parent;
     }
@@ -361,8 +322,6 @@  extern (C++) final class CPPNamespaceDeclaration : AttribDeclaration
     {
         v.visit(this);
     }
-
-    override inout(CPPNamespaceDeclaration) isCPPNamespaceDeclaration() inout { return this; }
 }
 
 /***********************************************************
@@ -385,6 +344,7 @@  extern (C++) final class VisibilityDeclaration : AttribDeclaration
     extern (D) this(Loc loc, Visibility visibility, Dsymbols* decl) @safe
     {
         super(loc, null, decl);
+        this.dsym = DSYM.visibilityDeclaration;
         this.visibility = visibility;
         //printf("decl = %p\n", decl);
     }
@@ -398,6 +358,7 @@  extern (C++) final class VisibilityDeclaration : AttribDeclaration
     extern (D) this(Loc loc, Identifier[] pkg_identifiers, Dsymbols* decl)
     {
         super(loc, null, decl);
+        this.dsym = DSYM.visibilityDeclaration;
         this.visibility.kind = Visibility.Kind.package_;
         this.pkg_identifiers = pkg_identifiers;
         if (pkg_identifiers.length > 0)
@@ -431,11 +392,6 @@  extern (C++) final class VisibilityDeclaration : AttribDeclaration
         return buf.extractChars();
     }
 
-    override inout(VisibilityDeclaration) isVisibilityDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -460,6 +416,7 @@  extern (C++) final class AlignDeclaration : AttribDeclaration
     extern (D) this(Loc loc, Expression exp, Dsymbols* decl)
     {
         super(loc, null, decl);
+        this.dsym = DSYM.alignDeclaration;
         if (exp)
         {
             exps = new Expressions();
@@ -470,12 +427,14 @@  extern (C++) final class AlignDeclaration : AttribDeclaration
     extern (D) this(Loc loc, Expressions* exps, Dsymbols* decl) @safe
     {
         super(loc, null, decl);
+        this.dsym = DSYM.alignDeclaration;
         this.exps = exps;
     }
 
     extern (D) this(Loc loc, structalign_t salign, Dsymbols* decl) @safe
     {
         super(loc, null, decl);
+        this.dsym = DSYM.alignDeclaration;
         this.salign = salign;
     }
 
@@ -507,6 +466,7 @@  extern (C++) final class AnonDeclaration : AttribDeclaration
     extern (D) this(Loc loc, bool isunion, Dsymbols* decl) @safe
     {
         super(loc, null, decl);
+        this.dsym = DSYM.anonDeclaration;
         this.isunion = isunion;
     }
 
@@ -521,11 +481,6 @@  extern (C++) final class AnonDeclaration : AttribDeclaration
         return (isunion ? "anonymous union" : "anonymous struct");
     }
 
-    override inout(AnonDeclaration) isAnonDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -545,6 +500,7 @@  extern (C++) final class PragmaDeclaration : AttribDeclaration
     extern (D) this(Loc loc, Identifier ident, Expressions* args, Dsymbols* decl) @safe
     {
         super(loc, ident, decl);
+        this.dsym = DSYM.pragmaDeclaration;
         this.args = args;
     }
 
@@ -580,6 +536,7 @@  extern (C++) class ConditionalDeclaration : AttribDeclaration
     extern (D) this(Loc loc, Condition condition, Dsymbols* decl, Dsymbols* elsedecl) @safe
     {
         super(loc, null, decl);
+        this.dsym = DSYM.conditionalDeclaration;
         //printf("ConditionalDeclaration::ConditionalDeclaration()\n");
         this.condition = condition;
         this.elsedecl = elsedecl;
@@ -591,22 +548,6 @@  extern (C++) class ConditionalDeclaration : AttribDeclaration
         return new ConditionalDeclaration(loc, condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
     }
 
-    override final bool oneMember(out Dsymbol ps, Identifier ident)
-    {
-        //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition.inc);
-        if (condition.inc != Include.notComputed)
-        {
-            Dsymbols* d = condition.include(null) ? decl : elsedecl;
-            return Dsymbol.oneMembers(d, ps, ident);
-        }
-        else
-        {
-            bool res = (Dsymbol.oneMembers(decl, ps, ident) && ps is null && Dsymbol.oneMembers(elsedecl, ps, ident) && ps is null);
-            ps = null;
-            return res;
-        }
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -627,6 +568,7 @@  extern (C++) final class StaticIfDeclaration : ConditionalDeclaration
     extern (D) this(Loc loc, Condition condition, Dsymbols* decl, Dsymbols* elsedecl) @safe
     {
         super(loc, condition, decl, elsedecl);
+        this.dsym = DSYM.staticIfDeclaration;
         //printf("StaticIfDeclaration::StaticIfDeclaration()\n");
     }
 
@@ -641,11 +583,6 @@  extern (C++) final class StaticIfDeclaration : ConditionalDeclaration
         return "static if";
     }
 
-    override inout(StaticIfDeclaration) isStaticIfDeclaration() inout pure @safe
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -676,6 +613,7 @@  extern (C++) final class StaticForeachDeclaration : AttribDeclaration
     extern (D) this(StaticForeach sfe, Dsymbols* decl) @safe
     {
         super(sfe.loc, null, decl);
+        this.dsym = DSYM.staticForeachDeclaration;
         this.sfe = sfe;
     }
 
@@ -687,21 +625,6 @@  extern (C++) final class StaticForeachDeclaration : AttribDeclaration
             Dsymbol.arraySyntaxCopy(decl));
     }
 
-    override bool oneMember(out Dsymbol ps, Identifier ident)
-    {
-        // Required to support IFTI on a template that contains a
-        // `static foreach` declaration.  `super.oneMember` calls
-        // include with a `null` scope.  As `static foreach` requires
-        // the scope for expansion, `oneMember` can only return a
-        // precise result once `static foreach` has been expanded.
-        if (cached)
-        {
-            return super.oneMember(ps, ident);
-        }
-        ps = null; // a `static foreach` declaration may in general expand to multiple symbols
-        return false;
-    }
-
     override const(char)* kind() const
     {
         return "static foreach";
@@ -746,16 +669,11 @@  extern(C++) final class ForwardingAttribDeclaration : AttribDeclaration
     this(Dsymbols* decl) @safe
     {
         super(decl);
+        this.dsym = DSYM.forwardingAttribDeclaration;
         sym = new ForwardingScopeDsymbol();
         sym.symtab = new DsymbolTable();
     }
 
-
-    override inout(ForwardingAttribDeclaration) isForwardingAttribDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -778,6 +696,7 @@  extern (C++) final class MixinDeclaration : AttribDeclaration
     {
         super(loc, null, null);
         //printf("MixinDeclaration(loc = %d)\n", loc.linnum);
+        this.dsym = DSYM.mixinDeclaration;
         this.exps = exps;
     }
 
@@ -792,11 +711,6 @@  extern (C++) final class MixinDeclaration : AttribDeclaration
         return "mixin";
     }
 
-    override inout(MixinDeclaration) isMixinDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -815,6 +729,7 @@  extern (C++) final class UserAttributeDeclaration : AttribDeclaration
     extern (D) this(Expressions* atts, Dsymbols* decl) @safe
     {
         super(decl);
+        this.dsym = DSYM.userAttributeDeclaration;
         this.atts = atts;
     }
 
diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h
index ab5f219db88..873c1bdb3da 100644
--- a/gcc/d/dmd/attrib.h
+++ b/gcc/d/dmd/attrib.h
@@ -29,11 +29,7 @@  class AttribDeclaration : public Dsymbol
 public:
     Dsymbols *decl;     // array of Dsymbol's
     const char *kind() const override;
-    bool oneMember(Dsymbol *&ps, Identifier *ident) override;
     bool hasPointers() override final;
-    bool hasStaticCtorOrDtor() override final;
-    AttribDeclaration *isAttribDeclaration() override { return this; }
-
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -43,8 +39,6 @@  public:
     StorageClass stc;
 
     StorageClassDeclaration *syntaxCopy(Dsymbol *s) override;
-    bool oneMember(Dsymbol *&ps, Identifier *ident) override final;
-    StorageClassDeclaration *isStorageClassDeclaration() override { return this; }
 
     void accept(Visitor *v) override { v->visit(this); }
 };
@@ -96,7 +90,6 @@  public:
     VisibilityDeclaration *syntaxCopy(Dsymbol *s) override;
     const char *kind() const override;
     const char *toPrettyChars(bool unused) override;
-    VisibilityDeclaration *isVisibilityDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -121,7 +114,6 @@  public:
 
     AnonDeclaration *syntaxCopy(Dsymbol *s) override;
     const char *kind() const override;
-    AnonDeclaration *isAnonDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -142,7 +134,6 @@  public:
     Dsymbols *elsedecl; // array of Dsymbol's for else block
 
     ConditionalDeclaration *syntaxCopy(Dsymbol *s) override;
-    bool oneMember(Dsymbol *&ps, Identifier *ident) override final;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -154,7 +145,6 @@  public:
     d_bool onStack;
 
     StaticIfDeclaration *syntaxCopy(Dsymbol *s) override;
-    StaticIfDeclaration *isStaticIfDeclaration() override { return this; }
     const char *kind() const override;
     void accept(Visitor *v) override { v->visit(this); }
 };
@@ -169,7 +159,6 @@  public:
     Dsymbols *cache;
 
     StaticForeachDeclaration *syntaxCopy(Dsymbol *s) override;
-    bool oneMember(Dsymbol *&ps, Identifier *ident) override;
     const char *kind() const override;
     void accept(Visitor *v) override { v->visit(this); }
 };
@@ -179,7 +168,6 @@  class ForwardingAttribDeclaration final : public AttribDeclaration
 public:
     ForwardingScopeDsymbol *sym;
 
-    ForwardingAttribDeclaration *isForwardingAttribDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index 93b6dc3852e..6454d736d5a 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -51,11 +51,11 @@  import dmd.tokens;
  * Returns:
  *      merged storage class
  */
-StorageClass mergeFuncAttrs(StorageClass s1, const FuncDeclaration f) pure @safe
+STC mergeFuncAttrs(STC s1, const FuncDeclaration f) pure @safe
 {
     if (!f)
         return s1;
-    StorageClass s2 = (f.storage_class & STC.disable);
+    STC s2 = (f.storage_class & STC.disable);
 
     auto tf = f.type.isTypeFunction();
     if (tf.trust == TRUST.safe)
@@ -75,7 +75,7 @@  StorageClass mergeFuncAttrs(StorageClass s1, const FuncDeclaration f) pure @safe
     const sa = s1 & s2;
     const so = s1 | s2;
 
-    StorageClass stc = (sa & (STC.pure_ | STC.nothrow_ | STC.nogc)) | (so & STC.disable);
+    STC stc = (sa & (STC.pure_ | STC.nothrow_ | STC.nogc)) | (so & STC.disable);
 
     if (so & STC.system)
         stc |= STC.system;
@@ -269,7 +269,7 @@  FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc)
         return null;
 
     //printf("StructDeclaration::buildOpAssign() %s\n", sd.toChars());
-    StorageClass stc = STC.safe;
+    STC stc = STC.safe;
     Loc declLoc = sd.loc;
     Loc loc; // internal code should have no loc to prevent coverage
 
@@ -387,7 +387,7 @@  FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc)
     sd.hasIdentityAssign = true; // temporary mark identity assignable
     const errors = global.startGagging(); // Do not report errors, even if the template opAssign fbody makes it.
     Scope* sc2 = sc.push();
-    sc2.stc = 0;
+    sc2.stc = STC.none;
     sc2.linkage = LINK.d;
     fop.dsymbolSemantic(sc2);
     fop.semantic2(sc2);
@@ -607,7 +607,7 @@  FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
     auto tf = new TypeFunction(ParameterList(parameters), Type.tbool, LINK.d, STC.const_);
     tf = tf.addSTC(STC.const_).toTypeFunction();
     Identifier id = Id.xopEquals;
-    auto fop = new FuncDeclaration(declLoc, Loc.initial, id, 0, tf);
+    auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.none, tf);
     fop.isGenerated = true;
     fop.parent = sd;
     Expression e1 = new IdentifierExp(loc, Id.This);
@@ -616,7 +616,7 @@  FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
     fop.fbody = new ReturnStatement(loc, e);
     const errors = global.startGagging(); // Do not report errors
     Scope* sc2 = sc.push();
-    sc2.stc = 0;
+    sc2.stc = STC.none;
     sc2.linkage = LINK.d;
     fop.dsymbolSemantic(sc2);
     fop.semantic2(sc2);
@@ -731,7 +731,7 @@  FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
     auto tf = new TypeFunction(ParameterList(parameters), Type.tint32, LINK.d, STC.const_);
     tf = tf.addSTC(STC.const_).toTypeFunction();
     Identifier id = Id.xopCmp;
-    auto fop = new FuncDeclaration(declLoc, Loc.initial, id, 0, tf);
+    auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.none, tf);
     fop.isGenerated = true;
     fop.parent = sd;
     Expression e1 = new IdentifierExp(loc, Id.This);
@@ -740,7 +740,7 @@  FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
     fop.fbody = new ReturnStatement(loc, e);
     const errors = global.startGagging(); // Do not report errors
     Scope* sc2 = sc.push();
-    sc2.stc = 0;
+    sc2.stc = STC.none;
     sc2.linkage = LINK.d;
     fop.dsymbolSemantic(sc2);
     fop.semantic2(sc2);
@@ -877,7 +877,7 @@  FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc)
         "return h;";
     fop.fbody = new MixinStatement(loc, new StringExp(loc, code));
     Scope* sc2 = sc.push();
-    sc2.stc = 0;
+    sc2.stc = STC.none;
     sc2.linkage = LINK.d;
     fop.dsymbolSemantic(sc2);
     fop.semantic2(sc2);
@@ -905,7 +905,7 @@  void buildDtors(AggregateDeclaration ad, Scope* sc)
     if (ad.isUnionDeclaration())
         return;                    // unions don't have destructors
 
-    StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
+    STC stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
     Loc declLoc = ad.userDtors.length ? ad.userDtors[0].loc : ad.loc;
     Loc loc; // internal code should have no loc to prevent coverage
     FuncDeclaration xdtor_fwd = null;
@@ -1109,7 +1109,7 @@  private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
     //   // TODO: if (del) delete (char*)this;
     //   return (void*) this;
     // }
-    Parameter delparam = new Parameter(Loc.initial, STC.undefined_, Type.tuns32, Identifier.idPool("del"), new IntegerExp(dtor.loc, 0, Type.tuns32), null);
+    Parameter delparam = new Parameter(Loc.initial, STC.none, Type.tuns32, Identifier.idPool("del"), new IntegerExp(dtor.loc, 0, Type.tuns32), null);
     Parameters* params = new Parameters;
     params.push(delparam);
     const stc = dtor.storage_class & ~STC.scope_; // because we add the `return this;` later
@@ -1224,8 +1224,8 @@  FuncDeclaration buildInv(AggregateDeclaration ad, Scope* sc)
 
     default:
         Expression e = null;
-        StorageClass stcx = 0;
-        StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
+        STC stcx = STC.none;
+        STC stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
         foreach (i, inv; ad.invs)
         {
             stc = mergeFuncAttrs(stc, inv);
@@ -1234,7 +1234,7 @@  FuncDeclaration buildInv(AggregateDeclaration ad, Scope* sc)
                 // What should do?
             }
             const stcy = (inv.storage_class & STC.synchronized_) |
-                         (inv.type.mod & MODFlags.shared_ ? STC.shared_ : 0);
+                         (inv.type.mod & MODFlags.shared_ ? STC.shared_ : STC.none);
             if (i == 0)
                 stcx = stcy;
             else if (stcx ^ stcy)
@@ -1278,7 +1278,7 @@  FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
     const hasUserDefinedPosblit = sd.postblits.length && !sd.postblits[0].isDisabled ? true : false;
 
     // by default, the storage class of the created postblit
-    StorageClass stc = STC.safe;
+    STC stc = STC.safe;
     Loc declLoc = sd.postblits.length ? sd.postblits[0].loc : sd.loc;
     Loc loc; // internal code should have no loc to prevent coverage
 
@@ -1559,11 +1559,11 @@  FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
  * Returns:
  *  The copy constructor declaration for struct `sd`.
  */
-private CtorDeclaration generateCtorDeclaration(StructDeclaration sd, const StorageClass paramStc, const StorageClass funcStc, bool move)
+private CtorDeclaration generateCtorDeclaration(StructDeclaration sd, const STC paramStc, const STC funcStc, bool move)
 {
     auto fparams = new Parameters();
     auto structType = sd.type;
-    StorageClass stc = move ? 0 : STC.ref_;     // the only difference between copy or move
+    STC stc = move ? STC.none : STC.ref_;     // the only difference between copy or move
     fparams.push(new Parameter(Loc.initial, paramStc | stc, structType, Id.p, null, null));
     ParameterList pList = ParameterList(fparams);
     auto tf = new TypeFunction(pList, structType, LINK.d, STC.ref_);
@@ -1773,7 +1773,7 @@  void buildCopyOrMoveCtor(StructDeclaration sd, Scope* sc, bool move)
     ccd.addMember(sc, sd);
     const errors = global.startGagging();
     Scope* sc2 = sc.push();
-    sc2.stc = 0;
+    sc2.stc = STC.none;
     sc2.linkage = LINK.d;
     ccd.dsymbolSemantic(sc2);
     ccd.semantic2(sc2);
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index 48b73e4384f..80e4043ce0d 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -24,7 +24,7 @@  import dmd.dscope;
 import dmd.dsymbol;
 import dmd.errors;
 import dmd.expression;
-import dmd.expressionsem : expressionSemantic, evalStaticCondition, resolveProperties;
+import dmd.expressionsem : evalStaticCondition;
 import dmd.globals;
 import dmd.identifier;
 import dmd.location;
@@ -144,51 +144,6 @@  extern (C++) final class StaticForeach : RootObject
         );
     }
 
-    /*****************************************
-     * Turn an aggregate which is an array into an expression tuple
-     * of its elements. I.e., lower
-     *     static foreach (x; [1, 2, 3, 4]) { ... }
-     * to
-     *     static foreach (x; AliasSeq!(1, 2, 3, 4)) { ... }
-     */
-    private extern(D) void lowerArrayAggregate(Scope* sc)
-    {
-        auto aggr = aggrfe.aggr;
-        Expression el = new ArrayLengthExp(aggr.loc, aggr);
-        sc = sc.startCTFE();
-        el = el.expressionSemantic(sc);
-        sc = sc.endCTFE();
-        el = el.optimize(WANTvalue);
-        el = el.ctfeInterpret();
-        if (el.op != EXP.int64)
-        {
-            aggrfe.aggr = ErrorExp.get();
-            return;
-        }
-
-        Expressions* es;
-        if (auto ale = aggr.isArrayLiteralExp())
-        {
-            // Directly use the elements of the array for the TupleExp creation
-            es = ale.elements;
-        }
-        else
-        {
-            const length = cast(size_t)el.toInteger();
-            es = new Expressions(length);
-            foreach (i; 0 .. length)
-            {
-                auto index = new IntegerExp(loc, i, Type.tsize_t);
-                auto value = new IndexExp(aggr.loc, aggr, index);
-                (*es)[i] = value;
-            }
-        }
-        aggrfe.aggr = new TupleExp(aggr.loc, es);
-        aggrfe.aggr = aggrfe.aggr.expressionSemantic(sc);
-        aggrfe.aggr = aggrfe.aggr.optimize(WANTvalue);
-        aggrfe.aggr = aggrfe.aggr.ctfeInterpret();
-    }
-
     /*****************************************
      * Wrap a statement into a function literal and call it.
      *
@@ -198,9 +153,9 @@  extern (C++) final class StaticForeach : RootObject
      * Returns:
      *     AST of the expression `(){ s; }()` with location loc.
      */
-    private extern(D) Expression wrapAndCall(Loc loc, Statement s)
+    extern(D) Expression wrapAndCall(Loc loc, Statement s)
     {
-        auto tf = new TypeFunction(ParameterList(), null, LINK.default_, 0);
+        auto tf = new TypeFunction(ParameterList(), null, LINK.default_, STC.none);
         auto fd = new FuncLiteralDeclaration(loc, loc, tf, TOK.reserved, null);
         fd.fbody = s;
         auto fe = new FuncExp(loc, fd);
@@ -221,7 +176,7 @@  extern (C++) final class StaticForeach : RootObject
      *     `foreach (parameters; lower .. upper) s;`
      *     Where aggregate/lower, upper are as for the current StaticForeach.
      */
-    private extern(D) Statement createForeach(Loc loc, Parameters* parameters, Statement s)
+    extern(D) Statement createForeach(Loc loc, Parameters* parameters, Statement s)
     {
         if (aggrfe)
         {
@@ -254,7 +209,7 @@  extern (C++) final class StaticForeach : RootObject
      *         }
      */
 
-    private extern(D) TypeStruct createTupleType(Loc loc, Expressions* e, Scope* sc)
+    extern(D) TypeStruct createTupleType(Loc loc, Expressions* e, Scope* sc)
     {   // TODO: move to druntime?
         auto sid = Identifier.generateId("Tuple");
         auto sdecl = new StructDeclaration(loc, sid, false);
@@ -262,7 +217,7 @@  extern (C++) final class StaticForeach : RootObject
         sdecl.members = new Dsymbols();
         auto fid = Identifier.idPool(tupleFieldName);
         auto ty = new TypeTypeof(loc, new TupleExp(loc, e));
-        sdecl.members.push(new VarDeclaration(loc, ty, fid, null, 0));
+        sdecl.members.push(new VarDeclaration(loc, ty, fid, null, STC.none));
         auto r = cast(TypeStruct)sdecl.type;
         if (global.params.useTypeInfo && Type.dtypeinfo)
             r.vtinfo = TypeInfoStructDeclaration.create(r); // prevent typeinfo from going to object file
@@ -280,205 +235,11 @@  extern (C++) final class StaticForeach : RootObject
      *     An AST for the expression `Tuple(e)`.
      */
 
-    private extern(D) Expression createTuple(Loc loc, TypeStruct type, Expressions* e) @safe
+    extern(D) Expression createTuple(Loc loc, TypeStruct type, Expressions* e) @safe
     {   // TODO: move to druntime?
         return new CallExp(loc, new TypeExp(loc, type), e);
     }
 
-
-    /*****************************************
-     * Lower any aggregate that is not an array to an array using a
-     * regular foreach loop within CTFE.  If there are multiple
-     * `static foreach` loop variables, an array of tuples is
-     * generated. In thise case, the field `needExpansion` is set to
-     * true to indicate that the static foreach loop expansion will
-     * need to expand the tuples into multiple variables.
-     *
-     * For example, `static foreach (x; range) { ... }` is lowered to:
-     *
-     *     static foreach (x; {
-     *         typeof({
-     *             foreach (x; range) return x;
-     *         }())[] __res;
-     *         foreach (x; range) __res ~= x;
-     *         return __res;
-     *     }()) { ... }
-     *
-     * Finally, call `lowerArrayAggregate` to turn the produced
-     * array into an expression tuple.
-     *
-     * Params:
-     *     sc = The current scope.
-     */
-
-    private void lowerNonArrayAggregate(Scope* sc)
-    {
-        auto nvars = aggrfe ? aggrfe.parameters.length : 1;
-        auto aloc = aggrfe ? aggrfe.aggr.loc : rangefe.lwr.loc;
-        // We need three sets of foreach loop variables because the
-        // lowering contains three foreach loops.
-        Parameters*[3] pparams = [new Parameters(), new Parameters(), new Parameters()];
-        foreach (i; 0 .. nvars)
-        {
-            foreach (params; pparams)
-            {
-                auto p = aggrfe ? (*aggrfe.parameters)[i] : rangefe.param;
-                params.push(new Parameter(aloc, p.storageClass, p.type, p.ident, null, null));
-            }
-        }
-        Expression[2] res;
-        TypeStruct tplty = null;
-        if (nvars == 1) // only one `static foreach` variable, generate identifiers.
-        {
-            foreach (i; 0 .. 2)
-            {
-                res[i] = new IdentifierExp(aloc, (*pparams[i])[0].ident);
-            }
-        }
-        else // multiple `static foreach` variables, generate tuples.
-        {
-            foreach (i; 0 .. 2)
-            {
-                auto e = new Expressions(pparams[0].length);
-                foreach (j, ref elem; *e)
-                {
-                    auto p = (*pparams[i])[j];
-                    elem = new IdentifierExp(aloc, p.ident);
-                }
-                if (!tplty)
-                {
-                    tplty = createTupleType(aloc, e, sc);
-                }
-                res[i] = createTuple(aloc, tplty, e);
-            }
-            needExpansion = true; // need to expand the tuples later
-        }
-        // generate remaining code for the new aggregate which is an
-        // array (see documentation comment).
-        if (rangefe)
-        {
-            sc = sc.startCTFE();
-            rangefe.lwr = rangefe.lwr.expressionSemantic(sc);
-            rangefe.lwr = resolveProperties(sc, rangefe.lwr);
-            rangefe.upr = rangefe.upr.expressionSemantic(sc);
-            rangefe.upr = resolveProperties(sc, rangefe.upr);
-            sc = sc.endCTFE();
-            rangefe.lwr = rangefe.lwr.optimize(WANTvalue);
-            rangefe.lwr = rangefe.lwr.ctfeInterpret();
-            rangefe.upr = rangefe.upr.optimize(WANTvalue);
-            rangefe.upr = rangefe.upr.ctfeInterpret();
-        }
-        auto s1 = new Statements();
-        auto sfe = new Statements();
-        if (tplty) sfe.push(new ExpStatement(loc, tplty.sym));
-        sfe.push(new ReturnStatement(aloc, res[0]));
-        s1.push(createForeach(aloc, pparams[0], new CompoundStatement(aloc, sfe)));
-        s1.push(new ExpStatement(aloc, new AssertExp(aloc, IntegerExp.literal!0)));
-        Type ety = new TypeTypeof(aloc, wrapAndCall(aloc, new CompoundStatement(aloc, s1)));
-        auto aty = ety.arrayOf();
-        auto idres = Identifier.generateId("__res");
-        auto vard = new VarDeclaration(aloc, aty, idres, null, STC.temp);
-        auto s2 = new Statements();
-
-        // Run 'typeof' gagged to avoid duplicate errors and if it fails just create
-        // an empty foreach to expose them.
-        const olderrors = global.startGagging();
-        ety = ety.typeSemantic(aloc, sc);
-        if (global.endGagging(olderrors))
-            s2.push(createForeach(aloc, pparams[1], null));
-        else
-        {
-            s2.push(new ExpStatement(aloc, vard));
-            auto catass = new CatAssignExp(aloc, new IdentifierExp(aloc, idres), res[1]);
-            s2.push(createForeach(aloc, pparams[1], new ExpStatement(aloc, catass)));
-            s2.push(new ReturnStatement(aloc, new IdentifierExp(aloc, idres)));
-        }
-
-        Expression aggr = void;
-        Type indexty = void;
-
-        if (rangefe && (indexty = ety).isIntegral())
-        {
-            rangefe.lwr.type = indexty;
-            rangefe.upr.type = indexty;
-            auto lwrRange = getIntRange(rangefe.lwr);
-            auto uprRange = getIntRange(rangefe.upr);
-
-            const lwr = rangefe.lwr.toInteger();
-            auto  upr = rangefe.upr.toInteger();
-            size_t length = 0;
-
-            if (lwrRange.imin <= uprRange.imax)
-                    length = cast(size_t) (upr - lwr);
-
-            auto exps = new Expressions(length);
-
-            if (rangefe.op == TOK.foreach_)
-            {
-                foreach (i; 0 .. length)
-                    (*exps)[i] = new IntegerExp(aloc, lwr + i, indexty);
-            }
-            else
-            {
-                --upr;
-                foreach (i; 0 .. length)
-                    (*exps)[i] = new IntegerExp(aloc, upr - i, indexty);
-            }
-            aggr = new ArrayLiteralExp(aloc, indexty.arrayOf(), exps);
-        }
-        else
-        {
-            aggr = wrapAndCall(aloc, new CompoundStatement(aloc, s2));
-            sc = sc.startCTFE();
-            aggr = aggr.expressionSemantic(sc);
-            aggr = resolveProperties(sc, aggr);
-            sc = sc.endCTFE();
-            aggr = aggr.optimize(WANTvalue);
-            aggr = aggr.ctfeInterpret();
-        }
-
-        assert(!!aggrfe ^ !!rangefe);
-        aggrfe = new ForeachStatement(loc, TOK.foreach_, pparams[2], aggr,
-                                      aggrfe ? aggrfe._body : rangefe._body,
-                                      aggrfe ? aggrfe.endloc : rangefe.endloc);
-        rangefe = null;
-        lowerArrayAggregate(sc); // finally, turn generated array into expression tuple
-    }
-
-    /*****************************************
-     * Perform `static foreach` lowerings that are necessary in order
-     * to finally expand the `static foreach` using
-     * `dmd.statementsem.makeTupleForeach`.
-     */
-    extern(D) void prepare(Scope* sc)
-    {
-        assert(sc);
-
-        if (aggrfe)
-        {
-            sc = sc.startCTFE();
-            aggrfe.aggr = aggrfe.aggr.expressionSemantic(sc);
-            sc = sc.endCTFE();
-        }
-
-        if (aggrfe && aggrfe.aggr.type.toBasetype().ty == Terror)
-        {
-            return;
-        }
-
-        if (!ready())
-        {
-            if (aggrfe && aggrfe.aggr.type.toBasetype().ty == Tarray)
-            {
-                lowerArrayAggregate(sc);
-            }
-            else
-            {
-                lowerNonArrayAggregate(sc);
-            }
-        }
-    }
-
     /*****************************************
      * Returns:
      *     `true` iff ready to call `dmd.statementsem.makeTupleForeach`.
diff --git a/gcc/d/dmd/cond.h b/gcc/d/dmd/cond.h
index ec68d19c04a..191164fad6f 100644
--- a/gcc/d/dmd/cond.h
+++ b/gcc/d/dmd/cond.h
@@ -71,7 +71,6 @@  public:
     static void addGlobalIdent(const char *ident);
 
     int include(Scope *sc) override;
-    DebugCondition *isDebugCondition() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -82,7 +81,6 @@  public:
     static void addPredefinedGlobalIdent(const char *ident);
 
     int include(Scope *sc) override;
-    VersionCondition *isVersionCondition() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 9f1eab7fc6c..3efda07f5fc 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -1445,8 +1445,10 @@  final class CParser(AST) : Parser!AST
         auto e = cparseOrExp();
         while (token.value == TOK.andAnd)
         {
+            e = new AST.CastExp(loc, e, AST.Type.tbool);
             nextToken();
             auto e2 = cparseOrExp();
+            e2 = new AST.CastExp(loc, e2, AST.Type.tbool);
             e = new AST.LogicalExp(loc, EXP.andAnd, e, e2);
         }
         return e;
@@ -1465,8 +1467,10 @@  final class CParser(AST) : Parser!AST
         auto e = cparseAndAndExp();
         while (token.value == TOK.orOr)
         {
+            e = new AST.CastExp(loc, e, AST.Type.tbool);
             nextToken();
             auto e2 = cparseAndAndExp();
+            e2 = new AST.CastExp(loc, e2, AST.Type.tbool);
             e = new AST.LogicalExp(loc, EXP.orOr, e, e2);
         }
         return e;
@@ -1686,7 +1690,7 @@  final class CParser(AST) : Parser!AST
     private AST.Expression cparseStatementExpression()
     {
         AST.ParameterList parameterList;
-        StorageClass stc = 0;
+        STC stc = STC.none;
         const loc = token.loc;
         auto symbolsSave = symbols;
         symbols = new AST.Dsymbols();
@@ -1710,7 +1714,7 @@  final class CParser(AST) : Parser!AST
         }
 
         auto tf = new AST.TypeFunction(parameterList, null, LINK.d, stc);
-        auto fd = new AST.FuncLiteralDeclaration(loc, token.loc, tf, TOK.delegate_, null, null, 0);
+        auto fd = new AST.FuncLiteralDeclaration(loc, token.loc, tf, TOK.delegate_, null, null, STC.none);
         fd.fbody = fbody;
 
         auto fe = new AST.FuncExp(loc, fd);
@@ -2046,7 +2050,7 @@  final class CParser(AST) : Parser!AST
                         error("no initializer for function declaration");
                     if (specifier.scw & SCW.x_Thread_local)
                         error("functions cannot be `_Thread_local`"); // C11 6.7.1-4
-                    StorageClass stc = specifiersToSTC(level, specifier);
+                    STC stc = specifiersToSTC(level, specifier);
                     stc &= ~STC.gshared;        // no gshared functions
                     auto fd = new AST.FuncDeclaration(token.loc, Loc.initial, id, stc, dt, specifier.noreturn);
                     specifiersToFuncDeclaration(fd, specifier);
@@ -2233,7 +2237,7 @@  final class CParser(AST) : Parser!AST
         auto body = cparseStatement(ParseStatementFlags.curly);  // don't start a new scope; continue with parameter scope
         typedefTab.pop();                                        // end of function scope
 
-        StorageClass stc = specifiersToSTC(LVL.global, specifier);
+        STC stc = specifiersToSTC(LVL.global, specifier);
         stc &= ~STC.gshared;    // no gshared functions
         auto fd = new AST.FuncDeclaration(locFunc, prevloc, id, stc, ft, specifier.noreturn);
         specifiersToFuncDeclaration(fd, specifier);
@@ -3018,7 +3022,7 @@  final class CParser(AST) : Parser!AST
 
                         auto parameterList = cparseParameterList();
                         const lkg = specifier.mod & MOD.x__stdcall ? LINK.windows : linkage;
-                        StorageClass stc = specifier._nothrow ? STC.nothrow_ : 0;
+                        STC stc = specifier._nothrow ? STC.nothrow_ : STC.none;
                         if (specifier._pure)
                             stc |= STC.pure_;
                         stc |= defaultStorageClasses;
@@ -3174,7 +3178,7 @@  final class CParser(AST) : Parser!AST
     {
         auto parameters = new AST.Parameters();
         AST.VarArg varargs = AST.VarArg.none;
-        StorageClass varargsStc;
+        STC varargsStc;
 
         check(TOK.leftParenthesis);
         if (token.value == TOK.void_ && peekNext() == TOK.rightParenthesis) // func(void)
@@ -3537,7 +3541,7 @@  final class CParser(AST) : Parser!AST
             break;
         }
         nextToken();
-        auto s = new AST.CompoundAsmStatement(loc, statements, 0);
+        auto s = new AST.CompoundAsmStatement(loc, statements, STC.none);
         return s;
     }
 
@@ -3922,7 +3926,7 @@  final class CParser(AST) : Parser!AST
                     cparseGnuAttributes(specifierx);
                 }
 
-                auto em = new AST.EnumMember(mloc, ident, value, null, 0, null, null);
+                auto em = new AST.EnumMember(mloc, ident, value, null, STC.none, null, null);
                 members.push(em);
 
                 if (token.value == TOK.comma)
@@ -5162,9 +5166,9 @@  final class CParser(AST) : Parser!AST
      * Returns:
      *  corresponding D storage class
      */
-    StorageClass specifiersToSTC(LVL level, const ref Specifier specifier)
+    STC specifiersToSTC(LVL level, const ref Specifier specifier)
     {
-        StorageClass stc;
+        STC stc;
         if (specifier.scw & SCW.x_Thread_local)
         {
             if (level == LVL.global)
@@ -6205,8 +6209,8 @@  final class CParser(AST) : Parser!AST
                             if (token.value != TOK.endOfFile)
                                 break;
                             auto ret = new AST.ReturnStatement(exp.loc, exp);
-                            auto parameterList = AST.ParameterList(new AST.Parameters(), VarArg.none, 0);
-                            StorageClass stc = STC.auto_;
+                            auto parameterList = AST.ParameterList(new AST.Parameters(), VarArg.none, STC.none);
+                            STC stc = STC.auto_;
                             auto tf = new AST.TypeFunction(parameterList, null, LINK.d, stc);
                             auto fd = new AST.FuncDeclaration(exp.loc, exp.loc, id, stc, tf, 0);
                             fd.fbody = ret;
@@ -6251,7 +6255,7 @@  final class CParser(AST) : Parser!AST
 
                                 if (token.value != TOK.identifier)
                                     break Lswitch;
-                                auto param = new AST.Parameter(token.loc, 0, null, token.ident, null, null);
+                                auto param = new AST.Parameter(token.loc, STC.none, null, token.ident, null, null);
                                 parameters.push(param);
                                 nextToken();
                                 if (token.value == TOK.comma)
@@ -6266,7 +6270,7 @@  final class CParser(AST) : Parser!AST
 
                             //auto pstart = p;
                             nextToken();
-                            auto parameterList = AST.ParameterList(parameters, varargs, 0);
+                            auto parameterList = AST.ParameterList(parameters, varargs, STC.none);
                             /* Create a type for each parameter. Add it to the template parameter list,
                              * and the parameter list.
                              */
@@ -6297,7 +6301,7 @@  final class CParser(AST) : Parser!AST
 
                             // Generate function
                             auto ret = new AST.ReturnStatement(exp.loc, exp);
-                            StorageClass stc = STC.auto_;
+                            STC stc = STC.auto_;
                             auto tf = new AST.TypeFunction(parameterList, null, LINK.d, stc);
                             auto fd = new AST.FuncDeclaration(exp.loc, exp.loc, id, stc, tf, 0);
                             fd.fbody = ret;
diff --git a/gcc/d/dmd/cxxfrontend.d b/gcc/d/dmd/cxxfrontend.d
index 3cd4ced6b49..ecf339962c2 100644
--- a/gcc/d/dmd/cxxfrontend.d
+++ b/gcc/d/dmd/cxxfrontend.d
@@ -15,6 +15,7 @@  import dmd.arraytypes;
 import dmd.astenums;
 import dmd.attrib;
 import dmd.common.outbuffer : OutBuffer;
+import dmd.dclass : ClassDeclaration;
 import dmd.declaration : TypeInfoDeclaration;
 import dmd.denum : EnumDeclaration;
 import dmd.dmodule /*: Module*/;
@@ -179,6 +180,18 @@  Dsymbols* include(Dsymbol d, Scope* sc)
     return dmd.dsymbolsem.include(d, sc);
 }
 
+bool isFuncHidden(ClassDeclaration cd, FuncDeclaration fd)
+{
+    import dmd.dsymbolsem;
+    return dmd.dsymbolsem.isFuncHidden(cd, fd);
+}
+
+Dsymbol vtblSymbol(ClassDeclaration cd)
+{
+    import dmd.dsymbolsem;
+    return dmd.dsymbolsem.vtblSymbol(cd);
+}
+
 /***********************************************************
  * dtemplate.d
  */
@@ -264,6 +277,19 @@  bool fill(StructDeclaration sd, Loc loc,
     return dmd.expressionsem.fill(sd, loc, elements, ctorinit);
 }
 
+/***********************************************************
+ * func.d
+ */
+FuncDeclaration genCfunc(Parameters* fparams, Type treturn, const(char)* name, StorageClass stc = STC.none)
+{
+    return FuncDeclaration.genCfunc(fparams, treturn, name, cast(STC) stc);
+}
+
+FuncDeclaration genCfunc(Parameters* fparams, Type treturn, Identifier id, StorageClass stc = STC.none)
+{
+    return FuncDeclaration.genCfunc(fparams, treturn, id, cast(STC) stc);
+}
+
 /***********************************************************
  * funcsem.d
  */
@@ -511,7 +537,7 @@  Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool
                     cppCovariant = false)
 {
     import dmd.typesem;
-    return dmd.typesem.covariant(src, t, pstc, cppCovariant);
+    return dmd.typesem.covariant(src, t, cast(STC*) pstc, cppCovariant);
 }
 
 bool isZeroInit(Type t, Loc loc)
@@ -643,7 +669,7 @@  Type addMod(Type type, MOD mod)
 Type addStorageClass(Type type, StorageClass stc)
 {
     import dmd.typesem;
-    return dmd.typesem.addStorageClass(type, stc);
+    return dmd.typesem.addStorageClass(type, cast(STC) stc);
 }
 
 Type pointerTo(Type type)
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 172c8278f7f..21ddd752ecd 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -704,6 +704,12 @@  MATCH implicitConvTo(Expression e, Type t)
                 if (!tn.isConst() && !tn.isImmutable())
                     return MATCH.nomatch;
                 m = MATCH.constant;
+
+                // After converting e.g. ubyte[] to const(ubyte)[], don't change
+                // to MATCH.convert, return MATCH.constant
+                //  https://github.com/dlang/dmd/issues/20635
+                if (e.type.ty == t.ty && e.type.nextOf().ty == tn.ty)
+                    return m;
             }
             if (e.type != t && e.hexString && tn.isIntegral && (tn.size == e.sz || (!e.committed && (e.len % tn.size) == 0)))
             {
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index b59c5205fd6..b21ec0033e0 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -23,7 +23,7 @@  import dmd.gluelayer;
 import dmd.declaration;
 import dmd.dscope;
 import dmd.dsymbol;
-import dmd.dsymbolsem : dsymbolSemantic, addMember, search, setFieldOffset;
+import dmd.dsymbolsem : dsymbolSemantic, addMember, setFieldOffset;
 import dmd.errors;
 import dmd.func;
 import dmd.id;
@@ -206,6 +206,7 @@  extern (C++) class ClassDeclaration : AggregateDeclaration
             id = Identifier.generateAnonymousId("class");
 
         super(loc, id);
+        this.dsym = DSYM.classDeclaration;
 
         static immutable msg = "only object.d can define this reserved class name";
 
@@ -613,40 +614,6 @@  extern (C++) class ClassDeclaration : AggregateDeclaration
         return classKind == ClassKind.d;
     }
 
-    final bool isFuncHidden(FuncDeclaration fd)
-    {
-        import dmd.funcsem : overloadApply;
-        //printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toPrettyChars());
-        Dsymbol s = this.search(Loc.initial, fd.ident, SearchOpt.ignoreAmbiguous | SearchOpt.ignoreErrors);
-        if (!s)
-        {
-            //printf("not found\n");
-            /* Because, due to a hack, if there are multiple definitions
-             * of fd.ident, NULL is returned.
-             */
-            return false;
-        }
-        s = s.toAlias();
-        if (auto os = s.isOverloadSet())
-        {
-            foreach (sm; os.a)
-            {
-                auto fm = sm.isFuncDeclaration();
-                if (overloadApply(fm, s => fd == s.isFuncDeclaration()))
-                    return false;
-            }
-            return true;
-        }
-        else
-        {
-            auto f = s.isFuncDeclaration();
-            //printf("%s fdstart = %p\n", s.kind(), fdstart);
-            if (overloadApply(f, s => fd == s.isFuncDeclaration()))
-                return false;
-            return !fd.parent.isTemplateMixin();
-        }
-    }
-
     /****************
      * Find virtual function matching identifier and type.
      * Used to build virtual function tables for interface implementations.
@@ -921,31 +888,11 @@  extern (C++) class ClassDeclaration : AggregateDeclaration
     // Back end
     Dsymbol vtblsym;
 
-    final Dsymbol vtblSymbol()
-    {
-        if (!vtblsym)
-        {
-            auto vtype = Type.tvoidptr.immutableOf().sarrayOf(vtbl.length);
-            auto var = new VarDeclaration(loc, vtype, Identifier.idPool("__vtbl"), null, STC.immutable_ | STC.static_);
-            var.addMember(null, this);
-            var.isdataseg = 1;
-            var._linkage = LINK.d;
-            var.semanticRun = PASS.semanticdone; // no more semantic wanted
-            vtblsym = var;
-        }
-        return vtblsym;
-    }
-
     extern (D) final bool isErrorException()
     {
         return errorException && (this == errorException || errorException.isBaseOf(this, null));
     }
 
-    override final inout(ClassDeclaration) isClassDeclaration() inout @nogc nothrow pure @safe
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -959,6 +906,7 @@  extern (C++) final class InterfaceDeclaration : ClassDeclaration
     extern (D) this(Loc loc, Identifier id, BaseClasses* baseclasses)
     {
         super(loc, id, baseclasses, null, false);
+        this.dsym = DSYM.interfaceDeclaration;
         if (id == Id.IUnknown) // IUnknown is the root of all COM interfaces
         {
             com = true;
@@ -1058,11 +1006,6 @@  extern (C++) final class InterfaceDeclaration : ClassDeclaration
         return com;
     }
 
-    override inout(InterfaceDeclaration) isInterfaceDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 30f017d8952..870401bb69d 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -87,7 +87,7 @@  extern (C++) abstract class Declaration : Dsymbol
 {
     Type type;
     Type originalType;  // before semantic analysis
-    StorageClass storage_class = STC.undefined_;
+    STC storage_class = STC.none;
     // overridden symbol with pragma(mangle, "...")
     const(char)[] mangleOverride;
     Visibility visibility;
@@ -106,15 +106,15 @@  extern (C++) abstract class Declaration : Dsymbol
     import dmd.common.bitfields;
     mixin(generateBitFields!(BitFields, ubyte));
 
-    final extern (D) this(Identifier ident) @safe
+    final extern (D) this(DSYM tag, Identifier ident) @safe
     {
-        super(ident);
+        super(tag, ident);
         visibility = Visibility(Visibility.Kind.undefined);
     }
 
-    final extern (D) this(Loc loc, Identifier ident) @safe
+    final extern (D) this(DSYM tag, Loc loc, Identifier ident) @safe
     {
-        super(loc, ident);
+        super(tag, loc, ident);
         visibility = Visibility(Visibility.Kind.undefined);
     }
 
@@ -274,11 +274,6 @@  extern (C++) abstract class Declaration : Dsymbol
         return visibility;
     }
 
-    override final inout(Declaration) isDeclaration() inout pure nothrow @nogc @safe
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -296,7 +291,7 @@  extern (C++) final class TupleDeclaration : Declaration
 
     extern (D) this(Loc loc, Identifier ident, Objects* objects) @safe
     {
-        super(loc, ident);
+        super(DSYM.tupleDeclaration, loc, ident);
         this.objects = objects;
     }
 
@@ -350,7 +345,7 @@  extern (C++) final class TupleDeclaration : Declaration
                 }
                 else
                 {
-                    auto arg = new Parameter(Loc.initial, 0, t, null, null, null);
+                    auto arg = new Parameter(Loc.initial, STC.none, t, null, null, null);
                 }
                 (*args)[i] = arg;
                 if (!t.deco)
@@ -424,11 +419,6 @@  extern (C++) final class TupleDeclaration : Declaration
         return 0;
     }
 
-    override inout(TupleDeclaration) isTupleDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -447,7 +437,7 @@  extern (C++) final class AliasDeclaration : Declaration
 
     extern (D) this(Loc loc, Identifier ident, Type type) @safe
     {
-        super(loc, ident);
+        super(DSYM.aliasDeclaration, loc, ident);
         //debug printf("AliasDeclaration(id = '%s', type = `%s`, %p)\n", ident.toChars(), dmd.hdrgen.toChars(type), type.isTypeIdentifier());
         this.type = type;
         assert(type);
@@ -455,7 +445,7 @@  extern (C++) final class AliasDeclaration : Declaration
 
     extern (D) this(Loc loc, Identifier ident, Dsymbol s) @safe
     {
-        super(loc, ident);
+        super(DSYM.aliasDeclaration, loc, ident);
         //debug printf("AliasDeclaration(id = '%s', s = `%s`)\n", ident.toChars(), s.toChars());
         assert(s != this);
         this.aliassym = s;
@@ -732,11 +722,6 @@  extern (C++) final class AliasDeclaration : Declaration
             aliassym && aliassym.isOverloadable();
     }
 
-    override inout(AliasDeclaration) isAliasDeclaration() inout
-    {
-        return this;
-    }
-
     /** Returns: `true` if this instance was created to make a template parameter
     visible in the scope of a template body, `false` otherwise */
     extern (D) bool isAliasedTemplateParameter() const
@@ -759,7 +744,7 @@  extern (C++) final class OverDeclaration : Declaration
 
     extern (D) this(Identifier ident, Dsymbol s) @safe
     {
-        super(ident);
+        super(DSYM.overDeclaration, ident);
         this.aliassym = s;
     }
 
@@ -817,11 +802,6 @@  extern (C++) final class OverDeclaration : Declaration
         return result;
     }
 
-    override inout(OverDeclaration) isOverDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -887,7 +867,7 @@  extern (C++) class VarDeclaration : Declaration
     byte canassign;                 // it can be assigned to
     ubyte isdataseg;                // private data for isDataseg 0 unset, 1 true, 2 false
 
-    final extern (D) this(Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
+    final extern (D) this(Loc loc, Type type, Identifier ident, Initializer _init, STC storage_class = STC.none)
     in
     {
         assert(ident);
@@ -895,7 +875,7 @@  extern (C++) class VarDeclaration : Declaration
     do
     {
         //printf("VarDeclaration('%s')\n", ident.toChars());
-        super(loc, ident);
+        super(DSYM.varDeclaration, loc, ident);
         debug
         {
             if (!type && !_init)
@@ -912,9 +892,9 @@  extern (C++) class VarDeclaration : Declaration
         this.storage_class = storage_class;
     }
 
-    static VarDeclaration create(Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
+    static VarDeclaration create(Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.none)
     {
-        return new VarDeclaration(loc, type, ident, _init, storage_class);
+        return new VarDeclaration(loc, type, ident, _init, cast(STC) storage_class);
     }
 
     override VarDeclaration syntaxCopy(Dsymbol s)
@@ -1217,12 +1197,6 @@  extern (C++) class VarDeclaration : Declaration
         return s;
     }
 
-    // Eliminate need for dynamic_cast
-    override final inout(VarDeclaration) isVarDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1242,7 +1216,7 @@  extern (C++) class BitFieldDeclaration : VarDeclaration
     final extern (D) this(Loc loc, Type type, Identifier ident, Expression width)
     {
         super(loc, type, ident, null);
-
+        this.dsym = DSYM.bitFieldDeclaration;
         this.width = width;
         this.storage_class |= STC.field;
     }
@@ -1256,11 +1230,6 @@  extern (C++) class BitFieldDeclaration : VarDeclaration
         return bf;
     }
 
-    override final inout(BitFieldDeclaration) isBitFieldDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1302,17 +1271,11 @@  extern (C++) final class SymbolDeclaration : Declaration
 
     extern (D) this(Loc loc, AggregateDeclaration dsym) @safe
     {
-        super(loc, dsym.ident);
+        super(DSYM.symbolDeclaration, loc, dsym.ident);
         this.dsym = dsym;
         storage_class |= STC.const_;
     }
 
-    // Eliminate need for dynamic_cast
-    override inout(SymbolDeclaration) isSymbolDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1357,6 +1320,7 @@  extern (C++) class TypeInfoDeclaration : VarDeclaration
     final extern (D) this(Type tinfo)
     {
         super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
+        this.dsym = DSYM.typeInfoDeclaration;
         this.tinfo = tinfo;
         storage_class = STC.static_ | STC.gshared;
         visibility = Visibility(Visibility.Kind.public_);
@@ -1374,11 +1338,6 @@  extern (C++) class TypeInfoDeclaration : VarDeclaration
         assert(0); // should never be produced by syntax
     }
 
-    override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1795,6 +1754,7 @@  extern (C++) final class ThisDeclaration : VarDeclaration
     extern (D) this(Loc loc, Type t)
     {
         super(loc, t, Id.This, null);
+        this.dsym = DSYM.thisDeclaration;
         storage_class |= STC.nodtor;
     }
 
@@ -1803,11 +1763,6 @@  extern (C++) final class ThisDeclaration : VarDeclaration
         assert(0); // should never be produced by syntax
     }
 
-    override inout(ThisDeclaration) isThisDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 6fef6a5b3a4..4d23d86ea58 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -37,6 +37,8 @@  namespace dmd
     bool checkClosure(FuncDeclaration* fd);
     MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, Identifiers *names);
     PURE isPure(FuncDeclaration *f);
+    FuncDeclaration *genCfunc(Parameters *args, Type *treturn, const char *name, StorageClass stc=0);
+    FuncDeclaration *genCfunc(Parameters *args, Type *treturn, Identifier *id, StorageClass stc=0);
 }
 
 //enum STC : ulong from astenums.d:
@@ -160,7 +162,6 @@  public:
 
     Visibility visible() override final;
 
-    Declaration *isDeclaration() override final { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -180,7 +181,6 @@  public:
     Dsymbol *toAlias2() override;
     bool needThis() override;
 
-    TupleDeclaration *isTupleDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -202,7 +202,6 @@  public:
     Dsymbol *toAlias2() override;
     bool isOverloadable() const override;
 
-    AliasDeclaration *isAliasDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -222,7 +221,6 @@  public:
     Dsymbol *isUnique();
     bool isOverloadable() const override;
 
-    OverDeclaration *isOverDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -300,7 +298,6 @@  public:
     bool needsScopeDtor();
     Dsymbol *toAlias() override final;
     // Eliminate need for dynamic_cast
-    VarDeclaration *isVarDeclaration() override final { return (VarDeclaration *)this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -315,7 +312,6 @@  public:
     unsigned bitOffset;
 
     BitFieldDeclaration *syntaxCopy(Dsymbol *) override;
-    BitFieldDeclaration *isBitFieldDeclaration() override final { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -329,7 +325,6 @@  public:
     AggregateDeclaration *dsym;
 
     // Eliminate need for dynamic_cast
-    SymbolDeclaration *isSymbolDeclaration() override { return (SymbolDeclaration *)this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -341,7 +336,6 @@  public:
     static TypeInfoDeclaration *create(Type *tinfo);
     TypeInfoDeclaration *syntaxCopy(Dsymbol *) override final;
 
-    TypeInfoDeclaration *isTypeInfoDeclaration() override final { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -481,7 +475,6 @@  class ThisDeclaration final : public VarDeclaration
 {
 public:
     ThisDeclaration *syntaxCopy(Dsymbol *) override;
-    ThisDeclaration *isThisDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -735,11 +728,6 @@  public:
     bool hasNestedFrameRefs();
     ParameterList getParameterList();
 
-    static FuncDeclaration *genCfunc(Parameters *args, Type *treturn, const char *name, StorageClass stc=0);
-    static FuncDeclaration *genCfunc(Parameters *args, Type *treturn, Identifier *id, StorageClass stc=0);
-
-    FuncDeclaration *isFuncDeclaration() override final { return this; }
-
     virtual FuncDeclaration *toAliasFunc() { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
@@ -750,7 +738,6 @@  public:
     FuncDeclaration *funcalias;
     d_bool hasOverloads;
 
-    FuncAliasDeclaration *isFuncAliasDeclaration() override { return this; }
     const char *kind() const override;
 
     FuncDeclaration *toAliasFunc() override;
@@ -773,7 +760,6 @@  public:
     bool addPreInvariant() override;
     bool addPostInvariant() override;
 
-    FuncLiteralDeclaration *isFuncLiteralDeclaration() override { return this; }
     const char *kind() const override;
     const char *toPrettyChars(bool QualifyTypes = false) override;
     void accept(Visitor *v) override { v->visit(this); }
@@ -790,7 +776,6 @@  public:
     bool addPreInvariant() override;
     bool addPostInvariant() override;
 
-    CtorDeclaration *isCtorDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -803,7 +788,6 @@  public:
     bool addPostInvariant() override;
     bool overloadInsert(Dsymbol *s) override;
 
-    PostBlitDeclaration *isPostBlitDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -817,7 +801,6 @@  public:
     bool addPostInvariant() override;
     bool overloadInsert(Dsymbol *s) override;
 
-    DtorDeclaration *isDtorDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -829,9 +812,7 @@  public:
     bool isVirtual() const override final;
     bool addPreInvariant() override final;
     bool addPostInvariant() override final;
-    bool hasStaticCtorOrDtor() override final;
 
-    StaticCtorDeclaration *isStaticCtorDeclaration() override final { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -841,7 +822,6 @@  public:
     bool standalone;
     SharedStaticCtorDeclaration *syntaxCopy(Dsymbol *) override;
 
-    SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -853,11 +833,9 @@  public:
     StaticDtorDeclaration *syntaxCopy(Dsymbol *) override;
     AggregateDeclaration *isThis() override final;
     bool isVirtual() const override final;
-    bool hasStaticCtorOrDtor() override final;
     bool addPreInvariant() override final;
     bool addPostInvariant() override final;
 
-    StaticDtorDeclaration *isStaticDtorDeclaration() override final { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -866,7 +844,6 @@  class SharedStaticDtorDeclaration final : public StaticDtorDeclaration
 public:
     SharedStaticDtorDeclaration *syntaxCopy(Dsymbol *) override;
 
-    SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -878,7 +855,6 @@  public:
     bool addPreInvariant() override;
     bool addPostInvariant() override;
 
-    InvariantDeclaration *isInvariantDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -896,7 +872,6 @@  public:
     bool addPreInvariant() override;
     bool addPostInvariant() override;
 
-    UnitTestDeclaration *isUnitTestDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -909,6 +884,5 @@  public:
     bool addPreInvariant() override;
     bool addPostInvariant() override;
 
-    NewDeclaration *isNewDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index a650425c382..e85e24ab9e2 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/dmd/denum.d
@@ -70,6 +70,7 @@  extern (C++) final class EnumDeclaration : ScopeDsymbol
         //printf("EnumDeclaration() %p %s : %s\n", this, toChars(), memtype.toChars());
         type = new TypeEnum(this);
         this.memtype = memtype;
+        this.dsym = DSYM.enumDeclaration;
         visibility = Visibility(Visibility.Kind.undefined);
     }
 
@@ -81,13 +82,6 @@  extern (C++) final class EnumDeclaration : ScopeDsymbol
         return ed;
     }
 
-    override bool oneMember(out Dsymbol ps, Identifier ident)
-    {
-        if (isAnonymous())
-            return Dsymbol.oneMembers(members, ps, ident);
-        return Dsymbol.oneMember(ps, ident);
-    }
-
     override Type getType()
     {
         return type;
@@ -120,11 +114,6 @@  extern (C++) final class EnumDeclaration : ScopeDsymbol
         return isSpecialEnumIdent(ident) && memtype;
     }
 
-    override inout(EnumDeclaration) isEnumDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -159,10 +148,11 @@  extern (C++) final class EnumMember : VarDeclaration
         super(loc, null, id ? id : Id.empty, new ExpInitializer(loc, value));
         this.origValue = value;
         this.origType = origType;
+        this.dsym = DSYM.enumMember;
     }
 
     extern(D) this(Loc loc, Identifier id, Expression value, Type memtype,
-        StorageClass stc, UserAttributeDeclaration uad, DeprecatedDeclaration dd)
+        STC stc, UserAttributeDeclaration uad, DeprecatedDeclaration dd)
     {
         this(loc, id, value, memtype);
         storage_class = stc;
@@ -187,11 +177,6 @@  extern (C++) final class EnumMember : VarDeclaration
         return "enum member";
     }
 
-    override inout(EnumMember) isEnumMember() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d
index 8a2c27153d4..1f48e330ab4 100644
--- a/gcc/d/dmd/dimport.d
+++ b/gcc/d/dmd/dimport.d
@@ -59,7 +59,7 @@  extern (C++) final class Import : Dsymbol
             return id;
         }
 
-        super(loc, selectIdent());
+        super(DSYM.import_, loc, selectIdent());
 
         assert(id);
         version (none)
@@ -161,11 +161,6 @@  extern (C++) final class Import : Dsymbol
         return imp && !imp.aliasId;
     }
 
-    override inout(Import) isImport() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 3a08c10daf5..4beee42484a 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -2796,6 +2796,13 @@  public:
             printf("%s NewExp::interpret() %s\n", e.loc.toChars(), e.toChars());
         }
 
+        if (e.placement)
+        {
+            error(e.placement.loc, "`new ( %s )` PlacementExpression cannot be evaluated at compile time", e.placement.toChars());
+            result = CTFEExp.cantexp;
+            return;
+        }
+
         Expression epre = interpret(pue, e.argprefix, istate, CTFEGoal.Nothing);
         if (exceptionOrCant(epre))
             return;
@@ -5042,7 +5049,7 @@  public:
             auto ce = e.e2.isCallExp();
             assert(ce);
 
-            auto ne = new NewExp(e.loc, null, e.type, ce.arguments);
+            auto ne = new NewExp(e.loc, null, null, e.type, ce.arguments);
             ne.type = e.e1.type;
 
             result = interpret(ne, istate);
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 3264c34bf67..dea8df640a0 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -180,6 +180,7 @@  extern (C++) class Package : ScopeDsymbol
         super(loc, ident);
         __gshared uint packageTag;
         this.tag = packageTag++;
+        this.dsym = DSYM.package_;
     }
 
     override const(char)* kind() const nothrow
@@ -253,11 +254,6 @@  extern (C++) class Package : ScopeDsymbol
         return dst;
     }
 
-    override final inout(Package) isPackage() inout
-    {
-        return this;
-    }
-
     /**
      * Checks if pkg is a sub-package of this
      *
@@ -445,6 +441,7 @@  extern (C++) final class Module : Package
     extern (D) this(Loc loc, const(char)[] filename, Identifier ident, int doDocComment, int doHdrGen)
     {
         super(loc, ident);
+        this.dsym = DSYM.module_;
         const(char)[] srcfilename;
         //printf("Module::Module(filename = '%.*s', ident = '%s')\n", cast(int)filename.length, filename.ptr, ident.toChars());
         this.arg = filename;
@@ -1178,11 +1175,6 @@  extern (C++) final class Module : Package
 
     uint[uint] ctfe_cov; /// coverage information from ctfe execution_count[line]
 
-    override inout(Module) isModule() inout nothrow
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 3001bd7b8e9..2a29ef2de93 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -176,7 +176,7 @@  extern (C++) struct Scope
     Visibility visibility = Visibility(Visibility.Kind.public_);
     int explicitVisibility;         /// set if in an explicit visibility attribute
 
-    StorageClass stc;               /// storage class
+    STC stc;                        /// storage class
 
     DeprecatedDeclaration depdecl;  /// customized deprecation message
 
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index 0a0b366e091..3a26002608a 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -119,6 +119,7 @@  extern (C++) class StructDeclaration : AggregateDeclaration
     extern (D) this(Loc loc, Identifier id, bool inObject)
     {
         super(loc, id);
+        this.dsym = DSYM.structDeclaration;
         zeroInit = false; // assume false until we do semantic processing
         ispod = ThreeState.none;
         // For forward references
@@ -374,11 +375,6 @@  extern (C++) class StructDeclaration : AggregateDeclaration
         return postblit || hasCopyCtor;
     }
 
-    override final inout(StructDeclaration) isStructDeclaration() inout @nogc nothrow pure @safe
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -543,6 +539,7 @@  extern (C++) final class UnionDeclaration : StructDeclaration
     extern (D) this(Loc loc, Identifier id)
     {
         super(loc, id, false);
+        this.dsym = DSYM.unionDeclaration;
     }
 
     override UnionDeclaration syntaxCopy(Dsymbol s)
@@ -558,11 +555,6 @@  extern (C++) final class UnionDeclaration : StructDeclaration
         return "union";
     }
 
-    override inout(UnionDeclaration) isUnionDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 64cf6be84ee..e71c8902989 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -51,6 +51,7 @@  import dmd.statement;
 import dmd.staticassert;
 import dmd.tokens;
 import dmd.visitor;
+import dmd.dsymbolsem;
 
 import dmd.common.outbuffer;
 
@@ -258,6 +259,76 @@  private struct DsymbolAttributes
     UserAttributeDeclaration userAttribDecl;
 }
 
+enum DSYM : ubyte
+{
+    none,
+    dsymbol,
+    linkDeclaration,
+    cppMangleDeclaration,
+    alignDeclaration,
+    pragmaDeclaration,
+    conditionalDeclaration,
+    staticForeachDeclaration,
+    userAttributeDeclaration,
+    labelDsymbol,
+    aliasThis,
+    package_,
+    module_,
+    enumMember,
+    templateDeclaration,
+    templateInstance,
+    templateMixin,
+    forwardingAttribDeclaration,
+    nspace,
+    declaration,
+    storageClassDeclaration,
+    expressionDsymbol,
+    aliasAssign,
+    thisDeclaration,
+    bitFieldDeclaration,
+    typeInfoDeclaration,
+    tupleDeclaration,
+    aliasDeclaration,
+    aggregateDeclaration,
+    funcDeclaration,
+    funcAliasDeclaration,
+    overDeclaration,
+    funcLiteralDeclaration,
+    ctorDeclaration,
+    postBlitDeclaration,
+    dtorDeclaration,
+    staticCtorDeclaration,
+    staticDtorDeclaration,
+    sharedStaticCtorDeclaration,
+    sharedStaticDtorDeclaration,
+    invariantDeclaration,
+    unitTestDeclaration,
+    newDeclaration,
+    varDeclaration,
+    versionSymbol,
+    debugSymbol,
+    classDeclaration,
+    structDeclaration,
+    unionDeclaration,
+    interfaceDeclaration,
+    scopeDsymbol,
+    forwardingScopeDsymbol,
+    withScopeSymbol,
+    arrayScopeSymbol,
+    import_,
+    enumDeclaration,
+    symbolDeclaration,
+    attribDeclaration,
+    anonDeclaration,
+    cppNamespaceDeclaration,
+    visibilityDeclaration,
+    overloadSet,
+    mixinDeclaration,
+    staticAssert,
+    staticIfDeclaration,
+    cAsmDeclaration
+}
+
 /***********************************************************
  */
 extern (C++) class Dsymbol : ASTNode
@@ -268,33 +339,42 @@  extern (C++) class Dsymbol : ASTNode
     Scope* _scope;          // !=null means context to use for semantic()
     private DsymbolAttributes* atts; /// attached attribute declarations
     const Loc loc;          // where defined
-    bool errors;            // this symbol failed to pass semantic()
-    PASS semanticRun = PASS.initial;
     ushort localNum;        /// perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab
+    static struct BitFields
+    {
+        bool errors;            // this symbol failed to pass semantic()
+        PASS semanticRun = PASS.initial;
+    }
+    import dmd.common.bitfields;
+    mixin(generateBitFields!(BitFields, ubyte));
+    DSYM dsym;
 
-    final extern (D) this() nothrow @safe
+    final extern (D) this(DSYM tag) nothrow @safe
     {
         //printf("Dsymbol::Dsymbol(%p)\n", this);
+        this.dsym = tag;
         loc = Loc.initial;
     }
 
-    final extern (D) this(Identifier ident) nothrow @safe
+    final extern (D) this(DSYM tag, Identifier ident) nothrow @safe
     {
         //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
+        this.dsym = tag;
         this.loc = Loc.initial;
         this.ident = ident;
     }
 
-    final extern (D) this(Loc loc, Identifier ident) nothrow @safe
+    final extern (D) this(DSYM tag, Loc loc, Identifier ident) nothrow @safe
     {
         //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
+        this.dsym = tag;
         this.loc = loc;
         this.ident = ident;
     }
 
     static Dsymbol create(Identifier ident) nothrow @safe
     {
-        return new Dsymbol(ident);
+        return new Dsymbol(DSYM.dsymbol, ident);
     }
 
     final override const(char)* toChars() const
@@ -820,20 +900,6 @@  extern (C++) class Dsymbol : ASTNode
         assert(0);
     }
 
-    /**************************************
-     * Determine if this symbol is only one.
-     * Returns:
-     *      false, ps = null: There are 2 or more symbols
-     *      true,  ps = null: There are zero symbols
-     *      true,  ps = symbol: The one and only one symbol
-     */
-    bool oneMember(out Dsymbol ps, Identifier ident)
-    {
-        //printf("Dsymbol::oneMember()\n");
-        ps = this;
-        return true;
-    }
-
     /*****************************************
      * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
      */
@@ -850,7 +916,7 @@  extern (C++) class Dsymbol : ASTNode
         for (size_t i = 0; i < members.length; i++)
         {
             Dsymbol sx = (*members)[i];
-            bool x = sx.oneMember(ps, ident);
+            bool x = sx.oneMember(ps, ident); //MYTODO: this temporarily creates a new dependency to dsymbolsem, will need to extract oneMembers() later
             //printf("\t[%d] kind %s = %d, s = %p\n", i, sx.kind(), x, *ps);
             if (!x)
             {
@@ -906,12 +972,6 @@  extern (C++) class Dsymbol : ASTNode
         return false;
     }
 
-    bool hasStaticCtorOrDtor()
-    {
-        //printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars());
-        return false;
-    }
-
     void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories)
     {
     }
@@ -1008,64 +1068,181 @@  extern (C++) class Dsymbol : ASTNode
         v.visit(this);
     }
 
-  pure nothrow @safe @nogc:
-
-    // Eliminate need for dynamic_cast
-    inout(Package)                     isPackage()                     inout { return null; }
-    inout(Module)                      isModule()                      inout { return null; }
-    inout(EnumMember)                  isEnumMember()                  inout { return null; }
-    inout(TemplateDeclaration)         isTemplateDeclaration()         inout { return null; }
-    inout(TemplateInstance)            isTemplateInstance()            inout { return null; }
-    inout(TemplateMixin)               isTemplateMixin()               inout { return null; }
-    inout(ForwardingAttribDeclaration) isForwardingAttribDeclaration() inout { return null; }
-    inout(Nspace)                      isNspace()                      inout { return null; }
-    inout(Declaration)                 isDeclaration()                 inout { return null; }
-    inout(StorageClassDeclaration)     isStorageClassDeclaration()     inout { return null; }
-    inout(ExpressionDsymbol)           isExpressionDsymbol()           inout { return null; }
-    inout(AliasAssign)                 isAliasAssign()                 inout { return null; }
-    inout(ThisDeclaration)             isThisDeclaration()             inout { return null; }
-    inout(BitFieldDeclaration)         isBitFieldDeclaration()         inout { return null; }
-    inout(TypeInfoDeclaration)         isTypeInfoDeclaration()         inout { return null; }
-    inout(TupleDeclaration)            isTupleDeclaration()            inout { return null; }
-    inout(AliasDeclaration)            isAliasDeclaration()            inout { return null; }
-    inout(AggregateDeclaration)        isAggregateDeclaration()        inout { return null; }
-    inout(FuncDeclaration)             isFuncDeclaration()             inout { return null; }
-    inout(FuncAliasDeclaration)        isFuncAliasDeclaration()        inout { return null; }
-    inout(OverDeclaration)             isOverDeclaration()             inout { return null; }
-    inout(FuncLiteralDeclaration)      isFuncLiteralDeclaration()      inout { return null; }
-    inout(CtorDeclaration)             isCtorDeclaration()             inout { return null; }
-    inout(PostBlitDeclaration)         isPostBlitDeclaration()         inout { return null; }
-    inout(DtorDeclaration)             isDtorDeclaration()             inout { return null; }
-    inout(StaticCtorDeclaration)       isStaticCtorDeclaration()       inout { return null; }
-    inout(StaticDtorDeclaration)       isStaticDtorDeclaration()       inout { return null; }
-    inout(SharedStaticCtorDeclaration) isSharedStaticCtorDeclaration() inout { return null; }
-    inout(SharedStaticDtorDeclaration) isSharedStaticDtorDeclaration() inout { return null; }
-    inout(InvariantDeclaration)        isInvariantDeclaration()        inout { return null; }
-    inout(UnitTestDeclaration)         isUnitTestDeclaration()         inout { return null; }
-    inout(NewDeclaration)              isNewDeclaration()              inout { return null; }
-    inout(VarDeclaration)              isVarDeclaration()              inout { return null; }
-    inout(VersionSymbol)               isVersionSymbol()               inout { return null; }
-    inout(DebugSymbol)                 isDebugSymbol()                 inout { return null; }
-    inout(ClassDeclaration)            isClassDeclaration()            inout { return null; }
-    inout(StructDeclaration)           isStructDeclaration()           inout { return null; }
-    inout(UnionDeclaration)            isUnionDeclaration()            inout { return null; }
-    inout(InterfaceDeclaration)        isInterfaceDeclaration()        inout { return null; }
-    inout(ScopeDsymbol)                isScopeDsymbol()                inout { return null; }
-    inout(ForwardingScopeDsymbol)      isForwardingScopeDsymbol()      inout { return null; }
-    inout(WithScopeSymbol)             isWithScopeSymbol()             inout { return null; }
-    inout(ArrayScopeSymbol)            isArrayScopeSymbol()            inout { return null; }
-    inout(Import)                      isImport()                      inout { return null; }
-    inout(EnumDeclaration)             isEnumDeclaration()             inout { return null; }
-    inout(SymbolDeclaration)           isSymbolDeclaration()           inout { return null; }
-    inout(AttribDeclaration)           isAttribDeclaration()           inout { return null; }
-    inout(AnonDeclaration)             isAnonDeclaration()             inout { return null; }
-    inout(CPPNamespaceDeclaration)     isCPPNamespaceDeclaration()     inout { return null; }
-    inout(VisibilityDeclaration)       isVisibilityDeclaration()       inout { return null; }
-    inout(OverloadSet)                 isOverloadSet()                 inout { return null; }
-    inout(MixinDeclaration)            isMixinDeclaration()            inout { return null; }
-    inout(StaticAssert)                isStaticAssert()                inout { return null; }
-    inout(StaticIfDeclaration)         isStaticIfDeclaration()         inout { return null; }
-    inout(CAsmDeclaration)             isCAsmDeclaration()             inout { return null; }
+  pure nothrow @trusted @nogc final:
+
+    inout(Package)                     isPackage()                     inout { return (dsym == DSYM.package_ || dsym == DSYM.module_) ? cast(inout(Package)) cast(void*) this : null; }
+    inout(Module)                      isModule()                      inout { return dsym == DSYM.module_ ? cast(inout(Module)) cast(void*) this : null; }
+    inout(EnumMember)                  isEnumMember()                  inout { return dsym == DSYM.enumMember ? cast(inout(EnumMember)) cast(void*) this : null; }
+    inout(TemplateDeclaration)         isTemplateDeclaration()         inout { return dsym == DSYM.templateDeclaration ? cast(inout(TemplateDeclaration)) cast(void*) this : null; }
+    inout(TemplateInstance)            isTemplateInstance()            inout { return (dsym == DSYM.templateInstance || dsym == DSYM.templateMixin) ? cast(inout(TemplateInstance)) cast(void*) this : null; }
+    inout(TemplateMixin)               isTemplateMixin()               inout { return dsym == DSYM.templateMixin ? cast(inout(TemplateMixin)) cast(void*) this : null; }
+    inout(ForwardingAttribDeclaration) isForwardingAttribDeclaration() inout { return dsym == DSYM.forwardingAttribDeclaration ? cast(inout(ForwardingAttribDeclaration)) cast(void*) this : null; }
+    inout(Nspace)                      isNspace()                      inout { return dsym == DSYM.nspace ? cast(inout(Nspace)) cast(void*) this : null; }
+    inout(Declaration)                 isDeclaration()                 inout {
+        switch (dsym)
+        {
+        case DSYM.tupleDeclaration:
+        case DSYM.aliasDeclaration:
+        case DSYM.overDeclaration:
+        case DSYM.varDeclaration:
+            case DSYM.bitFieldDeclaration:
+            case DSYM.typeInfoDeclaration:
+            case DSYM.thisDeclaration:
+            case DSYM.enumMember:
+        case DSYM.symbolDeclaration:
+        case DSYM.funcDeclaration:
+            case DSYM.funcAliasDeclaration:
+            case DSYM.funcLiteralDeclaration:
+            case DSYM.ctorDeclaration:
+            case DSYM.postBlitDeclaration:
+            case DSYM.dtorDeclaration:
+            case DSYM.staticCtorDeclaration:
+                case DSYM.sharedStaticCtorDeclaration:
+            case DSYM.staticDtorDeclaration:
+                case DSYM.sharedStaticDtorDeclaration:
+            case DSYM.invariantDeclaration:
+            case DSYM.unitTestDeclaration:
+            case DSYM.newDeclaration:
+            return cast(inout(Declaration)) cast(void*) this;
+        default:
+            return null;
+        }
+    }
+    inout(StorageClassDeclaration)     isStorageClassDeclaration()     inout { return dsym == DSYM.storageClassDeclaration ? cast(inout(StorageClassDeclaration)) cast(void*) this : null; }
+    inout(ExpressionDsymbol)           isExpressionDsymbol()           inout { return dsym == DSYM.expressionDsymbol ? cast(inout(ExpressionDsymbol)) cast(void*) this : null; }
+    inout(AliasAssign)                 isAliasAssign()                 inout { return dsym == DSYM.aliasAssign ? cast(inout(AliasAssign)) cast(void*) this : null; }
+    inout(ThisDeclaration)             isThisDeclaration()             inout { return dsym == DSYM.thisDeclaration ? cast(inout(ThisDeclaration)) cast(void*) this : null; }
+    inout(BitFieldDeclaration)         isBitFieldDeclaration()         inout { return dsym == DSYM.bitFieldDeclaration ? cast(inout(BitFieldDeclaration)) cast(void*) this : null; }
+    inout(TypeInfoDeclaration)         isTypeInfoDeclaration()         inout { return dsym == DSYM.typeInfoDeclaration ? cast(inout(TypeInfoDeclaration)) cast(void*) this : null; }
+    inout(TupleDeclaration)            isTupleDeclaration()            inout { return dsym == DSYM.tupleDeclaration ? cast(inout(TupleDeclaration)) cast(void*) this : null; }
+    inout(AliasDeclaration)            isAliasDeclaration()            inout { return dsym == DSYM.aliasDeclaration ? cast(inout(AliasDeclaration)) cast(void*) this : null; }
+    inout(AggregateDeclaration)        isAggregateDeclaration()        inout {
+        switch (dsym)
+        {
+        case DSYM.aggregateDeclaration:
+        case DSYM.structDeclaration:
+        case DSYM.unionDeclaration:
+        case DSYM.classDeclaration:
+        case DSYM.interfaceDeclaration:
+            return cast(inout(AggregateDeclaration)) cast(void*) this;
+        default:
+            return null;
+        }
+    }
+    inout(FuncDeclaration)             isFuncDeclaration()             inout {
+        switch (dsym)
+        {
+        case DSYM.funcDeclaration:
+            case DSYM.funcAliasDeclaration:
+            case DSYM.funcLiteralDeclaration:
+            case DSYM.ctorDeclaration:
+            case DSYM.postBlitDeclaration:
+            case DSYM.dtorDeclaration:
+            case DSYM.staticCtorDeclaration:
+                case DSYM.sharedStaticCtorDeclaration:
+            case DSYM.staticDtorDeclaration:
+                case DSYM.sharedStaticDtorDeclaration:
+            case DSYM.invariantDeclaration:
+            case DSYM.unitTestDeclaration:
+            case DSYM.newDeclaration:
+            return cast(inout(FuncDeclaration)) cast(void*) this;
+        default:
+            return null;
+        }
+    }
+    inout(FuncAliasDeclaration)        isFuncAliasDeclaration()        inout { return dsym == DSYM.funcAliasDeclaration ? cast(inout(FuncAliasDeclaration)) cast(void*) this : null; }
+    inout(OverDeclaration)             isOverDeclaration()             inout { return dsym == DSYM.overDeclaration ? cast(inout(OverDeclaration)) cast(void*) this : null; }
+    inout(FuncLiteralDeclaration)      isFuncLiteralDeclaration()      inout { return dsym == DSYM.funcLiteralDeclaration ? cast(inout(FuncLiteralDeclaration)) cast(void*) this : null; }
+    inout(CtorDeclaration)             isCtorDeclaration()             inout { return dsym == DSYM.ctorDeclaration ? cast(inout(CtorDeclaration)) cast(void*) this : null; }
+    inout(PostBlitDeclaration)         isPostBlitDeclaration()         inout { return dsym == DSYM.postBlitDeclaration ? cast(inout(PostBlitDeclaration)) cast(void*) this : null; }
+    inout(DtorDeclaration)             isDtorDeclaration()             inout { return dsym == DSYM.dtorDeclaration ? cast(inout(DtorDeclaration)) cast(void*) this : null; }
+    inout(StaticCtorDeclaration)       isStaticCtorDeclaration()       inout { return (dsym == DSYM.staticCtorDeclaration || dsym == DSYM.sharedStaticCtorDeclaration) ? cast(inout(StaticCtorDeclaration)) cast(void*) this : null; }
+    inout(StaticDtorDeclaration)       isStaticDtorDeclaration()       inout { return (dsym == DSYM.staticDtorDeclaration || dsym == DSYM.sharedStaticDtorDeclaration) ? cast(inout(StaticDtorDeclaration)) cast(void*) this : null; }
+    inout(SharedStaticCtorDeclaration) isSharedStaticCtorDeclaration() inout { return dsym == DSYM.sharedStaticCtorDeclaration ? cast(inout(SharedStaticCtorDeclaration)) cast(void*) this : null; }
+    inout(SharedStaticDtorDeclaration) isSharedStaticDtorDeclaration() inout { return dsym == DSYM.sharedStaticDtorDeclaration ? cast(inout(SharedStaticDtorDeclaration)) cast(void*) this : null; }
+    inout(InvariantDeclaration)        isInvariantDeclaration()        inout { return dsym == DSYM.invariantDeclaration ? cast(inout(InvariantDeclaration)) cast(void*) this : null; }
+    inout(UnitTestDeclaration)         isUnitTestDeclaration()         inout { return dsym == DSYM.unitTestDeclaration ? cast(inout(UnitTestDeclaration)) cast(void*) this : null; }
+    inout(NewDeclaration)              isNewDeclaration()              inout { return dsym == DSYM.newDeclaration ? cast(inout(NewDeclaration)) cast(void*) this : null; }
+    inout(VarDeclaration)              isVarDeclaration()              inout {
+        switch (dsym)
+        {
+        case DSYM.varDeclaration:
+            case DSYM.bitFieldDeclaration:
+            case DSYM.typeInfoDeclaration:
+            case DSYM.thisDeclaration:
+            case DSYM.enumMember:
+            return cast(inout(VarDeclaration)) cast(void*) this;
+        default:
+            return null;
+        }
+    }
+    inout(VersionSymbol)               isVersionSymbol()               inout { return dsym == DSYM.versionSymbol ? cast(inout(VersionSymbol)) cast(void*) this : null; }
+    inout(DebugSymbol)                 isDebugSymbol()                 inout { return dsym == DSYM.debugSymbol ? cast(inout(DebugSymbol)) cast(void*) this : null; }
+    inout(ClassDeclaration)            isClassDeclaration()            inout { return (dsym == DSYM.classDeclaration || dsym == DSYM.interfaceDeclaration) ? cast(inout(ClassDeclaration)) cast(void*) this : null; }
+    inout(StructDeclaration)           isStructDeclaration()           inout { return (dsym == DSYM.structDeclaration || dsym == DSYM.unionDeclaration) ? cast(inout(StructDeclaration)) cast(void*) this : null; }
+    inout(UnionDeclaration)            isUnionDeclaration()            inout { return dsym == DSYM.unionDeclaration ? cast(inout(UnionDeclaration)) cast(void*) this : null; }
+    inout(InterfaceDeclaration)        isInterfaceDeclaration()        inout { return dsym == DSYM.interfaceDeclaration ? cast(inout(InterfaceDeclaration)) cast(void*) this : null; }
+    inout(ScopeDsymbol)                isScopeDsymbol()                inout {
+        switch (dsym)
+        {
+        case DSYM.enumDeclaration:
+        case DSYM.scopeDsymbol:
+        case DSYM.package_:
+            case DSYM.module_:
+        case DSYM.nspace:
+        case DSYM.templateInstance:
+            case DSYM.templateMixin:
+        case DSYM.templateDeclaration:
+        case DSYM.aggregateDeclaration:
+            case DSYM.structDeclaration:
+                case DSYM.unionDeclaration:
+            case DSYM.classDeclaration:
+                case DSYM.interfaceDeclaration:
+        case DSYM.withScopeSymbol:
+        case DSYM.arrayScopeSymbol:
+        case DSYM.forwardingScopeDsymbol:
+            return cast(inout(ScopeDsymbol)) cast(void*) this;
+        default:
+            return null;
+        }
+    }
+    inout(ForwardingScopeDsymbol)      isForwardingScopeDsymbol()      inout { return dsym == DSYM.forwardingScopeDsymbol ? cast(inout(ForwardingScopeDsymbol)) cast(void*) this : null; }
+    inout(WithScopeSymbol)             isWithScopeSymbol()             inout { return dsym == DSYM.withScopeSymbol ? cast(inout(WithScopeSymbol)) cast(void*) this : null; }
+    inout(ArrayScopeSymbol)            isArrayScopeSymbol()            inout { return dsym == DSYM.arrayScopeSymbol ? cast(inout(ArrayScopeSymbol)) cast(void*) this : null; }
+    inout(Import)                      isImport()                      inout { return dsym == DSYM.import_ ? cast(inout(Import)) cast(void*) this : null; }
+    inout(EnumDeclaration)             isEnumDeclaration()             inout { return dsym == DSYM.enumDeclaration ? cast(inout(EnumDeclaration)) cast(void*) this : null; }
+    inout(SymbolDeclaration)           isSymbolDeclaration()           inout { return dsym == DSYM.symbolDeclaration ? cast(inout(SymbolDeclaration)) cast(void*) this : null; }
+    inout(AttribDeclaration)           isAttribDeclaration()           inout {
+        switch (dsym)
+        {
+        case DSYM.attribDeclaration:
+        case DSYM.storageClassDeclaration:
+        case DSYM.linkDeclaration:
+        case DSYM.cppMangleDeclaration:
+        case DSYM.cppNamespaceDeclaration:
+        case DSYM.visibilityDeclaration:
+        case DSYM.alignDeclaration:
+        case DSYM.anonDeclaration:
+        case DSYM.pragmaDeclaration:
+        case DSYM.conditionalDeclaration:
+            case DSYM.staticIfDeclaration:
+        case DSYM.staticForeachDeclaration:
+        case DSYM.forwardingAttribDeclaration:
+        case DSYM.mixinDeclaration:
+        case DSYM.userAttributeDeclaration:
+            return cast(inout(AttribDeclaration)) cast(void*) this;
+        default:
+            return null;
+        }
+    }
+    inout(AnonDeclaration)             isAnonDeclaration()             inout { return dsym == DSYM.anonDeclaration ? cast(inout(AnonDeclaration)) cast(void*) this : null; }
+    inout(CPPNamespaceDeclaration)     isCPPNamespaceDeclaration()     inout { return dsym == DSYM.cppNamespaceDeclaration ? cast(inout(CPPNamespaceDeclaration)) cast(void*) this : null; }
+    inout(VisibilityDeclaration)       isVisibilityDeclaration()       inout { return dsym == DSYM.visibilityDeclaration ? cast(inout(VisibilityDeclaration)) cast(void*) this : null; }
+    inout(OverloadSet)                 isOverloadSet()                 inout { return dsym == DSYM.overloadSet ? cast(inout(OverloadSet)) cast(void*) this : null; }
+    inout(MixinDeclaration)            isMixinDeclaration()            inout { return dsym == DSYM.mixinDeclaration ? cast(inout(MixinDeclaration)) cast(void*) this : null; }
+    inout(StaticAssert)                isStaticAssert()                inout { return dsym == DSYM.staticAssert ? cast(inout(StaticAssert)) cast(void*) this : null; }
+    inout(StaticIfDeclaration)         isStaticIfDeclaration()         inout { return dsym == DSYM.staticIfDeclaration ? cast(inout(StaticIfDeclaration)) cast(void*) this : null; }
+    inout(CAsmDeclaration)             isCAsmDeclaration()             inout { return dsym == DSYM.cAsmDeclaration ? cast(inout(CAsmDeclaration)) cast(void*) this : null; }
 }
 
 /***********************************************************
@@ -1088,16 +1265,17 @@  private:
 public:
     final extern (D) this() nothrow @safe
     {
+        super(DSYM.scopeDsymbol);
     }
 
     final extern (D) this(Identifier ident) nothrow @safe
     {
-        super(ident);
+        super(DSYM.scopeDsymbol, ident);
     }
 
     final extern (D) this(Loc loc, Identifier ident) nothrow @safe
     {
-        super(loc, ident);
+        super(DSYM.scopeDsymbol, loc, ident);
     }
 
     override ScopeDsymbol syntaxCopy(Dsymbol s)
@@ -1307,29 +1485,6 @@  public:
         return symtab.lookup(id);
     }
 
-    /****************************************
-     * Return true if any of the members are static ctors or static dtors, or if
-     * any members have members that are.
-     */
-    override bool hasStaticCtorOrDtor()
-    {
-        if (members)
-        {
-            for (size_t i = 0; i < members.length; i++)
-            {
-                Dsymbol member = (*members)[i];
-                if (member.hasStaticCtorOrDtor())
-                    return true;
-            }
-        }
-        return false;
-    }
-
-    override final inout(ScopeDsymbol) isScopeDsymbol() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1346,11 +1501,7 @@  extern (C++) final class WithScopeSymbol : ScopeDsymbol
     extern (D) this(WithStatement withstate) nothrow @safe
     {
         this.withstate = withstate;
-    }
-
-    override inout(WithScopeSymbol) isWithScopeSymbol() inout
-    {
-        return this;
+        this.dsym = DSYM.withScopeSymbol;
     }
 
     override void accept(Visitor v)
@@ -1374,6 +1525,7 @@  extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
         assert(exp.op == EXP.index || exp.op == EXP.slice || exp.op == EXP.array);
         this._scope = sc;
         this.arrayContent = exp;
+        this.dsym = DSYM.arrayScopeSymbol;
     }
 
     extern (D) this(Scope* sc, TypeTuple type) nothrow @safe
@@ -1388,11 +1540,6 @@  extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
         this.arrayContent = td;
     }
 
-    override inout(ArrayScopeSymbol) isArrayScopeSymbol() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1408,7 +1555,7 @@  extern (C++) final class OverloadSet : Dsymbol
 
     extern (D) this(Identifier ident, OverloadSet os = null) nothrow
     {
-        super(ident);
+        super(DSYM.overloadSet, ident);
         if (os)
         {
             a.pushSlice(os.a[]);
@@ -1420,11 +1567,6 @@  extern (C++) final class OverloadSet : Dsymbol
         a.push(s);
     }
 
-    override inout(OverloadSet) isOverloadSet() inout
-    {
-        return this;
-    }
-
     override const(char)* kind() const
     {
         return "overloadset";
@@ -1447,6 +1589,7 @@  extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
     extern (D) this() nothrow @safe
     {
         super();
+        this.dsym = DSYM.forwardingScopeDsymbol;
     }
 
     override Dsymbol symtabInsert(Dsymbol s) nothrow
@@ -1515,11 +1658,6 @@  extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
 
     override const(char)* kind()const{ return "local scope"; }
 
-    override inout(ForwardingScopeDsymbol) isForwardingScopeDsymbol() inout nothrow
-    {
-        return this;
-    }
-
 }
 
 /**
@@ -1532,14 +1670,9 @@  extern (C++) final class ExpressionDsymbol : Dsymbol
     Expression exp;
     this(Expression exp) nothrow @safe
     {
-        super();
+        super(DSYM.expressionDsymbol);
         this.exp = exp;
     }
-
-    override inout(ExpressionDsymbol) isExpressionDsymbol() inout nothrow
-    {
-        return this;
-    }
 }
 
 /**********************************************
@@ -1557,7 +1690,7 @@  extern (C++) final class AliasAssign : Dsymbol
 
     extern (D) this(Loc loc, Identifier ident, Type type, Dsymbol aliassym) nothrow @safe
     {
-        super(loc, null);
+        super(DSYM.aliasAssign, loc, null);
         this.ident = ident;
         this.type = type;
         this.aliassym = aliassym;
@@ -1572,11 +1705,6 @@  extern (C++) final class AliasAssign : Dsymbol
         return aa;
     }
 
-    override inout(AliasAssign) isAliasAssign() inout
-    {
-        return this;
-    }
-
     override const(char)* kind() const
     {
         return "alias assignment";
@@ -1669,15 +1797,10 @@  extern (C++) final class CAsmDeclaration : Dsymbol
     Expression code;
     extern (D) this(Expression e) nothrow @safe
     {
-        super();
+        super(DSYM.cAsmDeclaration);
         this.code = e;
     }
 
-    override inout(CAsmDeclaration) isCAsmDeclaration() inout nothrow
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 8209dea02ee..e3ea87632d1 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -183,9 +183,15 @@  private:
     DsymbolAttributes* atts;
 public:
     Loc loc;                    // where defined
-    d_bool errors;                // this symbol failed to pass semantic()
-    PASS semanticRun;
     unsigned short localNum;        // perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab
+
+    bool errors() const;
+    PASS semanticRun() const;
+    PASS semanticRun(PASS v);
+private:
+    unsigned char bitfields;
+    unsigned char dsym;
+public:
     static Dsymbol *create(Identifier *);
     const char *toChars() const final override;
     DeprecatedDeclaration* depdecl();
@@ -237,9 +243,7 @@  public:
     virtual bool needThis();                    // need a 'this' pointer?
     virtual Visibility visible();
     virtual Dsymbol *syntaxCopy(Dsymbol *s);    // copy only syntax trees
-    virtual bool oneMember(Dsymbol *&ps, Identifier *ident);
     virtual bool hasPointers();
-    virtual bool hasStaticCtorOrDtor();
     virtual void addObjcSymbols(ClassDeclarations *, ClassDeclarations *) { }
 
     virtual void addComment(const utf8_t *comment);
@@ -251,61 +255,61 @@  public:
     bool inNonRoot();
 
     // Eliminate need for dynamic_cast
-    virtual Package *isPackage() { return nullptr; }
-    virtual Module *isModule() { return nullptr; }
-    virtual EnumMember *isEnumMember() { return nullptr; }
-    virtual TemplateDeclaration *isTemplateDeclaration() { return nullptr; }
-    virtual TemplateInstance *isTemplateInstance() { return nullptr; }
-    virtual TemplateMixin *isTemplateMixin() { return nullptr; }
-    virtual ForwardingAttribDeclaration *isForwardingAttribDeclaration() { return nullptr; }
-    virtual Nspace *isNspace() { return nullptr; }
-    virtual Declaration *isDeclaration() { return nullptr; }
-    virtual StorageClassDeclaration *isStorageClassDeclaration(){ return nullptr; }
-    virtual ExpressionDsymbol *isExpressionDsymbol() { return nullptr; }
-    virtual AliasAssign *isAliasAssign() { return nullptr; }
-    virtual ThisDeclaration *isThisDeclaration() { return nullptr; }
-    virtual BitFieldDeclaration *isBitFieldDeclaration() { return nullptr; }
-    virtual TypeInfoDeclaration *isTypeInfoDeclaration() { return nullptr; }
-    virtual TupleDeclaration *isTupleDeclaration() { return nullptr; }
-    virtual AliasDeclaration *isAliasDeclaration() { return nullptr; }
-    virtual AggregateDeclaration *isAggregateDeclaration() { return nullptr; }
-    virtual FuncDeclaration *isFuncDeclaration() { return nullptr; }
-    virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return nullptr; }
-    virtual OverDeclaration *isOverDeclaration() { return nullptr; }
-    virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return nullptr; }
-    virtual CtorDeclaration *isCtorDeclaration() { return nullptr; }
-    virtual PostBlitDeclaration *isPostBlitDeclaration() { return nullptr; }
-    virtual DtorDeclaration *isDtorDeclaration() { return nullptr; }
-    virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return nullptr; }
-    virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return nullptr; }
-    virtual SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return nullptr; }
-    virtual SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return nullptr; }
-    virtual InvariantDeclaration *isInvariantDeclaration() { return nullptr; }
-    virtual UnitTestDeclaration *isUnitTestDeclaration() { return nullptr; }
-    virtual NewDeclaration *isNewDeclaration() { return nullptr; }
-    virtual VarDeclaration *isVarDeclaration() { return nullptr; }
-    virtual VersionSymbol *isVersionSymbol() { return nullptr; }
-    virtual DebugSymbol *isDebugSymbol() { return nullptr; }
-    virtual ClassDeclaration *isClassDeclaration() { return nullptr; }
-    virtual StructDeclaration *isStructDeclaration() { return nullptr; }
-    virtual UnionDeclaration *isUnionDeclaration() { return nullptr; }
-    virtual InterfaceDeclaration *isInterfaceDeclaration() { return nullptr; }
-    virtual ScopeDsymbol *isScopeDsymbol() { return nullptr; }
-    virtual ForwardingScopeDsymbol *isForwardingScopeDsymbol() { return nullptr; }
-    virtual WithScopeSymbol *isWithScopeSymbol() { return nullptr; }
-    virtual ArrayScopeSymbol *isArrayScopeSymbol() { return nullptr; }
-    virtual Import *isImport() { return nullptr; }
-    virtual EnumDeclaration *isEnumDeclaration() { return nullptr; }
-    virtual SymbolDeclaration *isSymbolDeclaration() { return nullptr; }
-    virtual AttribDeclaration *isAttribDeclaration() { return nullptr; }
-    virtual AnonDeclaration *isAnonDeclaration() { return nullptr; }
-    virtual CPPNamespaceDeclaration *isCPPNamespaceDeclaration() { return nullptr; }
-    virtual VisibilityDeclaration *isVisibilityDeclaration() { return nullptr; }
-    virtual OverloadSet *isOverloadSet() { return nullptr; }
-    virtual MixinDeclaration *isMixinDeclaration() { return nullptr; }
-    virtual StaticAssert *isStaticAssert() { return nullptr; }
-    virtual StaticIfDeclaration *isStaticIfDeclaration() { return nullptr; }
-    virtual CAsmDeclaration *isCAsmDeclaration() { return nullptr; }
+    Package *isPackage();
+    Module *isModule();
+    EnumMember *isEnumMember();
+    TemplateDeclaration *isTemplateDeclaration();
+    TemplateInstance *isTemplateInstance();
+    TemplateMixin *isTemplateMixin();
+    ForwardingAttribDeclaration *isForwardingAttribDeclaration();
+    Nspace *isNspace();
+    Declaration *isDeclaration();
+    StorageClassDeclaration *isStorageClassDeclaration();
+    ExpressionDsymbol *isExpressionDsymbol();
+    AliasAssign *isAliasAssign();
+    ThisDeclaration *isThisDeclaration();
+    BitFieldDeclaration *isBitFieldDeclaration();
+    TypeInfoDeclaration *isTypeInfoDeclaration();
+    TupleDeclaration *isTupleDeclaration();
+    AliasDeclaration *isAliasDeclaration();
+    AggregateDeclaration *isAggregateDeclaration();
+    FuncDeclaration *isFuncDeclaration();
+    FuncAliasDeclaration *isFuncAliasDeclaration();
+    OverDeclaration *isOverDeclaration();
+    FuncLiteralDeclaration *isFuncLiteralDeclaration();
+    CtorDeclaration *isCtorDeclaration();
+    PostBlitDeclaration *isPostBlitDeclaration();
+    DtorDeclaration *isDtorDeclaration();
+    StaticCtorDeclaration *isStaticCtorDeclaration();
+    StaticDtorDeclaration *isStaticDtorDeclaration();
+    SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration();
+    SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration();
+    InvariantDeclaration *isInvariantDeclaration();
+    UnitTestDeclaration *isUnitTestDeclaration();
+    NewDeclaration *isNewDeclaration();
+    VarDeclaration *isVarDeclaration();
+    VersionSymbol *isVersionSymbol();
+    DebugSymbol *isDebugSymbol();
+    ClassDeclaration *isClassDeclaration();
+    StructDeclaration *isStructDeclaration();
+    UnionDeclaration *isUnionDeclaration();
+    InterfaceDeclaration *isInterfaceDeclaration();
+    ScopeDsymbol *isScopeDsymbol();
+    ForwardingScopeDsymbol *isForwardingScopeDsymbol();
+    WithScopeSymbol *isWithScopeSymbol();
+    ArrayScopeSymbol *isArrayScopeSymbol();
+    Import *isImport();
+    EnumDeclaration *isEnumDeclaration();
+    SymbolDeclaration *isSymbolDeclaration();
+    AttribDeclaration *isAttribDeclaration();
+    AnonDeclaration *isAnonDeclaration();
+    CPPNamespaceDeclaration *isCPPNamespaceDeclaration();
+    VisibilityDeclaration *isVisibilityDeclaration();
+    OverloadSet *isOverloadSet();
+    MixinDeclaration *isMixinDeclaration();
+    StaticAssert *isStaticAssert();
+    StaticIfDeclaration *isStaticIfDeclaration();
+    CAsmDeclaration *isCAsmDeclaration();
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -332,9 +336,7 @@  public:
     const char *kind() const override;
     virtual Dsymbol *symtabInsert(Dsymbol *s);
     virtual Dsymbol *symtabLookup(Dsymbol *s, Identifier *id);
-    bool hasStaticCtorOrDtor() override;
 
-    ScopeDsymbol *isScopeDsymbol() override final { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -346,7 +348,6 @@  public:
     WithStatement *withstate;
 
 
-    WithScopeSymbol *isWithScopeSymbol() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -357,7 +358,6 @@  class ArrayScopeSymbol final : public ScopeDsymbol
 public:
     RootObject *arrayContent;
 
-    ArrayScopeSymbol *isArrayScopeSymbol() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -369,7 +369,6 @@  public:
     Dsymbols a;         // array of Dsymbols
 
     void push(Dsymbol *s);
-    OverloadSet *isOverloadSet() override { return this; }
     const char *kind() const override;
     void accept(Visitor *v) override { v->visit(this); }
 };
@@ -384,7 +383,6 @@  public:
     void importScope(Dsymbol *s, Visibility visibility) override;
     const char *kind() const override;
 
-    ForwardingScopeDsymbol *isForwardingScopeDsymbol() override { return this; }
 };
 
 class ExpressionDsymbol final : public Dsymbol
@@ -392,7 +390,6 @@  class ExpressionDsymbol final : public Dsymbol
 public:
     Expression *exp;
 
-    ExpressionDsymbol *isExpressionDsymbol() override { return this; }
 };
 
 class CAsmDeclaration final : public Dsymbol
@@ -400,7 +397,6 @@  class CAsmDeclaration final : public Dsymbol
 public:
     Expression *code;   // string expression
 
-    CAsmDeclaration *isCAsmDeclaration() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -433,4 +429,6 @@  namespace dmd
     void setScope(Dsymbol *d, Scope *sc);
     void importAll(Dsymbol *d, Scope *sc);
     void addComment(Dsymbol *d, const char *comment);
+    bool oneMember(Dsymbol *d, Dsymbol *&ps, Identifier *ident);
+    bool hasStaticCtorOrDtor(Dsymbol *d);
 }
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index b01736677cb..894ac0dc61b 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -812,7 +812,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
                     }
                     else if (isAliasThisTuple(e))
                     {
-                        auto v = copyToTemp(0, "__tup", e);
+                        auto v = copyToTemp(STC.none, "__tup", e);
                         v.dsymbolSemantic(sc);
                         auto ve = new VarExp(dsym.loc, v);
                         ve.type = e.type;
@@ -896,7 +896,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 else
                     ti = dsym._init ? dsym._init.syntaxCopy() : null;
 
-                StorageClass storage_class = STC.temp | dsym.storage_class;
+                STC storage_class = STC.temp | dsym.storage_class;
                 if ((dsym.storage_class & STC.parameter) && (arg.storageClass & STC.parameter))
                     storage_class |= arg.storageClass;
                 auto v = new VarDeclaration(dsym.loc, arg.type, id, ti, storage_class);
@@ -935,7 +935,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
         else if (dsym.type.isWild())
             dsym.storage_class |= STC.wild;
 
-        if (StorageClass stc = dsym.storage_class & (STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_))
+        if (STC stc = dsym.storage_class & (STC.synchronized_ | STC.override_ | STC.abstract_ | STC.final_))
         {
             if (stc == STC.final_)
                 .error(dsym.loc, "%s `%s` cannot be `final`, perhaps you meant `const`?", dsym.kind, dsym.toPrettyChars);
@@ -955,7 +955,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
         if (dsym.storage_class & STC.scope_)
         {
-            StorageClass stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.gshared);
+            STC stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.gshared);
             if (stc)
             {
                 OutBuffer buf;
@@ -1024,7 +1024,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 }
                 // If it's a member template
                 AggregateDeclaration ad2 = ti.tempdecl.isMember();
-                if (ad2 && dsym.storage_class != STC.undefined_)
+                if (ad2 && dsym.storage_class != STC.none)
                 {
                     .error(dsym.loc, "%s `%s` - cannot use template to add field to aggregate `%s`", dsym.kind, dsym.toPrettyChars, ad2.toChars());
                 }
@@ -1312,9 +1312,12 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
                             ex = (cast(AssignExp)ex).e2;
                         if (auto ne = ex.isNewExp())
                         {
+                            if (ne.placement)
+                            {
+                            }
                             /* See if initializer is a NewExp that can be allocated on the stack.
                              */
-                            if (dsym.type.toBasetype().ty == Tclass)
+                            else if (dsym.type.toBasetype().ty == Tclass)
                             {
                                 /* Unsafe to allocate on stack if constructor is not `scope` because the `this` can leak.
                                  * https://issues.dlang.org/show_bug.cgi?id=23145
@@ -1775,7 +1778,8 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
             s.dsymbolSemantic(sc2);
             errors |= s.errors;
         }
-        ad.errors |= errors;
+        if (errors)
+            ad.errors = true;
         if (sc2 != sc)
             sc2.pop();
 
@@ -2678,7 +2682,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
              */
 
             auto v = new VarDeclaration(Loc.initial, Type.tint32, Id.gate, null);
-            v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : 0);
+            v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : STC.none);
 
             auto sa = new Statements();
             Statement s = new ExpStatement(Loc.initial, v);
@@ -2962,7 +2966,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
          */
         sd.members.foreachDsymbol( s => s.setScope(sc2) );
         sd.members.foreachDsymbol( s => s.importAll(sc2) );
-        sd.members.foreachDsymbol( (s) { s.dsymbolSemantic(sc2); sd.errors |= s.errors; } );
+        sd.members.foreachDsymbol( (s) { s.dsymbolSemantic(sc2); if (sd.errors) s.errors = true; } );
 
         if (sd.errors)
             sd.type = Type.terror;
@@ -3683,7 +3687,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
                 // This is required if other lowerings add code to the generated constructor which
                 // is less strict (e.g. `preview=dtorfields` might introduce a call to a less qualified dtor)
 
-                auto ctor = new CtorDeclaration(cldec.loc, Loc.initial, 0, tf);
+                auto ctor = new CtorDeclaration(cldec.loc, Loc.initial, STC.none, tf);
                 ctor.storage_class |= STC.inference | (fd.storage_class & STC.scope_);
                 ctor.isGenerated = true;
                 ctor.fbody = new CompoundStatement(Loc.initial, new Statements());
@@ -4180,7 +4184,8 @@  private extern(C++) class AddMemberVisitor : Visitor
             }
 
             // If using C tag/prototype/forward declaration rules
-            if (sc.inCfile && !dsym.isImport())
+            if (sc && sc.inCfile && !dsym.isImport())
+            // When merging master, replace with: if (sc && sc.inCfile && !dsym.isImport())
             {
                 if (handleTagSymbols(*sc, dsym, s2, sds))
                     return;
@@ -4834,7 +4839,7 @@  void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
             continue;
         Type t = isType((*tempinst.tiargs)[i]);
         assert(t);
-        if (StorageClass stc = ModToStc(t.mod))
+        if (STC stc = ModToStc(t.mod))
         {
             //printf("t = %s, stc = x%llx\n", t.toChars(), stc);
             auto s = new Dsymbols();
@@ -4862,11 +4867,11 @@  void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList
     _scope = _scope.push(tempinst.argsym);
     _scope.tinst = tempinst;
     _scope.minst = tempinst.minst;
-    //scope.stc = 0;
+    //scope.stc = STC.none;
 
     // Declare each template parameter as an alias for the argument type
     Scope* paramscope = _scope.push();
-    paramscope.stc = 0;
+    paramscope.stc = STC.none;
     paramscope.visibility = Visibility(Visibility.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=14169
                                               // template parameters should be public
     tempinst.declareParameters(paramscope);
@@ -5199,7 +5204,7 @@  void aliasSeqInstanceSemantic(TemplateInstance tempinst, Scope* sc, TemplateDecl
 {
     //printf("[%s] aliasSeqInstance.dsymbolSemantic('%s')\n", tempinst.loc.toChars(), tempinst.toChars());
     Scope* paramscope = sc.push();
-    paramscope.stc = 0;
+    paramscope.stc = STC.none;
     paramscope.visibility = Visibility(Visibility.Kind.public_);
 
     TemplateTupleParameter ttp = (*tempdecl.parameters)[0].isTemplateTupleParameter();
@@ -5224,7 +5229,7 @@  void aliasInstanceSemantic(TemplateInstance tempinst, Scope* sc, TemplateDeclara
 {
     //printf("[%s] aliasInstance.dsymbolSemantic('%s')\n", tempinst.loc.toChars(), tempinst.toChars());
     Scope* paramscope = sc.push();
-    paramscope.stc = 0;
+    paramscope.stc = STC.none;
     paramscope.visibility = Visibility(Visibility.Kind.public_);
 
     TemplateTypeParameter ttp = (*tempdecl.parameters)[0].isTemplateTypeParameter();
@@ -7414,7 +7419,7 @@  private extern(C++) class NewScopeVisitor : Visitor
 
     override void visit(StorageClassDeclaration swt)
     {
-        StorageClass scstc = sc.stc;
+        STC scstc = sc.stc;
         /* These sets of storage classes are mutually exclusive,
          * so choose the innermost or most recent one.
          */
@@ -7967,3 +7972,241 @@  private extern(C++) class CheckCtorConstInitVisitor : Visitor
 
     override void visit(Dsymbol d){}
 }
+
+/**************************************
+* Determine if this symbol is only one.
+* Returns:
+*      false, ps = null: There are 2 or more symbols
+*      true,  ps = null: There are zero symbols
+*      true,  ps = symbol: The one and only one symbol
+*/
+bool oneMember(Dsymbol d, out Dsymbol ps, Identifier ident)
+{
+    scope v = new OneMemberVisitor(ps, ident);
+    d.accept(v);
+    return v.result;
+}
+
+private extern(C++) class OneMemberVisitor : Visitor
+{
+    alias visit = Visitor.visit;
+
+    Dsymbol* ps;
+    Identifier ident;
+    bool result;
+
+    this(out Dsymbol ps, Identifier ident)
+    {
+        this.ps = &ps;
+        this.ident = ident;
+    }
+
+    override void visit(AttribDeclaration atb)
+    {
+        Dsymbols* d = atb.include(null);
+        result = Dsymbol.oneMembers(d, *ps, ident);
+    }
+
+    override void visit(StaticForeachDeclaration sfd)
+    {
+        // Required to support IFTI on a template that contains a
+        // `static foreach` declaration.  `super.oneMember` calls
+        // include with a `null` scope.  As `static foreach` requires
+        // the scope for expansion, `oneMember` can only return a
+        // precise result once `static foreach` has been expanded.
+        if (sfd.cached)
+        {
+            this.visit(cast(AttribDeclaration) sfd);
+        }
+        else
+        {
+            *ps = null; // a `static foreach` declaration may in general expand to multiple symbols
+            result = false;
+        }
+    }
+
+    override void visit(StorageClassDeclaration scd)
+    {
+        bool t = Dsymbol.oneMembers(scd.decl, *ps, ident);
+        if (t && *ps)
+        {
+            /* This is to deal with the following case:
+             * struct Tick {
+             *   template to(T) { const T to() { ... } }
+             * }
+             * For eponymous function templates, the 'const' needs to get attached to 'to'
+             * before the semantic analysis of 'to', so that template overloading based on the
+             * 'this' pointer can be successful.
+             */
+            if (FuncDeclaration fd = (*ps).isFuncDeclaration())
+            {
+                /* Use storage_class2 instead of storage_class otherwise when we do .di generation
+                 * we'll wind up with 'const const' rather than 'const'.
+                 */
+                /* Don't think we need to worry about mutually exclusive storage classes here
+                 */
+                fd.storage_class2 |= scd.stc;
+            }
+        }
+        result = t;
+    }
+
+    override void visit(ConditionalDeclaration cd)
+    {
+        //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition.inc);
+        if (cd.condition.inc != Include.notComputed)
+        {
+            Dsymbols* d = cd.condition.include(null) ? cd.decl : cd.elsedecl;
+            result = Dsymbol.oneMembers(d, *ps, ident);
+        }
+        else
+        {
+            bool res = (Dsymbol.oneMembers(cd.decl, *ps, ident) && *ps is null && Dsymbol.oneMembers(cd.elsedecl, *ps, ident) && *ps is null);
+            *ps = null;
+            result = res;
+        }
+    }
+
+    override void visit(ScopeDsymbol sd)
+    {
+        if (sd.isAnonymous())
+            result = Dsymbol.oneMembers(sd.members, *ps, ident);
+        else {
+            // visit(Dsymbol dsym)
+            *ps = sd;
+            result = true;
+        }
+    }
+
+    override void visit(StaticAssert sa)
+    {
+        //printf("StaticAssert::oneMember())\n");
+        *ps = null;
+        result = true;
+    }
+
+    override void visit(TemplateInstance ti)
+    {
+        *ps = null;
+        result = true;
+    }
+
+    override void visit(TemplateMixin tm)
+    {
+        *ps = tm;
+        result = true;
+    }
+
+    override void visit(Dsymbol dsym)
+    {
+        *ps = dsym;
+        result = true;
+    }
+}
+
+/****************************************
+* Return true if any of the members are static ctors or static dtors, or if
+* any members have members that are.
+*/
+extern(C++) bool hasStaticCtorOrDtor(Dsymbol d)
+{
+    scope v = new HasStaticCtorOrDtor();
+    d.accept(v);
+    return v.result;
+}
+
+private extern(C++) class HasStaticCtorOrDtor : Visitor
+{
+    import dmd.mtype : Type;
+
+    alias visit = Visitor.visit;
+    bool result;
+
+    // attrib.d
+    override void visit(AttribDeclaration ad){
+        result = ad.include(null).foreachDsymbol( (s) { return s.hasStaticCtorOrDtor(); } ) != 0;
+    }
+
+    // dsymbol.d
+    override void visit(Dsymbol d){
+        //printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars());
+        result = false;
+    }
+
+    override void visit(ScopeDsymbol sd) {
+        if (sd.members)
+        {
+            for (size_t i = 0; i < sd.members.length; i++)
+            {
+                Dsymbol member = (*(sd.members))[i];
+                if (member.hasStaticCtorOrDtor())
+                    result = true;
+                    return;
+            }
+        }
+        result = false;
+    }
+
+    // dtemplate.d
+    override void visit(TemplateDeclaration td) {
+        result = false; // don't scan uninstantiated templates
+    }
+
+    // func.d
+    override void visit(StaticCtorDeclaration scd) {
+        result = true;
+    }
+
+    override void visit(StaticDtorDeclaration sdd) @nogc nothrow pure @safe {
+        result = true;
+    }
+}
+
+extern(C++) bool isFuncHidden(ClassDeclaration cd, FuncDeclaration fd)
+{
+    import dmd.funcsem : overloadApply;
+    //printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toPrettyChars());
+    Dsymbol s = cd.search(Loc.initial, fd.ident, SearchOpt.ignoreAmbiguous | SearchOpt.ignoreErrors);
+    if (!s)
+    {
+        //printf("not found\n");
+        /* Because, due to a hack, if there are multiple definitions
+            * of fd.ident, NULL is returned.
+            */
+        return false;
+    }
+    s = s.toAlias();
+    if (auto os = s.isOverloadSet())
+    {
+        foreach (sm; os.a)
+        {
+            auto fm = sm.isFuncDeclaration();
+            if (overloadApply(fm, s => fd == s.isFuncDeclaration()))
+                return false;
+        }
+        return true;
+    }
+    else
+    {
+        auto f = s.isFuncDeclaration();
+        //printf("%s fdstart = %p\n", s.kind(), fdstart);
+        if (overloadApply(f, s => fd == s.isFuncDeclaration()))
+            return false;
+        return !fd.parent.isTemplateMixin();
+    }
+}
+
+Dsymbol vtblSymbol(ClassDeclaration cd)
+{
+    if (!cd.vtblsym)
+    {
+        auto vtype = Type.tvoidptr.immutableOf().sarrayOf(cd.vtbl.length);
+        auto var = new VarDeclaration(cd.loc, vtype, Identifier.idPool("__vtbl"), null, STC.immutable_ | STC.static_);
+        var.addMember(null, cd);
+        var.isdataseg = 1;
+        var._linkage = LINK.d;
+        var.semanticRun = PASS.semanticdone; // no more semantic wanted
+        cd.vtblsym = var;
+    }
+    return cd.vtblsym;
+}
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index c19d4b942f2..2b5b461457b 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -53,7 +53,7 @@  import dmd.dinterpret;
 import dmd.dmodule;
 import dmd.dscope;
 import dmd.dsymbol;
-import dmd.dsymbolsem : dsymbolSemantic, checkDeprecated, aliasSemantic, search, search_correct, setScope, importAll, include;
+import dmd.dsymbolsem : dsymbolSemantic, checkDeprecated, aliasSemantic, search, search_correct, setScope, importAll, include, hasStaticCtorOrDtor;
 import dmd.errors;
 import dmd.errorsink;
 import dmd.expression;
@@ -605,6 +605,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
     extern (D) this(Loc loc, Identifier ident, TemplateParameters* parameters, Expression constraint, Dsymbols* decldefs, bool ismixin = false, bool literal = false)
     {
         super(loc, ident);
+        this.dsym = DSYM.templateDeclaration;
         static if (LOG)
         {
             printf("TemplateDeclaration(this = %p, id = '%s')\n", this, ident.toChars());
@@ -743,11 +744,6 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
         return true;
     }
 
-    override bool hasStaticCtorOrDtor()
-    {
-        return false; // don't scan uninstantiated templates
-    }
-
     override const(char)* kind() const
     {
         return (onemember && onemember.isAggregateDeclaration()) ? onemember.kind() : "template";
@@ -890,11 +886,6 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
         instances.remove(tibox);
     }
 
-    override inout(TemplateDeclaration) isTemplateDeclaration() inout
-    {
-        return this;
-    }
-
     /**
      * Check if the last template parameter is a tuple one,
      * and returns it if so, else returns `null`.
@@ -3002,6 +2993,8 @@  private bool reliesOnTemplateParameters(Expression e, TemplateParameter[] tparam
         override void visit(NewExp e)
         {
             //printf("NewExp.reliesOnTemplateParameters('%s')\n", e.toChars());
+            if (e.placement)
+                e.placement.accept(this);
             if (e.thisexp)
                 e.thisexp.accept(this);
             result = e.newtype.reliesOnTemplateParameters(tparams);
@@ -3738,6 +3731,7 @@  extern (C++) class TemplateInstance : ScopeDsymbol
         {
             printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident.toChars() : "null");
         }
+        this.dsym = DSYM.templateInstance;
         this.name = ident;
         this.tiargs = tiargs;
     }
@@ -3753,6 +3747,7 @@  extern (C++) class TemplateInstance : ScopeDsymbol
         {
             printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td.toChars());
         }
+        this.dsym = DSYM.templateInstance;
         this.name = td.ident;
         this.tiargs = tiargs;
         this.tempdecl = td;
@@ -3823,12 +3818,6 @@  extern (C++) class TemplateInstance : ScopeDsymbol
         return "template instance";
     }
 
-    override bool oneMember(out Dsymbol ps, Identifier ident)
-    {
-        ps = null;
-        return true;
-    }
-
     override final const(char)* toPrettyCharsHelper()
     {
         OutBuffer buf;
@@ -5342,11 +5331,6 @@  extern (C++) class TemplateInstance : ScopeDsymbol
         --nest;
     }
 
-    override final inout(TemplateInstance) isTemplateInstance() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -5490,6 +5474,7 @@  extern (C++) final class TemplateMixin : TemplateInstance
               tqual.idents.length ? cast(Identifier)tqual.idents[tqual.idents.length - 1] : (cast(TypeIdentifier)tqual).ident,
               tiargs ? tiargs : new Objects());
         //printf("TemplateMixin(ident = '%s')\n", ident ? ident.toChars() : "");
+        this.dsym = DSYM.templateMixin;
         this.ident = ident;
         this.tqual = tqual;
     }
@@ -5505,11 +5490,6 @@  extern (C++) final class TemplateMixin : TemplateInstance
         return "mixin";
     }
 
-    override bool oneMember(out Dsymbol ps, Identifier ident)
-    {
-        return Dsymbol.oneMember(ps, ident);
-    }
-
     override bool hasPointers()
     {
         //printf("TemplateMixin.hasPointers() %s\n", toChars());
@@ -5590,11 +5570,6 @@  extern (C++) final class TemplateMixin : TemplateInstance
         return true;
     }
 
-    override inout(TemplateMixin) isTemplateMixin() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/dversion.d b/gcc/d/dmd/dversion.d
index 5fd740f649d..5a24ea9a289 100644
--- a/gcc/d/dmd/dversion.d
+++ b/gcc/d/dmd/dversion.d
@@ -34,12 +34,12 @@  extern (C++) final class DebugSymbol : Dsymbol
 {
     extern (D) this(Loc loc, Identifier ident) @safe
     {
-        super(loc, ident);
+        super(DSYM.debugSymbol, loc, ident);
     }
 
     extern (D) this(Loc loc) @safe
     {
-        super(loc, null);
+        super(DSYM.aliasDeclaration, loc, null);
     }
 
     override DebugSymbol syntaxCopy(Dsymbol s)
@@ -55,11 +55,6 @@  extern (C++) final class DebugSymbol : Dsymbol
         return "debug";
     }
 
-    override inout(DebugSymbol) isDebugSymbol() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -75,12 +70,12 @@  extern (C++) final class VersionSymbol : Dsymbol
 
     extern (D) this(Loc loc, Identifier ident) @safe
     {
-        super(loc, ident);
+        super(DSYM.versionSymbol, loc, ident);
     }
 
     extern (D) this(Loc loc) @safe
     {
-        super(loc, null);
+        super(DSYM.versionSymbol, loc, null);
     }
 
     override VersionSymbol syntaxCopy(Dsymbol s)
@@ -96,11 +91,6 @@  extern (C++) final class VersionSymbol : Dsymbol
         return "version";
     }
 
-    override inout(VersionSymbol) isVersionSymbol() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h
index a51c50c39c6..7f149f4901a 100644
--- a/gcc/d/dmd/enum.h
+++ b/gcc/d/dmd/enum.h
@@ -52,14 +52,12 @@  public:
     bool inuse(bool v);
 
     EnumDeclaration *syntaxCopy(Dsymbol *s) override;
-    bool oneMember(Dsymbol *&ps, Identifier *ident) override;
     Type *getType() override;
     const char *kind() const override;
     bool isDeprecated() const override;       // is Dsymbol deprecated?
     Visibility visible() override;
     bool isSpecial() const;
 
-    EnumDeclaration *isEnumDeclaration() override { return this; }
 
     Symbol *sinit;
     void accept(Visitor *v) override { v->visit(this); }
@@ -87,6 +85,5 @@  public:
     EnumMember *syntaxCopy(Dsymbol *s) override;
     const char *kind() const override;
 
-    EnumMember *isEnumMember() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index b9e89e8fcc7..35897d66b2a 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -1637,6 +1637,9 @@  void escapeExp(Expression e, ref scope EscapeByResults er, int deref)
 
     void visitNew(NewExp e)
     {
+        if (e.placement)
+            escapeExp(e.placement, er, deref);
+
         Type tb = e.newtype.toBasetype();
         if (tb.isTypeStruct() && !e.member && e.arguments)
         {
@@ -1863,9 +1866,9 @@  void escapeExp(Expression e, ref scope EscapeByResults er, int deref)
  * Returns:
  *      storage class for fd's `this`
  */
-StorageClass getThisStorageClass(FuncDeclaration fd)
+STC getThisStorageClass(FuncDeclaration fd)
 {
-    StorageClass stc;
+    STC stc;
     auto tf = fd.type.toBasetype().isTypeFunction();
     if (tf.isReturn)
         stc |= STC.return_;
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 388023f53c6..f8dacd11911 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -304,8 +304,8 @@  extern (C++) abstract class Expression : ASTNode
 
     static struct BitFields
     {
-        bool parens;    // if this is a parenthesized expression
-        bool rvalue;    // true if this is considered to be an rvalue, even if it is an lvalue
+    bool parens;    // if this is a parenthesized expression
+    bool rvalue;    // true if this is considered to be an rvalue, even if it is an lvalue
     }
     import dmd.common.bitfields;
     mixin(generateBitFields!(BitFields, ubyte));
@@ -2446,6 +2446,7 @@  extern (C++) final class NewExp : Expression
     Type newtype;
     Expressions* arguments;     // Array of Expression's
     Identifiers* names;         // Array of names corresponding to expressions
+    Expression placement;       // if !=null, then PlacementExpression
 
     Expression argprefix;       // expression to be evaluated just before arguments[]
     CtorDeclaration member;     // constructor function
@@ -2458,23 +2459,25 @@  extern (C++) final class NewExp : Expression
     /// The fields are still separate for backwards compatibility
     extern (D) ArgumentList argumentList() { return ArgumentList(arguments, names); }
 
-    extern (D) this(Loc loc, Expression thisexp, Type newtype, Expressions* arguments, Identifiers* names = null) @safe
+    extern (D) this(Loc loc, Expression placement, Expression thisexp, Type newtype, Expressions* arguments, Identifiers* names = null) @safe
     {
         super(loc, EXP.new_);
+        this.placement = placement;
         this.thisexp = thisexp;
         this.newtype = newtype;
         this.arguments = arguments;
         this.names = names;
     }
 
-    static NewExp create(Loc loc, Expression thisexp, Type newtype, Expressions* arguments) @safe
+    static NewExp create(Loc loc, Expression placement, Expression thisexp, Type newtype, Expressions* arguments) @safe
     {
-        return new NewExp(loc, thisexp, newtype, arguments);
+        return new NewExp(loc, placement, thisexp, newtype, arguments);
     }
 
     override NewExp syntaxCopy()
     {
         return new NewExp(loc,
+            placement ? placement.syntaxCopy() : null,
             thisexp ? thisexp.syntaxCopy() : null,
             newtype.syntaxCopy(),
             arraySyntaxCopy(arguments),
@@ -2495,10 +2498,12 @@  extern (C++) final class NewAnonClassExp : Expression
     Expression thisexp;     // if !=null, 'this' for class being allocated
     ClassDeclaration cd;    // class being instantiated
     Expressions* arguments; // Array of Expression's to call class constructor
+    Expression placement;   // if !=null, then PlacementExpression
 
-    extern (D) this(Loc loc, Expression thisexp, ClassDeclaration cd, Expressions* arguments) @safe
+    extern (D) this(Loc loc, Expression placement, Expression thisexp, ClassDeclaration cd, Expressions* arguments) @safe
     {
         super(loc, EXP.newAnonymousClass);
+        this.placement = placement;
         this.thisexp = thisexp;
         this.cd = cd;
         this.arguments = arguments;
@@ -2506,7 +2511,9 @@  extern (C++) final class NewAnonClassExp : Expression
 
     override NewAnonClassExp syntaxCopy()
     {
-        return new NewAnonClassExp(loc, thisexp ? thisexp.syntaxCopy() : null, cd.syntaxCopy(null), arraySyntaxCopy(arguments));
+        return new NewAnonClassExp(loc, placement ? placement.syntaxCopy : null,
+                                        thisexp ? thisexp.syntaxCopy() : null,
+                                        cd.syntaxCopy(null), arraySyntaxCopy(arguments));
     }
 
     override void accept(Visitor v)
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index a4bb01940a2..9c1e17aba09 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -40,6 +40,7 @@  class OverloadSet;
 class StringExp;
 class InterpExp;
 class LoweredAssignExp;
+class StaticForeach;
 #ifdef IN_GCC
 typedef union tree_node Symbol;
 #else
@@ -50,6 +51,7 @@  namespace dmd
 {
     // in expressionsem.d
     Expression *expressionSemantic(Expression *e, Scope *sc);
+    void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc);
     // in typesem.d
     Expression *defaultInit(Type *mt, Loc loc, const bool isCfile = false);
 
@@ -517,6 +519,7 @@  public:
     Type *newtype;
     Expressions *arguments;     // Array of Expression's
     Identifiers *names;         // Array of names corresponding to expressions
+    Expression *placement;      // if !NULL, placement expression
 
     Expression *argprefix;      // expression to be evaluated just before arguments[]
 
@@ -526,7 +529,7 @@  public:
 
     Expression *lowering;       // lowered druntime hook: `_d_newclass`
 
-    static NewExp *create(Loc loc, Expression *thisexp, Type *newtype, Expressions *arguments);
+    static NewExp *create(Loc loc, Expression *placement, Expression *thisexp, Type *newtype, Expressions *arguments);
     NewExp *syntaxCopy() override;
 
     void accept(Visitor *v) override { v->visit(this); }
@@ -540,6 +543,7 @@  public:
     Expression *thisexp;        // if !NULL, 'this' for class being allocated
     ClassDeclaration *cd;       // class being instantiated
     Expressions *arguments;     // Array of Expression's to call class constructor
+    Expression *placement;      // if !NULL, placement expression
 
     NewAnonClassExp *syntaxCopy() override;
     void accept(Visitor *v) override { v->visit(this); }
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 22fbfc29969..22e9b8ca1da 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -25,6 +25,7 @@  import dmd.astcodegen;
 import dmd.astenums;
 import dmd.canthrow;
 import dmd.chkformat;
+import dmd.cond;
 import dmd.ctorflow;
 import dmd.dscope;
 import dmd.dsymbol;
@@ -1452,11 +1453,6 @@  private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2
         auto arguments = new Expressions(1);
         (*arguments)[0] = eleft;
         e = new CallExp(loc, e, arguments);
-
-        // https://issues.dlang.org/show_bug.cgi?id=24017
-        if (sc.debug_)
-            e.isCallExp().inDebugStatement = true;
-
         e = e.expressionSemantic(sc);
         return e;
     }
@@ -3161,7 +3157,7 @@  private bool functionParameters(Loc loc, Scope* sc,
                     auto args = new Expressions(nargs - i);
                     foreach (u; i .. nargs)
                         (*args)[u - i] = (*arguments)[u];
-                    arg = new NewExp(loc, null, p.type, args);
+                    arg = new NewExp(loc, null, null, p.type, args);
                     break;
                 }
             default:
@@ -3324,7 +3320,7 @@  private bool functionParameters(Loc loc, Scope* sc,
                 {   /* allow rvalues to be passed to ref parameters by copying
                      * them to a temp, then pass the temp as the argument
                      */
-                    auto v = copyToTemp(0, "__rvalue", arg);
+                    auto v = copyToTemp(STC.none, "__rvalue", arg);
                     Expression ev = new DeclarationExp(arg.loc, v);
                     ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
                     arg = ev.expressionSemantic(sc);
@@ -3406,7 +3402,7 @@  private bool functionParameters(Loc loc, Scope* sc,
                 {
                     // allocate the array literal as temporary static array on the stack
                     ale.type = ale.type.nextOf().sarrayOf(ale.elements.length);
-                    auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale);
+                    auto tmp = copyToTemp(STC.none, "__arrayliteral_on_stack", ale);
                     tmp.storage_class |= STC.exptemp;
                     auto declareTmp = new DeclarationExp(ale.loc, tmp);
                     auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp),
@@ -4879,6 +4875,28 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             printf("\tnewtype: %s\n", exp.newtype.toChars());
         }
 
+        if (exp.placement)
+        {
+            exp.placement = exp.placement.expressionSemantic(sc);
+            auto p = exp.placement;
+            if (p.op == EXP.error)
+                return setError();
+            if (!p.isLvalue())
+            {
+                error(p.loc, "PlacementExpression `%s` is an rvalue, but must be an lvalue", p.toChars());
+                return setError();
+            }
+            if (sc.setUnsafe(false, p.loc, "`@safe` function `%s` cannot use placement `new`", sc.func))
+            {
+                return setError();
+            }
+            if (!exp.placement.type.isNaked())
+            {
+                error(p.loc, "PlacementExpression `%s` of type `%s` be unshared and mutable", p.toChars(), toChars(p.type));
+                return setError();
+            }
+        }
+
         //for error messages if the argument in [] is not convertible to size_t
         const originalNewtype = exp.newtype;
 
@@ -4965,6 +4983,19 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return setError();
         }
 
+        uinteger_t placementSize;
+        if (exp.placement)
+        {
+            placementSize = size(exp.placement.type, exp.placement.loc);
+            auto objectSize = size(tb, exp.placement.loc);
+            //printf("placementSize: %lld objectSize: %lld\n", placementSize, objectSize);
+            if (!tb.isTypeClass && placementSize < objectSize)
+            {
+                error(exp.placement.loc, "new placement size %llu must be >= object size %llu", placementSize, objectSize);
+                return setError();
+            }
+        }
+
         const size_t nargs = exp.arguments ? exp.arguments.length : 0;
         Expression newprefix = null;
 
@@ -4973,9 +5004,14 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             auto cd = tc.sym;
             if (cd.errors)
                 return setError();
-            cd.size(exp.loc);
+            auto objectSize = cd.size(exp.loc);
             if (cd.sizeok != Sizeok.done)
                 return setError();
+            if (exp.placement && placementSize < objectSize)
+            {
+                error(exp.placement.loc, "new placement size %llu must be >= class object size %llu", placementSize, objectSize);
+                return setError();
+            }
             if (!cd.ctor)
                 cd.ctor = cd.searchCtor();
             if (cd.noDefaultCtor && !nargs && !cd.defaultCtor)
@@ -5185,6 +5221,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 return;
             }
             else if (sc.needsCodegen() && // interpreter doesn't need this lowered
+                     !exp.placement &&
                      !exp.onstack && !exp.type.isScopeClass()) // these won't use the GC
             {
                 /* replace `new T(arguments)` with `core.lifetime._d_newclassT!T(arguments)`
@@ -5290,10 +5327,16 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
 
             exp.type = exp.type.pointerTo();
-            tryLowerToNewItem(exp);
+            if (!exp.placement)
+                tryLowerToNewItem(exp);
         }
         else if (tb.ty == Tarray)
         {
+            if (exp.placement)
+            {
+                error(exp.placement.loc, "placement new cannot be used with dynamic arrays");
+                return setError();
+            }
             if (!nargs)
             {
                 // https://issues.dlang.org/show_bug.cgi?id=20422
@@ -5364,7 +5407,10 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     goto LskipNewArrayLowering;
             }
 
-            if (nargs == 1)
+            if (exp.placement)  // no need to lower
+            {
+            }
+            else if (nargs == 1)
             {
                 auto hook = global.params.tracegc ? Id._d_newarrayTTrace : Id._d_newarrayT;
                 if (!verifyHookExist(exp.loc, *sc, hook, "new array"))
@@ -5448,10 +5494,16 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
 
             exp.type = exp.type.pointerTo();
-            tryLowerToNewItem(exp);
+            if (!exp.placement)
+                tryLowerToNewItem(exp);
         }
         else if (tb.ty == Taarray)
         {
+            if (exp.placement)
+            {
+                error(exp.placement.loc, "placement new cannot be used with associative arrays");
+                return setError();
+            }
             // e.g. `new Alias(args)`
             if (nargs)
             {
@@ -5501,7 +5553,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             sds.members.push(e.cd);
         }
 
-        Expression n = new NewExp(e.loc, e.thisexp, e.cd.type, e.arguments);
+        Expression n = new NewExp(e.loc, e.placement, e.thisexp, e.cd.type, e.arguments);
 
         Expression c = new CommaExp(e.loc, d, n);
         result = c.expressionSemantic(sc);
@@ -5841,6 +5893,19 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             printf("CallExp::semantic() %s\n", exp.toChars());
         }
 
+        scope (exit)
+        {
+            if (TypeFunction tf = exp.f ? cast(TypeFunction)exp.f.type : null)
+            {
+                result.rvalue = tf.isRvalue;
+                if (tf.isRvalue && !tf.isRef)
+                {
+                    error(exp.f.loc, "`__rvalue` only valid on functions that return by `ref`");
+                    setError();
+                }
+            }
+        }
+
         Objects* tiargs = null; // initial list of template arguments
         Expression ethis = null;
         Type tthis = null;
@@ -6369,7 +6434,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 tthis = ue.e1.type;
                 if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual))
                 {
-                    if (checkParamArgumentEscape(*sc, exp.f, Id.This, exp.f.vthis, STC.undefined_, ethis, false, false))
+                    if (checkParamArgumentEscape(*sc, exp.f, Id.This, exp.f.vthis, STC.none, ethis, false, false))
                         return setError();
                 }
             }
@@ -6851,10 +6916,10 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 Loc loc = exp.loc;
 
                 auto vptr = new DotIdExp(loc, new ThisExp(loc), Id.__vptr);
-                auto vptrTmpDecl = copyToTemp(0, "__vptrTmp", vptr);
+                auto vptrTmpDecl = copyToTemp(STC.none, "__vptrTmp", vptr);
                 auto declareVptrTmp = new DeclarationExp(loc, vptrTmpDecl);
 
-                auto superTmpDecl = copyToTemp(0, "__superTmp", result);
+                auto superTmpDecl = copyToTemp(STC.none, "__superTmp", result);
                 auto declareSuperTmp = new DeclarationExp(loc, superTmpDecl);
 
                 auto declareTmps = new CommaExp(loc, declareVptrTmp, declareSuperTmp);
@@ -7871,7 +7936,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                         return res.expressionSemantic(sc);
                     }
 
-                    const stc = op.isLvalue() ? STC.ref_ : 0;
+                    const stc = op.isLvalue() ? STC.ref_ : STC.none;
                     auto tmp = copyToTemp(stc, "__assertOp", op);
                     tmp.dsymbolSemantic(sc);
 
@@ -8039,7 +8104,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             exp.msg = resolveProperties(sc, exp.msg);
             exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
             exp.msg = exp.msg.optimize(WANTvalue);
-            checkParamArgumentEscape(*sc, null, null, null, STC.undefined_, exp.msg, true, false);
+            checkParamArgumentEscape(*sc, null, null, null, STC.none, exp.msg, true, false);
         }
 
         if (exp.msg && exp.msg.op == EXP.error)
@@ -10149,7 +10214,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             /* Rewrite as:
              * auto tmp = e1; ++e1; tmp
              */
-            auto tmp = copyToTemp(0, "__pitmp", exp.e1);
+            auto tmp = copyToTemp(STC.none, "__pitmp", exp.e1);
             Expression ea = new DeclarationExp(exp.loc, tmp);
 
             Expression eb = exp.e1.syntaxCopy();
@@ -10787,7 +10852,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                                 return;
                             }
                         }
-                        else if (sd.hasMoveCtor && !e2x.isCallExp() && !e2x.isStructLiteralExp())
+                        else if (sd.hasMoveCtor && (!e2x.isCallExp() || e2x.rvalue) && !e2x.isStructLiteralExp())
                         {
                             // #move
                             /* The !e2x.isCallExp() is because it is already an rvalue
@@ -11677,7 +11742,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             // `__assigntmp` will be destroyed together with the array `ae.e1`.
             // When `ae.e2` is a variadic arg array, it is also `scope`, so
             // `__assigntmp` may also be scope.
-            StorageClass stc = STC.nodtor;
+            STC stc = STC.nodtor;
             if (isArrayAssign)
                 stc |= STC.rvalue | STC.scope_;
 
@@ -13020,6 +13085,11 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             error(exp.loc, "compare not defined for complex operands");
             return setError();
         }
+        else if (t1.isTypeFunction() || t2.isTypeFunction())
+        {
+            error(exp.loc, "comparison is not defined for function types");
+            return setError();
+        }
         else if (t1.ty == Taarray || t2.ty == Taarray)
         {
             error(exp.loc, "`%s` is not defined for associative arrays", EXPtoString(exp.op).ptr);
@@ -13325,6 +13395,12 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
+        if (t1.isTypeFunction() || t2.isTypeFunction())
+        {
+            error(exp.loc, "operator `==` is not defined for function types");
+            return setError();
+        }
+
         if (auto tv = t1.isTypeVector())
             exp.type = tv.toBooleanVector();
 
@@ -13381,6 +13457,12 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (exp.e2.op == EXP.call)
             exp.e2 = (cast(CallExp)exp.e2).addDtorHook(sc);
 
+        if (exp.e1.type.isTypeFunction() || exp.e2.type.isTypeFunction())
+        {
+            error(exp.loc, "operator `is` is not defined for function types");
+            return setError();
+        }
+
         if (exp.e1.type.toBasetype().ty == Tsarray ||
             exp.e2.type.toBasetype().ty == Tsarray)
             deprecation(exp.loc, "identity comparison of static arrays "
@@ -14611,7 +14693,7 @@  MATCH matchType(FuncExp funcExp, Type to, Scope* sc, FuncExp* presult, ErrorSink
         convertMatch = true;
 
         auto tfy = new TypeFunction(tfx.parameterList, tof.next,
-                    tfx.linkage, STC.undefined_);
+                    tfx.linkage, STC.none);
         tfy.mod = tfx.mod;
         tfy.trust = tfx.trust;
         tfy.isNothrow = tfx.isNothrow;
@@ -14928,6 +15010,8 @@  bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
 
         bool visitNew(NewExp e)
         {
+            if (e.placement)
+                check(e.placement, false);
             if (e.thisexp)
                 check(e.thisexp, false);
             return false;
@@ -15111,6 +15195,8 @@  Expression resolveLoc(Expression exp, Loc loc, Scope* sc)
 
     Expression visitNew(NewExp exp)
     {
+        if (exp.placement)
+            exp.placement = exp.placement.resolveLoc(loc, sc);
         if (exp.thisexp)
             exp.thisexp = exp.thisexp.resolveLoc(loc, sc);
         if (exp.argprefix)
@@ -15332,7 +15418,7 @@  Expression addDtorHook(Expression e, Scope* sc)
             buf[0 .. prefix.length] = prefix;
             buf[prefix.length .. len] = ident[0 .. len - prefix.length];
 
-            auto tmp = copyToTemp(0, buf[0 .. len], exp);
+            auto tmp = copyToTemp(STC.none, buf[0 .. len], exp);
             Expression ae = new DeclarationExp(exp.loc, tmp);
             Expression e = new CommaExp(exp.loc, ae, new VarExp(exp.loc, tmp));
             e = e.expressionSemantic(sc);
@@ -15365,7 +15451,7 @@  Expression addDtorHook(Expression e, Scope* sc)
                 /* Type needs destruction, so declare a tmp
                  * which the back end will recognize and call dtor on
                  */
-                auto tmp = copyToTemp(0, Id.__tmpfordtor.toString(), exp);
+                auto tmp = copyToTemp(STC.none, Id.__tmpfordtor.toString(), exp);
                 auto de = new DeclarationExp(exp.loc, tmp);
                 auto ve = new VarExp(exp.loc, tmp);
                 Expression e = new CommaExp(exp.loc, de, ve);
@@ -17346,3 +17432,243 @@  bool fill(StructDeclaration sd, Loc loc, ref Expressions elements, bool ctorinit
 
     return !errors;
 }
+
+/*****************************************
+* Lower any aggregate that is not an array to an array using a
+* regular foreach loop within CTFE.  If there are multiple
+* `static foreach` loop variables, an array of tuples is
+* generated. In thise case, the field `needExpansion` is set to
+* true to indicate that the static foreach loop expansion will
+* need to expand the tuples into multiple variables.
+*
+* For example, `static foreach (x; range) { ... }` is lowered to:
+*
+*     static foreach (x; {
+*         typeof({
+*             foreach (x; range) return x;
+*         }())[] __res;
+*         foreach (x; range) __res ~= x;
+*         return __res;
+*     }()) { ... }
+*
+* Finally, call `lowerArrayAggregate` to turn the produced
+* array into an expression tuple.
+*
+* Params:
+*     sfe = The 'static foreach'.
+*     sc = The current scope.
+*/
+extern (C++) void lowerNonArrayAggregate(StaticForeach sfe, Scope* sc)
+{
+    import dmd.statement;
+
+    auto nvars = sfe.aggrfe ? sfe.aggrfe.parameters.length : 1;
+    auto aloc = sfe.aggrfe ? sfe.aggrfe.aggr.loc : sfe.rangefe.lwr.loc;
+    // We need three sets of foreach loop variables because the
+    // lowering contains three foreach loops.
+    Parameters*[3] pparams = [new Parameters(), new Parameters(), new Parameters()];
+    foreach (i; 0 .. nvars)
+    {
+        foreach (params; pparams)
+        {
+            auto p = sfe.aggrfe ? (*sfe.aggrfe.parameters)[i] : sfe.rangefe.param;
+            params.push(new Parameter(aloc, p.storageClass, p.type, p.ident, null, null));
+        }
+    }
+    Expression[2] res;
+    TypeStruct tplty = null;
+    if (nvars == 1) // only one `static foreach` variable, generate identifiers.
+    {
+        foreach (i; 0 .. 2)
+        {
+            res[i] = new IdentifierExp(aloc, (*pparams[i])[0].ident);
+        }
+    }
+    else // multiple `static foreach` variables, generate tuples.
+    {
+        foreach (i; 0 .. 2)
+        {
+            auto e = new Expressions(pparams[0].length);
+            foreach (j, ref elem; *e)
+            {
+                auto p = (*pparams[i])[j];
+                elem = new IdentifierExp(aloc, p.ident);
+            }
+            if (!tplty)
+            {
+                tplty = sfe.createTupleType(aloc, e, sc);
+            }
+            res[i] = sfe.createTuple(aloc, tplty, e);
+        }
+        sfe.needExpansion = true; // need to expand the tuples later
+    }
+    // generate remaining code for the new aggregate which is an
+    // array (see documentation comment).
+    if (sfe.rangefe)
+    {
+        sc = sc.startCTFE();
+        sfe.rangefe.lwr = sfe.rangefe.lwr.expressionSemantic(sc);
+        sfe.rangefe.lwr = resolveProperties(sc, sfe.rangefe.lwr);
+        sfe.rangefe.upr = sfe.rangefe.upr.expressionSemantic(sc);
+        sfe.rangefe.upr = resolveProperties(sc, sfe.rangefe.upr);
+        sc = sc.endCTFE();
+        sfe.rangefe.lwr = sfe.rangefe.lwr.optimize(WANTvalue);
+        sfe.rangefe.lwr = sfe.rangefe.lwr.ctfeInterpret();
+        sfe.rangefe.upr = sfe.rangefe.upr.optimize(WANTvalue);
+        sfe.rangefe.upr = sfe.rangefe.upr.ctfeInterpret();
+    }
+    auto s1 = new Statements();
+    auto stmts = new Statements();
+    if (tplty) stmts.push(new ExpStatement(sfe.loc, tplty.sym));
+    stmts.push(new ReturnStatement(aloc, res[0]));
+    s1.push(sfe.createForeach(aloc, pparams[0], new CompoundStatement(aloc, stmts)));
+    s1.push(new ExpStatement(aloc, new AssertExp(aloc, IntegerExp.literal!0)));
+    Type ety = new TypeTypeof(aloc, sfe.wrapAndCall(aloc, new CompoundStatement(aloc, s1)));
+    auto aty = ety.arrayOf();
+    auto idres = Identifier.generateId("__res");
+    auto vard = new VarDeclaration(aloc, aty, idres, null, STC.temp);
+    auto s2 = new Statements();
+
+    // Run 'typeof' gagged to avoid duplicate errors and if it fails just create
+    // an empty foreach to expose them.
+    const olderrors = global.startGagging();
+    ety = ety.typeSemantic(aloc, sc);
+    if (global.endGagging(olderrors))
+        s2.push(sfe.createForeach(aloc, pparams[1], null));
+    else
+    {
+        s2.push(new ExpStatement(aloc, vard));
+        auto catass = new CatAssignExp(aloc, new IdentifierExp(aloc, idres), res[1]);
+        s2.push(sfe.createForeach(aloc, pparams[1], new ExpStatement(aloc, catass)));
+        s2.push(new ReturnStatement(aloc, new IdentifierExp(aloc, idres)));
+    }
+
+    Expression aggr = void;
+    Type indexty = void;
+
+    if (sfe.rangefe && (indexty = ety).isIntegral())
+    {
+        sfe.rangefe.lwr.type = indexty;
+        sfe.rangefe.upr.type = indexty;
+        auto lwrRange = getIntRange(sfe.rangefe.lwr);
+        auto uprRange = getIntRange(sfe.rangefe.upr);
+
+        const lwr = sfe.rangefe.lwr.toInteger();
+        auto  upr = sfe.rangefe.upr.toInteger();
+        size_t length = 0;
+
+        if (lwrRange.imin <= uprRange.imax)
+                length = cast(size_t) (upr - lwr);
+
+        auto exps = new Expressions(length);
+
+        if (sfe.rangefe.op == TOK.foreach_)
+        {
+            foreach (i; 0 .. length)
+                (*exps)[i] = new IntegerExp(aloc, lwr + i, indexty);
+        }
+        else
+        {
+            --upr;
+            foreach (i; 0 .. length)
+                (*exps)[i] = new IntegerExp(aloc, upr - i, indexty);
+        }
+        aggr = new ArrayLiteralExp(aloc, indexty.arrayOf(), exps);
+    }
+    else
+    {
+        aggr = sfe.wrapAndCall(aloc, new CompoundStatement(aloc, s2));
+        sc = sc.startCTFE();
+        aggr = aggr.expressionSemantic(sc);
+        aggr = resolveProperties(sc, aggr);
+        sc = sc.endCTFE();
+        aggr = aggr.optimize(WANTvalue);
+        aggr = aggr.ctfeInterpret();
+    }
+
+    assert(!!sfe.aggrfe ^ !!sfe.rangefe);
+    sfe.aggrfe = new ForeachStatement(sfe.loc, TOK.foreach_, pparams[2], aggr,
+                                    sfe.aggrfe ? sfe.aggrfe._body : sfe.rangefe._body,
+                                    sfe.aggrfe ? sfe.aggrfe.endloc : sfe.rangefe.endloc);
+    sfe.rangefe = null;
+    sfe.lowerArrayAggregate(sc); // finally, turn generated array into expression tuple
+}
+
+/*****************************************
+* Perform `static foreach` lowerings that are necessary in order
+* to finally expand the `static foreach` using
+* `dmd.statementsem.makeTupleForeach`.
+*/
+extern(D) void prepare(StaticForeach sfe, Scope* sc)
+{
+    assert(sc);
+
+    if (sfe.aggrfe)
+    {
+        sc = sc.startCTFE();
+        sfe.aggrfe.aggr = sfe.aggrfe.aggr.expressionSemantic(sc);
+        sc = sc.endCTFE();
+    }
+
+    if (sfe.aggrfe && sfe.aggrfe.aggr.type.toBasetype().ty == Terror)
+    {
+        return;
+    }
+
+    if (!sfe.ready())
+    {
+        if (sfe.aggrfe && sfe.aggrfe.aggr.type.toBasetype().ty == Tarray)
+        {
+            sfe.lowerArrayAggregate(sc);
+        }
+        else
+        {
+            sfe.lowerNonArrayAggregate(sc);
+        }
+    }
+}
+
+/*****************************************
+    * Turn an aggregate which is an array into an expression tuple
+    * of its elements. I.e., lower
+    *     static foreach (x; [1, 2, 3, 4]) { ... }
+    * to
+    *     static foreach (x; AliasSeq!(1, 2, 3, 4)) { ... }
+    */
+extern(D) void lowerArrayAggregate(StaticForeach sfe, Scope* sc)
+{
+    auto aggr = sfe.aggrfe.aggr;
+    Expression el = new ArrayLengthExp(aggr.loc, aggr);
+    sc = sc.startCTFE();
+    el = el.expressionSemantic(sc);
+    sc = sc.endCTFE();
+    el = el.optimize(WANTvalue);
+    el = el.ctfeInterpret();
+    if (el.op != EXP.int64)
+    {
+        sfe.aggrfe.aggr = ErrorExp.get();
+        return;
+    }
+
+    Expressions* es;
+    if (auto ale = aggr.isArrayLiteralExp())
+    {
+        // Directly use the elements of the array for the TupleExp creation
+        es = ale.elements;
+    }
+    else
+    {
+        const length = cast(size_t)el.toInteger();
+        es = new Expressions(length);
+        foreach (i; 0 .. length)
+        {
+            auto index = new IntegerExp(sfe.loc, i, Type.tsize_t);
+            auto value = new IndexExp(aggr.loc, aggr, index);
+            (*es)[i] = value;
+        }
+    }
+    sfe.aggrfe.aggr = new TupleExp(aggr.loc, es);
+    sfe.aggrfe.aggr = sfe.aggrfe.aggr.expressionSemantic(sc);
+    sfe.aggrfe.aggr = sfe.aggrfe.aggr.optimize(WANTvalue);
+    sfe.aggrfe.aggr = sfe.aggrfe.aggr.ctfeInterpret();
+}
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index e5b72e2bb3c..7c36823de6e 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -235,7 +235,7 @@  extern (C++) class FuncDeclaration : Declaration
     */
     Type tintro;
 
-    StorageClass storage_class2;        /// storage class for template onemember's
+    STC storage_class2;        /// storage class for template onemember's
 
     // Things that should really go into Scope
 
@@ -296,9 +296,9 @@  extern (C++) class FuncDeclaration : Declaration
      */
     ObjcFuncDeclaration objc;
 
-    extern (D) this(Loc loc, Loc endloc, Identifier ident, StorageClass storage_class, Type type, bool noreturn = false)
+    extern (D) this(Loc loc, Loc endloc, Identifier ident, STC storage_class, Type type, bool noreturn = false)
     {
-        super(loc, ident);
+        super(DSYM.funcDeclaration, loc, ident);
         //.printf("FuncDeclaration(id = '%s', type = %s)\n", ident.toChars(), type.toChars());
         //.printf("storage_class = x%llx\n", storage_class);
         this.storage_class = storage_class;
@@ -322,7 +322,7 @@  extern (C++) class FuncDeclaration : Declaration
 
     static FuncDeclaration create(Loc loc, Loc endloc, Identifier id, StorageClass storage_class, Type type, bool noreturn = false)
     {
-        return new FuncDeclaration(loc, endloc, id, storage_class, type, noreturn);
+        return new FuncDeclaration(loc, endloc, id, cast(STC) storage_class, type, noreturn);
     }
 
     final nothrow pure @safe
@@ -1006,12 +1006,12 @@  extern (C++) class FuncDeclaration : Declaration
     /**********************************
      * Generate a FuncDeclaration for a runtime library function.
      */
-    static FuncDeclaration genCfunc(Parameters* fparams, Type treturn, const(char)* name, StorageClass stc = 0)
+    extern (D) static FuncDeclaration genCfunc(Parameters* fparams, Type treturn, const(char)* name, STC stc = STC.none)
     {
         return genCfunc(fparams, treturn, Identifier.idPool(name[0 .. strlen(name)]), stc);
     }
 
-    static FuncDeclaration genCfunc(Parameters* fparams, Type treturn, Identifier id, StorageClass stc = 0)
+    extern (D) static FuncDeclaration genCfunc(Parameters* fparams, Type treturn, Identifier id, STC stc = STC.none)
     {
         FuncDeclaration fd;
         TypeFunction tf;
@@ -1043,11 +1043,6 @@  extern (C++) class FuncDeclaration : Declaration
         return fd;
     }
 
-    override final inout(FuncDeclaration) isFuncDeclaration() inout
-    {
-        return this;
-    }
-
     inout(FuncDeclaration) toAliasFunc() inout @safe
     {
         return this;
@@ -1243,6 +1238,7 @@  extern (C++) final class FuncAliasDeclaration : FuncDeclaration
         super(funcalias.loc, funcalias.endloc, ident, funcalias.storage_class, funcalias.type);
         assert(funcalias != this);
         this.funcalias = funcalias;
+        this.dsym = DSYM.funcAliasDeclaration;
 
         this.hasOverloads = hasOverloads;
         if (hasOverloads)
@@ -1259,11 +1255,6 @@  extern (C++) final class FuncAliasDeclaration : FuncDeclaration
         userAttribDecl = funcalias.userAttribDecl;
     }
 
-    override inout(FuncAliasDeclaration) isFuncAliasDeclaration() inout
-    {
-        return this;
-    }
-
     override const(char)* kind() const
     {
         return "function alias";
@@ -1290,9 +1281,10 @@  extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
     // backend
     bool deferToObj;
 
-    extern (D) this(Loc loc, Loc endloc, Type type, TOK tok, ForeachStatement fes, Identifier id = null, StorageClass storage_class = STC.undefined_)
+    extern (D) this(Loc loc, Loc endloc, Type type, TOK tok, ForeachStatement fes, Identifier id = null, STC storage_class = STC.none)
     {
         super(loc, endloc, null, storage_class, type);
+        this.dsym = DSYM.funcLiteralDeclaration;
         this.ident = id ? id : Id.empty;
         this.tok = tok;
         this.fes = fes;
@@ -1338,11 +1330,6 @@  extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
         return false;
     }
 
-    override inout(FuncLiteralDeclaration) isFuncLiteralDeclaration() inout
-    {
-        return this;
-    }
-
     override const(char)* kind() const
     {
         // GCC requires the (char*) casts
@@ -1371,9 +1358,10 @@  extern (C++) final class CtorDeclaration : FuncDeclaration
 {
     bool isCpCtor;    // copy constructor
     bool isMoveCtor;  // move constructor (aka rvalue constructor)
-    extern (D) this(Loc loc, Loc endloc, StorageClass stc, Type type)
+    extern (D) this(Loc loc, Loc endloc, STC stc, Type type)
     {
         super(loc, endloc, Id.ctor, stc, type);
+        this.dsym = DSYM.ctorDeclaration;
         //printf("CtorDeclaration(loc = %s) %s %p\n", loc.toChars(), toChars(), this);
     }
 
@@ -1405,11 +1393,6 @@  extern (C++) final class CtorDeclaration : FuncDeclaration
         return (isThis() && vthis && global.params.useInvariants == CHECKENABLE.on);
     }
 
-    override inout(CtorDeclaration) isCtorDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1420,9 +1403,10 @@  extern (C++) final class CtorDeclaration : FuncDeclaration
  */
 extern (C++) final class PostBlitDeclaration : FuncDeclaration
 {
-    extern (D) this(Loc loc, Loc endloc, StorageClass stc, Identifier id)
+    extern (D) this(Loc loc, Loc endloc, STC stc, Identifier id)
     {
         super(loc, endloc, id, stc, null);
+        this.dsym = DSYM.postBlitDeclaration;
     }
 
     override PostBlitDeclaration syntaxCopy(Dsymbol s)
@@ -1453,11 +1437,6 @@  extern (C++) final class PostBlitDeclaration : FuncDeclaration
         return false; // cannot overload postblits
     }
 
-    override inout(PostBlitDeclaration) isPostBlitDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1470,12 +1449,14 @@  extern (C++) final class DtorDeclaration : FuncDeclaration
 {
     extern (D) this(Loc loc, Loc endloc)
     {
-        super(loc, endloc, Id.dtor, STC.undefined_, null);
+        super(loc, endloc, Id.dtor, STC.none, null);
+        this.dsym = DSYM.dtorDeclaration;
     }
 
-    extern (D) this(Loc loc, Loc endloc, StorageClass stc, Identifier id)
+    extern (D) this(Loc loc, Loc endloc, STC stc, Identifier id)
     {
         super(loc, endloc, id, stc, null);
+        this.dsym = DSYM.dtorDeclaration;
     }
 
     override DtorDeclaration syntaxCopy(Dsymbol s)
@@ -1513,11 +1494,6 @@  extern (C++) final class DtorDeclaration : FuncDeclaration
         return false; // cannot overload destructors
     }
 
-    override inout(DtorDeclaration) isDtorDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1528,14 +1504,16 @@  extern (C++) final class DtorDeclaration : FuncDeclaration
  */
 extern (C++) class StaticCtorDeclaration : FuncDeclaration
 {
-    extern (D) this(Loc loc, Loc endloc, StorageClass stc)
+    extern (D) this(Loc loc, Loc endloc, STC stc)
     {
         super(loc, endloc, Identifier.generateIdWithLoc("_staticCtor", loc), STC.static_ | stc, null);
+        this.dsym = DSYM.staticCtorDeclaration;
     }
 
-    extern (D) this(Loc loc, Loc endloc, string name, StorageClass stc)
+    extern (D) this(Loc loc, Loc endloc, string name, STC stc)
     {
         super(loc, endloc, Identifier.generateIdWithLoc(name, loc), STC.static_ | stc, null);
+        this.dsym = DSYM.staticCtorDeclaration;
     }
 
     override StaticCtorDeclaration syntaxCopy(Dsymbol s)
@@ -1566,16 +1544,6 @@  extern (C++) class StaticCtorDeclaration : FuncDeclaration
         return false;
     }
 
-    override final bool hasStaticCtorOrDtor() @nogc nothrow pure @safe
-    {
-        return true;
-    }
-
-    override final inout(StaticCtorDeclaration) isStaticCtorDeclaration() inout @nogc nothrow pure @safe
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1589,9 +1557,10 @@  extern (C++) final class SharedStaticCtorDeclaration : StaticCtorDeclaration
     /// Exclude this constructor from cyclic dependency check
     bool standalone;
 
-    extern (D) this(Loc loc, Loc endloc, StorageClass stc)
+    extern (D) this(Loc loc, Loc endloc, STC stc)
     {
         super(loc, endloc, "_sharedStaticCtor", stc);
+        this.dsym = DSYM.sharedStaticCtorDeclaration;
     }
 
     override SharedStaticCtorDeclaration syntaxCopy(Dsymbol s)
@@ -1602,11 +1571,6 @@  extern (C++) final class SharedStaticCtorDeclaration : StaticCtorDeclaration
         return scd;
     }
 
-    override inout(SharedStaticCtorDeclaration) isSharedStaticCtorDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1619,14 +1583,16 @@  extern (C++) class StaticDtorDeclaration : FuncDeclaration
 {
     VarDeclaration vgate; // 'gate' variable
 
-    extern (D) this(Loc loc, Loc endloc, StorageClass stc)
+    extern (D) this(Loc loc, Loc endloc, STC stc)
     {
         super(loc, endloc, Identifier.generateIdWithLoc("_staticDtor", loc), STC.static_ | stc, null);
+        this.dsym = DSYM.staticDtorDeclaration;
     }
 
-    extern (D) this(Loc loc, Loc endloc, string name, StorageClass stc)
+    extern (D) this(Loc loc, Loc endloc, string name, STC stc)
     {
         super(loc, endloc, Identifier.generateIdWithLoc(name, loc), STC.static_ | stc, null);
+        this.dsym = DSYM.staticDtorDeclaration;
     }
 
     override StaticDtorDeclaration syntaxCopy(Dsymbol s)
@@ -1647,11 +1613,6 @@  extern (C++) class StaticDtorDeclaration : FuncDeclaration
         return false;
     }
 
-    override final bool hasStaticCtorOrDtor()
-    {
-        return true;
-    }
-
     override final bool addPreInvariant()
     {
         return false;
@@ -1662,11 +1623,6 @@  extern (C++) class StaticDtorDeclaration : FuncDeclaration
         return false;
     }
 
-    override final inout(StaticDtorDeclaration) isStaticDtorDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1677,9 +1633,10 @@  extern (C++) class StaticDtorDeclaration : FuncDeclaration
  */
 extern (C++) final class SharedStaticDtorDeclaration : StaticDtorDeclaration
 {
-    extern (D) this(Loc loc, Loc endloc, StorageClass stc)
+    extern (D) this(Loc loc, Loc endloc, STC stc)
     {
         super(loc, endloc, "_sharedStaticDtor", stc);
+        this.dsym = DSYM.sharedStaticDtorDeclaration;
     }
 
     override SharedStaticDtorDeclaration syntaxCopy(Dsymbol s)
@@ -1690,11 +1647,6 @@  extern (C++) final class SharedStaticDtorDeclaration : StaticDtorDeclaration
         return sdd;
     }
 
-    override inout(SharedStaticDtorDeclaration) isSharedStaticDtorDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1705,11 +1657,12 @@  extern (C++) final class SharedStaticDtorDeclaration : StaticDtorDeclaration
  */
 extern (C++) final class InvariantDeclaration : FuncDeclaration
 {
-    extern (D) this(Loc loc, Loc endloc, StorageClass stc, Identifier id, Statement fbody)
+    extern (D) this(Loc loc, Loc endloc, STC stc, Identifier id, Statement fbody)
     {
         // Make a unique invariant for now; we'll fix it up as we add it to the aggregate invariant list.
         super(loc, endloc, id ? id : Identifier.generateId("__invariant"), stc, null);
         this.fbody = fbody;
+        this.dsym = DSYM.invariantDeclaration;
     }
 
     override InvariantDeclaration syntaxCopy(Dsymbol s)
@@ -1735,11 +1688,6 @@  extern (C++) final class InvariantDeclaration : FuncDeclaration
         return false;
     }
 
-    override inout(InvariantDeclaration) isInvariantDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1765,10 +1713,11 @@  extern (C++) final class UnitTestDeclaration : FuncDeclaration
     // toObjFile() these nested functions after this one
     FuncDeclarations deferredNested;
 
-    extern (D) this(Loc loc, Loc endloc, StorageClass stc, char* codedoc)
+    extern (D) this(Loc loc, Loc endloc, STC stc, char* codedoc)
     {
         super(loc, endloc, Identifier.generateIdWithLoc("__unittest", loc), stc, null);
         this.codedoc = codedoc;
+        this.dsym = DSYM.unitTestDeclaration;
     }
 
     override UnitTestDeclaration syntaxCopy(Dsymbol s)
@@ -1799,11 +1748,6 @@  extern (C++) final class UnitTestDeclaration : FuncDeclaration
         return false;
     }
 
-    override inout(UnitTestDeclaration) isUnitTestDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -1814,9 +1758,10 @@  extern (C++) final class UnitTestDeclaration : FuncDeclaration
  */
 extern (C++) final class NewDeclaration : FuncDeclaration
 {
-    extern (D) this(Loc loc, StorageClass stc)
+    extern (D) this(Loc loc, STC stc)
     {
         super(loc, Loc.initial, Id.classNew, STC.static_ | stc, null);
+        this.dsym = DSYM.newDeclaration;
     }
 
     override NewDeclaration syntaxCopy(Dsymbol s)
@@ -1847,11 +1792,6 @@  extern (C++) final class NewDeclaration : FuncDeclaration
         return false;
     }
 
-    override inout(NewDeclaration) isNewDeclaration() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d
index 4658a5a7b8b..113d28f9364 100644
--- a/gcc/d/dmd/funcsem.d
+++ b/gcc/d/dmd/funcsem.d
@@ -1275,6 +1275,7 @@  extern (D) void declareThis(FuncDeclaration fd, Scope* sc)
     const bool dualCtx = (fd.toParent2() != fd.toParentLocal());
     if (dualCtx)
         fd.hasDualContext = true;
+
     auto ad = fd.isThis();
     if (!dualCtx && !ad && !fd.isNested())
     {
@@ -1369,7 +1370,7 @@  int findVtblIndex(FuncDeclaration fd, Dsymbol[] vtbl)
     import dmd.typesem : covariant;
 
     FuncDeclaration mismatch = null;
-    StorageClass mismatchstc = 0;
+    STC mismatchstc = STC.none;
     int mismatchvi = -1;
     int exactvi = -1;
     int bestvi = -1;
@@ -1401,7 +1402,7 @@  int findVtblIndex(FuncDeclaration fd, Dsymbol[] vtbl)
             continue;
         }
 
-        StorageClass stc = 0;
+        STC stc = STC.none;
         const cov = fd.type.covariant(fdv.type, &stc);
         //printf("\tbaseclass cov = %d\n", cov);
         final switch (cov)
@@ -1428,7 +1429,7 @@  int findVtblIndex(FuncDeclaration fd, Dsymbol[] vtbl)
     }
     if (fd._linkage == LINK.cpp && bestvi != -1)
     {
-        StorageClass stc = 0;
+        STC stc = STC.none;
         FuncDeclaration fdv = vtbl[bestvi].isFuncDeclaration();
         assert(fdv && fdv.ident == fd.ident);
         if (fd.type.covariant(fdv.type, &stc, /*cppCovariant=*/true) == Covariant.no)
@@ -2648,7 +2649,7 @@  void buildEnsureRequire(FuncDeclaration thisfd)
         tf.isNogc = f.isNogc;
         tf.purity = f.purity;
         tf.trust = f.trust;
-        auto fd = new FuncDeclaration(loc, loc, Id.require, STC.undefined_, tf);
+        auto fd = new FuncDeclaration(loc, loc, Id.require, STC.none, tf);
         fd.fbody = thisfd.frequire;
         Statement s1 = new ExpStatement(loc, fd);
         Expression e = new CallExp(loc, new VarExp(loc, fd, false), thisfd.fdrequireParams);
@@ -2689,7 +2690,7 @@  void buildEnsureRequire(FuncDeclaration thisfd)
         tf.isNogc = f.isNogc;
         tf.purity = f.purity;
         tf.trust = f.trust;
-        auto fd = new FuncDeclaration(loc, loc, Id.ensure, STC.undefined_, tf);
+        auto fd = new FuncDeclaration(loc, loc, Id.ensure, STC.none, tf);
         fd.fbody = thisfd.fensure;
         Statement s1 = new ExpStatement(loc, fd);
         Expression e = new CallExp(loc, new VarExp(loc, fd, false), thisfd.fdensureParams);
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 0ef955a0339..62f49a0c1ca 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -429,7 +429,7 @@  private void statementToBuffer(Statement s, ref OutBuffer buf, ref HdrGenState h
         if (p)
         {
             // Print condition assignment
-            StorageClass stc = p.storageClass;
+            STC stc = p.storageClass;
             if (!p.type && !stc)
                 stc = STC.auto_;
             if (stcToBuffer(buf, stc))
@@ -2531,6 +2531,13 @@  private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
             buf.writeByte('.');
         }
         buf.writestring("new ");
+        if (e.placement)
+        {
+            buf.writeByte('(');
+            expToBuffer(e.placement, PREC.assign, buf, hgs);
+            buf.writeByte(')');
+            buf.writeByte(' ');
+        }
         typeToBuffer(e.newtype, null, buf, hgs);
         if (e.arguments && e.arguments.length)
         {
@@ -2548,6 +2555,13 @@  private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
             buf.writeByte('.');
         }
         buf.writestring("new");
+        if (e.placement)
+        {
+            buf.writeByte(' ');
+            buf.writeByte('(');
+            expToBuffer(e.placement, PREC.assign, buf, hgs);
+            buf.writeByte(')');
+        }
         buf.writestring(" class ");
         if (e.arguments && e.arguments.length)
         {
@@ -3283,7 +3297,7 @@  void toCBuffer(const Initializer iz, ref OutBuffer buf, ref HdrGenState hgs)
     initializerToBuffer(cast() iz, buf, hgs);
 }
 
-bool stcToBuffer(ref OutBuffer buf, StorageClass stc) @safe
+bool stcToBuffer(ref OutBuffer buf, STC stc) @safe
 {
     //printf("stc: %llx\n", stc);
     bool result = false;
@@ -3349,11 +3363,11 @@  bool stcToBuffer(ref OutBuffer buf, StorageClass stc) @safe
  * and return a string representation of it.
  * stc is reduced by the one picked.
  */
-string stcToString(ref StorageClass stc) @safe
+string stcToString(ref STC stc) @safe
 {
     static struct SCstring
     {
-        StorageClass stc;
+        STC stc;
         string id;
     }
 
@@ -3396,7 +3410,7 @@  string stcToString(ref StorageClass stc) @safe
     ];
     foreach (ref entry; table)
     {
-        const StorageClass tbl = entry.stc;
+        const STC tbl = entry.stc;
         assert(tbl & STC.visibleStorageClasses);
         if (stc & tbl)
         {
@@ -3629,7 +3643,7 @@  private void parameterToBuffer(Parameter p, ref OutBuffer buf, ref HdrGenState h
     if (p.storageClass & STC.auto_)
         buf.writestring("auto ");
 
-    StorageClass stc = p.storageClass;
+    STC stc = p.storageClass;
     if (p.storageClass & STC.in_)
     {
         buf.writestring("in ");
diff --git a/gcc/d/dmd/import.h b/gcc/d/dmd/import.h
index bfbb5510134..dc41a005089 100644
--- a/gcc/d/dmd/import.h
+++ b/gcc/d/dmd/import.h
@@ -44,6 +44,5 @@  public:
     Dsymbol *toAlias() override;
     bool overloadInsert(Dsymbol *s) override;
 
-    Import *isImport() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d
index 490032066e0..753c70ac88b 100644
--- a/gcc/d/dmd/json.d
+++ b/gcc/d/dmd/json.d
@@ -333,7 +333,7 @@  public:
         }
     }
 
-    extern(D) void propertyStorageClass(const char[] name, StorageClass stc)
+    extern(D) void propertyStorageClass(const char[] name, STC stc)
     {
         stc &= STC.visibleStorageClasses;
         if (stc)
diff --git a/gcc/d/dmd/mangle/package.d b/gcc/d/dmd/mangle/package.d
index d184fe9f42c..de4d45f8849 100644
--- a/gcc/d/dmd/mangle/package.d
+++ b/gcc/d/dmd/mangle/package.d
@@ -451,7 +451,7 @@  void mangleParameter(Parameter p, ref OutBuffer buf, ref Backref backref)
 
     switch (stc & ((STC.IOR | STC.lazy_) & ~STC.constscoperef))
     {
-    case 0:
+    case STC.none:
         break;
     case STC.in_:
         buf.writeByte('I');
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index 82e1b4a341e..ec1a11b9c66 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -47,8 +47,6 @@  public:
 
     bool equals(const RootObject * const o) const override;
 
-    Package *isPackage() override final { return this; }
-
     bool isAncestorPackageOf(const Package * const pkg) const;
 
     void accept(Visitor *v) override { v->visit(this); }
@@ -158,7 +156,6 @@  public:
 
     void *ctfe_cov;             // stores coverage information from ctfe
 
-    Module *isModule() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 84899d003ca..b5276312a08 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -232,9 +232,9 @@  unittest
 /************************************
  * Convert MODxxxx to STCxxx
  */
-StorageClass ModToStc(uint mod) pure nothrow @nogc @safe
+STC ModToStc(uint mod) pure nothrow @nogc @safe
 {
-    StorageClass stc = 0;
+    STC stc = STC.none;
     if (mod & MODFlags.immutable_)
         stc |= STC.immutable_;
     if (mod & MODFlags.const_)
@@ -1108,7 +1108,7 @@  extern (C++) abstract class Type : ASTNode
      * Apply STCxxxx bits to existing type.
      * Use *before* semantic analysis is run.
      */
-    extern (D) final Type addSTC(StorageClass stc)
+    extern (D) final Type addSTC(STC stc)
     {
         Type t = this;
         if (t.isImmutable())
@@ -2488,6 +2488,7 @@  extern (C++) final class TypeFunction : TypeNext
         bool isInOutQual;      /// inout on the qualifier
         bool isCtor;           /// the function is a constructor
         bool isReturnScope;    /// `this` is returned by value
+        bool isRvalue;         /// returned reference should be treated as rvalue
     }
 
     import dmd.common.bitfields : generateBitFields;
@@ -2499,7 +2500,7 @@  extern (C++) final class TypeFunction : TypeNext
     byte inuse;
     ArgumentList inferenceArguments; // function arguments to determine `auto ref` in type semantic
 
-    extern (D) this(ParameterList pl, Type treturn, LINK linkage, StorageClass stc = 0) @safe
+    extern (D) this(ParameterList pl, Type treturn, LINK linkage, STC stc = STC.none) @safe
     {
         super(Tfunction, treturn);
         //if (!treturn) *(char*)0=0;
@@ -2531,6 +2532,8 @@  extern (C++) final class TypeFunction : TypeNext
             this.isScopeQual = true;
         if (stc & STC.scopeinferred)
             this.isScopeInferred = true;
+        if (stc & STC.rvalue)
+            this.isRvalue = true;
 
         this.trust = TRUST.default_;
         if (stc & STC.safe)
@@ -2541,9 +2544,9 @@  extern (C++) final class TypeFunction : TypeNext
             this.trust = TRUST.trusted;
     }
 
-    static TypeFunction create(Parameters* parameters, Type treturn, ubyte varargs, LINK linkage, StorageClass stc = 0) @safe
+    static TypeFunction create(Parameters* parameters, Type treturn, ubyte varargs, LINK linkage, StorageClass stc = STC.none) @safe
     {
-        return new TypeFunction(ParameterList(parameters, cast(VarArg)varargs), treturn, linkage, stc);
+        return new TypeFunction(ParameterList(parameters, cast(VarArg)varargs), treturn, linkage, cast(STC) stc);
     }
 
     override const(char)* kind() const
@@ -2567,6 +2570,7 @@  extern (C++) final class TypeFunction : TypeNext
         t.isScopeQual = isScopeQual;
         t.isReturnInferred = isReturnInferred;
         t.isScopeInferred = isScopeInferred;
+        t.isRvalue = isRvalue;
         t.isInOutParam = isInOutParam;
         t.isInOutQual = isInOutQual;
         t.trust = trust;
@@ -3548,7 +3552,7 @@  extern (C++) final class TypeTuple : Type
         {
             Expression e = (*exps)[i];
             assert(e.type.ty != Ttuple);
-            auto arg = new Parameter(e.loc, STC.undefined_, e.type, null, null, null);
+            auto arg = new Parameter(e.loc, STC.none, e.type, null, null, null);
             (*arguments)[i] = arg;
         }
         this.arguments = arguments;
@@ -3573,15 +3577,15 @@  extern (C++) final class TypeTuple : Type
     {
         super(Ttuple);
         arguments = new Parameters();
-        arguments.push(new Parameter(Loc.initial, 0, t1, null, null, null));
+        arguments.push(new Parameter(Loc.initial, STC.none, t1, null, null, null));
     }
 
     extern (D) this(Type t1, Type t2)
     {
         super(Ttuple);
         arguments = new Parameters();
-        arguments.push(new Parameter(Loc.initial, 0, t1, null, null, null));
-        arguments.push(new Parameter(Loc.initial, 0, t2, null, null, null));
+        arguments.push(new Parameter(Loc.initial, STC.none, t1, null, null, null));
+        arguments.push(new Parameter(Loc.initial, STC.none, t2, null, null, null));
     }
 
     static TypeTuple create() @safe
@@ -3806,11 +3810,11 @@  extern (C++) struct ParameterList
 {
     /// The raw (unexpanded) formal parameters, possibly containing tuples.
     Parameters* parameters;
-    StorageClass stc;                   // storage class of ...
+    STC stc;                   // storage class of ...
     VarArg varargs = VarArg.none;
     bool hasIdentifierList;             // true if C identifier-list style
 
-    this(Parameters* parameters, VarArg varargs = VarArg.none, StorageClass stc = 0) @safe
+    this(Parameters* parameters, VarArg varargs = VarArg.none, STC stc = STC.none) @safe
     {
         this.parameters = parameters;
         this.varargs = varargs;
@@ -3909,13 +3913,13 @@  extern (C++) final class Parameter : ASTNode
     import dmd.attrib : UserAttributeDeclaration;
 
     Loc loc;
-    StorageClass storageClass;
+    STC storageClass;
     Type type;
     Identifier ident;
     Expression defaultArg;
     UserAttributeDeclaration userAttribDecl; // user defined attributes
 
-    extern (D) this(Loc loc, StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe
+    extern (D) this(Loc loc, STC storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe
     {
         this.loc = loc;
         this.type = type;
@@ -3927,7 +3931,7 @@  extern (C++) final class Parameter : ASTNode
 
     static Parameter create(Loc loc, StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl) @safe
     {
-        return new Parameter(loc, storageClass, type, ident, defaultArg, userAttribDecl);
+        return new Parameter(loc, cast(STC) storageClass, type, ident, defaultArg, userAttribDecl);
     }
 
     Parameter syntaxCopy()
@@ -4139,21 +4143,21 @@  extern (C++) final class Parameter : ASTNode
     bool isCovariant(bool returnByRef, const Parameter p)
         const pure nothrow @nogc @safe
     {
-        ulong thisSTC = this.storageClass;
-        ulong otherSTC = p.storageClass;
+        STC thisSTC = this.storageClass;
+        STC otherSTC = p.storageClass;
 
         if (thisSTC & STC.constscoperef)
             thisSTC |= STC.scope_;
         if (otherSTC & STC.constscoperef)
             otherSTC |= STC.scope_;
 
-        const mask = STC.ref_ | STC.out_ | STC.lazy_ | (((thisSTC | otherSTC) & STC.constscoperef) ? STC.in_ : 0);
+        const mask = STC.ref_ | STC.out_ | STC.lazy_ | (((thisSTC | otherSTC) & STC.constscoperef) ? STC.in_ : STC.none);
         if ((thisSTC & mask) != (otherSTC & mask))
             return false;
         return isCovariantScope(returnByRef, thisSTC, otherSTC);
     }
 
-    extern (D) static bool isCovariantScope(bool returnByRef, StorageClass from, StorageClass to) pure nothrow @nogc @safe
+    extern (D) static bool isCovariantScope(bool returnByRef, STC from, STC to) pure nothrow @nogc @safe
     {
         // Workaround for failing covariance when finding a common type of delegates,
         // some of which have parameters with inferred scope
@@ -4340,21 +4344,21 @@  bool isIndexableNonAggregate(Type t)
 
 /***************************************
  * Computes how a parameter may be returned.
- * Shrinking the representation is necessary because StorageClass is so wide
+ * Shrinking the representation is necessary because STC is so wide
  * Params:
  *   stc = storage class of parameter
  * Returns:
  *   value from enum ScopeRef
  */
-ScopeRef buildScopeRef(StorageClass stc) pure nothrow @nogc @safe
+ScopeRef buildScopeRef(STC stc) pure nothrow @nogc @safe
 {
     if (stc & STC.out_)
         stc |= STC.ref_;        // treat `out` and `ref` the same
 
     ScopeRef result;
-    final switch (stc & (STC.ref_ | STC.scope_ | STC.return_))
+    switch (stc & (STC.ref_ | STC.scope_ | STC.return_))
     {
-        case 0:                        result = ScopeRef.None;        break;
+        case STC.none:           result = ScopeRef.None;        break;
 
         /* can occur in case test/compilable/testsctreturn.d
          * related to https://issues.dlang.org/show_bug.cgi?id=20149
@@ -4372,6 +4376,8 @@  ScopeRef buildScopeRef(StorageClass stc) pure nothrow @nogc @safe
             result = stc & STC.returnScope ? ScopeRef.Ref_ReturnScope
                                            : ScopeRef.ReturnRef_Scope;
             break;
+        default:
+            assert(0);
     }
     return result;
 }
diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index 1dd6a27d7b2..6515e9665c5 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -137,6 +137,8 @@  public:
 
     override void visit(NewExp e)
     {
+        if (e.placement)
+            return;     // placement new doesn't use the GC
         if (e.member && !e.member.isNogc() && f.setGC(e.loc, null))
         {
             // @nogc-ness is already checked in NewExp::semantic
diff --git a/gcc/d/dmd/nspace.d b/gcc/d/dmd/nspace.d
index 0014ec60559..35d7835ba49 100644
--- a/gcc/d/dmd/nspace.d
+++ b/gcc/d/dmd/nspace.d
@@ -66,6 +66,7 @@  extern (C++) final class Nspace : ScopeDsymbol
     {
         super(loc, ident);
         //printf("Nspace::Nspace(ident = %s)\n", ident.toChars());
+        this.dsym = DSYM.nspace;
         this.members = members;
         this.identExp = identExp;
     }
@@ -88,11 +89,6 @@  extern (C++) final class Nspace : ScopeDsymbol
         return "namespace";
     }
 
-    override inout(Nspace) isNspace() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/nspace.h b/gcc/d/dmd/nspace.h
index cbee2fb7914..db5c47f0708 100644
--- a/gcc/d/dmd/nspace.h
+++ b/gcc/d/dmd/nspace.h
@@ -23,6 +23,5 @@  class Nspace final : public ScopeDsymbol
     Nspace *syntaxCopy(Dsymbol *s) override;
     bool hasPointers() override;
     const char *kind() const override;
-    Nspace *isNspace() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
diff --git a/gcc/d/dmd/ob.d b/gcc/d/dmd/ob.d
index 5acc69faf31..39cb74c1c82 100644
--- a/gcc/d/dmd/ob.d
+++ b/gcc/d/dmd/ob.d
@@ -1723,6 +1723,8 @@  void genKill(ref ObState obstate, ObNode* ob)
 
             override void visit(NewExp e)
             {
+                if (e.placement)
+                    e.placement.accept(this);
                 if (e.arguments)
                 {
                     foreach (ex; *e.arguments)
@@ -2464,6 +2466,9 @@  void checkObErrors(ref ObState obstate)
 
             override void visit(NewExp e)
             {
+                if (e.placement)
+                    e.placement.accept(this);
+
                 if (e.arguments)
                 {
                     foreach (ex; *e.arguments)
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index b66ddcb005f..3510d3a54fa 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -751,6 +751,7 @@  Expression optimize(Expression e, int result, bool keepLvalue = false)
 
     void visitNew(NewExp e)
     {
+        expOptimize(e.placement, WANTvalue);
         expOptimize(e.thisexp, WANTvalue);
         // Optimize parameters
         if (e.arguments)
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 33e0e5a1131..2a92704dfbf 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -327,7 +327,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 pAttrs.comment = token.blockComment.ptr;
             }
             AST.Visibility.Kind prot;
-            StorageClass stc;
+            STC stc;
             AST.Condition condition;
 
             linkage = linksave;
@@ -536,7 +536,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     }
                     // Workaround 14894. Add an empty unittest declaration to keep
                     // the number of symbols in this scope independent of -unittest.
-                    s = new AST.UnitTestDeclaration(loc, token.loc, STC.undefined_, null);
+                    s = new AST.UnitTestDeclaration(loc, token.loc, STC.none, null);
                 }
                 break;
 
@@ -744,7 +744,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
 
                 a = parseBlock(pLastDecl, pAttrs);
                 auto stc2 = getStorageClass!AST(pAttrs);
-                if (stc2 != STC.undefined_)
+                if (stc2 != STC.none)
                 {
                     s = new AST.StorageClassDeclaration(scdLoc, stc2, a);
                 }
@@ -1101,7 +1101,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
      * Starts with token on the first ident.
      * Ends with scanner past closing ';'
      */
-    private AST.Dsymbols* parseAutoDeclarations(StorageClass storageClass, const(char)* comment)
+    private AST.Dsymbols* parseAutoDeclarations(STC storageClass, const(char)* comment)
     {
         //printf("parseAutoDeclarations\n");
         auto a = new AST.Dsymbols();
@@ -1216,9 +1216,9 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
      * Returns:
      *   The combination of both storage classes (`orig | added`).
      */
-    private StorageClass appendStorageClass(StorageClass orig, StorageClass added)
+    private STC appendStorageClass(STC orig, STC added)
     {
-        void checkConflictSTCGroup(bool at = false)(StorageClass group)
+        void checkConflictSTCGroup(bool at = false)(STC group)
         {
             if (added & group && orig & group & ((orig & group) - 1))
                 error(
@@ -1308,13 +1308,13 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
      *   If the attribute is builtin, the return value will be non-zero.
      *   Otherwise, 0 is returned, and `pudas` will be appended to.
      */
-    private StorageClass parseAttribute(ref AST.Expressions* udas)
+    private STC parseAttribute(ref AST.Expressions* udas)
     {
         nextToken();
         if (token.value == TOK.identifier)
         {
             // If we find a builtin attribute, we're done, return immediately.
-            if (StorageClass stc = isBuiltinAtAttribute(token.ident))
+            if (STC stc = isBuiltinAtAttribute(token.ident))
                 return stc;
 
             // Allow identifier, template instantiation, or function call
@@ -1332,7 +1332,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             if (udas is null)
                 udas = new AST.Expressions();
             udas.push(exp);
-            return 0;
+            return STC.none;
         }
 
         AST.Expression templateArgToExp(RootObject o, Loc loc)
@@ -1359,7 +1359,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             auto args = parseTemplateArgumentList();
             foreach (arg; *args)
                 udas.push(templateArgToExp(arg, token.loc));
-            return 0;
+            return STC.none;
         }
 
         if (auto o = parseTemplateSingleArgument())
@@ -1367,7 +1367,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             if (udas is null)
                 udas = new AST.Expressions();
             udas.push(templateArgToExp(o, token.loc));
-            return 0;
+            return STC.none;
         }
 
         if (token.isKeyword())
@@ -1375,17 +1375,17 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         else
             error("`@identifier` or `@(ArgumentList)` expected, not `@%s`", token.toChars());
 
-        return 0;
+        return STC.none;
     }
 
     /***********************************************
      * Parse const/immutable/shared/inout/nothrow/pure postfix
      */
-    private StorageClass parsePostfix(StorageClass storageClass, AST.Expressions** pudas)
+    private STC parsePostfix(STC storageClass, AST.Expressions** pudas)
     {
         while (1)
         {
-            StorageClass stc;
+            STC stc;
             switch (token.value)
             {
             case TOK.const_:
@@ -1422,6 +1422,10 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 stc = STC.scope_;
                 break;
 
+            case TOK.rvalue:
+                stc = STC.rvalue;
+                break;
+
             case TOK.at:
                 {
                     AST.Expressions* udas = null;
@@ -1458,16 +1462,16 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         }
     }
 
-    private StorageClass parseTypeCtor()
+    private STC parseTypeCtor()
     {
-        StorageClass storageClass = STC.undefined_;
+        STC storageClass = STC.none;
 
         while (1)
         {
             if (peekNext() == TOK.leftParenthesis)
                 return storageClass;
 
-            StorageClass stc;
+            STC stc;
             switch (token.value)
             {
             case TOK.const_:
@@ -2411,7 +2415,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     {
         AST.Expressions* udas = null;
         const loc = token.loc;
-        StorageClass stc = getStorageClass!AST(pAttrs);
+        STC stc = getStorageClass!AST(pAttrs);
 
         nextToken();
         if (token.value == TOK.leftParenthesis && peekNext() == TOK.this_ && peekNext2() == TOK.rightParenthesis)
@@ -2462,7 +2466,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             if (stc & STC.static_)
                 error(loc, "constructor cannot be static");
         }
-        else if (StorageClass ss = stc & (STC.shared_ | STC.static_)) // this()
+        else if (STC ss = stc & (STC.shared_ | STC.static_)) // this()
         {
             if (ss == STC.static_)
                 error(loc, "use `static this()` to declare a static constructor");
@@ -2504,7 +2508,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     {
         AST.Expressions* udas = null;
         const loc = token.loc;
-        StorageClass stc = getStorageClass!AST(pAttrs);
+        STC stc = getStorageClass!AST(pAttrs);
 
         nextToken();
         check(TOK.this_);
@@ -2512,7 +2516,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         check(TOK.rightParenthesis);
 
         stc = parsePostfix(stc, &udas);
-        if (StorageClass ss = stc & (STC.shared_ | STC.static_))
+        if (STC ss = stc & (STC.shared_ | STC.static_))
         {
             if (ss == STC.static_)
                 error(loc, "use `static ~this()` to declare a static destructor");
@@ -2540,7 +2544,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     {
         //Expressions *udas = NULL;
         const loc = token.loc;
-        StorageClass stc = getStorageClass!AST(pAttrs);
+        STC stc = getStorageClass!AST(pAttrs);
 
         nextToken();
         nextToken();
@@ -2552,7 +2556,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             error(loc, "use `shared static this()` to declare a shared static constructor");
         else if (stc & STC.static_)
             appendStorageClass(stc, STC.static_); // complaint for the redundancy
-        else if (StorageClass modStc = stc & STC.TYPECTOR)
+        else if (STC modStc = stc & STC.TYPECTOR)
         {
             OutBuffer buf;
             AST.stcToBuffer(buf, modStc);
@@ -2574,7 +2578,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     {
         AST.Expressions* udas = null;
         const loc = token.loc;
-        StorageClass stc = getStorageClass!AST(pAttrs);
+        STC stc = getStorageClass!AST(pAttrs);
 
         nextToken();
         nextToken();
@@ -2587,7 +2591,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             error(loc, "use `shared static ~this()` to declare a shared static destructor");
         else if (stc & STC.static_)
             appendStorageClass(stc, STC.static_); // complaint for the redundancy
-        else if (StorageClass modStc = stc & STC.TYPECTOR)
+        else if (STC modStc = stc & STC.TYPECTOR)
         {
             OutBuffer buf;
             AST.stcToBuffer(buf, modStc);
@@ -2615,7 +2619,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     {
         //Expressions *udas = NULL;
         const loc = token.loc;
-        StorageClass stc = getStorageClass!AST(pAttrs);
+        STC stc = getStorageClass!AST(pAttrs);
 
         nextToken();
         nextToken();
@@ -2624,9 +2628,9 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         check(TOK.rightParenthesis);
 
         stc = parsePostfix(stc & ~STC.TYPECTOR, null) | stc;
-        if (StorageClass ss = stc & (STC.shared_ | STC.static_))
+        if (STC ss = stc & (STC.shared_ | STC.static_))
             appendStorageClass(stc, ss); // complaint for the redundancy
-        else if (StorageClass modStc = stc & STC.TYPECTOR)
+        else if (STC modStc = stc & STC.TYPECTOR)
         {
             OutBuffer buf;
             AST.stcToBuffer(buf, modStc);
@@ -2648,7 +2652,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     {
         AST.Expressions* udas = null;
         const loc = token.loc;
-        StorageClass stc = getStorageClass!AST(pAttrs);
+        STC stc = getStorageClass!AST(pAttrs);
 
         nextToken();
         nextToken();
@@ -2658,9 +2662,9 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         check(TOK.rightParenthesis);
 
         stc = parsePostfix(stc & ~STC.TYPECTOR, &udas) | stc;
-        if (StorageClass ss = stc & (STC.shared_ | STC.static_))
+        if (STC ss = stc & (STC.shared_ | STC.static_))
             appendStorageClass(stc, ss); // complaint for the redundancy
-        else if (StorageClass modStc = stc & STC.TYPECTOR)
+        else if (STC modStc = stc & STC.TYPECTOR)
         {
             OutBuffer buf;
             AST.stcToBuffer(buf, modStc);
@@ -2689,7 +2693,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     private AST.Dsymbol parseInvariant(PrefixAttributes!AST* pAttrs)
     {
         const loc = token.loc;
-        StorageClass stc = getStorageClass!AST(pAttrs);
+        STC stc = getStorageClass!AST(pAttrs);
 
         nextToken();
         if (token.value == TOK.leftParenthesis) // optional () or invariant (expression);
@@ -2731,7 +2735,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     private AST.Dsymbol parseUnitTest(PrefixAttributes!AST* pAttrs)
     {
         const loc = token.loc;
-        StorageClass stc = getStorageClass!AST(pAttrs);
+        STC stc = getStorageClass!AST(pAttrs);
 
         nextToken();
 
@@ -2773,7 +2777,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     private AST.Dsymbol parseNewDeclaration(PrefixAttributes!AST* pAttrs)
     {
         const loc = token.loc;
-        StorageClass stc = getStorageClass!AST(pAttrs);
+        STC stc = getStorageClass!AST(pAttrs);
         if (!(stc & STC.disable))
         {
             error("`new` allocator must be annotated with `@disabled`");
@@ -2792,7 +2796,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     {
         auto parameters = new AST.Parameters();
         VarArg varargs = VarArg.none;
-        StorageClass varargsStc;
+        STC varargsStc;
 
         // Attributes allowed for ...
         enum VarArgsStc = STC.const_ | STC.immutable_ | STC.shared_ | STC.scope_ | STC.return_ | STC.returnScope;
@@ -2802,8 +2806,8 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         {
             Identifier ai = null;
             AST.Type at;
-            StorageClass storageClass = 0;
-            StorageClass stc;
+            STC storageClass = STC.none;
+            STC stc;
             AST.Expression ae;
             AST.Expressions* udas = null;
             for (; 1; nextToken())
@@ -2855,7 +2859,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 case TOK.at:
                     {
                         AST.Expressions* exps = null;
-                        StorageClass stc2 = parseAttribute(exps);
+                        STC stc2 = parseAttribute(exps);
                         if (stc2 & atAttrGroup)
                         {
                             error("`@%s` attribute for function parameter is not supported", token.toChars());
@@ -2961,7 +2965,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                         if (token.value == TOK.at)
                         {
                             AST.Expressions* exps = null;
-                            StorageClass stc2 = parseAttribute(exps);
+                            STC stc2 = parseAttribute(exps);
                             if (stc2 & atAttrGroup)
                             {
                                 error("`@%s` attribute for function parameter is not supported", token.toChars());
@@ -3059,7 +3063,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 Identifier ident = null;
 
                 AST.Expressions* udas;
-                StorageClass stc;
+                STC stc;
                 AST.Expression deprecationMessage;
                 enum attributeErrorMessage = "`%s` is not a valid attribute for enum members";
             Lattrs:
@@ -3068,7 +3072,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     switch (token.value)
                     {
                         case TOK.at:
-                            if (StorageClass _stc = parseAttribute(udas))
+                            if (STC _stc = parseAttribute(udas))
                             {
                                 if (_stc == STC.disable)
                                     stc |= _stc;
@@ -3499,7 +3503,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
          *        shared inout type
          *  shared inout const type
          */
-        StorageClass stc = 0;
+        STC stc = STC.none;
         while (1)
         {
             switch (token.value)
@@ -3983,7 +3987,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
 
                     auto parameterList = parseParameterList(null);
 
-                    StorageClass stc = parsePostfix(STC.undefined_, null);
+                    STC stc = parsePostfix(STC.none, null);
                     auto tf = new AST.TypeFunction(parameterList, t, linkage, stc);
                     if (stc & (STC.const_ | STC.immutable_ | STC.shared_ | STC.wild | STC.return_))
                     {
@@ -4019,7 +4023,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
      * Reference: https://dlang.org/spec/declaration.html#Declarator
      */
     private AST.Type parseDeclarator(AST.Type t, ref int palt, Identifier* pident,
-        AST.TemplateParameters** tpl = null, StorageClass storageClass = 0,
+        AST.TemplateParameters** tpl = null, STC storageClass = STC.none,
         bool* pdisable = null, AST.Expressions** pudas = null)
     {
         //printf("parseDeclarator(tpl = %p)\n", tpl);
@@ -4160,7 +4164,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     /* Parse const/immutable/shared/inout/nothrow/pure/return postfix
                      */
                     // merge prefix storage classes
-                    StorageClass stc = parsePostfix(storageClass, pudas);
+                    STC stc = parsePostfix(storageClass, pudas);
 
                     AST.Type tf = new AST.TypeFunction(parameterList, t, linkage, stc);
                     tf = tf.addSTC(stc);
@@ -4187,11 +4191,11 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         return ts;
     }
 
-    private void parseStorageClasses(ref StorageClass storage_class, ref LINK link,
+    private void parseStorageClasses(ref STC storage_class, ref LINK link,
         ref bool setAlignment, ref AST.Expression ealign, ref AST.Expressions* udas,
         out Loc linkloc)
     {
-        StorageClass stc;
+        STC stc;
         bool sawLinkage = false; // seen a linkage declaration
 
         linkloc = Loc.initial;
@@ -4369,7 +4373,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
      */
     private AST.Dsymbols* parseDeclarations(bool autodecl, PrefixAttributes!AST* pAttrs, const(char)* comment)
     {
-        StorageClass storage_class = STC.undefined_;
+        STC storage_class = STC.none;
         LINK link = linkage;
         Loc linkloc = this.linkLoc;
         bool setAlignment = false;
@@ -4500,7 +4504,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         if (pAttrs)
         {
             storage_class |= pAttrs.storageClass;
-            //pAttrs.storageClass = STC.undefined_;
+            //pAttrs.storageClass = STC.none;
         }
 
         AST.Type tfirst = null;
@@ -4606,9 +4610,9 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
 
                 AST.Expression constraint = null;
                 //printf("%s funcdecl t = %s, storage_class = x%lx\n", loc.toChars(), t.toChars(), storage_class);
-                auto f = new AST.FuncDeclaration(loc, Loc.initial, ident, storage_class | (disable ? STC.disable : 0), t);
+                auto f = new AST.FuncDeclaration(loc, Loc.initial, ident, storage_class | (disable ? STC.disable : STC.none), t);
                 if (pAttrs)
-                    pAttrs.storageClass = STC.undefined_;
+                    pAttrs.storageClass = STC.none;
                 if (tpl)
                     constraint = parseConstraint();
                 AST.Dsymbol s = parseContracts(f, !!tpl);
@@ -4644,7 +4648,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     auto tempdecl = new AST.TemplateDeclaration(loc, tplIdent, tpl, constraint, decldefs);
                     s = tempdecl;
 
-                    StorageClass stc2 = STC.undefined_;
+                    STC stc2 = STC.none;
                     if (storage_class & STC.static_)
                     {
                         assert(f.storage_class & STC.static_);
@@ -4657,7 +4661,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                         f.storage_class &= ~STC.deprecated_;
                         stc2 |= STC.deprecated_;
                     }
-                    if (stc2 != STC.undefined_)
+                    if (stc2 != STC.none)
                     {
                         auto ax = new AST.Dsymbols();
                         ax.push(s);
@@ -4697,7 +4701,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     auto v = new AST.VarDeclaration(loc, t, ident, _init);
                     v.storage_class = storage_class;
                     if (pAttrs)
-                        pAttrs.storageClass = STC.undefined_;
+                        pAttrs.storageClass = STC.none;
                     s = v;
                 }
 
@@ -4812,7 +4816,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         Loc linkloc = this.linkLoc;
         AST.Expressions* udas;
         LINK link = linkage;
-        StorageClass storage_class = STC.undefined_;
+        STC storage_class = STC.none;
         AST.Expression ealign;
         bool setAlignment = false;
 
@@ -4870,7 +4874,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                         return;
                     hasParsedAttributes = true;
                     udas = null;
-                    storage_class = STC.undefined_;
+                    storage_class = STC.none;
                     link = linkage;
                     linkloc = this.linkLoc;
                     setAlignment = false;
@@ -4885,7 +4889,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 AST.Dsymbol s;
 
                 bool attributesAppended;
-                const StorageClass funcStc = parseTypeCtor();
+                const STC funcStc = parseTypeCtor();
                 Token* tk;
                 // function literal?
                 if (token.value == TOK.function_ ||
@@ -5058,7 +5062,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         AST.TemplateParameters* tpl = null;
         AST.ParameterList parameterList;
         AST.Type tret = null;
-        StorageClass stc = 0;
+        STC stc = STC.none;
         TOK save = TOK.reserved;
 
         switch (token.value)
@@ -5137,7 +5141,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 // (parameters) { statements... }
                 parameterList = parseParameterList(&tpl);
                 stc = parsePostfix(stc, null);
-                if (StorageClass modStc = stc & STC.TYPECTOR)
+                if (STC modStc = stc & STC.TYPECTOR)
                 {
                     if (save == TOK.function_)
                     {
@@ -5485,8 +5489,8 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             AST.Type at;
             Loc aloc;
 
-            StorageClass storageClass = 0;
-            StorageClass stc = 0;
+            STC storageClass = STC.none;
+            STC stc = STC.none;
         Lagain:
             if (stc)
             {
@@ -5663,8 +5667,8 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     AST.Parameter parseAssignCondition()
     {
         AST.Parameter param = null;
-        StorageClass storageClass = 0;
-        StorageClass stc = 0;
+        STC storageClass = STC.none;
+        STC stc = STC.none;
     Lwhile:
         while (1)
         {
@@ -7005,7 +7009,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         Loc labelloc;
 
         nextToken();
-        StorageClass stc = parsePostfix(STC.undefined_, null);  // optional FunctionAttributes
+        STC stc = parsePostfix(STC.none, null);  // optional FunctionAttributes
         if (stc & (STC.const_ | STC.immutable_ | STC.shared_ | STC.wild))
             error("`const`/`immutable`/`shared`/`inout` attributes are not allowed on `asm` blocks");
 
@@ -8773,7 +8777,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         case TOK.const_:
         case TOK.immutable_: // immutable(type)(arguments) / immutable(type).init
             {
-                StorageClass stc = parseTypeCtor();
+                STC stc = parseTypeCtor();
 
                 AST.Type t = parseBasicType();
                 t = t.addSTC(stc);
@@ -9502,7 +9506,17 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     {
         const loc = token.loc;
 
-        nextToken();
+        nextToken();     // skip past `new`
+
+        // parse PlacementExpression if any
+        AST.Expression placement;
+        if (token.value == TOK.leftParenthesis)
+        {
+            nextToken();
+            placement = parseAssignExp();
+            check(TOK.rightParenthesis);
+        }
+
         AST.Expressions* arguments = null;
         AST.Identifiers* names = null;
 
@@ -9538,7 +9552,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             }
 
             auto cd = new AST.ClassDeclaration(loc, id, baseclasses, members, false);
-            auto e = new AST.NewAnonClassExp(loc, thisexp, cd, arguments);
+            auto e = new AST.NewAnonClassExp(loc, placement, thisexp, cd, arguments);
             return e;
         }
 
@@ -9562,7 +9576,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             parseNamedArguments(arguments, names);
         }
 
-        auto e = new AST.NewExp(loc, thisexp, t, arguments, names);
+        auto e = new AST.NewExp(loc, placement, thisexp, t, arguments, names);
         return e;
     }
 
@@ -9590,7 +9604,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
      * Returns:
      *  storage class for attribute, 0 if not
      */
-    static StorageClass isBuiltinAtAttribute(Identifier ident)
+    static STC isBuiltinAtAttribute(Identifier ident)
     {
         return (ident == Id.property) ? STC.property :
                (ident == Id.nogc)     ? STC.nogc     :
@@ -9600,10 +9614,10 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                (ident == Id.live)     ? STC.live     :
                (ident == Id.future)   ? STC.future   :
                (ident == Id.disable)  ? STC.disable  :
-               0;
+               STC.none;
     }
 
-    enum StorageClass atAttrGroup =
+    enum STC atAttrGroup =
                 STC.property |
                 STC.nogc     |
                 STC.safe     |
@@ -9800,7 +9814,7 @@  enum ParseStatementFlags : int
 
 struct PrefixAttributes(AST)
 {
-    StorageClass storageClass;
+    STC storageClass;
     AST.Expression depmsg;
     LINK link;
     AST.Visibility visibility;
@@ -9852,13 +9866,13 @@  private enum CARRAYDECL = 1;
 /*****************************
  * Destructively extract storage class from pAttrs.
  */
-private StorageClass getStorageClass(AST)(PrefixAttributes!(AST)* pAttrs)
+private STC getStorageClass(AST)(PrefixAttributes!(AST)* pAttrs)
 {
-    StorageClass stc = STC.undefined_;
+    STC stc = STC.none;
     if (pAttrs)
     {
         stc = pAttrs.storageClass;
-        pAttrs.storageClass = STC.undefined_;
+        pAttrs.storageClass = STC.none;
     }
     return stc;
 }
diff --git a/gcc/d/dmd/pragmasem.d b/gcc/d/dmd/pragmasem.d
index c5d18ef40a5..a7299a0e9b7 100644
--- a/gcc/d/dmd/pragmasem.d
+++ b/gcc/d/dmd/pragmasem.d
@@ -567,7 +567,7 @@  private bool pragmaMsgSemantic(Loc loc, Scope* sc, Expressions* args)
         return false;
 
     buf.writestring("\n");
-    fprintf(stderr, buf.extractChars);
+    fprintf(stderr, "%s", buf.extractChars);
     return true;
 }
 
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index f7a7ce150b3..b9ac0c699f4 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -478,7 +478,7 @@  private extern(C++) final class Semantic3Visitor : Visitor
                 foreach (i, fparam; f.parameterList)
                 {
                     Identifier id = fparam.ident;
-                    StorageClass stc = 0;
+                    STC stc = STC.none;
                     if (!id)
                     {
                         /* Generate identifier for un-named parameter,
@@ -1349,7 +1349,7 @@  private extern(C++) final class Semantic3Visitor : Visitor
             sc = sc.push();
             if (funcdecl.isCtorDeclaration()) // https://issues.dlang.org/show_bug.cgi?id=#15665
                 f.isCtor = true;
-            sc.stc = 0;
+            sc.stc = STC.none;
             sc.linkage = funcdecl._linkage; // https://issues.dlang.org/show_bug.cgi?id=8496
             funcdecl.type = f.typeSemantic(funcdecl.loc, sc);
             sc = sc.pop();
@@ -1489,9 +1489,9 @@  private extern(C++) final class Semantic3Visitor : Visitor
                 // storage_class is apparently not set for dtor & ctor
                 OutBuffer ob;
                 stcToBuffer(ob,
-                    (ngErr ? STC.nogc : 0) |
-                    (puErr ? STC.pure_ : 0) |
-                    (saErr ? STC.system : 0)
+                    (ngErr ? STC.nogc : STC.none) |
+                    (puErr ? STC.pure_ : STC.none) |
+                    (saErr ? STC.system : STC.none)
                 );
                 ctor.loc.error("`%s` has stricter attributes than its destructor (`%s`)", ctor.toPrettyChars(), ob.peekChars());
                 ctor.loc.errorSupplemental("The destructor will be called if an exception is thrown");
diff --git a/gcc/d/dmd/sideeffect.d b/gcc/d/dmd/sideeffect.d
index 659b0f4e0a5..c8c0c783e9c 100644
--- a/gcc/d/dmd/sideeffect.d
+++ b/gcc/d/dmd/sideeffect.d
@@ -374,7 +374,7 @@  bool discardValue(Expression e)
  * Returns:
  *  Newly created temporary variable.
  */
-VarDeclaration copyToTemp(StorageClass stc, const char[] name, Expression e)
+VarDeclaration copyToTemp(STC stc, const char[] name, Expression e)
 {
     assert(name[0] == '_' && name[1] == '_');
     auto vd = new VarDeclaration(e.loc, e.type,
@@ -413,7 +413,7 @@  Expression extractSideEffect(Scope* sc, const char[] name,
         (sc.ctfe ? !hasSideEffect(e) : isTrivialExp(e)))
         return e;
 
-    auto vd = copyToTemp(0, name, e);
+    auto vd = copyToTemp(STC.none, name, e);
     vd.storage_class |= e.isLvalue() ? STC.ref_ : STC.rvalue;
 
     e0 = Expression.combine(e0, new DeclarationExp(vd.loc, vd)
diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d
index 3b5f5f88526..1d63946bb5e 100644
--- a/gcc/d/dmd/statement.d
+++ b/gcc/d/dmd/statement.d
@@ -1715,7 +1715,7 @@  extern (C++) final class LabelDsymbol : Dsymbol
 
     extern (D) this(Identifier ident, Loc loc = Loc.initial) @safe
     {
-        super(loc, ident);
+        super(DSYM.labelDsymbol, loc, ident);
     }
 
     static LabelDsymbol create(Identifier ident) @safe
@@ -1799,7 +1799,7 @@  extern (C++) final class InlineAsmStatement : AsmStatement
  */
 extern (C++) final class GccAsmStatement : AsmStatement
 {
-    StorageClass stc;           // attributes of the asm {} block
+    STC stc;           // attributes of the asm {} block
     Expression insn;            // string expression that is the template for assembler code
     Expressions* args;          // input and output operands of the statement
     uint outputargs;            // of the operands in 'args', the number of output operands
@@ -1830,9 +1830,9 @@  extern (C++) final class GccAsmStatement : AsmStatement
  */
 extern (C++) final class CompoundAsmStatement : CompoundStatement
 {
-    StorageClass stc; // postfix attributes like nothrow/pure/@trusted
+    STC stc; // postfix attributes like nothrow/pure/@trusted
 
-    extern (D) this(Loc loc, Statements* statements, StorageClass stc) @safe
+    extern (D) this(Loc loc, Statements* statements, STC stc) @safe
     {
         super(loc, statements, STMT.CompoundAsm);
         this.stc = stc;
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 4029fdac38a..d19052b504c 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -135,7 +135,16 @@  private Expression checkAssignmentAsCondition(Expression e, Scope* sc)
     return e;
 }
 
-// Performs semantic analysis in Statement AST nodes
+/**
+ * Performs semantic analysis in Statement AST nodes
+ *
+ * Params:
+ *   s = statement to perform semantic analysis on
+ *   sc = scope in which statement resides
+ *
+ * Returns: statement `s` after semantic analysis.
+ * Can be `null`, for example with `pragma(msg, "")`
+ */
 Statement statementSemantic(Statement s, Scope* sc)
 {
     import dmd.compiler;
@@ -1291,7 +1300,7 @@  Statement statementSemanticVisit(Statement s, Scope* sc)
                 }
                 else
                 {
-                    r = copyToTemp(0, "__r", fs.aggr);
+                    r = copyToTemp(STC.none, "__r", fs.aggr);
                     r.dsymbolSemantic(sc);
                     _init = new ExpStatement(loc, r);
                     if (vinit)
@@ -3074,14 +3083,14 @@  Statement statementSemanticVisit(Statement s, Scope* sc)
                  *  _d_monitorenter(tmp);
                  *  try { body } finally { _d_monitorexit(tmp); }
                  */
-                auto tmp = copyToTemp(0, "__sync", ss.exp);
+                auto tmp = copyToTemp(STC.none, "__sync", ss.exp);
                 tmp.dsymbolSemantic(sc);
 
                 auto cs = new Statements();
                 cs.push(new ExpStatement(ss.loc, tmp));
 
                 auto args = new Parameters();
-                args.push(new Parameter(Loc.initial, 0, ClassDeclaration.object.type, null, null, null));
+                args.push(new Parameter(Loc.initial, STC.none, ClassDeclaration.object.type, null, null, null));
 
                 FuncDeclaration fdenter = FuncDeclaration.genCfunc(args, Type.tvoid, Id.monitorenter);
                 Expression e = new CallExp(ss.loc, fdenter, new VarExp(ss.loc, tmp));
@@ -3123,7 +3132,7 @@  Statement statementSemanticVisit(Statement s, Scope* sc)
             cs.push(new ExpStatement(ss.loc, v));
 
             auto enterArgs = new Parameters();
-            enterArgs.push(new Parameter(Loc.initial, 0, t.pointerTo(), null, null, null));
+            enterArgs.push(new Parameter(Loc.initial, STC.none, t.pointerTo(), null, null, null));
 
             FuncDeclaration fdenter = FuncDeclaration.genCfunc(enterArgs, Type.tvoid, Id.criticalenter, STC.nothrow_);
             Expression e = new AddrExp(ss.loc, tmpExp);
@@ -3133,7 +3142,7 @@  Statement statementSemanticVisit(Statement s, Scope* sc)
             cs.push(new ExpStatement(ss.loc, e));
 
             auto exitArgs = new Parameters();
-            exitArgs.push(new Parameter(Loc.initial, 0, t, null, null, null));
+            exitArgs.push(new Parameter(Loc.initial, STC.none, t, null, null, null));
 
             FuncDeclaration fdexit = FuncDeclaration.genCfunc(exitArgs, Type.tvoid, Id.criticalexit, STC.nothrow_);
             e = new CallExp(ss.loc, fdexit, tmpExp);
@@ -3220,7 +3229,7 @@  Statement statementSemanticVisit(Statement s, Scope* sc)
                      *   }
                      * }
                      */
-                    auto tmp = copyToTemp(0, "__withtmp", ws.exp);
+                    auto tmp = copyToTemp(STC.none, "__withtmp", ws.exp);
                     tmp.dsymbolSemantic(sc);
                     auto es = new ExpStatement(ws.loc, tmp);
                     ws.exp = new VarExp(ws.loc, tmp);
@@ -3488,6 +3497,7 @@  Statement statementSemanticVisit(Statement s, Scope* sc)
             sc = sc.push();
             sc.debug_ = true;
             ds.statement = ds.statement.statementSemantic(sc);
+            debugThrowWalker(ds.statement);
             sc.pop();
         }
         result = ds.statement;
@@ -3847,11 +3857,11 @@  private extern(D) Expression applyArray(ForeachStatement fs, Expression flde,
     auto params = new Parameters();
     params.push(new Parameter(Loc.initial, STC.in_, tn.arrayOf(), null, null, null));
     auto dgparams = new Parameters();
-    dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null));
+    dgparams.push(new Parameter(Loc.initial, STC.none, Type.tvoidptr, null, null, null));
     if (dim == 2)
-        dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null));
+        dgparams.push(new Parameter(Loc.initial, STC.none, Type.tvoidptr, null, null, null));
     dgty = new TypeDelegate(new TypeFunction(ParameterList(dgparams), Type.tint32, LINK.d));
-    params.push(new Parameter(Loc.initial, 0, dgty, null, null, null));
+    params.push(new Parameter(Loc.initial, STC.none, dgty, null, null, null));
     fdapply = FuncDeclaration.genCfunc(params, Type.tint32, fdname.ptr);
 
     if (tab.isTypeSArray())
@@ -3912,14 +3922,14 @@  private extern(D) Expression applyAssocArray(ForeachStatement fs, Expression fld
     if (!fdapply[i])
     {
         auto params = new Parameters();
-        params.push(new Parameter(Loc.initial, 0, Type.tvoid.pointerTo(), null, null, null));
+        params.push(new Parameter(Loc.initial, STC.none, Type.tvoid.pointerTo(), null, null, null));
         params.push(new Parameter(Loc.initial, STC.const_, Type.tsize_t, null, null, null));
         auto dgparams = new Parameters();
-        dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null));
+        dgparams.push(new Parameter(Loc.initial, STC.none, Type.tvoidptr, null, null, null));
         if (dim == 2)
-            dgparams.push(new Parameter(Loc.initial, 0, Type.tvoidptr, null, null, null));
+            dgparams.push(new Parameter(Loc.initial, STC.none, Type.tvoidptr, null, null, null));
         fldeTy[i] = new TypeDelegate(new TypeFunction(ParameterList(dgparams), Type.tint32, LINK.d));
-        params.push(new Parameter(Loc.initial, 0, fldeTy[i], null, null, null));
+        params.push(new Parameter(Loc.initial, STC.none, fldeTy[i], null, null, null));
         fdapply[i] = FuncDeclaration.genCfunc(params, Type.tint32, i ? Id._aaApply2 : Id._aaApply);
     }
 
@@ -3990,7 +4000,7 @@  private FuncExp foreachBodyToFunction(Scope* sc, ForeachStatement fs, TypeFuncti
     auto params = new Parameters();
     foreach (i, p; *fs.parameters)
     {
-        StorageClass stc = STC.ref_ | (p.storageClass & STC.scope_);
+        STC stc = STC.ref_ | (p.storageClass & STC.scope_);
         Identifier id;
 
         p.type = p.type.typeSemantic(fs.loc, sc);
@@ -4034,7 +4044,7 @@  private FuncExp foreachBodyToFunction(Scope* sc, ForeachStatement fs, TypeFuncti
     }
     // https://issues.dlang.org/show_bug.cgi?id=13840
     // Throwable nested function inside nothrow function is acceptable.
-    StorageClass stc = mergeFuncAttrs(STC.safe | STC.pure_ | STC.nogc, fs.func);
+    STC stc = mergeFuncAttrs(STC.safe | STC.pure_ | STC.nogc, fs.func);
     auto tf = new TypeFunction(ParameterList(params), Type.tint32, LINK.d, stc);
     fs.cases = new Statements();
     fs.gotos = new ScopeStatements();
@@ -4099,7 +4109,7 @@  void catchSemantic(Catch c, Scope* sc)
         return;
     }
 
-    StorageClass stc;
+    STC stc;
     auto cd = c.type.toBasetype().isClassHandle();
     if (!cd)
     {
@@ -4256,7 +4266,7 @@  Statement scopeCode(Statement statement, Scope* sc, out Statement sentry, out St
                  *  sexception:    x = true;
                  *  sfinally: if (!x) statement;
                  */
-                auto v = copyToTemp(0, "__os", IntegerExp.createBool(false));
+                auto v = copyToTemp(STC.none, "__os", IntegerExp.createBool(false));
                 v.dsymbolSemantic(sc);
                 sentry = new ExpStatement(statement.loc, v);
 
@@ -4449,7 +4459,7 @@  public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
          * Returns:
          *     `true` iff the declaration was successful.
          */
-        bool declareVariable(StorageClass storageClass, Type type, Identifier ident, Expression e, Type t)
+        bool declareVariable(STC storageClass, Type type, Identifier ident, Expression e, Type t)
         {
             if (storageClass & (STC.out_ | STC.lazy_) ||
                 storageClass & STC.ref_ && !te)
@@ -4590,7 +4600,7 @@  public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
             {   // expand tuples into multiple `static foreach` variables.
                 assert(e && !t);
                 auto ident = Identifier.generateId("__value");
-                declareVariable(0, e.type, ident, e, null);
+                declareVariable(STC.none, e.type, ident, e, null);
                 import dmd.cond: StaticForeach;
                 auto field = Identifier.idPool(StaticForeach.tupleFieldName.ptr,StaticForeach.tupleFieldName.length);
                 Expression access = new DotIdExp(loc, e, field);
@@ -4760,7 +4770,6 @@  private Statements* flatten(Statement statement, Scope* sc)
                 if (dc)
                 {
                     s = new DebugStatement(cs.loc, cs.ifbody);
-                    debugThrowWalker(cs.ifbody);
                 }
                 else
                     s = cs.ifbody;
@@ -4932,7 +4941,8 @@  Params:
 */
 private void debugThrowWalker(Statement s)
 {
-
+    if (!s)
+        return;
     extern(C++) final class DebugWalker : SemanticTimeTransitiveVisitor
     {
         alias visit = SemanticTimeTransitiveVisitor.visit;
diff --git a/gcc/d/dmd/staticassert.d b/gcc/d/dmd/staticassert.d
index 3d73ae836d5..0e959bc84af 100644
--- a/gcc/d/dmd/staticassert.d
+++ b/gcc/d/dmd/staticassert.d
@@ -30,7 +30,7 @@  extern (C++) final class StaticAssert : Dsymbol
 
     extern (D) this(Loc loc, Expression exp, Expression msg)
     {
-        super(loc, Id.empty);
+        super(DSYM.staticAssert, loc, Id.empty);
         this.exp = exp;
         this.msgs = new Expressions(1);
         (*this.msgs)[0] = msg;
@@ -38,7 +38,7 @@  extern (C++) final class StaticAssert : Dsymbol
 
     extern (D) this(Loc loc, Expression exp, Expressions* msgs)
     {
-        super(loc, Id.empty);
+        super(DSYM.staticAssert, loc, Id.empty);
         this.exp = exp;
         this.msgs = msgs;
     }
@@ -49,23 +49,11 @@  extern (C++) final class StaticAssert : Dsymbol
         return new StaticAssert(loc, exp.syntaxCopy(), msgs ? Expression.arraySyntaxCopy(msgs) : null);
     }
 
-    override bool oneMember(out Dsymbol ps, Identifier ident)
-    {
-        //printf("StaticAssert::oneMember())\n");
-        ps = null;
-        return true;
-    }
-
     override const(char)* kind() const
     {
         return "static assert";
     }
 
-    override inout(StaticAssert) isStaticAssert() inout
-    {
-        return this;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
diff --git a/gcc/d/dmd/staticassert.h b/gcc/d/dmd/staticassert.h
index ed76de07012..9a10dee9692 100644
--- a/gcc/d/dmd/staticassert.h
+++ b/gcc/d/dmd/staticassert.h
@@ -21,8 +21,6 @@  public:
     Expressions *msg;
 
     StaticAssert *syntaxCopy(Dsymbol *s) override;
-    bool oneMember(Dsymbol *&ps, Identifier *ident) override;
     const char *kind() const override;
-    StaticAssert *isStaticAssert() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index 5bb0de50063..e98a1d6a619 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -77,12 +77,10 @@  public:
 
     TemplateDeclaration *syntaxCopy(Dsymbol *) override;
     bool overloadInsert(Dsymbol *s) override;
-    bool hasStaticCtorOrDtor() override;
     const char *kind() const override;
 
     Visibility visible() override;
 
-    TemplateDeclaration *isTemplateDeclaration() override { return this; }
 
     bool isDeprecated() const override;
     bool isOverloadable() const override;
@@ -270,14 +268,12 @@  public:
     TemplateInstance *syntaxCopy(Dsymbol *) override;
     Dsymbol *toAlias() override final;   // resolve real symbol
     const char *kind() const override;
-    bool oneMember(Dsymbol *&ps, Identifier *ident) override;
     const char* toPrettyCharsHelper() override final;
     Identifier *getIdent() override final;
 
     bool isDiscardable();
     bool needsCodegen();
 
-    TemplateInstance *isTemplateInstance() override final { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -288,10 +284,8 @@  public:
 
     TemplateMixin *syntaxCopy(Dsymbol *s) override;
     const char *kind() const override;
-    bool oneMember(Dsymbol *&ps, Identifier *ident) override;
     bool hasPointers() override;
 
-    TemplateMixin *isTemplateMixin() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
 };
 
diff --git a/gcc/d/dmd/templatesem.d b/gcc/d/dmd/templatesem.d
index 48c4297b6b4..e514456225c 100644
--- a/gcc/d/dmd/templatesem.d
+++ b/gcc/d/dmd/templatesem.d
@@ -120,7 +120,7 @@  void templateDeclarationSemantic(Scope* sc, TemplateDeclaration tempdecl)
     auto paramsym = new ScopeDsymbol();
     paramsym.parent = tempdecl.parent;
     Scope* paramscope = sc.push(paramsym);
-    paramscope.stc = 0;
+    paramscope.stc = STC.none;
 
     if (global.params.ddoc.doOutput)
     {
@@ -603,7 +603,7 @@  Scope* createScopeForTemplateParameters(TemplateDeclaration td, TemplateInstance
     paramscope.tinst = ti;
     paramscope.minst = sc.minst;
     paramscope.callsc = sc;
-    paramscope.stc = 0;
+    paramscope.stc = STC.none;
     return paramscope;
 }
 
@@ -905,7 +905,7 @@  extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat
         // Match attributes of tthis against attributes of fd
         if (fd.type && !fd.isCtorDeclaration() && !(td._scope.stc & STC.static_))
         {
-            StorageClass stc = td._scope.stc | fd.storage_class2;
+            STC stc = td._scope.stc | fd.storage_class2;
             // Propagate parent storage class, https://issues.dlang.org/show_bug.cgi?id=5504
             Dsymbol p = td.parent;
             while (p.isTemplateDeclaration() || p.isTemplateInstance())
@@ -2491,7 +2491,7 @@  private extern(C++) class DummyArgVisitor : Visitor
             return;
         }
         if (!tap.sdummy)
-            tap.sdummy = new Dsymbol();
+            tap.sdummy = new Dsymbol(DSYM.dsymbol);
         result = tap.sdummy;
     }
 
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 42344c68fd0..dedfeb77a2f 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -1523,7 +1523,7 @@  Expression semanticTraits(TraitsExp e, Scope* sc)
         if (!fparams.parameters)
             return ErrorExp.get();
 
-        StorageClass stc;
+        STC stc;
 
         // Set stc to storage class of the ith parameter
         auto ex = isExpression((*e.args)[1]);
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 7f87ac4d731..d382101192d 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -2348,7 +2348,7 @@  Type typeSemantic(Type type, Loc loc, Scope* sc)
             /* Create a scope for evaluating the default arguments for the parameters
              */
             Scope* argsc = sc.push();
-            argsc.stc = 0; // don't inherit storage class
+            argsc.stc = STC.none; // don't inherit storage class
             argsc.visibility = Visibility(Visibility.Kind.public_);
             argsc.func = null;
 
@@ -2404,12 +2404,12 @@  Type typeSemantic(Type type, Loc loc, Scope* sc)
                             // https://issues.dlang.org/show_bug.cgi?id=12744
                             // If the storage classes of narg
                             // conflict with the ones in fparam, it's ignored.
-                            StorageClass stc  = fparam.storageClass | narg.storageClass;
-                            StorageClass stc1 = fparam.storageClass & (STC.ref_ | STC.out_ | STC.lazy_);
-                            StorageClass stc2 =   narg.storageClass & (STC.ref_ | STC.out_ | STC.lazy_);
+                            STC stc  = fparam.storageClass | narg.storageClass;
+                            STC stc1 = fparam.storageClass & (STC.ref_ | STC.out_ | STC.lazy_);
+                            STC stc2 =   narg.storageClass & (STC.ref_ | STC.out_ | STC.lazy_);
                             if (stc1 && stc2 && stc1 != stc2)
                             {
-                                OutBuffer buf1;  stcToBuffer(buf1, stc1 | ((stc1 & STC.ref_) ? (fparam.storageClass & STC.auto_) : 0));
+                                OutBuffer buf1;  stcToBuffer(buf1, stc1 | ((stc1 & STC.ref_) ? (fparam.storageClass & STC.auto_) : STC.none));
                                 OutBuffer buf2;  stcToBuffer(buf2, stc2);
 
                                 .error(loc, "incompatible parameter storage classes `%s` and `%s`",
@@ -2985,8 +2985,14 @@  Type typeSemantic(Type type, Loc loc, Scope* sc)
     Type visitTag(TypeTag mtype)
     {
         //printf("TypeTag.semantic() %s\n", mtype.toChars());
-        Type returnType(Type t)
-        {
+        Type returnType(TypeTag tt)
+        {
+            Type t = tt.resolved;
+            // To make const checking work, the const STC needs to be added:
+            // t = t.resolved.addSTC(mtype.mod.ModToStc);
+            // However, this currently fails compilable/test22875.i
+            // Apparently there's some aliasing going on, where mutable
+            // versions of the type also get const applied to them.
             return t.deco ? t : t.merge();
         }
 
@@ -2994,7 +3000,7 @@  Type typeSemantic(Type type, Loc loc, Scope* sc)
         {
             /* struct S s, *p;
              */
-            return returnType(mtype.resolved.addSTC(mtype.mod));
+            return returnType(mtype);
         }
 
         /* Find the current scope by skipping tag scopes.
@@ -3067,7 +3073,7 @@  Type typeSemantic(Type type, Loc loc, Scope* sc)
         {
             mtype.id = Identifier.generateId("__tag"[]);
             declareTag();
-            return returnType(mtype.resolved.addSTC(mtype.mod));
+            return returnType(mtype);
         }
 
         /* look for pre-existing declaration
@@ -3080,7 +3086,7 @@  Type typeSemantic(Type type, Loc loc, Scope* sc)
             if (mtype.tok == TOK.enum_ && !mtype.members)
                 .error(mtype.loc, "`enum %s` is incomplete without members", mtype.id.toChars()); // C11 6.7.2.3-3
             declareTag();
-            return returnType(mtype.resolved.addSTC(mtype.mod));
+            return returnType(mtype);
         }
 
         /* A redeclaration only happens if both declarations are in
@@ -3180,7 +3186,7 @@  Type typeSemantic(Type type, Loc loc, Scope* sc)
                 declareTag();
             }
         }
-        return returnType(mtype.resolved.addSTC(mtype.mod));
+        return returnType(mtype);
     }
 
     switch (type.ty)
@@ -6182,7 +6188,7 @@  Dsymbol toDsymbol(Type type, Scope* sc)
 /************************************
  * Add storage class modifiers to type.
  */
-Type addStorageClass(Type type, StorageClass stc)
+Type addStorageClass(Type type, STC stc)
 {
     Type visitType(Type t)
     {
@@ -6214,7 +6220,7 @@  Type addStorageClass(Type type, StorageClass stc)
             (stc & STC.safe && t.trust < TRUST.trusted))
         {
             // Klunky to change these
-            auto tf = new TypeFunction(t.parameterList, t.next, t.linkage, 0);
+            auto tf = new TypeFunction(t.parameterList, t.next, t.linkage, STC.none);
             tf.mod = t.mod;
             tf.inferenceArguments = tf_src.inferenceArguments;
             tf.purity = t.purity;
@@ -6345,7 +6351,7 @@  Type getComplexLibraryType(Loc loc, Scope* sc, TY ty)
  * Returns:
  *     An enum value of either `Covariant.yes` or a reason it's not covariant.
  */
-Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovariant = false)
+Covariant covariant(Type src, Type t, STC* pstc = null, bool cppCovariant = false)
 {
     version (none)
     {
@@ -6355,8 +6361,8 @@  Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovaria
         printf("mod = %x, %x\n", src.mod, t.mod);
     }
     if (pstc)
-        *pstc = 0;
-    StorageClass stc = 0;
+        *pstc = STC.none;
+    STC stc = STC.none;
 
     bool notcovariant = false;
 
@@ -6506,8 +6512,8 @@  Lcovariant:
 
     if (!t1.isRef && (t1.isScopeQual || t2.isScopeQual))
     {
-        StorageClass stc1 = t1.isScopeQual ? STC.scope_ : 0;
-        StorageClass stc2 = t2.isScopeQual ? STC.scope_ : 0;
+        STC stc1 = t1.isScopeQual ? STC.scope_ : STC.none;
+        STC stc2 = t2.isScopeQual ? STC.scope_ : STC.none;
         if (t1.isReturn)
         {
             stc1 |= STC.return_;
@@ -6605,7 +6611,7 @@  Lnotcovariant:
  * Returns:
  *  storage class with STC.scope_ or STC.return_ OR'd in
  */
-StorageClass parameterStorageClass(TypeFunction tf, Type tthis, Parameter p, VarDeclarations* outerVars = null,
+STC parameterStorageClass(TypeFunction tf, Type tthis, Parameter p, VarDeclarations* outerVars = null,
     bool indirect = false)
 {
     //printf("parameterStorageClass(p: %s)\n", p.toChars());
diff --git a/gcc/d/dmd/version.h b/gcc/d/dmd/version.h
index 7913c96c3f8..8840b59b982 100644
--- a/gcc/d/dmd/version.h
+++ b/gcc/d/dmd/version.h
@@ -18,7 +18,6 @@  public:
     DebugSymbol *syntaxCopy(Dsymbol *) override;
 
     const char *kind() const override;
-    DebugSymbol *isDebugSymbol() override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -28,6 +27,5 @@  public:
     VersionSymbol *syntaxCopy(Dsymbol *) override;
 
     const char *kind() const override;
-    VersionSymbol *isVersionSymbol() override;
     void accept(Visitor *v) override { v->visit(this); }
 };
diff --git a/gcc/d/dmd/visitor/postorder.d b/gcc/d/dmd/visitor/postorder.d
index af12f1e9e9e..39c38a284f4 100644
--- a/gcc/d/dmd/visitor/postorder.d
+++ b/gcc/d/dmd/visitor/postorder.d
@@ -82,13 +82,13 @@  public:
     override void visit(NewExp e)
     {
         //printf("NewExp::apply(): %s\n", toChars());
-        doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
+        doCond(e.placement) || doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
     }
 
     override void visit(NewAnonClassExp e)
     {
         //printf("NewAnonClassExp::apply(): %s\n", toChars());
-        doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
+        doCond(e.placement) || doCond(e.thisexp) || doCond(e.arguments.peekSlice()) || applyTo(e);
     }
 
     override void visit(TypeidExp e)
diff --git a/gcc/d/dmd/visitor/transitive.d b/gcc/d/dmd/visitor/transitive.d
index c3ce13e2d40..89c23320b9d 100644
--- a/gcc/d/dmd/visitor/transitive.d
+++ b/gcc/d/dmd/visitor/transitive.d
@@ -994,6 +994,8 @@  package(dmd.visitor) mixin template ParseVisitMethods(AST)
     override void visit(AST.NewExp e)
     {
         //printf("Visiting NewExp\n");
+        if (e.placement)
+            e.placement.accept(this);
         if (e.thisexp)
             e.thisexp.accept(this);
         visitType(e.newtype);
@@ -1003,6 +1005,8 @@  package(dmd.visitor) mixin template ParseVisitMethods(AST)
     override void visit(AST.NewAnonClassExp e)
     {
         //printf("Visiting NewAnonClassExp\n");
+        if (e.placement)
+            e.placement.accept(this);
         if (e.thisexp)
             e.thisexp.accept(this);
         visitArgs(e.arguments.peekSlice());
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index da794ea5f2b..0415763b60d 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -1783,7 +1783,7 @@  public:
 
   void visit (DelegateExp *e) final override
   {
-    if (e->func->semanticRun == PASS::semantic3done)
+    if (e->func->semanticRun () == PASS::semantic3done)
       {
 	/* Add the function as nested function if it belongs to this module.
 	   ie: it is a member of this module, or it is a template instance.  */
@@ -2246,6 +2246,15 @@  public:
 	    new_call = build_nop (type, build_address (var));
 	    setup_exp = modify_expr (var, aggregate_initializer_decl (cd));
 	  }
+	else if (e->placement != NULL)
+	  {
+	    /* Generate: placement_expr = typeid(class).init  */
+	    tree placement_expr = build_expr (e->placement);
+	    new_call = build_nop (type, build_address (placement_expr));
+	    tree class_init = build_vconvert (TREE_TYPE (placement_expr),
+					      aggregate_initializer_decl (cd));
+	    setup_exp = modify_expr (placement_expr, class_init);
+	  }
 	else
 	  {
 	    /* Generate: _d_newclass()
@@ -2318,12 +2327,22 @@  public:
 	    return;
 	  }
 
-	/* This case should have been rewritten to `_d_newitemT' during the
-	   semantic phase.  */
-	gcc_assert (e->lowering);
+	if (e->placement != NULL)
+	  {
+	    /* Generate: &placement_expr  */
+	    tree placement_expr = build_expr (e->placement);
+	    new_call = build_nop (build_ctype (tb),
+				  build_address (placement_expr));
+	  }
+	else
+	  {
+	    /* This case should have been rewritten to `_d_newitemT' during the
+	       semantic phase.  */
+	    gcc_assert (e->lowering);
 
-	/* Generate: _d_newitemT()  */
-	new_call = build_expr (e->lowering);
+	    /* Generate: _d_newitemT()  */
+	    new_call = build_expr (e->lowering);
+	  }
 
 	if (e->member || !e->arguments)
 	  {
@@ -2396,12 +2415,22 @@  public:
 	    return;
 	  }
 
-	/* This case should have been rewritten to `_d_newitemT' during the
-	   semantic phase.  */
-	gcc_assert (e->lowering);
+	if (e->placement != NULL)
+	  {
+	    /* Generate: &placement_expr  */
+	    tree placement_expr = build_expr (e->placement);
+	    result = build_nop (build_ctype (tb),
+				build_address (placement_expr));
+	  }
+	else
+	  {
+	    /* This case should have been rewritten to `_d_newitemT' during the
+	       semantic phase.  */
+	    gcc_assert (e->lowering);
 
-	/* Generate: _d_newitemT()  */
-	result = build_expr (e->lowering);
+	    /* Generate: _d_newitemT()  */
+	    result = build_expr (e->lowering);
+	  }
 
 	if (e->arguments && e->arguments->length == 1)
 	  {
diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc
index 85b6e42eb7e..471ac43cbea 100644
--- a/gcc/d/modules.cc
+++ b/gcc/d/modules.cc
@@ -143,13 +143,13 @@  get_internal_fn (tree ident, const Visibility &visibility)
       name = IDENTIFIER_POINTER (s);
     }
 
-  FuncDeclaration *fd = FuncDeclaration::genCfunc (NULL, Type::tvoid,
-						   Identifier::idPool (name));
+  FuncDeclaration *fd = dmd::genCfunc (NULL, Type::tvoid,
+				       Identifier::idPool (name));
   fd->isGenerated (true);
   fd->loc = Loc::singleFilename (mod->srcfile.toChars ());
   fd->parent = mod;
   fd->visibility = visibility;
-  fd->semanticRun = PASS::semantic3done;
+  fd->semanticRun (PASS::semantic3done);
 
   return fd;
 }
diff --git a/gcc/testsuite/gdc.test/compilable/bug11735.d b/gcc/testsuite/gdc.test/compilable/bug11735.d
index b94cb6e77da..be61a50585b 100644
--- a/gcc/testsuite/gdc.test/compilable/bug11735.d
+++ b/gcc/testsuite/gdc.test/compilable/bug11735.d
@@ -13,6 +13,7 @@  print dstring
 foo_str
 foo_wstr
 foo_dstr
+X%nY
 ---
 */
 
@@ -33,4 +34,7 @@  void main()
     pragma(msg, a);
     pragma(msg, b);
     pragma(msg, c);
+
+    // https://github.com/dlang/dmd/issues/20894
+    pragma(msg, "X%nY");
 }
diff --git a/gcc/testsuite/gdc.test/compilable/placementnew.d b/gcc/testsuite/gdc.test/compilable/placementnew.d
new file mode 100644
index 00000000000..e7181bbee7e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/placementnew.d
@@ -0,0 +1,4 @@ 
+void f(int* p) @nogc
+{
+    new(*p) int;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test21177.d b/gcc/testsuite/gdc.test/compilable/test21177.d
index b485304c188..a75a0d52631 100644
--- a/gcc/testsuite/gdc.test/compilable/test21177.d
+++ b/gcc/testsuite/gdc.test/compilable/test21177.d
@@ -1,5 +1,6 @@ 
 // https://issues.dlang.org/show_bug.cgi?id=21177
 /*
+REQUIRED_ARGS: -verrors=simple
 DISABLED: win
 TEST_OUTPUT:
 ---
diff --git a/gcc/testsuite/gdc.test/compilable/test24017.d b/gcc/testsuite/gdc.test/compilable/test24017.d
deleted file mode 100644
index 0d039781201..00000000000
--- a/gcc/testsuite/gdc.test/compilable/test24017.d
+++ /dev/null
@@ -1,11 +0,0 @@ 
-// https://issues.dlang.org/show_bug.cgi?id=24017
-
-// REQUIRED_ARGS: -debug
-
-void writeln(string) {}
-
-void main() nothrow
-{
-    debug writeln("Hello");
-    debug "Hello".writeln;
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21849.d b/gcc/testsuite/gdc.test/fail_compilation/fail21849.d
index 75821f69eab..700e4242778 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail21849.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21849.d
@@ -29,6 +29,10 @@  void fail21849c()
     string s = "
 ß-utf"; undefined_identifier;
 }
+
+// Test correct context with line directive present
+// https://github.com/dlang/dmd/issues/20929
+#line 32
 void fail21849d()
 {
     string s = "
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22151.d b/gcc/testsuite/gdc.test/fail_compilation/fail22151.d
index c6c3b1b742b..9b5d5aad7be 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail22151.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22151.d
@@ -2,10 +2,13 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail22151.d(14): Error: function `test` is not an lvalue and cannot be modified
-fail_compilation/fail22151.d(15): Error: function `test2` is not an lvalue and cannot be modified
-fail_compilation/fail22151.d(18): Error: function pointed to by `fp` is not an lvalue and cannot be modified
-fail_compilation/fail22151.d(21): Error: function pointed to by `ff` is not an lvalue and cannot be modified
+fail_compilation/fail22151.d(17): Error: function `test` is not an lvalue and cannot be modified
+fail_compilation/fail22151.d(18): Error: function `test2` is not an lvalue and cannot be modified
+fail_compilation/fail22151.d(21): Error: function pointed to by `fp` is not an lvalue and cannot be modified
+fail_compilation/fail22151.d(24): Error: function pointed to by `ff` is not an lvalue and cannot be modified
+fail_compilation/fail22151.d(27): Error: operator `==` is not defined for function types
+fail_compilation/fail22151.d(28): Error: operator `is` is not defined for function types
+fail_compilation/fail22151.d(29): Error: comparison is not defined for function types
 ---
 */
 
@@ -19,6 +22,11 @@  void test()
 
     auto ff = &test2;
     *ff = *&test2;
+
+    // https://github.com/dlang/dmd/issues/18281
+    const c = *fp == *fp;
+    const d = *fp is *fp;
+    const e = *fp < *fp;
 }
 
 void test2();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/placenew.d b/gcc/testsuite/gdc.test/fail_compilation/placenew.d
new file mode 100644
index 00000000000..033d078e191
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/placenew.d
@@ -0,0 +1,80 @@ 
+/* TEST_OUTPUT:
+---
+fail_compilation/placenew.d(23): Error: PlacementExpression `3` is an rvalue, but must be an lvalue
+fail_compilation/placenew.d(28): Error: undefined identifier `x`
+fail_compilation/placenew.d(36): Error: `new ( i )` PlacementExpression cannot be evaluated at compile time
+fail_compilation/placenew.d(39):        called from here: `xxx()`
+fail_compilation/placenew.d(39):        while evaluating: `static assert(xxx() == 1)`
+fail_compilation/placenew.d(48): Error: new placement size 24 must be >= object size 40
+fail_compilation/placenew.d(54): Error: placement new cannot be used with associative arrays
+fail_compilation/placenew.d(67): Error: new placement size 4 must be >= class object size $?:32=16|64=24$
+fail_compilation/placenew.d(77): Error: `@safe` function `test7` cannot use placement `new` is not allowed in a `@safe` function
+---
+*/
+
+void test0()
+{
+    int i;
+    int* pi = new (i) int;
+}
+
+void test1()
+{
+    int* pi = new (3) int;
+}
+
+void test2()
+{
+    int* px = new (x) int;
+}
+
+void test3()
+{
+    int xxx()
+    {
+        int i;
+        int* pi = new (i) int(1);
+        return 1;
+    }
+    static assert(xxx() == 1);
+}
+
+struct S { int[6] a; }
+struct T { int[10] a; }
+
+void test4()
+{
+    S s;
+    new (s) T();
+}
+
+void test5()
+{
+    T p;
+    auto aa = new(p) int[int*];
+}
+
+/*************************************************/
+
+class C6
+{
+    int i, j;
+}
+
+int test6()
+{
+    int k;
+    C6 c = new(k) C6;
+    return c.j;
+}
+
+/*************************************************/
+
+@safe
+void test7()
+{
+    int i;
+    int* p = new(i) int;
+}
+
+/*************************************************/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20859.d b/gcc/testsuite/gdc.test/fail_compilation/test20859.d
new file mode 100644
index 00000000000..50fa9e0d491
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test20859.d
@@ -0,0 +1,11 @@ 
+/**
+TEST_OUTPUT:
+---
+fail_compilation/test20859.d(8): Error: variable `test20859.ICE.__vtbl` conflicts with variable `test20859.ICE.__vtbl` at fail_compilation/test20859.d(10)
+---
+*/
+
+class ICE
+{
+    void **__vtbl;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/literal.d b/gcc/testsuite/gdc.test/runnable/literal.d
index 3cc7e51197b..c78f4776aaf 100644
--- a/gcc/testsuite/gdc.test/runnable/literal.d
+++ b/gcc/testsuite/gdc.test/runnable/literal.d
@@ -277,8 +277,16 @@  void testHexstring()
     static immutable ulong[] z0 = cast(immutable ulong[]) x"1111 1111 1111 1111 0000 000F 0000 0000";
     static immutable ulong[] z1 = [0x1111_1111_1111_1111, 0x0000_000E_0000_0000];
     static assert(z0 !is z1);
+
+    // https://github.com/dlang/dmd/issues/20635
+    f20635(cast(ubyte[]) x"00");
+    f20635(cast(const ubyte[]) x"00");
+    f20635(cast(immutable ubyte[]) x"00");
 }
 
+void f20635(const ubyte[] value){}
+void f20635(const string value){}
+
 /***************************************************/
 
 int main()
diff --git a/gcc/testsuite/gdc.test/runnable/placenew.d b/gcc/testsuite/gdc.test/runnable/placenew.d
new file mode 100644
index 00000000000..d90d10a5e74
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/placenew.d
@@ -0,0 +1,106 @@ 
+import core.stdc.stdio;
+import core.stdc.stdlib;
+
+/*************************************************/
+
+struct S
+{
+    float d;
+    int i;
+    char c;
+}
+
+void test1()
+{
+    S s;
+    S* p = new (s) S();
+    assert(p.i == 0 && p.c == 0xFF);
+}
+
+void test2()
+{
+    S s;
+    S* p = new (s) S(i:3);
+    assert(p.i == 3 && p.c == 0xFF);
+}
+
+/*************************************************/
+
+struct S3
+{
+    int i;
+    this(int i) { this.i = i + 3; }
+}
+
+void test3()
+{
+    S3 s;
+    s.i = 20;
+    S3* p = new (s) S3(4);
+    assert(p.i == 7);
+}
+
+
+/*************************************************/
+
+void test4()
+{
+    int i = 3;
+    int* p = new(i) int;
+    *p = 4;
+    assert(i == 4);
+
+    p = new(i) int(7);
+    assert(i == 7);
+}
+
+/*************************************************/
+
+class C5
+{
+    int i, j = 4;
+}
+
+int test5()
+{
+    int[10] k;
+    C5 c = new(k) C5;
+    //printf("c.j: %d\n", c.j);
+    assert(c.j == 4);
+    assert(cast(void*)c == cast(void*)k.ptr);
+    return c.j;
+}
+
+/*************************************************/
+
+struct S6
+{
+    int i = 1, j = 4, k = 9;
+}
+
+ref void[T.sizeof] mallocate(T)()
+{
+    return *(cast(void[T.sizeof]*) malloc(T.sizeof));
+}
+
+void test6()
+{
+    S6* ps = new(mallocate!S6()) S6;
+    assert(ps.i == 1);
+    assert(ps.j == 4);
+    assert(ps.k == 9);
+}
+
+/*************************************************/
+
+int main()
+{
+    test1();
+    test2();
+    test3();
+    test4();
+    test5();
+    test6();
+
+    return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/template3.d b/gcc/testsuite/gdc.test/runnable/template3.d
index e3313672d08..7b90cff29a2 100644
--- a/gcc/testsuite/gdc.test/runnable/template3.d
+++ b/gcc/testsuite/gdc.test/runnable/template3.d
@@ -240,6 +240,16 @@  void test8()
 
 /*********************************************************/
 
+// https://github.com/dlang/dmd/issues/20907
+struct Bar { enum bar = 1; }
+void foo(A)(A[], A[1 << A.bar]) {}
+void test20907()
+{
+    foo((Bar[]).init, (Bar[2]).init);
+}
+
+/*********************************************************/
+
 int main()
 {
     test1();
@@ -250,6 +260,7 @@  int main()
     test6();
     test7();
     test8();
+    test20907();
 
     printf("Success\n");
     return 0;
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 66cfdd6ad4a..070d9fec28b 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@ 
-53a1cc8d13e8db2cb1642219320a8dfc1b0cc6c5
+603225372b211bb66dd0ea1a939043ace5a650cf
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.