diff mbox series

[committed] d: Merge upstream dmd, druntime e48bc0987d, phobos 2458e8f82.

Message ID 20231029154732.191984-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Merge upstream dmd, druntime e48bc0987d, phobos 2458e8f82. | expand

Commit Message

Iain Buclaw Oct. 29, 2023, 3:47 p.m. UTC
Hi,

This patch merges the D front-end and runtime library with upstream dmd
e48bc0987d, and standard library with phobos 2458e8f82.

Synchronizing with the v2.106.0-beta.1 release.

D front-end changes:

    - Import dmd v2.106.0-beta.1.

D runtime changes:

    - Import druntime v2.106.0-beta.1.

Phobos changes:

    - Import phobos v2.106.0-beta.1.


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

Regards,
Iain.

---
gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd e48bc0987d.
	* expr.cc (ExprVisitor::visit (NewExp *)): Update for new front-end
	interface.
	* runtime.def (NEWARRAYT): Remove.
	(NEWARRAYIT): Remove.

libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime e48bc0987d.
	* src/MERGE: Merge upstream phobos 2458e8f82.
---
 gcc/d/dmd/MERGE                               |   2 +-
 gcc/d/dmd/VERSION                             |   2 +-
 gcc/d/dmd/aggregate.d                         |   8 +-
 gcc/d/dmd/aggregate.h                         |   8 -
 gcc/d/dmd/aliasthis.h                         |   2 +-
 gcc/d/dmd/attrib.h                            |   1 -
 gcc/d/dmd/canthrow.d                          |   2 +-
 gcc/d/dmd/cond.d                              |   2 +-
 gcc/d/dmd/cond.h                              |   2 -
 gcc/d/dmd/cparse.d                            |  17 +-
 gcc/d/dmd/dcast.d                             |   2 +-
 gcc/d/dmd/dclass.d                            |   8 +-
 gcc/d/dmd/declaration.d                       |   1 +
 gcc/d/dmd/declaration.h                       |  12 -
 gcc/d/dmd/denum.d                             |   2 +-
 gcc/d/dmd/dimport.d                           |   2 +-
 gcc/d/dmd/dinterpret.d                        |   3 +
 gcc/d/dmd/dmodule.d                           |   2 +-
 gcc/d/dmd/dscope.d                            |   2 +-
 gcc/d/dmd/dstruct.d                           |   2 +-
 gcc/d/dmd/dsymbol.d                           |   7 +-
 gcc/d/dmd/dsymbolsem.d                        |  15 +-
 gcc/d/dmd/dtemplate.d                         |   8 +-
 gcc/d/dmd/expression.d                        |  90 ++-----
 gcc/d/dmd/expression.h                        |  88 +------
 gcc/d/dmd/expressionsem.d                     |  53 ++++
 gcc/d/dmd/func.d                              |  20 +-
 gcc/d/dmd/globals.h                           |   6 +-
 gcc/d/dmd/hdrgen.d                            |  38 ++-
 gcc/d/dmd/id.d                                |   2 +
 gcc/d/dmd/import.h                            |   1 -
 gcc/d/dmd/init.h                              |   1 -
 gcc/d/dmd/location.d                          |   2 +-
 gcc/d/dmd/module.h                            |   1 -
 gcc/d/dmd/mtype.d                             |  16 +-
 gcc/d/dmd/mtype.h                             |  12 -
 gcc/d/dmd/objc.h                              |   2 -
 gcc/d/dmd/scope.h                             |   2 -
 gcc/d/dmd/sideeffect.d                        |   4 +-
 gcc/d/dmd/statement.d                         |   6 +-
 gcc/d/dmd/statement.h                         |   4 +-
 gcc/d/dmd/template.h                          |   5 -
 gcc/d/dmd/tokens.d                            |   2 +-
 gcc/d/dmd/tokens.h                            |   3 -
 gcc/d/expr.cc                                 |  20 +-
 gcc/d/runtime.def                             |   9 +-
 .../gdc.test/fail_compilation/ice10727a.d     |   2 +
 .../gdc.test/fail_compilation/ice10727b.d     |   2 +
 libphobos/libdruntime/MERGE                   |   2 +-
 .../core/internal/array/construction.d        | 167 +++++++++++++
 .../libdruntime/core/internal/array/utils.d   | 236 ++++++++++++++++++
 libphobos/libdruntime/core/lifetime.d         |  13 +-
 .../libdruntime/core/sys/freebsd/ifaddrs.d    |  41 +++
 .../libdruntime/core/sys/freebsd/net/if_dl.d  |  42 ++++
 .../libdruntime/core/sys/freebsd/sys/socket.d | 131 ++++++++++
 .../libdruntime/core/sys/freebsd/sys/types.d  |  58 +++++
 .../libdruntime/core/sys/posix/sys/types.d    |   4 +-
 libphobos/libdruntime/object.d                |   2 +
 libphobos/libdruntime/rt/lifetime.d           |  26 +-
 libphobos/src/MERGE                           |   2 +-
 libphobos/src/std/parallelism.d               |   2 +-
 libphobos/src/std/range/primitives.d          |  10 +-
 libphobos/src/std/traits.d                    |  57 +++++
 63 files changed, 962 insertions(+), 334 deletions(-)
 create mode 100644 libphobos/libdruntime/core/sys/freebsd/ifaddrs.d
 create mode 100644 libphobos/libdruntime/core/sys/freebsd/net/if_dl.d
 create mode 100644 libphobos/libdruntime/core/sys/freebsd/sys/socket.d
 create mode 100644 libphobos/libdruntime/core/sys/freebsd/sys/types.d

Comments

Rainer Orth Oct. 30, 2023, 4:37 p.m. UTC | #1
Hi Iain,

> This patch merges the D front-end and runtime library with upstream dmd
> e48bc0987d, and standard library with phobos 2458e8f82.
>
> Synchronizing with the v2.106.0-beta.1 release.
>
> D front-end changes:
>
>     - Import dmd v2.106.0-beta.1.

this patch broke D bootstrap, it seems:

/vol/gcc/src/hg/master/local/gcc/d/expr.cc: In member function 'virtual void ExprVisitor::visit(NewExp*)':
/vol/gcc/src/hg/master/local/gcc/d/expr.cc:2361:21: error: unused variable 'tarray' [-Werror=unused-variable]
 2361 |         TypeDArray *tarray = tb->isTypeDArray ();
      |                     ^~~~~~

It removed the uses of tarray, but kept the initialization.

	Rainer
Iain Buclaw Oct. 31, 2023, 2:58 a.m. UTC | #2
Excerpts from Rainer Orth's message of Oktober 30, 2023 5:37 pm:
> Hi Iain,
> 
>> This patch merges the D front-end and runtime library with upstream dmd
>> e48bc0987d, and standard library with phobos 2458e8f82.
>>
>> Synchronizing with the v2.106.0-beta.1 release.
>>
>> D front-end changes:
>>
>>     - Import dmd v2.106.0-beta.1.
> 
> this patch broke D bootstrap, it seems:
> 
> /vol/gcc/src/hg/master/local/gcc/d/expr.cc: In member function 'virtual void ExprVisitor::visit(NewExp*)':
> /vol/gcc/src/hg/master/local/gcc/d/expr.cc:2361:21: error: unused variable 'tarray' [-Werror=unused-variable]
>  2361 |         TypeDArray *tarray = tb->isTypeDArray ();
>       |                     ^~~~~~
> 
> It removed the uses of tarray, but kept the initialization.
> 

Hi Rainer,

Thanks for spotting, I'll fix it up.

Iain.
diff mbox series

Patch

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index bfadeaa0c68..2a0baf09a4b 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-f4be7f6f7bae75f1613b862940cdd533b5ae99b2
+e48bc0987dfec35bc76a3015ee3e85906ce86dfd
 
 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 fd05dcf2136..b272d4bbe5c 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@ 
-v2.105.2
+v2.106.0-beta.1
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index 68b5f1b48f1..d9b48b531d7 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -192,7 +192,7 @@  extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
      * Returns:
      *      The total number of fields minus the number of hidden fields.
      */
-    final size_t nonHiddenFields()
+    extern (D) final size_t nonHiddenFields()
     {
         return fields.length - isNested() - (vthis2 !is null);
     }
@@ -202,7 +202,7 @@  extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
      * Returns:
      *      false if failed to determine the size.
      */
-    final bool determineSize(const ref Loc loc)
+    extern (D) final bool determineSize(const ref Loc loc)
     {
         //printf("AggregateDeclaration::determineSize() %s, sizeok = %d\n", toChars(), sizeok);
 
@@ -609,7 +609,7 @@  extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
     }
 
     /// Flag this aggregate as deprecated
-    final void setDeprecated()
+    extern (D) final void setDeprecated()
     {
         this.storage_class |= STC.deprecated_;
     }
@@ -745,7 +745,7 @@  extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
     /*******************************************
      * Look for constructor declaration.
      */
-    final Dsymbol searchCtor()
+    extern (D) final Dsymbol searchCtor()
     {
         auto s = search(Loc.initial, Id.ctor);
         if (s)
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index 4b107e0f2a9..58a0126de1a 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -114,17 +114,13 @@  public:
 
     virtual Scope *newScope(Scope *sc);
     void setScope(Scope *sc) override final;
-    size_t nonHiddenFields();
-    bool determineSize(const Loc &loc);
     virtual void finalizeSize() = 0;
     uinteger_t size(const Loc &loc) override final;
     bool fill(const Loc &loc, Expressions &elements, bool ctorinit);
     Type *getType() override final;
     bool isDeprecated() const override final; // is aggregate deprecated?
-    void setDeprecated();
     bool isNested() const;
     bool isExport() const override final;
-    Dsymbol *searchCtor();
 
     Visibility visible() override final;
 
@@ -279,12 +275,10 @@  public:
     ObjcClassDeclaration objc;          // Data for a class declaration that is needed for the Objective-C integration
     Symbol *cpp_type_info_ptr_sym;      // cached instance of class Id.cpp_type_info_ptr
 
-    void classError(const char* fmt, const char* arg);
     static ClassDeclaration *create(const Loc &loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject);
     const char *toPrettyChars(bool QualifyTypes = false) override;
     ClassDeclaration *syntaxCopy(Dsymbol *s) override;
     Scope *newScope(Scope *sc) override;
-    bool isBaseOf2(ClassDeclaration *cd);
 
     #define OFFSET_RUNTIME 0x76543210
     #define OFFSET_FWDREF 0x76543211
@@ -292,11 +286,9 @@  public:
 
     bool isBaseInfoComplete();
     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final;
-    ClassDeclaration *searchBase(Identifier *ident);
     void finalizeSize() override;
     bool hasMonitor();
     bool isFuncHidden(FuncDeclaration *fd);
-    FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
     bool isCOMclass() const;
     virtual bool isCOMinterface() const;
     bool isCPPclass() const;
diff --git a/gcc/d/dmd/aliasthis.h b/gcc/d/dmd/aliasthis.h
index 389cff40054..092490fd5de 100644
--- a/gcc/d/dmd/aliasthis.h
+++ b/gcc/d/dmd/aliasthis.h
@@ -21,7 +21,7 @@  public:
    // alias Identifier this;
     Identifier *ident;
     Dsymbol    *sym;
-    bool       isDeprecated_;
+    d_bool     isDeprecated_;
 
     AliasThis *syntaxCopy(Dsymbol *) override;
     const char *kind() const override;
diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h
index 1e75598c72a..f47a1f6f836 100644
--- a/gcc/d/dmd/attrib.h
+++ b/gcc/d/dmd/attrib.h
@@ -123,7 +123,6 @@  public:
     Expressions *alignExps;
     structalign_t salign;
 
-    AlignDeclaration(const Loc &loc, Expression *ealign, Dsymbols *decl);
     AlignDeclaration *syntaxCopy(Dsymbol *s) override;
     Scope *newScope(Scope *sc) override;
     void accept(Visitor *v) override { v->visit(this); }
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index bb1fd6fc974..8aece3bdd71 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -55,7 +55,7 @@  enum CT : BE
  *      eSink = if !null, then send error messages to eSink
  * Returns: `CT.exception` or `CT.error` if the expression may throw exceptions.
  */
-extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, ErrorSink eSink)
+CT canThrow(Expression e, FuncDeclaration func, ErrorSink eSink)
 {
     //printf("Expression::canThrow(%d) %s\n", mustNotThrow, e.toChars());
     // stop walking if we determine this expression can throw
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index e4d1096db48..9fa8a25462f 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -133,7 +133,7 @@  extern (C++) final class StaticForeach : RootObject
         this.rangefe = rangefe;
     }
 
-    StaticForeach syntaxCopy()
+    extern (D) StaticForeach syntaxCopy()
     {
         return new StaticForeach(
             loc,
diff --git a/gcc/d/dmd/cond.h b/gcc/d/dmd/cond.h
index 45094d14991..d02ae1321c5 100644
--- a/gcc/d/dmd/cond.h
+++ b/gcc/d/dmd/cond.h
@@ -53,8 +53,6 @@  public:
     ForeachRangeStatement *rangefe;
 
     d_bool needExpansion;
-
-    StaticForeach *syntaxCopy();
 };
 
 class DVCondition : public Condition
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index d183b8227c8..0b738cdc3d5 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -1923,7 +1923,12 @@  final class CParser(AST) : Parser!AST
                     }
                 }
                 if (isalias)
-                    s = new AST.AliasDeclaration(token.loc, id, dt);
+                {
+                    auto ad = new AST.AliasDeclaration(token.loc, id, dt);
+                    ad.adFlags |= ad.hidden; // do not print when generating .di files
+                    s = ad;
+                }
+
                 insertTypedefToTypedefTab(id, dt);       // remember typedefs
             }
             else if (id)
@@ -1960,7 +1965,9 @@  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
-                    auto fd = new AST.FuncDeclaration(token.loc, Loc.initial, id, specifiersToSTC(level, specifier), dt, specifier.noreturn);
+                    StorageClass 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);
                     s = fd;
                 }
@@ -2136,7 +2143,9 @@  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
 
-        auto fd = new AST.FuncDeclaration(locFunc, prevloc, id, specifiersToSTC(LVL.global, specifier), ft, specifier.noreturn);
+        StorageClass 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);
 
         if (addFuncName)
@@ -5289,7 +5298,7 @@  final class CParser(AST) : Parser!AST
             (*decls)[0] = s;
             s = new AST.AlignDeclaration(s.loc, specifier.alignExps, decls);
         }
-        else if (!specifier.packalign.isDefault())
+        else if (!specifier.packalign.isDefault() && !specifier.packalign.isUnknown())
         {
             //printf("  applying packalign %d\n", cast(int)specifier.packalign);
             // Wrap #pragma pack in an AlignDeclaration
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 9f661ea410b..e4d580513fe 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -3684,7 +3684,7 @@  void fix16997(Scope* sc, UnaExp ue)
  * This is to enable comparing things like an immutable
  * array with a mutable one.
  */
-extern (C++) bool arrayTypeCompatibleWithoutCasting(Type t1, Type t2)
+extern (D) bool arrayTypeCompatibleWithoutCasting(Type t1, Type t2)
 {
     t1 = t1.toBasetype();
     t2 = t2.toBasetype();
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index 0fbbb1128e7..09a4f4ef3f2 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -367,7 +367,7 @@  extern (C++) class ClassDeclaration : AggregateDeclaration
         baseok = Baseok.none;
     }
 
-    final void classError(const(char)* fmt, const(char)* arg)
+    extern (D) private void classError(const(char)* fmt, const(char)* arg)
     {
         .error(loc, fmt, kind, toPrettyChars, arg);
     }
@@ -423,7 +423,7 @@  extern (C++) class ClassDeclaration : AggregateDeclaration
      * Determine if 'this' is a base class of cd.
      * This is used to detect circular inheritance only.
      */
-    final bool isBaseOf2(ClassDeclaration cd) pure nothrow @nogc
+    extern (D) final bool isBaseOf2(ClassDeclaration cd) pure nothrow @nogc
     {
         if (!cd)
             return false;
@@ -538,7 +538,7 @@  extern (C++) class ClassDeclaration : AggregateDeclaration
      * Returns:
      *  ClassDeclaration if found, null if not
      */
-    final ClassDeclaration searchBase(Identifier ident)
+    extern (D) final ClassDeclaration searchBase(Identifier ident)
     {
         foreach (b; *baseclasses)
         {
@@ -716,7 +716,7 @@  extern (C++) class ClassDeclaration : AggregateDeclaration
      * Errors:
      *  prints error message if more than one match
      */
-    final FuncDeclaration findFunc(Identifier ident, TypeFunction tf)
+    extern (D) final FuncDeclaration findFunc(Identifier ident, TypeFunction tf)
     {
         //printf("ClassDeclaration.findFunc(%s, %s) %s\n", ident.toChars(), tf.toChars(), toChars());
         FuncDeclaration fdmatch = null;
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 40463b4d970..d634e7fe545 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -244,6 +244,7 @@  extern (C++) abstract class Declaration : Dsymbol
       enum wasRead    = 1; // set if AliasDeclaration was read
       enum ignoreRead = 2; // ignore any reads of AliasDeclaration
       enum nounderscore = 4; // don't prepend _ to mangled name
+      enum hidden       = 8; // don't print this in .di files
 
     Symbol* isym;           // import version of csym
 
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 71f2baa525f..8cd295f1e06 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -705,15 +705,11 @@  public:
     bool functionSemantic3();
     bool equals(const RootObject * const o) const override final;
 
-    int overrides(FuncDeclaration *fd);
     int findVtblIndex(Dsymbols *vtbl, int dim);
-    BaseClass *overrideInterface();
     bool overloadInsert(Dsymbol *s) override;
     bool inUnittest();
     MATCH leastAsSpecialized(FuncDeclaration *g, Identifiers *names);
     LabelDsymbol *searchLabel(Identifier *ident, const Loc &loc);
-    int getLevel(FuncDeclaration *fd, int intypeof); // lexical nesting level difference
-    int getLevelAndCheck(const Loc &loc, Scope *sc, FuncDeclaration *fd);
     const char *toPrettyChars(bool QualifyTypes = false) override;
     const char *toFullSignature();  // for diagnostics, e.g. 'int foo(int x, int y) pure'
     bool isMain() const;
@@ -726,13 +722,9 @@  public:
     bool isOverloadable() const override final;
     bool isAbstract() override final;
     PURE isPure();
-    PURE isPureBypassingInference();
     bool isSafe();
-    bool isSafeBypassingInference();
     bool isTrusted();
-
     bool isNogc();
-    bool isNogcBypassingInference();
 
     virtual bool isNested() const;
     AggregateDeclaration *isThis() override;
@@ -752,8 +744,6 @@  public:
     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);
 
-    bool checkNRVO();
-
     FuncDeclaration *isFuncDeclaration() override final { return this; }
 
     virtual FuncDeclaration *toAliasFunc() { return this; }
@@ -789,8 +779,6 @@  public:
     bool addPreInvariant() override;
     bool addPostInvariant() override;
 
-    void modifyReturns(Scope *sc, Type *tret);
-
     FuncLiteralDeclaration *isFuncLiteralDeclaration() override { return this; }
     const char *kind() const override;
     const char *toPrettyChars(bool QualifyTypes = false) override;
diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index 98bf4dd2aad..f33b5fd543e 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/dmd/denum.d
@@ -99,7 +99,7 @@  extern (C++) final class EnumDeclaration : ScopeDsymbol
             ScopeDsymbol.addMember(sc, sds);
         }
 
-        addEnumMembers(this, sc, sds);
+        addEnumMembersToSymtab(this, sc, sds);
     }
 
     override void setScope(Scope* sc)
diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d
index 3b8d9f6722d..d74c8603420 100644
--- a/gcc/d/dmd/dimport.d
+++ b/gcc/d/dmd/dimport.d
@@ -128,7 +128,7 @@  extern (C++) final class Import : Dsymbol
      * Returns:
      *  true for errors, false for success
      */
-    bool load(Scope* sc)
+    extern (D) bool load(Scope* sc)
     {
         //printf("Import::load('%s') %p\n", toPrettyChars(), this);
         // See if existing module
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index fc5a3aaf62c..cbd9740e089 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -2975,6 +2975,9 @@  public:
         }
     }
 
+    private alias fp_t = extern (D) UnionExp function(const ref Loc loc, Type, Expression, Expression);
+    private alias fp2_t = extern (D) bool function(const ref Loc loc, EXP, Expression, Expression);
+
     extern (D) private void interpretCommon(BinExp e, fp_t fp)
     {
         debug (LOG)
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 9031b157000..548928a0124 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -1095,7 +1095,7 @@  extern (C++) final class Module : Package
         return Package.symtabInsert(s);
     }
 
-    void deleteObjFile()
+    extern (D) void deleteObjFile()
     {
         if (global.params.obj)
             File.remove(objfile.toChars());
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 14dbe9c6149..3853512005c 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -344,7 +344,7 @@  extern (C++) struct Scope
      * Returns:
      *  symbol if found, null if not
      */
-    extern (C++) Dsymbol search(const ref Loc loc, Identifier ident, Dsymbol* pscopesym, int flags = IgnoreNone)
+    extern (D) Dsymbol search(const ref Loc loc, Identifier ident, Dsymbol* pscopesym, int flags = IgnoreNone)
     {
         version (LOGSEARCH)
         {
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index 56aad3eece3..5171e1f3106 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -71,7 +71,7 @@  extern (C++) FuncDeclaration search_toString(StructDeclaration sd)
  *      sc = context
  *      t = type that TypeInfo is being generated for
  */
-extern (C++) void semanticTypeInfo(Scope* sc, Type t)
+extern (D) void semanticTypeInfo(Scope* sc, Type t)
 {
     if (sc)
     {
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 6538664eace..579a542de3c 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -141,13 +141,14 @@  struct Visibility
     Kind kind;
     Package pkg;
 
-    extern (D):
-
-    this(Visibility.Kind kind) pure nothrow @nogc @safe
+    extern(C++) this(Visibility.Kind kind, Package pkg = null) pure nothrow @nogc @safe
     {
         this.kind = kind;
+        this.pkg  = pkg;
     }
 
+    extern (D):
+
     /**
      * Checks if `this` is less or more visible than `other`
      *
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 4de037c8f68..8309e4a846b 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -2260,7 +2260,7 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
          * so we have to do what addMember() does and install the enum members in the right symbol
          * table
          */
-        addEnumMembers(ed, sc, sc.getScopesym());
+        addEnumMembersToSymtab(ed, sc, sc.getScopesym());
 
         if (sc.flags & SCOPE.Cfile)
         {
@@ -5824,9 +5824,10 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
  *      sc = context of `ed`
  *      sds = symbol table that `ed` resides in
  */
-void addEnumMembers(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
+void addEnumMembersToSymtab(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
 {
-    //printf("addEnumMembers(ed: %p)\n", ed);
+    const bool isCEnum = (sc.flags & SCOPE.Cfile) != 0; // it's an ImportC enum
+    //printf("addEnumMembersToSymtab(ed: %s added: %d Cfile: %d)\n", ed.toChars(), ed.added, isCEnum);
     if (ed.added)
         return;
     ed.added = true;
@@ -5834,7 +5835,6 @@  void addEnumMembers(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
     if (!ed.members)
         return;
 
-    const bool isCEnum = (sc.flags & SCOPE.Cfile) != 0; // it's an ImportC enum
     const bool isAnon = ed.isAnonymous();
 
     if ((isCEnum || isAnon) && !sds.symtab)
@@ -5847,10 +5847,15 @@  void addEnumMembers(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds)
     {
         if (EnumMember em = s.isEnumMember())
         {
+            //printf("adding EnumMember %s to %s %d\n", em.toChars(), ed.toChars(), isCEnum);
             em.ed = ed;
             if (isCEnum)
             {
-                //printf("adding EnumMember %s to %p\n", em.toChars(), ed);
+                /* C doesn't add the enum member to the symbol table of the enum tag, it adds
+                 * it to the symbol table that the tag is in. This is in contrast to D, where enum
+                 * members become members of the enum tag. To accommodate this, we add
+                 * the enum members to both symbol tables.
+                 */
                 em.addMember(sc, ed);   // add em to ed's symbol table
                 em.addMember(sc, sds);  // add em to symbol table that ed is in
                 em.parent = ed; // restore it after previous addMember() changed it
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index ae49dda9315..5dca6dfec6e 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -1241,7 +1241,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
      *      match   this is at least as specialized as td2
      *      0       td2 is more specialized than this
      */
-    MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration td2, ArgumentList argumentList)
+    extern (D) MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration td2, ArgumentList argumentList)
     {
         enum LOG_LEASTAS = 0;
         static if (LOG_LEASTAS)
@@ -2258,7 +2258,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
     /**************************************************
      * Declare template parameter tp with value o, and install it in the scope sc.
      */
-    RootObject declareParameter(Scope* sc, TemplateParameter tp, RootObject o)
+    extern (D) RootObject declareParameter(Scope* sc, TemplateParameter tp, RootObject o)
     {
         //printf("TemplateDeclaration.declareParameter('%s', o = %p)\n", tp.ident.toChars(), o);
         Type ta = isType(o);
@@ -2508,7 +2508,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
      * Returns:
      *   The last template parameter if it's a `TemplateTupleParameter`
      */
-    TemplateTupleParameter isVariadic()
+    extern (D) TemplateTupleParameter isVariadic()
     {
         size_t dim = parameters.length;
         if (dim == 0)
@@ -6203,7 +6203,7 @@  extern (C++) class TemplateInstance : ScopeDsymbol
         return false;
     }
 
-    final size_t toHash()
+    extern (D) final size_t toHash()
     {
         if (!hash)
         {
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 2c55f0ebc94..32ded3bd5f6 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -331,7 +331,7 @@  TemplateDeclaration getFuncTemplateDecl(Dsymbol s) @safe
  * to serve essentially as a Variant that will sit on the stack
  * during CTFE to reduce memory consumption.
  */
-extern (C++) struct UnionExp
+extern (D) struct UnionExp
 {
     // yes, default constructor does nothing
     extern (D) this(Expression e)
@@ -341,14 +341,14 @@  extern (C++) struct UnionExp
 
     /* Extract pointer to Expression
      */
-    extern (C++) Expression exp() return
+    extern (D) Expression exp() return
     {
         return cast(Expression)&u;
     }
 
     /* Convert to an allocated Expression
      */
-    extern (C++) Expression copy()
+    extern (D) Expression copy()
     {
         Expression e = exp();
         //if (e.size > sizeof(u)) printf("%s\n", EXPtoString(e.op).ptr);
@@ -526,7 +526,7 @@  extern (C++) abstract class Expression : ASTNode
     /*********************************
      * Does *not* do a deep copy.
      */
-    final Expression copy()
+    extern (D) final Expression copy()
     {
         Expression e;
         if (!size)
@@ -745,7 +745,7 @@  extern (C++) abstract class Expression : ASTNode
         return toLvalue(sc, e);
     }
 
-    final Expression implicitCastTo(Scope* sc, Type t)
+    extern (D) final Expression implicitCastTo(Scope* sc, Type t)
     {
         return .implicitCastTo(this, sc, t);
     }
@@ -755,7 +755,7 @@  extern (C++) abstract class Expression : ASTNode
         return .implicitConvTo(this, t);
     }
 
-    final Expression castTo(Scope* sc, Type t)
+    extern (D) final Expression castTo(Scope* sc, Type t)
     {
         return .castTo(this, sc, t);
     }
@@ -861,7 +861,7 @@  extern (C++) abstract class Expression : ASTNode
         return checkValue();
     }
 
-    final bool checkDeprecated(Scope* sc, Dsymbol s)
+    extern (D) final bool checkDeprecated(Scope* sc, Dsymbol s)
     {
         return s.checkDeprecated(loc, sc);
     }
@@ -1205,10 +1205,11 @@  extern (C++) abstract class Expression : ASTNode
             return false;
         if (sc.flags & (SCOPE.ctfe | SCOPE.debug_))
             return false;
-        /* The original expression (`new S(...)`) will be verified instead. This
-         * is to keep errors related to the original code and not the lowering.
+        /* The original expressions (`new S(...)` or `new S[...]``) will be
+         * verified instead. This is to keep errors related to the original code
+         * and not the lowering.
          */
-        if (f.ident == Id._d_newitemT)
+        if (f.ident == Id._d_newitemT || f.ident == Id._d_newarrayT)
             return false;
 
         if (!f.isNogc())
@@ -1568,12 +1569,6 @@  extern (C++) final class IntegerExp : Expression
         return new IntegerExp(loc, value, type);
     }
 
-    // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, const ref Loc loc, dinteger_t value, Type type)
-    {
-        emplaceExp!(IntegerExp)(pue, loc, value, type);
-    }
-
     override bool equals(const RootObject o) const
     {
         if (this == o)
@@ -1641,7 +1636,7 @@  extern (C++) final class IntegerExp : Expression
         return value;
     }
 
-    void setInteger(dinteger_t value)
+    extern (D) void setInteger(dinteger_t value)
     {
         this.value = normalize(type.toBasetype().ty, value);
     }
@@ -1838,12 +1833,6 @@  extern (C++) final class RealExp : Expression
         return new RealExp(loc, value, type);
     }
 
-    // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, const ref Loc loc, real_t value, Type type)
-    {
-        emplaceExp!(RealExp)(pue, loc, value, type);
-    }
-
     /********************************
      * Test to see if two reals are the same.
      * Regard NaN's as equivalent.
@@ -1936,12 +1925,6 @@  extern (C++) final class ComplexExp : Expression
         return new ComplexExp(loc, value, type);
     }
 
-    // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, const ref Loc loc, complex_t value, Type type)
-    {
-        emplaceExp!(ComplexExp)(pue, loc, value, type);
-    }
-
     override bool equals(const RootObject o) const
     {
         if (this == o)
@@ -2277,22 +2260,6 @@  extern (C++) final class StringExp : Expression
         return new StringExp(loc, string[0 .. len]);
     }
 
-    // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, const ref Loc loc, const(char)* s)
-    {
-        emplaceExp!(StringExp)(pue, loc, s.toDString());
-    }
-
-    extern (D) static void emplace(UnionExp* pue, const ref Loc loc, const(void)[] string)
-    {
-        emplaceExp!(StringExp)(pue, loc, string);
-    }
-
-    extern (D) static void emplace(UnionExp* pue, const ref Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix)
-    {
-        emplaceExp!(StringExp)(pue, loc, string, len, sz, postfix);
-    }
-
     override bool equals(const RootObject o) const
     {
         //printf("StringExp::equals('%s') %s\n", o.toChars(), toChars());
@@ -2428,7 +2395,7 @@  extern (C++) final class StringExp : Expression
      *  i = index
      *  c = code unit to set it to
      */
-    void setCodeUnit(size_t i, dchar c)
+    extern (D) void setCodeUnit(size_t i, dchar c)
     {
         assert(i < len);
         final switch (sz)
@@ -2778,12 +2745,6 @@  extern (C++) final class ArrayLiteralExp : Expression
         return new ArrayLiteralExp(loc, null, elements);
     }
 
-    // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, const ref Loc loc, Expressions* elements)
-    {
-        emplaceExp!(ArrayLiteralExp)(pue, loc, null, elements);
-    }
-
     override ArrayLiteralExp syntaxCopy()
     {
         return new ArrayLiteralExp(loc,
@@ -2822,12 +2783,12 @@  extern (C++) final class ArrayLiteralExp : Expression
         return false;
     }
 
-    Expression getElement(size_t i)
+    Expression getElement(size_t i) // use opIndex instead
     {
         return this[i];
     }
 
-    Expression opIndex(size_t i)
+    extern (D) Expression opIndex(size_t i)
     {
         auto el = (*elements)[i];
         return el ? el : basis;
@@ -3063,7 +3024,7 @@  extern (C++) final class StructLiteralExp : Expression
      * Gets expression at offset of type.
      * Returns NULL if not found.
      */
-    Expression getField(Type type, uint offset)
+    extern (D) Expression getField(Type type, uint offset)
     {
         //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
         //  /*toChars()*/"", type.toChars(), offset);
@@ -3113,7 +3074,7 @@  extern (C++) final class StructLiteralExp : Expression
      * Get index of field.
      * Returns -1 if not found.
      */
-    int getFieldIndex(Type type, uint offset)
+    extern (D) int getFieldIndex(Type type, uint offset)
     {
         /* Find which field offset is by looking at the field offsets
          */
@@ -4072,7 +4033,7 @@  extern (C++) abstract class UnaExp : Expression
      * Returns:
      *  ErrorExp
      */
-    final Expression incompatibleTypes()
+    extern (D) final Expression incompatibleTypes()
     {
         if (e1.type.toBasetype() == Type.terror)
             return e1;
@@ -4112,9 +4073,6 @@  extern (C++) abstract class UnaExp : Expression
     }
 }
 
-alias fp_t = UnionExp function(const ref Loc loc, Type, Expression, Expression);
-alias fp2_t = bool function(const ref Loc loc, EXP, Expression, Expression);
-
 /***********************************************************
  * Base class for binary operators
  */
@@ -4147,7 +4105,7 @@  extern (C++) abstract class BinExp : Expression
      * Returns:
      *  ErrorExp
      */
-    final Expression incompatibleTypes()
+    extern (D) final Expression incompatibleTypes()
     {
         if (e1.type.toBasetype() == Type.terror)
             return e1;
@@ -4357,7 +4315,7 @@  extern (C++) abstract class BinExp : Expression
 
     }
 
-    final Expression reorderSettingAAElem(Scope* sc)
+    extern (D) final Expression reorderSettingAAElem(Scope* sc)
     {
         BinExp be = this;
 
@@ -4729,7 +4687,7 @@  extern (C++) final class DotTemplateInstanceExp : UnaExp
         return new DotTemplateInstanceExp(loc, e1.syntaxCopy(), ti.name, TemplateInstance.arraySyntaxCopy(ti.tiargs));
     }
 
-    bool findTempDecl(Scope* sc)
+    extern (D) bool findTempDecl(Scope* sc)
     {
         static if (LOGSEMANTIC)
         {
@@ -5323,12 +5281,6 @@  extern (C++) final class VectorExp : UnaExp
         return new VectorExp(loc, e, t);
     }
 
-    // Same as create, but doesn't allocate memory.
-    static void emplace(UnionExp* pue, const ref Loc loc, Expression e, Type type)
-    {
-        emplaceExp!(VectorExp)(pue, loc, e, type);
-    }
-
     override VectorExp syntaxCopy()
     {
         return new VectorExp(loc, e1.syntaxCopy(), to.syntaxCopy());
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index a92d9ada6f5..cfd5198ce79 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -39,7 +39,6 @@  class ClassDeclaration;
 class OverloadSet;
 class StringExp;
 class LoweredAssignExp;
-struct UnionExp;
 #ifdef IN_GCC
 typedef union tree_node Symbol;
 #else
@@ -47,11 +46,6 @@  struct Symbol;          // back end symbol
 #endif
 
 void expandTuples(Expressions *exps, Identifiers *names = nullptr);
-bool isTrivialExp(Expression *e);
-bool hasSideEffect(Expression *e, bool assumeImpureCalls = false);
-
-enum BE : int32_t;
-BE canThrow(Expression *e, FuncDeclaration *func, ErrorSink *eSink);
 
 typedef unsigned char OwnedBy;
 enum
@@ -86,7 +80,6 @@  public:
 
     size_t size() const;
     static void _init();
-    Expression *copy();
     virtual Expression *syntaxCopy();
 
     // kludge for template.isExpression()
@@ -103,13 +96,10 @@  public:
     virtual bool isLvalue();
     virtual Expression *toLvalue(Scope *sc, Expression *e);
     virtual Expression *modifiableLvalue(Scope *sc, Expression *e);
-    Expression *implicitCastTo(Scope *sc, Type *t);
     MATCH implicitConvTo(Type *t);
-    Expression *castTo(Scope *sc, Type *t);
     virtual Expression *resolveLoc(const Loc &loc, Scope *sc);
     virtual bool checkType();
     virtual bool checkValue();
-    bool checkDeprecated(Scope *sc, Dsymbol *s);
     virtual Expression *addDtorHook(Scope *sc);
     Expression *addressOf();
     Expression *deref();
@@ -248,7 +238,6 @@  public:
     dinteger_t value;
 
     static IntegerExp *create(const Loc &loc, dinteger_t value, Type *type);
-    static void emplace(UnionExp *pue, const Loc &loc, dinteger_t value, Type *type);
     bool equals(const RootObject * const o) const override;
     dinteger_t toInteger() override;
     real_t toReal() override;
@@ -258,7 +247,6 @@  public:
     Expression *toLvalue(Scope *sc, Expression *e) override;
     void accept(Visitor *v) override { v->visit(this); }
     dinteger_t getInteger() { return value; }
-    void setInteger(dinteger_t value);
     template<int v>
     static IntegerExp literal();
 };
@@ -278,7 +266,6 @@  public:
     real_t value;
 
     static RealExp *create(const Loc &loc, real_t value, Type *type);
-    static void emplace(UnionExp *pue, const Loc &loc, real_t value, Type *type);
     bool equals(const RootObject * const o) const override;
     bool isIdentical(const Expression *e) const override;
     dinteger_t toInteger() override;
@@ -296,7 +283,6 @@  public:
     complex_t value;
 
     static ComplexExp *create(const Loc &loc, complex_t value, Type *type);
-    static void emplace(UnionExp *pue, const Loc &loc, complex_t value, Type *type);
     bool equals(const RootObject * const o) const override;
     bool isIdentical(const Expression *e) const override;
     dinteger_t toInteger() override;
@@ -376,15 +362,13 @@  public:
     void *string;       // char, wchar, or dchar data
     size_t len;         // number of chars, wchars, or dchars
     unsigned char sz;   // 1: char, 2: wchar, 4: dchar
-    bool committed;     // if type is committed
-    bool hexString;     // if string is parsed from a hex string literal
+    d_bool committed;   // if type is committed
+    d_bool hexString;   // if string is parsed from a hex string literal
 
     static StringExp *create(const Loc &loc, const char *s);
     static StringExp *create(const Loc &loc, const void *s, d_size_t len);
-    static void emplace(UnionExp *pue, const Loc &loc, const char *s);
     bool equals(const RootObject * const o) const override;
     char32_t getCodeUnit(d_size_t i) const;
-    void setCodeUnit(d_size_t i, char32_t c);
     StringExp *toStringExp() override;
     StringExp *toUTF8(Scope *sc);
     Optional<bool> toBool() override;
@@ -427,11 +411,9 @@  public:
     Expressions *elements;
 
     static ArrayLiteralExp *create(const Loc &loc, Expressions *elements);
-    static void emplace(UnionExp *pue, const Loc &loc, Expressions *elements);
     ArrayLiteralExp *syntaxCopy() override;
     bool equals(const RootObject * const o) const override;
-    Expression *getElement(d_size_t i); // use opIndex instead
-    Expression *opIndex(d_size_t i);
+    Expression *getElement(d_size_t i);
     Optional<bool> toBool() override;
     StringExp *toStringExp() override;
 
@@ -490,8 +472,6 @@  public:
     static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = NULL);
     bool equals(const RootObject * const o) const override;
     StructLiteralExp *syntaxCopy() override;
-    Expression *getField(Type *type, unsigned offset);
-    int getFieldIndex(Type *type, unsigned offset);
     Expression *addDtorHook(Scope *sc) override;
     Expression *toLvalue(Scope *sc, Expression *e) override;
 
@@ -702,7 +682,6 @@  public:
     Expression *e1;
 
     UnaExp *syntaxCopy() override;
-    Expression *incompatibleTypes();
     Expression *resolveLoc(const Loc &loc, Scope *sc) override final;
 
     void accept(Visitor *v) override { v->visit(this); }
@@ -718,9 +697,6 @@  public:
     Type *att2; // Save alias this type to detect recursion
 
     BinExp *syntaxCopy() override;
-    Expression *incompatibleTypes();
-
-    Expression *reorderSettingAAElem(Scope *sc);
 
     void accept(Visitor *v) override { v->visit(this); }
 };
@@ -806,7 +782,6 @@  public:
     TemplateInstance *ti;
 
     DotTemplateInstanceExp *syntaxCopy() override;
-    bool findTempDecl(Scope *sc);
     bool checkType() override;
     bool checkValue() override;
     void accept(Visitor *v) override { v->visit(this); }
@@ -925,7 +900,6 @@  public:
     OwnedBy ownedByCtfe;
 
     static VectorExp *create(const Loc &loc, Expression *e, Type *t);
-    static void emplace(UnionExp *pue, const Loc &loc, Expression *e, Type *t);
     VectorExp *syntaxCopy() override;
     void accept(Visitor *v) override { v->visit(this); }
 };
@@ -1386,62 +1360,6 @@  public:
 
 /****************************************************************/
 
-/* A type meant as a union of all the Expression types,
- * to serve essentially as a Variant that will sit on the stack
- * during CTFE to reduce memory consumption.
- */
-struct UnionExp
-{
-    UnionExp() { }  // yes, default constructor does nothing
-
-    UnionExp(Expression *e)
-    {
-        memcpy(this, (void *)e, e->size());
-    }
-
-    /* Extract pointer to Expression
-     */
-    Expression *exp() { return (Expression *)&u; }
-
-    /* Convert to an allocated Expression
-     */
-    Expression *copy();
-
-private:
-    // Ensure that the union is suitably aligned.
-#if defined(__GNUC__) || defined(__clang__)
-    __attribute__((aligned(8)))
-#elif defined(_MSC_VER)
-    __declspec(align(8))
-#elif defined(__DMC__)
-    #pragma pack(8)
-#endif
-    union
-    {
-        char exp       [sizeof(Expression)];
-        char integerexp[sizeof(IntegerExp)];
-        char errorexp  [sizeof(ErrorExp)];
-        char realexp   [sizeof(RealExp)];
-        char complexexp[sizeof(ComplexExp)];
-        char symoffexp [sizeof(SymOffExp)];
-        char stringexp [sizeof(StringExp)];
-        char arrayliteralexp [sizeof(ArrayLiteralExp)];
-        char assocarrayliteralexp [sizeof(AssocArrayLiteralExp)];
-        char structliteralexp [sizeof(StructLiteralExp)];
-        char nullexp   [sizeof(NullExp)];
-        char dotvarexp [sizeof(DotVarExp)];
-        char addrexp   [sizeof(AddrExp)];
-        char indexexp  [sizeof(IndexExp)];
-        char sliceexp  [sizeof(SliceExp)];
-        char vectorexp [sizeof(VectorExp)];
-    } u;
-#if defined(__DMC__)
-    #pragma pack()
-#endif
-};
-
-/****************************************************************/
-
 class ObjcClassReferenceExp final : public Expression
 {
 public:
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 3472f9254cb..ac8e5715b28 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -4406,6 +4406,58 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 (*exp.arguments)[i] = arg;
                 tb = tb.isTypeDArray().next.toBasetype();
             }
+
+            if (nargs == 1)
+            {
+                if (global.params.betterC || !sc.needsCodegen())
+                    goto LskipNewArrayLowering;
+
+                /* Class types may inherit base classes that have errors.
+                 * This may leak errors from the base class to the derived one
+                 * and then to the hook. Semantic analysis is performed eagerly
+                 * to a void this.
+                 */
+                if (auto tc = exp.type.nextOf.isTypeClass())
+                {
+                    tc.sym.dsymbolSemantic(sc);
+                    if (tc.sym.errors)
+                        goto LskipNewArrayLowering;
+                }
+
+                auto hook = global.params.tracegc ? Id._d_newarrayTTrace : Id._d_newarrayT;
+                if (!verifyHookExist(exp.loc, *sc, hook, "new array"))
+                    goto LskipNewArrayLowering;
+
+                /* Lower the memory allocation and initialization of `new T[n]`
+                 * to `_d_newarrayT!T(n)`.
+                 */
+                Expression lowering = new IdentifierExp(exp.loc, Id.empty);
+                lowering = new DotIdExp(exp.loc, lowering, Id.object);
+                auto tiargs = new Objects();
+                /* Remove `inout`, `const`, `immutable` and `shared` to reduce
+                 * the number of generated `_d_newarrayT` instances.
+                 */
+                const isShared = exp.type.nextOf.isShared();
+                auto t = exp.type.nextOf.unqualify(MODFlags.wild | MODFlags.const_ |
+                    MODFlags.immutable_ | MODFlags.shared_);
+                tiargs.push(t);
+                lowering = new DotTemplateInstanceExp(exp.loc, lowering, hook, tiargs);
+
+                auto arguments = new Expressions();
+                if (global.params.tracegc)
+                {
+                    auto funcname = (sc.callsc && sc.callsc.func) ?
+                        sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
+                    arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
+                    arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
+                    arguments.push(new StringExp(exp.loc, funcname.toDString()));
+                }
+                arguments.push((*exp.arguments)[0]);
+                arguments.push(new IntegerExp(exp.loc, isShared, Type.tbool));
+
+                lowering = new CallExp(exp.loc, lowering, arguments);
+                exp.lowering = lowering.expressionSemantic(sc);
+            }
         }
         else if (tb.isscalar())
         {
@@ -4447,6 +4499,7 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return setError();
         }
 
+    LskipNewArrayLowering:
         //printf("NewExp: '%s'\n", toChars());
         //printf("NewExp:type '%s'\n", type.toChars());
         semanticTypeInfo(sc, exp.type);
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index ac73e70db34..99848d80643 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -689,7 +689,7 @@  extern (C++) class FuncDeclaration : Declaration
      * Determine if 'this' overrides fd.
      * Return !=0 if it does.
      */
-    final int overrides(FuncDeclaration fd)
+    extern (D) final int overrides(FuncDeclaration fd)
     {
         int result = 0;
         if (fd.ident == ident)
@@ -838,7 +838,7 @@  extern (C++) class FuncDeclaration : Declaration
      * Returns:
      *  base class if overriding, null if not
      */
-    final BaseClass* overrideInterface()
+    extern (D) final BaseClass* overrideInterface()
     {
         for (ClassDeclaration cd = toParent2().isClassDeclaration(); cd; cd = cd.baseClass)
         {
@@ -1215,7 +1215,7 @@  extern (C++) class FuncDeclaration : Declaration
      *      -1      increase nesting by 1 (`fd` is nested within `this`)
      *      LevelError  error, `this` cannot call `fd`
      */
-    final int getLevel(FuncDeclaration fd, int intypeof)
+    extern (D) final int getLevel(FuncDeclaration fd, int intypeof)
     {
         //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd.toChars());
         Dsymbol fdparent = fd.toParent2();
@@ -1276,8 +1276,8 @@  extern (C++) class FuncDeclaration : Declaration
      *      -1      increase nesting by 1 (`fd` is nested within 'this')
      *      LevelError  error
      */
-    final int getLevelAndCheck(const ref Loc loc, Scope* sc, FuncDeclaration fd,
-                               Declaration decl)
+    extern (D) final int getLevelAndCheck(const ref Loc loc, Scope* sc, FuncDeclaration fd,
+                                          Declaration decl)
     {
         int level = getLevel(fd, sc.intypeof);
         if (level != LevelError)
@@ -1490,7 +1490,7 @@  extern (C++) class FuncDeclaration : Declaration
         return purity;
     }
 
-    final PURE isPureBypassingInference()
+    extern (D) final PURE isPureBypassingInference()
     {
         if (purityInprocess)
             return PURE.fwdref;
@@ -1544,7 +1544,7 @@  extern (C++) class FuncDeclaration : Declaration
         return type.toTypeFunction().trust == TRUST.safe;
     }
 
-    final bool isSafeBypassingInference()
+    extern (D) final bool isSafeBypassingInference()
     {
         return !(safetyInprocess) && isSafe();
     }
@@ -1612,7 +1612,7 @@  extern (C++) class FuncDeclaration : Declaration
         return type.toTypeFunction().isnogc;
     }
 
-    final bool isNogcBypassingInference()
+    extern (D) final bool isNogcBypassingInference()
     {
         return !nogcInprocess && isNogc();
     }
@@ -2935,7 +2935,7 @@  extern (C++) class FuncDeclaration : Declaration
      * Returns:
      *      `false` if the result cannot be returned by hidden reference.
      */
-    final bool checkNRVO()
+    extern (D) final bool checkNRVO()
     {
         if (!isNRVO() || returns is null)
             return false;
@@ -3939,7 +3939,7 @@  extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
      * If B to A conversion is convariant that requires offseet adjusting,
      * all return statements should be adjusted to return expressions typed A.
      */
-    void modifyReturns(Scope* sc, Type tret)
+    extern (D) void modifyReturns(Scope* sc, Type tret)
     {
         import dmd.statement_rewrite_walker;
 
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 4048286ce71..5c21be186d8 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -272,9 +272,9 @@  struct CompileEnv
     DString time;
     DString vendor;
     DString timestamp;
-    bool previewIn;
-    bool ddocOutput;
-    bool shortenedMethods;
+    d_bool previewIn;
+    d_bool ddocOutput;
+    d_bool shortenedMethods;
 };
 
 struct Global
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 9d585cb898b..d935bd3480b 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -58,6 +58,7 @@  struct HdrGenState
     bool hdrgen;        /// true if generating header file
     bool ddoc;          /// true if generating Ddoc file
     bool fullDump;      /// true if generating a full AST dump file
+    bool importcHdr;    /// true if generating a .di file from an ImportC file
 
     bool fullQual;      /// fully qualify types when printing
     int tpltMember;
@@ -85,6 +86,7 @@  extern (C++) void genhdrfile(Module m, ref OutBuffer buf)
     buf.writenl();
     HdrGenState hgs;
     hgs.hdrgen = true;
+    hgs.importcHdr = (m.filetype == FileType.c);
     toCBuffer(m, buf, hgs);
 }
 
@@ -1521,6 +1523,28 @@  void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
         buf.level--;
         buf.writeByte('}');
         buf.writenl();
+
+        if (!hgs.importcHdr)
+            return;
+
+        /* C enums get their members inserted into the symbol table of the enum declaration.
+         * This is accomplished in addEnumMembersToSymtab().
+         * But when generating D code from ImportC code, D rulez are followed.
+         * Accomplish this by generating an alias declaration for each member
+         */
+        foreach (em; *d.members)
+        {
+            if (!em)
+                continue;
+            buf.writestring("alias ");
+            buf.writestring(em.ident.toString);
+            buf.writestring(" = ");
+            buf.writestring(d.ident.toString);
+            buf.writeByte('.');
+            buf.writestring(em.ident.toString);
+            buf.writeByte(';');
+            buf.writenl();
+        }
     }
 
     void visitNspace(Nspace d)
@@ -1541,6 +1565,7 @@  void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
 
     void visitStructDeclaration(StructDeclaration d)
     {
+        //printf("visitStructDeclaration() %s\n", d.ident.toChars());
         buf.writestring(d.kind());
         buf.writeByte(' ');
         if (!d.isAnonymous())
@@ -1595,6 +1620,8 @@  void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
     {
         if (d.storage_class & STC.local)
             return;
+        if (d.adFlags & d.hidden)
+            return;
         buf.writestring("alias ");
         if (d.aliassym)
         {
@@ -1663,7 +1690,7 @@  void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
         //printf("FuncDeclaration::toCBuffer() '%s'\n", f.toChars());
         if (stcToBuffer(buf, f.storage_class))
             buf.writeByte(' ');
-        auto tf = cast(TypeFunction)f.type;
+        auto tf = f.type.isTypeFunction();
         typeToBuffer(tf, f.ident, buf, &hgs);
 
         if (hgs.hdrgen)
@@ -4038,6 +4065,7 @@  private void typeToBufferx(Type t, ref OutBuffer buf, HdrGenState* hgs)
 
     void visitIdentifier(TypeIdentifier t)
     {
+        //printf("visitTypeIdentifier() %s\n", t.ident.toChars());
         buf.writestring(t.ident.toString());
         visitTypeQualifiedHelper(t);
     }
@@ -4064,11 +4092,14 @@  private void typeToBufferx(Type t, ref OutBuffer buf, HdrGenState* hgs)
 
     void visitEnum(TypeEnum t)
     {
+        //printf("visitEnum: %s\n", t.sym.toChars());
         buf.writestring(hgs.fullQual ? t.sym.toPrettyChars() : t.sym.toChars());
     }
 
     void visitStruct(TypeStruct t)
     {
+        //printf("visitTypeStruct() %s\n", t.sym.toChars());
+
         // https://issues.dlang.org/show_bug.cgi?id=13776
         // Don't use ti.toAlias() to avoid forward reference error
         // while printing messages.
@@ -4095,6 +4126,11 @@  private void typeToBufferx(Type t, ref OutBuffer buf, HdrGenState* hgs)
     {
         if (t.mod & MODFlags.const_)
             buf.writestring("const ");
+        if (hgs.importcHdr && t.id)
+        {
+            buf.writestring(t.id.toChars());
+            return;
+        }
         buf.writestring(Token.toChars(t.tok));
         buf.writeByte(' ');
         if (t.id)
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index b506e6feb66..5fcda91b435 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -321,6 +321,8 @@  immutable Msgtable[] msgtable =
     { "_d_newclassTTrace" },
     { "_d_newitemT" },
     { "_d_newitemTTrace" },
+    { "_d_newarrayT" },
+    { "_d_newarrayTTrace" },
     { "_d_assert_fail" },
     { "dup" },
     { "_aaApply" },
diff --git a/gcc/d/dmd/import.h b/gcc/d/dmd/import.h
index ff25ba2045d..31ee61a65fb 100644
--- a/gcc/d/dmd/import.h
+++ b/gcc/d/dmd/import.h
@@ -41,7 +41,6 @@  public:
     const char *kind() const override;
     Visibility visible() override;
     Import *syntaxCopy(Dsymbol *s) override; // copy only syntax trees
-    void load(Scope *sc);
     void importAll(Scope *sc) override;
     Dsymbol *toAlias() override;
     void addMember(Scope *sc, ScopeDsymbol *sds) override;
diff --git a/gcc/d/dmd/init.h b/gcc/d/dmd/init.h
index 4ab5848454e..67d0527a3b2 100644
--- a/gcc/d/dmd/init.h
+++ b/gcc/d/dmd/init.h
@@ -79,7 +79,6 @@  public:
     d_bool isCarray;      // C array semantics
 
     bool isAssociativeArray() const;
-    Expression *toAssocArrayLiteral();
 
     void accept(Visitor *v) override { v->visit(this); }
 };
diff --git a/gcc/d/dmd/location.d b/gcc/d/dmd/location.d
index ef2bd0af779..9fe48b88844 100644
--- a/gcc/d/dmd/location.d
+++ b/gcc/d/dmd/location.d
@@ -64,7 +64,7 @@  nothrow:
         this.messageStyle = messageStyle;
     }
 
-    extern (D) this(const(char)* filename, uint linnum, uint charnum) @safe
+    extern (C++) this(const(char)* filename, uint linnum, uint charnum) @safe
     {
         this._linnum = linnum;
         this._charnum = charnum;
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index ce512667694..6e8153d485a 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -127,7 +127,6 @@  public:
     Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
     bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0) override;
     Dsymbol *symtabInsert(Dsymbol *s) override;
-    void deleteObjFile();
     static void runDeferredSemantic();
     static void runDeferredSemantic2();
     static void runDeferredSemantic3();
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 70a0c032e65..6af140f7491 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -1393,7 +1393,7 @@  extern (C++) abstract class Type : ASTNode
      * For our new type 'this', which is type-constructed from t,
      * fill in the cto, ito, sto, scto, wto shortcuts.
      */
-    final void fixTo(Type t)
+    extern (D) final void fixTo(Type t)
     {
         // If fixing this: immutable(T*) by t: immutable(T)*,
         // cache t to this.xto won't break transitivity.
@@ -1528,7 +1528,7 @@  extern (C++) abstract class Type : ASTNode
     /***************************
      * Look for bugs in constructing types.
      */
-    final void check()
+    extern (D) final void check()
     {
         if (mcache)
         with (mcache)
@@ -1722,7 +1722,7 @@  extern (C++) abstract class Type : ASTNode
      * Apply STCxxxx bits to existing type.
      * Use *before* semantic analysis is run.
      */
-    final Type addSTC(StorageClass stc)
+    extern (D) final Type addSTC(StorageClass stc)
     {
         Type t = this;
         if (t.isImmutable())
@@ -2555,7 +2555,7 @@  extern (C++) abstract class Type : ASTNode
      * Return the mask that an integral type will
      * fit into.
      */
-    final uinteger_t sizemask()
+    extern (D) final uinteger_t sizemask()
     {
         uinteger_t m;
         switch (toBasetype().ty)
@@ -5227,7 +5227,7 @@  extern (C++) abstract class TypeQualified : Type
     // us a `TypeQualified`
     abstract override TypeQualified syntaxCopy();
 
-    final void syntaxCopyHelper(TypeQualified t)
+    extern (D) final void syntaxCopyHelper(TypeQualified t)
     {
         //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t.toChars(), toChars());
         idents.setDim(t.idents.length);
@@ -5265,17 +5265,17 @@  extern (C++) abstract class TypeQualified : Type
         }
     }
 
-    final void addIdent(Identifier ident)
+    extern (D) final void addIdent(Identifier ident)
     {
         idents.push(ident);
     }
 
-    final void addInst(TemplateInstance inst)
+    extern (D) final void addInst(TemplateInstance inst)
     {
         idents.push(inst);
     }
 
-    final void addIndex(RootObject e)
+    extern (D) final void addIndex(RootObject e)
     {
         idents.push(e);
     }
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index aeeee8c7dad..e72d9187ca4 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -39,8 +39,6 @@  typedef union tree_node type;
 typedef struct TYPE type;
 #endif
 
-void semanticTypeInfo(Scope *sc, Type *t);
-
 Type *typeSemantic(Type *t, const Loc &loc, Scope *sc);
 Type *merge(Type *type);
 
@@ -272,9 +270,6 @@  public:
     Type *wildConstOf();
     Type *sharedWildOf();
     Type *sharedWildConstOf();
-    void fixTo(Type *t);
-    void check();
-    Type *addSTC(StorageClass stc);
     Type *castMod(MOD mod);
     Type *addMod(MOD mod);
     virtual Type *addStorageClass(StorageClass stc);
@@ -316,7 +311,6 @@  public:
     virtual bool hasInvariant();
     virtual Type *nextOf();
     Type *baseElemOf();
-    uinteger_t sizemask();
     virtual bool needsDestruction();
     virtual bool needsCopyOrPostblit();
     virtual bool needsNested();
@@ -707,10 +701,6 @@  public:
     // representing ident.ident!tiargs.ident. ... etc.
     Objects idents;
 
-    void syntaxCopyHelper(TypeQualified *t);
-    void addIdent(Identifier *ident);
-    void addInst(TemplateInstance *inst);
-    void addIndex(RootObject *expr);
     uinteger_t size(const Loc &loc) override;
 
     void accept(Visitor *v) override { v->visit(this); }
@@ -937,7 +927,5 @@  public:
 
 /**************************************************************/
 
-bool arrayTypeCompatibleWithoutCasting(Type *t1, Type *t2);
-
 // If the type is a class or struct, returns the symbol for it, else null.
 AggregateDeclaration *isAggregate(Type *t);
diff --git a/gcc/d/dmd/objc.h b/gcc/d/dmd/objc.h
index a5cc6f1b089..40f634e9122 100644
--- a/gcc/d/dmd/objc.h
+++ b/gcc/d/dmd/objc.h
@@ -30,8 +30,6 @@  struct ObjcSelector
 
     static void _init();
 
-    ObjcSelector(const char *sv, size_t len, size_t pcount);
-
     static ObjcSelector *create(FuncDeclaration *fdecl);
 };
 
diff --git a/gcc/d/dmd/scope.h b/gcc/d/dmd/scope.h
index 3c4ae495265..178542e37b0 100644
--- a/gcc/d/dmd/scope.h
+++ b/gcc/d/dmd/scope.h
@@ -126,6 +126,4 @@  struct Scope
 
     AliasDeclaration *aliasAsg; // if set, then aliasAsg is being assigned a new value,
                                 // do not set wasRead for it
-
-    Dsymbol *search(const Loc &loc, Identifier *ident, Dsymbol **pscopesym, int flags = IgnoreNone);
 };
diff --git a/gcc/d/dmd/sideeffect.d b/gcc/d/dmd/sideeffect.d
index 465bffe4da0..80c9a46958f 100644
--- a/gcc/d/dmd/sideeffect.d
+++ b/gcc/d/dmd/sideeffect.d
@@ -32,7 +32,7 @@  import dmd.visitor;
  *  1. save evaluation order
  *  2. prevent sharing of sub-expression in AST
  */
-extern (C++) bool isTrivialExp(Expression e)
+bool isTrivialExp(Expression e)
 {
     extern (C++) final class IsTrivialExp : StoppableVisitor
     {
@@ -70,7 +70,7 @@  extern (C++) bool isTrivialExp(Expression e)
  *   assumeImpureCalls = whether function calls should always be assumed to
  *                       be impure (e.g. debug is allowed to violate purity)
  */
-extern (C++) bool hasSideEffect(Expression e, bool assumeImpureCalls = false)
+bool hasSideEffect(Expression e, bool assumeImpureCalls = false)
 {
     extern (C++) final class LambdaHasSideEffect : StoppableVisitor
     {
diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d
index 5a31e07dc0f..b5906c8edc3 100644
--- a/gcc/d/dmd/statement.d
+++ b/gcc/d/dmd/statement.d
@@ -114,7 +114,7 @@  extern (C++) abstract class Statement : ASTNode
      * Returns:
      *     `true` if statement uses exception handling
      */
-    final bool usesEH()
+    extern (D) final bool usesEH()
     {
         extern (C++) final class UsesEH : StoppableVisitor
         {
@@ -153,7 +153,7 @@  extern (C++) abstract class Statement : ASTNode
      * Returns:
      *   `true` if statement 'comes from' somewhere else, like a goto
      */
-    final bool comeFrom()
+    extern (D) final bool comeFrom()
     {
         extern (C++) final class ComeFrom : StoppableVisitor
         {
@@ -192,7 +192,7 @@  extern (C++) abstract class Statement : ASTNode
      * Returns:
      *   `true` if statement has executable code.
      */
-    final bool hasCode()
+    extern (D) final bool hasCode()
     {
         extern (C++) final class HasCode : StoppableVisitor
         {
diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h
index 73feb3f912b..ef8423f1cf7 100644
--- a/gcc/d/dmd/statement.h
+++ b/gcc/d/dmd/statement.h
@@ -116,8 +116,6 @@  public:
     virtual Statement *getRelatedLabeled() { return this; }
     virtual bool hasBreak() const;
     virtual bool hasContinue() const;
-    bool usesEH();
-    bool comeFrom();
     bool hasCode();
     virtual Statement *last();
 
@@ -709,7 +707,7 @@  class AsmStatement : public Statement
 {
 public:
     Token *tokens;
-    bool caseSensitive;  // for register names
+    d_bool caseSensitive;  // for register names
 
     AsmStatement *syntaxCopy() override;
     void accept(Visitor *v) override { v->visit(this); }
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index 8622b5c6483..44f95ec0ec3 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -96,12 +96,8 @@  public:
 
     Visibility visible() override;
 
-    MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration* td2, ArgumentList argumentList);
-    RootObject *declareParameter(Scope *sc, TemplateParameter *tp, RootObject *o);
-
     TemplateDeclaration *isTemplateDeclaration() override { return this; }
 
-    TemplateTupleParameter *isVariadic();
     bool isDeprecated() const override;
     bool isOverloadable() const override;
 
@@ -298,7 +294,6 @@  public:
     const char *toChars() const override;
     const char* toPrettyCharsHelper() override final;
     Identifier *getIdent() override final;
-    hash_t toHash();
 
     bool isDiscardable();
     bool needsCodegen();
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index c76d549550a..317a6e6c382 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -900,7 +900,7 @@  extern (C++) struct Token
 
 nothrow:
 
-    int isKeyword() pure const @safe @nogc
+    extern (D) int isKeyword() pure const @safe @nogc
     {
         foreach (kw; keywords)
         {
diff --git a/gcc/d/dmd/tokens.h b/gcc/d/dmd/tokens.h
index b1f633fb9d9..560942d1e47 100644
--- a/gcc/d/dmd/tokens.h
+++ b/gcc/d/dmd/tokens.h
@@ -469,10 +469,7 @@  struct Token
         Identifier *ident;
     };
 
-    void free();
-
     Token() : next(NULL) {}
-    int isKeyword();
     const char *toChars() const;
 
     static const char *toChars(TOK value);
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 72180b100af..29f114a1b99 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -2368,22 +2368,10 @@  public:
 
 	if (e->arguments->length == 1)
 	  {
-	    /* Single dimension array allocations.  */
-	    Expression *arg = (*e->arguments)[0];
-
-	    if (tarray->next->size () == 0)
-	      {
-		/* Array element size is unknown.  */
-		this->result_ = d_array_value (build_ctype (e->type),
-					       size_int (0), null_pointer_node);
-		return;
-	      }
-
-	    libcall_fn libcall = tarray->next->isZeroInit ()
-	      ? LIBCALL_NEWARRAYT : LIBCALL_NEWARRAYIT;
-	    result = build_libcall (libcall, tb, 2,
-				    build_typeinfo (e, e->type),
-				    build_expr (arg));
+	    /* Single dimension array allocations has already been handled by
+	       the front-end.  */
+	    gcc_assert (e->lowering);
+	    result = build_expr (e->lowering);
 	  }
 	else
 	  {
diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def
index 4d1ba09f1a7..f7887e1548f 100644
--- a/gcc/d/runtime.def
+++ b/gcc/d/runtime.def
@@ -70,13 +70,8 @@  DEF_D_RUNTIME (DYNAMIC_CAST, "_d_dynamic_cast", RT(OBJECT),
 DEF_D_RUNTIME (INTERFACE_CAST, "_d_interface_cast", RT(OBJECT),
 	       P2(OBJECT, CLASSINFO), 0)
 
-/* Used when calling new on an array.  The `i' variant is for when the
-   initializer is nonzero, and the `m' variant is when initializing a
-   multi-dimensional array.  */
-DEF_D_RUNTIME (NEWARRAYT, "_d_newarrayT", RT(ARRAY_VOID),
-	       P2(CONST_TYPEINFO, SIZE_T), 0)
-DEF_D_RUNTIME (NEWARRAYIT, "_d_newarrayiT", RT(ARRAY_VOID),
-	       P2(CONST_TYPEINFO, SIZE_T), 0)
+/* Used when calling `new' on a multi-dimensional array.
+   The `i' variant is for when the initializer is nonzero.  */
 DEF_D_RUNTIME (NEWARRAYMTX, "_d_newarraymTX", RT(ARRAY_VOID),
 	       P2(CONST_TYPEINFO, ARRAY_SIZE_T), 0)
 DEF_D_RUNTIME (NEWARRAYMITX, "_d_newarraymiTX", RT(ARRAY_VOID),
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10727a.d b/gcc/testsuite/gdc.test/fail_compilation/ice10727a.d
index ebefe33f2db..6d3b223db0e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10727a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10727a.d
@@ -4,6 +4,8 @@ 
 TEST_OUTPUT:
 ---
 fail_compilation/imports/foo10727a.d(34): Error: undefined identifier `Frop`
+fail_compilation/imports/foo10727a.d(26): Error: template instance `foo10727a.CirBuff!(Foo)` error instantiating
+fail_compilation/imports/foo10727a.d(31):        instantiated from here: `Bar!(Foo)`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10727b.d b/gcc/testsuite/gdc.test/fail_compilation/ice10727b.d
index 125ac12b193..4a59d5ce6b5 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10727b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10727b.d
@@ -4,6 +4,8 @@ 
 TEST_OUTPUT:
 ---
 fail_compilation/imports/foo10727b.d(25): Error: undefined identifier `Frop`
+fail_compilation/imports/foo10727b.d(17): Error: template instance `foo10727b.CirBuff!(Foo)` error instantiating
+fail_compilation/imports/foo10727b.d(22):        instantiated from here: `Bar!(Foo)`
 ---
 */
 
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 794600274a3..2a0baf09a4b 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@ 
-4c18eed9674e04c1ca89fbc8bd5c4e483eb5477c
+e48bc0987dfec35bc76a3015ee3e85906ce86dfd
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/core/internal/array/construction.d b/libphobos/libdruntime/core/internal/array/construction.d
index 25083597761..54f8767139c 100644
--- a/libphobos/libdruntime/core/internal/array/construction.d
+++ b/libphobos/libdruntime/core/internal/array/construction.d
@@ -11,6 +11,11 @@  module core.internal.array.construction;
 
 import core.internal.traits : Unqual;
 
+debug(PRINTF)
+{
+    import core.stdc.stdio;
+}
+
 /**
  * Does array initialization (not assignment) from another array of the same element type.
  * Params:
@@ -319,3 +324,165 @@  void _d_arraysetctor(Tarr : T[], T)(scope Tarr p, scope ref T value) @trusted
     assert(!didThrow);
     assert(counter == 4);
 }
+
+/**
+ * Allocate an array with the garbage collector. Also initalize elements if
+ * their type has an initializer. Otherwise, not zero-initialize the array.
+ *
+ * Has three variants:
+ *      `_d_newarrayU` leaves elements uninitialized
+ *      `_d_newarrayT` initializes to 0 or based on initializer
+ *
+ * Params:
+ *      length = `.length` of resulting array
+ *
+ * Returns:
+ *      newly allocated array
+ */
+T[] _d_newarrayU(T)(size_t length, bool isShared=false) pure nothrow @nogc @trusted
+{
+    alias PureType = T[] function(size_t length, bool isShared) pure nothrow @nogc @trusted;
+    return (cast(PureType) &_d_newarrayUImpl!T)(length, isShared);
+}
+
+T[] _d_newarrayUImpl(T)(size_t length, bool isShared=false) @trusted
+{
+    import core.exception : onOutOfMemoryError;
+    import core.internal.array.utils : __arrayStart, __setArrayAllocLength, __arrayAlloc;
+
+    size_t elemSize = T.sizeof;
+    size_t arraySize;
+
+    debug(PRINTF) printf("_d_newarrayU(length = x%zu, size = %zu)\n", length, elemSize);
+    if (length == 0 || elemSize == 0)
+        return null;
+
+    version (D_InlineAsm_X86)
+    {
+        asm pure nothrow @nogc
+        {
+            mov     EAX, elemSize       ;
+            mul     EAX, length         ;
+            mov     arraySize, EAX      ;
+            jnc     Lcontinue           ;
+        }
+    }
+    else version (D_InlineAsm_X86_64)
+    {
+        asm pure nothrow @nogc
+        {
+            mov     RAX, elemSize       ;
+            mul     RAX, length         ;
+            mov     arraySize, RAX      ;
+            jnc     Lcontinue           ;
+        }
+    }
+    else
+    {
+        import core.checkedint : mulu;
+
+        bool overflow = false;
+        arraySize = mulu(elemSize, length, overflow);
+        if (!overflow)
+            goto Lcontinue;
+    }
+
+Loverflow:
+    onOutOfMemoryError();
+    assert(0);
+
+Lcontinue:
+    auto info = __arrayAlloc!T(arraySize);
+    if (!info.base)
+        goto Loverflow;
+    debug(PRINTF) printf("p = %p\n", info.base);
+
+    auto arrstart = __arrayStart(info);
+
+    __setArrayAllocLength!T(info, arraySize, isShared);
+
+    return (cast(T*) arrstart)[0 .. length];
+}
+
+/// ditto
+T[] _d_newarrayT(T)(size_t length, bool isShared=false) @trusted
+{
+    T[] result = _d_newarrayU!T(length, isShared);
+
+    static if (__traits(isZeroInit, T))
+    {
+        import core.stdc.string : memset;
+        memset(result.ptr, 0, length * T.sizeof);
+    }
+    else
+    {
+        import core.internal.lifetime : emplaceInitializer;
+        foreach (ref elem; result)
+            emplaceInitializer(elem);
+    }
+
+    return result;
+}
+
+unittest
+{
+    {
+        // zero-initialization
+        struct S { int x, y; }
+        S[] s = _d_newarrayT!S(10);
+
+        assert(s !is null);
+        assert(s.length == 10);
+        foreach (ref elem; s)
+        {
+            assert(elem.x == 0);
+            assert(elem.y == 0);
+        }
+    }
+    {
+        // S.init
+        struct S { int x = 2, y = 3; }
+        S[] s = _d_newarrayT!S(10);
+
+        assert(s.length == 10);
+        foreach (ref elem; s)
+        {
+            assert(elem.x == 2);
+            assert(elem.y == 3);
+        }
+    }
+}
+
+unittest
+{
+    int pblits;
+
+    struct S
+    {
+        this(this) { pblits++; }
+    }
+
+    S[] s = _d_newarrayT!S(2);
+
+    assert(s.length == 2);
+    assert(pblits == 0);
+}
+
+version (D_ProfileGC)
+{
+    /**
+    * TraceGC wrapper around $(REF _d_newitemT, core,lifetime).
+    */
+    T[] _d_newarrayTTrace(T)(string file, int line, string funcname, size_t length, bool isShared) @trusted
+    {
+        version (D_TypeInfo)
+        {
+            import core.internal.array.utils : TraceHook, gcStatsPure, accumulatePure;
+            mixin(TraceHook!(T.stringof, "_d_newarrayT"));
+
+            return _d_newarrayT!T(length, isShared);
+        }
+        else
+            assert(0, "Cannot create new array if compiling without support for runtime type information!");
+    }
+}
diff --git a/libphobos/libdruntime/core/internal/array/utils.d b/libphobos/libdruntime/core/internal/array/utils.d
index a16005e714d..57eb14bd6a7 100644
--- a/libphobos/libdruntime/core/internal/array/utils.d
+++ b/libphobos/libdruntime/core/internal/array/utils.d
@@ -10,6 +10,25 @@ 
 module core.internal.array.utils;
 
 import core.internal.traits : Parameters;
+import core.memory : GC;
+
+alias BlkInfo = GC.BlkInfo;
+alias BlkAttr = GC.BlkAttr;
+
+private
+{
+    enum : size_t
+    {
+        PAGESIZE = 4096,
+        BIGLENGTHMASK = ~(PAGESIZE - 1),
+        SMALLPAD = 1,
+        MEDPAD = ushort.sizeof,
+        LARGEPREFIX = 16, // 16 bytes padding at the front of the array
+        LARGEPAD = LARGEPREFIX + 1,
+        MAXSMALLSIZE = 256-SMALLPAD,
+        MAXMEDSIZE = (PAGESIZE / 2) - MEDPAD
+    }
+}
 
 auto gcStatsPure() nothrow pure
 {
@@ -136,3 +155,220 @@  template isPostblitNoThrow(T) {
     else
         enum isPostblitNoThrow = true;
 }
+
+/**
+ * Clear padding that might not be zeroed by the GC (it assumes it is within the
+ * requested size from the start, but it is actually at the end of the allocated
+ * block).
+ *
+ * Params:
+ *  info = array allocation data
+ *  arrSize = size of the array in bytes
+ *  padSize = size of the padding in bytes
+ */
+void __arrayClearPad()(ref BlkInfo info, size_t arrSize, size_t padSize) nothrow pure
+{
+    import core.stdc.string;
+    if (padSize > MEDPAD && !(info.attr & BlkAttr.NO_SCAN) && info.base)
+    {
+        if (info.size < PAGESIZE)
+            memset(info.base + arrSize, 0, padSize);
+        else
+            memset(info.base, 0, LARGEPREFIX);
+    }
+}
+
+/**
+ * Allocate an array memory block by applying the proper padding and assigning
+ * block attributes if not inherited from the existing block.
+ *
+ * Params:
+ *  arrSize = size of the allocated array in bytes
+ * Returns:
+ *  `BlkInfo` with allocation metadata
+ */
+BlkInfo __arrayAlloc(T)(size_t arrSize) @trusted
+{
+    import core.checkedint;
+    import core.lifetime : TypeInfoSize;
+    import core.internal.traits : hasIndirections;
+
+    enum typeInfoSize = TypeInfoSize!T;
+    BlkAttr attr = BlkAttr.APPENDABLE;
+
+    size_t padSize = arrSize > MAXMEDSIZE ?
+        LARGEPAD :
+        ((arrSize > MAXSMALLSIZE ? MEDPAD : SMALLPAD) + typeInfoSize);
+
+    bool overflow;
+    auto paddedSize = addu(arrSize, padSize, overflow);
+
+    if (overflow)
+        return BlkInfo();
+
+    /* `extern(C++)` classes don't have a classinfo pointer in their vtable,
+     * so the GC can't finalize them.
+     */
+    static if (typeInfoSize)
+        attr |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE;
+    static if (!hasIndirections!T)
+        attr |= BlkAttr.NO_SCAN;
+
+    auto bi = GC.qalloc(paddedSize, attr, typeid(T));
+    __arrayClearPad(bi, arrSize, padSize);
+    return bi;
+}
+
+/**
+ * Get the start of the array for the given block.
+ *
+ * Params:
+ *  info = array metadata
+ * Returns:
+ *  pointer to the start of the array
+ */
+void *__arrayStart()(return scope BlkInfo info) nothrow pure
+{
+    return info.base + ((info.size & BIGLENGTHMASK) ? LARGEPREFIX : 0);
+}
+
+/**
+ * Set the allocated length of the array block.  This is called when an array
+ * is appended to or its length is set.
+ *
+ * The allocated block looks like this for blocks < PAGESIZE:
+ * `|elem0|elem1|elem2|...|elemN-1|emptyspace|N*elemsize|`
+ *
+ * The size of the allocated length at the end depends on the block size:
+ *      a block of 16 to 256 bytes has an 8-bit length.
+ *      a block with 512 to pagesize/2 bytes has a 16-bit length.
+ *
+ * For blocks >= pagesize, the length is a size_t and is at the beginning of the
+ * block.  The reason we have to do this is because the block can extend into
+ * more pages, so we cannot trust the block length if it sits at the end of the
+ * block, because it might have just been extended.  If we can prove in the
+ * future that the block is unshared, we may be able to change this, but I'm not
+ * sure it's important.
+ *
+ * In order to do put the length at the front, we have to provide 16 bytes
+ * buffer space in case the block has to be aligned properly.  In x86, certain
+ * SSE instructions will only work if the data is 16-byte aligned.  In addition,
+ * we need the sentinel byte to prevent accidental pointers to the next block.
+ * Because of the extra overhead, we only do this for page size and above, where
+ * the overhead is minimal compared to the block size.
+ *
+ * So for those blocks, it looks like:
+ * `|N*elemsize|padding|elem0|elem1|...|elemN-1|emptyspace|sentinelbyte|``
+ *
+ * where `elem0` starts 16 bytes after the first byte.
+ */
+bool __setArrayAllocLength(T)(ref BlkInfo info, size_t newLength, bool isShared, size_t oldLength = ~0)
+{
+    import core.atomic;
+    import core.lifetime : TypeInfoSize;
+
+    size_t typeInfoSize = TypeInfoSize!T;
+
+    if (info.size <= 256)
+    {
+        import core.checkedint;
+
+        bool overflow;
+        auto newLengthPadded = addu(newLength,
+                                     addu(SMALLPAD, typeInfoSize, overflow),
+                                     overflow);
+
+        if (newLengthPadded > info.size || overflow)
+            // new size does not fit inside block
+            return false;
+
+        auto length = cast(ubyte *)(info.base + info.size - typeInfoSize - SMALLPAD);
+        if (oldLength != ~0)
+        {
+            if (isShared)
+            {
+                return cas(cast(shared)length, cast(ubyte)oldLength, cast(ubyte)newLength);
+            }
+            else
+            {
+                if (*length == cast(ubyte)oldLength)
+                    *length = cast(ubyte)newLength;
+                else
+                    return false;
+            }
+        }
+        else
+        {
+            // setting the initial length, no cas needed
+            *length = cast(ubyte)newLength;
+        }
+        if (typeInfoSize)
+        {
+            auto typeInfo = cast(TypeInfo*)(info.base + info.size - size_t.sizeof);
+            *typeInfo = cast()typeid(T);
+        }
+    }
+    else if (info.size < PAGESIZE)
+    {
+        if (newLength + MEDPAD + typeInfoSize > info.size)
+            // new size does not fit inside block
+            return false;
+        auto length = cast(ushort *)(info.base + info.size - typeInfoSize - MEDPAD);
+        if (oldLength != ~0)
+        {
+            if (isShared)
+            {
+                return cas(cast(shared)length, cast(ushort)oldLength, cast(ushort)newLength);
+            }
+            else
+            {
+                if (*length == oldLength)
+                    *length = cast(ushort)newLength;
+                else
+                    return false;
+            }
+        }
+        else
+        {
+            // setting the initial length, no cas needed
+            *length = cast(ushort)newLength;
+        }
+        if (typeInfoSize)
+        {
+            auto typeInfo = cast(TypeInfo*)(info.base + info.size - size_t.sizeof);
+            *typeInfo = cast()typeid(T);
+        }
+    }
+    else
+    {
+        if (newLength + LARGEPAD > info.size)
+            // new size does not fit inside block
+            return false;
+        auto length = cast(size_t *)(info.base);
+        if (oldLength != ~0)
+        {
+            if (isShared)
+            {
+                return cas(cast(shared)length, cast(size_t)oldLength, cast(size_t)newLength);
+            }
+            else
+            {
+                if (*length == oldLength)
+                    *length = newLength;
+                else
+                    return false;
+            }
+        }
+        else
+        {
+            // setting the initial length, no cas needed
+            *length = newLength;
+        }
+        if (typeInfoSize)
+        {
+            auto typeInfo = cast(TypeInfo*)(info.base + size_t.sizeof);
+            *typeInfo = cast()typeid(T);
+        }
+    }
+    return true; // resize succeeded
+}
diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d
index 3a55ca916c2..6b083eaa926 100644
--- a/libphobos/libdruntime/core/lifetime.d
+++ b/libphobos/libdruntime/core/lifetime.d
@@ -2731,7 +2731,8 @@  if (is(T == class))
 {
     import core.internal.traits : hasIndirections;
     import core.exception : onOutOfMemoryError;
-    import core.memory : GC, pureMalloc;
+    import core.memory : pureMalloc;
+    import core.memory : GC;
 
     alias BlkAttr = GC.BlkAttr;
 
@@ -2820,11 +2821,11 @@  T _d_newclassTTrace(T)(string file, int line, string funcname) @trusted
 T* _d_newitemT(T)() @trusted
 {
     import core.internal.lifetime : emplaceInitializer;
-    import core.internal.traits : hasElaborateDestructor, hasIndirections;
+    import core.internal.traits : hasIndirections;
     import core.memory : GC;
 
     auto flags = !hasIndirections!T ? GC.BlkAttr.NO_SCAN : GC.BlkAttr.NONE;
-    immutable tiSize = hasElaborateDestructor!T ? size_t.sizeof : 0;
+    immutable tiSize = TypeInfoSize!T;
     immutable itemSize = T.sizeof;
     immutable totalSize = itemSize + tiSize;
     if (tiSize)
@@ -3004,3 +3005,9 @@  version (D_ProfileGC)
             assert(0, "Cannot create new `struct` if compiling without support for runtime type information!");
     }
 }
+
+template TypeInfoSize(T)
+{
+    import core.internal.traits : hasElaborateDestructor;
+    enum TypeInfoSize = hasElaborateDestructor!T ? size_t.sizeof : 0;
+}
diff --git a/libphobos/libdruntime/core/sys/freebsd/ifaddrs.d b/libphobos/libdruntime/core/sys/freebsd/ifaddrs.d
new file mode 100644
index 00000000000..aa39ac4bb49
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/freebsd/ifaddrs.d
@@ -0,0 +1,41 @@ 
+//Written in the D programming language
+
+/++
+    D header file for FreeBSD's ifaddrs.h.
+
+    Copyright: Copyright 2023
+    License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+    Authors:   $(HTTP jmdavisprog.com, Jonathan M Davis)
+ +/
+module core.sys.freebsd.ifaddrs;
+
+version (FreeBSD):
+extern(C):
+@nogc:
+nothrow:
+
+import core.sys.posix.sys.socket : sockaddr;
+
+struct ifaddrs
+{
+    ifaddrs*  ifa_next;
+    char*     ifa_name;
+    uint      ifa_flags;
+    sockaddr* ifa_addr;
+    sockaddr* ifa_netmask;
+    sockaddr* ifa_dstaddr;
+    void*     ifa_data;
+}
+
+struct ifmaddrs
+{
+    ifmaddrs* ifma_next;
+    sockaddr* ifma_name;
+    sockaddr* ifma_addr;
+    sockaddr* ifma_lladdr;
+}
+
+int getifaddrs(ifaddrs**);
+void freeifaddrs(ifaddrs*);
+int getifmaddrs(ifmaddrs**);
+void freeifmaddrs(ifmaddrs*);
diff --git a/libphobos/libdruntime/core/sys/freebsd/net/if_dl.d b/libphobos/libdruntime/core/sys/freebsd/net/if_dl.d
new file mode 100644
index 00000000000..9f830610fc8
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/freebsd/net/if_dl.d
@@ -0,0 +1,42 @@ 
+//Written in the D programming language
+
+/++
+    D header file for FreeBSD's net/if_dl.h.
+
+    Copyright: Copyright 2023
+    License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+    Authors:   $(HTTP jmdavisprog.com, Jonathan M Davis)
+ +/
+module core.sys.freebsd.net.if_dl;
+
+version (FreeBSD):
+extern(C):
+@nogc:
+nothrow:
+
+import core.sys.freebsd.sys.types : caddr_t, c_caddr_t;
+import core.sys.posix.sys.socket : sa_family_t, sockaddr;
+
+struct sockaddr_dl
+{
+    ubyte       sdl_len;
+    sa_family_t sdl_family;
+    ushort      sdl_index;
+    ubyte       sdl_type;
+    ubyte       sdl_nlen;
+    ubyte       sdl_alen;
+    ubyte       sdl_slen;
+    ubyte[46]   sdl_data;
+}
+
+auto LLADDR()(sockaddr_dl* s) { return cast(caddr_t)(s.sdl_data.ptr + s.sdl_nlen); }
+auto CLLADDR()(const sockaddr_dl* s) { return cast(c_caddr_t)(s.sdl_data.ptr + s.sdl_nlen); }
+ushort LLINDEX()(const sockaddr_dl* s) { return s.sdl_index; }
+
+struct ifnet;
+sockaddr_dl* link_alloc_sdl(size_t, int);
+void link_free_sdl(sockaddr* sa);
+sockaddr_dl* link_init_sdl(ifnet*, sockaddr*, ubyte);
+
+void  link_addr(const char*, sockaddr_dl*);
+char* link_ntoa(const sockaddr_dl*);
diff --git a/libphobos/libdruntime/core/sys/freebsd/sys/socket.d b/libphobos/libdruntime/core/sys/freebsd/sys/socket.d
new file mode 100644
index 00000000000..6d61286ddfa
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/freebsd/sys/socket.d
@@ -0,0 +1,131 @@ 
+//Written in the D programming language
+
+/++
+    D header file for FreeBSD's extensions to POSIX's sys/socket.h.
+
+    Copyright: Copyright 2023
+    License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+    Authors:   $(HTTP jmdavisprog.com, Jonathan M Davis)
+ +/
+module core.sys.freebsd.sys.socket;
+
+public import core.sys.posix.sys.socket;
+
+version (FreeBSD):
+extern(C):
+@nogc:
+nothrow:
+
+// Creation flags, OR'ed into socket() and socketpair() type argument.
+enum : uint
+{
+    SOCK_CLOEXEC  = 0x10000000,
+    SOCK_NONBLOCK = 0x20000000,
+}
+
+// Option flags per-socket.
+enum : uint
+{
+    SO_USELOOPBACK  = 0x00000040,
+    SO_TIMESTAMP    = 0x00000400,
+    SO_ACCEPTFILTER = 0x00001000,
+    SO_BINTIME      = 0x00002000,
+
+    SO_NO_OFFLOAD   = 0x00004000,
+    SO_NO_DDP       = 0x00008000,
+    SO_REUSEPORT_LB = 0x00010000,
+    SO_RERROR       = 0x00020000,
+}
+
+
+// Additional options, not kept in so_options.
+enum : uint
+{
+    SO_LABEL           = 0x1009,
+    SO_PEERLABEL       = 0x1010,
+    SO_LISTENQLIMIT    = 0x1011,
+    SO_LISTENQLEN      = 0x1012,
+    SO_LISTENINCQLEN   = 0x1013,
+    SO_SETFIB          = 0x1014,
+    SO_USER_COOKIE     = 0x1015,
+    SO_PROTOCOL        = 0x1016,
+    SO_PROTOTYPE       = SO_PROTOCOL,
+    SO_TS_CLOCK        = 0x1017,
+    SO_MAX_PACING_RATE = 0x1018,
+    SO_DOMAIN          = 0x1019,
+
+    SO_TS_REALTIME_MICRO = 0,
+    SO_TS_BINTIME        = 1,
+    SO_TS_REALTIME       = 2,
+    SO_TS_MONOTONIC      = 3,
+    SO_TS_DEFAULT        = SO_TS_REALTIME_MICRO,
+    SO_TS_CLOCK_MAX      = SO_TS_MONOTONIC,
+}
+
+/+
+   Space reserved for new socket options added by third-party vendors.
+   This range applies to all socket option levels.  New socket options
+   in FreeBSD should always use an option value less than SO_VENDOR.
+ +/
+enum : uint
+{
+    SO_VENDOR = 0x80000000,
+}
+
+struct accept_filter_arg
+{
+    char[16]      af_name;
+    char [256-16] af_arg;
+}
+
+// Address families.
+enum : uint
+{
+    AF_LOCAL = AF_UNIX,
+
+    AF_IMPLINK = 3,
+    AF_PUP     = 4,
+    AF_CHAOS   = 5,
+    AF_NETBIOS = 6,
+    AF_ISO     = 7,
+    AF_OSI     = AF_ISO,
+    AF_ECMA    = 8,
+    AF_DATAKIT = 9,
+    AF_CCITT   = 10,
+    AF_SNA     = 11,
+    AF_DECnet  = 12,
+    AF_DLI     = 13,
+    AF_LAT     = 14,
+    AF_HYLINK  = 15,
+
+    AF_ROUTE       = 17,
+    AF_LINK        = 18,
+    pseudo_AF_XTP  = 19,
+    AF_COIP        = 20,
+    AF_CNT         = 21,
+    pseudo_AF_RTIP = 22,
+
+    AF_SIP        = 24,
+    pseudo_AF_PIP = 25,
+    AF_ISDN       = 26,
+    AF_E164       = AF_ISDN,
+    pseudo_AF_KEY = 27,
+
+    AF_NATM            = 29,
+    AF_ATM             = 30,
+    pseudo_AF_HDRCMPLT = 31,
+    AF_NETGRAPH        = 32,
+    AF_SLOW            = 33,
+    AF_SCLUSTER        = 34,
+    AF_ARP             = 35,
+    AF_BLUETOOTH       = 36,
+    AF_IEEE80211       = 37,
+    AF_NETLINK         = 38,
+
+    AF_INET_SDP = 40,
+
+    AF_INET6_SDP = 42,
+    AF_HYPERV    = 43,
+    AF_DIVERT    = 44,
+    AF_MAX       = 44,
+}
diff --git a/libphobos/libdruntime/core/sys/freebsd/sys/types.d b/libphobos/libdruntime/core/sys/freebsd/sys/types.d
new file mode 100644
index 00000000000..b927ddf815b
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/freebsd/sys/types.d
@@ -0,0 +1,58 @@ 
+//Written in the D programming language
+
+/++
+    D header file for FreeBSD's extensions to POSIX's sys/types.h.
+
+    Copyright: Copyright 2023
+    License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+    Authors:   $(HTTP jmdavisprog.com, Jonathan M Davis)
+ +/
+module core.sys.freebsd.sys.types;
+
+public import core.sys.posix.sys.types;
+
+version (FreeBSD):
+extern(C):
+@nogc:
+nothrow:
+
+import core.stdc.config;
+
+alias caddr_t = ubyte*;
+alias c_caddr_t = const(ubyte)*;
+
+alias cpuwhich_t = int;
+alias cpulevel_t = int;
+alias cpusetid_t = int;
+
+alias critical_t = size_t;
+alias daddr_t = long;
+
+alias fixpt_t = uint;
+
+alias accmode_t = int;
+
+alias register_t = size_t;
+
+alias sbintime_t = long;
+
+alias segsz_t = size_t;
+
+alias u_register_t = size_t;
+
+alias cap_ioctl_t = size_t;
+
+alias kpaddr_t = ulong;
+alias kvaddr_t = ulong;
+alias ksize_t = ulong;
+alias kssize_t = long;
+
+alias vm_offset_t = size_t;
+alias vm_ooffset_t = ulong;
+alias vm_paddr_t = ulong;
+alias vm_pindex_t = ulong;
+alias vm_size_t = size_t;
+
+alias rman_res_t = ulong;
+
+alias syscallarg_t = register_t;
diff --git a/libphobos/libdruntime/core/sys/posix/sys/types.d b/libphobos/libdruntime/core/sys/posix/sys/types.d
index f0ce29f3925..642b3839aa0 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/types.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/types.d
@@ -187,7 +187,7 @@  else version (FreeBSD)
     alias c_long    ssize_t;
     alias c_long    time_t;
     alias uint      uid_t;
-    alias uint      fflags_t;
+    alias uint      fflags_t; // non-standard
 }
 else version (NetBSD)
 {
@@ -866,7 +866,7 @@  else version (Darwin)
 }
 else version (FreeBSD)
 {
-    alias int lwpid_t;
+    alias int lwpid_t; // non-standard
 
     alias void* pthread_attr_t;
     alias void* pthread_cond_t;
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index 294d34dbe35..0111be0b617 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -4668,6 +4668,7 @@  version (D_ProfileGC)
     public import core.internal.array.appending : _d_arrayappendTTrace;
     public import core.internal.array.concatenation : _d_arraycatnTXTrace;
     public import core.lifetime : _d_newitemTTrace;
+    public import core.internal.array.construction : _d_newarrayTTrace;
 }
 public import core.internal.array.appending : _d_arrayappendcTXImpl;
 public import core.internal.array.comparison : __cmp;
@@ -4676,6 +4677,7 @@  public import core.internal.array.casting: __ArrayCast;
 public import core.internal.array.concatenation : _d_arraycatnTX;
 public import core.internal.array.construction : _d_arrayctor;
 public import core.internal.array.construction : _d_arraysetctor;
+public import core.internal.array.construction : _d_newarrayT;
 public import core.internal.array.arrayassign : _d_arrayassign_l;
 public import core.internal.array.arrayassign : _d_arrayassign_r;
 public import core.internal.array.arrayassign : _d_arraysetassign;
diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d
index 1245374ec5f..af3c6bb1296 100644
--- a/libphobos/libdruntime/rt/lifetime.d
+++ b/libphobos/libdruntime/rt/lifetime.d
@@ -13,6 +13,7 @@ 
 module rt.lifetime;
 
 import core.attribute : weak;
+import core.internal.array.utils : __arrayStart, __arrayClearPad;
 import core.memory;
 debug(PRINTF) import core.stdc.stdio;
 static import rt.tlsgc;
@@ -226,7 +227,6 @@  size_t structTypeInfoSize(const TypeInfo ti) pure nothrow @nogc
 private class ArrayAllocLengthLock
 {}
 
-
 /**
   Set the allocated length of the array block.  This is called
   any time an array is appended to or its length is set.
@@ -386,14 +386,6 @@  private size_t __arrayAllocLength(ref BlkInfo info, const TypeInfo tinext) pure
     return *cast(size_t *)(info.base);
 }
 
-/**
-  get the start of the array for the given block
-  */
-private void *__arrayStart(return scope BlkInfo info) nothrow pure
-{
-    return info.base + ((info.size & BIGLENGTHMASK) ? LARGEPREFIX : 0);
-}
-
 /**
   get the padding required to allocate size bytes.  Note that the padding is
   NOT included in the passed in size.  Therefore, do NOT call this function
@@ -404,22 +396,6 @@  private size_t __arrayPad(size_t size, const TypeInfo tinext) nothrow pure @trus
     return size > MAXMEDSIZE ? LARGEPAD : ((size > MAXSMALLSIZE ? MEDPAD : SMALLPAD) + structTypeInfoSize(tinext));
 }
 
-/**
-  clear padding that might not be zeroed by the GC (it assumes it is within the
-  requested size from the start, but it is actually at the end of the allocated block)
-  */
-private void __arrayClearPad(ref BlkInfo info, size_t arrsize, size_t padsize) nothrow pure
-{
-    import core.stdc.string;
-    if (padsize > MEDPAD && !(info.attr & BlkAttr.NO_SCAN) && info.base)
-    {
-        if (info.size < PAGESIZE)
-            memset(info.base + arrsize, 0, padsize);
-        else
-            memset(info.base, 0, LARGEPREFIX);
-    }
-}
-
 /**
   allocate an array memory block by applying the proper padding and
   assigning block attributes if not inherited from the existing block
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 9a979272d6e..a7bf856d747 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@ 
-d945686a4ff7d9fda0e2ee8d2ee201b66be2a287
+2458e8f82e3004197d8a66239a6b72e17264bb26
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/parallelism.d b/libphobos/src/std/parallelism.d
index 9b231f3ac8a..3fe8cd61fe0 100644
--- a/libphobos/src/std/parallelism.d
+++ b/libphobos/src/std/parallelism.d
@@ -1581,7 +1581,7 @@  public:
     auto logs = new double[10_000_000];
 
     // Parallel foreach works with or without an index
-    // variable.  It can be iterate by ref if range.front
+    // variable.  It can iterate by ref if range.front
     // returns by ref.
 
     // Iterate over logs using work units of size 100.
diff --git a/libphobos/src/std/range/primitives.d b/libphobos/src/std/range/primitives.d
index ef34a85e5ec..1a3fb06cf99 100644
--- a/libphobos/src/std/range/primitives.d
+++ b/libphobos/src/std/range/primitives.d
@@ -540,13 +540,9 @@  private void putChar(R, E)(ref R r, E e)
 if (isSomeChar!E)
 {
     // https://issues.dlang.org/show_bug.cgi?id=9186: Can't use (E[]).init
-    ref const( char)[] cstringInit();
-    ref const(wchar)[] wstringInit();
-    ref const(dchar)[] dstringInit();
-
-    enum csCond = is(typeof(doPut(r, cstringInit())));
-    enum wsCond = is(typeof(doPut(r, wstringInit())));
-    enum dsCond = is(typeof(doPut(r, dstringInit())));
+    enum csCond = is(typeof(doPut(r, (){ ref const( char)[] cstringInit(); return cstringInit(); }())));
+    enum wsCond = is(typeof(doPut(r, (){ ref const(wchar)[] wstringInit(); return wstringInit(); }())));
+    enum dsCond = is(typeof(doPut(r, (){ ref const(dchar)[] dstringInit(); return dstringInit(); }())));
 
     //Use "max" to avoid static type demotion
     enum ccCond = is(typeof(doPut(r,  char.max)));
diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d
index 2ed7ee527b0..aa69aacfd10 100644
--- a/libphobos/src/std/traits.d
+++ b/libphobos/src/std/traits.d
@@ -67,6 +67,7 @@ 
  *           $(LREF isAssignable)
  *           $(LREF isCovariantWith)
  *           $(LREF isImplicitlyConvertible)
+ *           $(LREF isQualifierConvertible)
  * ))
  * $(TR $(TD Type Constructors) $(TD
  *           $(LREF InoutOf)
@@ -5166,6 +5167,62 @@  enum bool isImplicitlyConvertible(From, To) = is(From : To);
     static assert( isImplicitlyConvertible!(string, const(char)[]));
 }
 
+/**
+Is `From` $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible) to `To`?
+*/
+enum bool isQualifierConvertible(From, To) =
+    is(immutable From == immutable To) && is(From* : To*);
+
+///
+@safe unittest
+{
+    // Mutable and immmutable both convert to const...
+    static assert( isQualifierConvertible!(char, const(char)));
+    static assert( isQualifierConvertible!(immutable(char), const(char)));
+    // ...but const does not convert back to mutable or immutable
+    static assert(!isQualifierConvertible!(const(char), char));
+    static assert(!isQualifierConvertible!(const(char), immutable(char)));
+}
+
+@safe unittest
+{
+    import std.meta : AliasSeq;
+
+    alias Ts = AliasSeq!(int, const int, shared int, inout int, const shared int,
+        const inout int, inout shared int, const inout shared int, immutable int);
+
+    // https://dlang.org/spec/const3.html#implicit_qualifier_conversions
+    enum _ = 0;
+    static immutable bool[Ts.length][Ts.length] conversions = [
+    //   m   c   s   i   cs  ci  is  cis im
+        [1,  1,  _,  _,  _,  _,  _,  _,  _],  // mutable
+        [_,  1,  _,  _,  _,  _,  _,  _,  _],  // const
+        [_,  _,  1,  _,  1,  _,  _,  _,  _],  // shared
+        [_,  1,  _,  1,  _,  1,  _,  _,  _],  // inout
+        [_,  _,  _,  _,  1,  _,  _,  _,  _],  // const shared
+        [_,  1,  _,  _,  _,  1,  _,  _,  _],  // const inout
+        [_,  _,  _,  _,  1,  _,  1,  1,  _],  // inout shared
+        [_,  _,  _,  _,  1,  _,  _,  1,  _],  // const inout shared
+        [_,  1,  _,  _,  1,  1,  _,  1,  1],  // immutable
+    ];
+
+    static foreach (i, From; Ts)
+    {
+        static foreach (j, To; Ts)
+        {
+            static assert(isQualifierConvertible!(From, To) == conversions[i][j],
+                "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`"
+                ~ " should be `" ~ (conversions[i][j] ? "true" : "false") ~ "`");
+        }
+    }
+}
+
+@safe unittest
+{
+    // int* -> void* is not a qualifier conversion
+    static assert(!isQualifierConvertible!(int, void));
+}
+
 /**
 Returns `true` iff a value of type `Rhs` can be assigned to a variable of
 type `Lhs`.