diff mbox series

[committed] d: Merge upstream dmd 821ed393d, druntime 454471d8, phobos 1206fc94f.

Message ID 20220613110714.948784-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Merge upstream dmd 821ed393d, druntime 454471d8, phobos 1206fc94f. | expand

Commit Message

Iain Buclaw June 13, 2022, 11:07 a.m. UTC
Hi,

This patches merges the D front-end with upstream dmd 821ed393d, and the
standard library with upstream druntime 454471d8 and phobos 1206fc94f.

D front-end changes:

    - Import latest bug fixes to mainline.

D runtime changes:

    - Fix duplicate Elf64_Dyn definitions on Solaris.
    - _d_newThrowable has been converted to a template.

Phobos changes:

    - Import latest bug fixes to mainline.

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 821ed393d.
	* expr.cc (ExprVisitor::visit (NewExp *)): Remove handled of
	allocating `@nogc' throwable object.
	* runtime.def (NEWTHROW): Remove.

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

Regards,
Iain.

---
libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime 454471d8.
	* libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add
	core/sync/package.d.
	* libdruntime/Makefile.in: Regenerate.
	* src/MERGE: Merge upstream phobos 1206fc94f.
---
 gcc/d/dmd/MERGE                               |   2 +-
 gcc/d/dmd/attrib.d                            |   6 +-
 gcc/d/dmd/cparse.d                            |  88 +++-
 gcc/d/dmd/cppmangle.d                         |   2 +-
 gcc/d/dmd/dcast.d                             |   4 +-
 gcc/d/dmd/dinterpret.d                        |  38 +-
 gcc/d/dmd/dscope.d                            |  17 +-
 gcc/d/dmd/dsymbol.d                           |  18 +-
 gcc/d/dmd/dsymbol.h                           |   2 -
 gcc/d/dmd/dsymbolsem.d                        |   7 -
 gcc/d/dmd/dtemplate.d                         |   8 +-
 gcc/d/dmd/expressionsem.d                     | 100 +++-
 gcc/d/dmd/func.d                              |   4 +-
 gcc/d/dmd/id.d                                |   1 +
 gcc/d/dmd/mtype.d                             |  13 +-
 gcc/d/dmd/mtype.h                             |  11 +
 gcc/d/dmd/parse.d                             |   2 +-
 gcc/d/dmd/scope.h                             |   1 +
 gcc/d/dmd/statement.d                         |   2 +-
 gcc/d/dmd/statementsem.d                      |  25 +-
 gcc/d/dmd/typesem.d                           | 471 +++++++++---------
 gcc/d/dmd/typinf.d                            |   9 +-
 gcc/d/expr.cc                                 |  10 +-
 gcc/d/runtime.def                             |   1 -
 .../gdc.test/compilable/imports/defines.c     |  28 ++
 gcc/testsuite/gdc.test/compilable/nogc.d      |   9 +
 gcc/testsuite/gdc.test/compilable/test22626.d |  23 +
 gcc/testsuite/gdc.test/compilable/test23076.d |  38 ++
 gcc/testsuite/gdc.test/compilable/test23142.d |  19 +
 gcc/testsuite/gdc.test/compilable/test23174.d |  58 +++
 .../gdc.test/compilable/testdefines.d         |  14 +
 .../gdc.test/compilable/testdip1008.d         |  19 +
 .../fail_compilation/mixin_template.d         |  10 +
 .../gdc.test/fail_compilation/noreturn.d      |  18 +
 .../gdc.test/fail_compilation/template_decl.d |   9 +
 .../gdc.test/fail_compilation/test21477.d     |  16 +
 .../gdc.test/fail_compilation/test23159.d     |  22 +
 .../gdc.test/fail_compilation/traits.d        |  18 +
 libphobos/libdruntime/MERGE                   |   2 +-
 libphobos/libdruntime/Makefile.am             |   6 +-
 libphobos/libdruntime/Makefile.in             |  30 +-
 libphobos/libdruntime/core/attribute.d        |  18 +-
 .../core/internal/array/equality.d            |  33 +-
 libphobos/libdruntime/core/lifetime.d         |  40 +-
 libphobos/libdruntime/core/stdcpp/xutility.d  |  15 +-
 .../core/sys/dragonflybsd/sys/elf32.d         |  10 +
 .../core/sys/dragonflybsd/sys/elf64.d         |  10 +
 libphobos/libdruntime/core/sys/elf/package.d  |  20 -
 .../libdruntime/core/sys/freebsd/sys/elf32.d  |  10 +
 .../libdruntime/core/sys/freebsd/sys/elf64.d  |  10 +
 libphobos/libdruntime/core/sys/linux/elf.d    |  20 +
 .../libdruntime/core/sys/netbsd/sys/elf32.d   |  10 +
 .../libdruntime/core/sys/netbsd/sys/elf64.d   |  10 +
 .../libdruntime/core/sys/openbsd/sys/elf32.d  |  10 +
 .../libdruntime/core/sys/openbsd/sys/elf64.d  |  10 +
 .../core/sys/solaris/sys/elftypes.d           |  18 +-
 .../libdruntime/core/sys/solaris/sys/link.d   | 235 +--------
 .../libdruntime/core/thread/threadbase.d      |   2 +-
 libphobos/libdruntime/rt/ehalloc.d            |  45 --
 libphobos/src/MERGE                           |   2 +-
 libphobos/src/std/mmfile.d                    |  10 +-
 libphobos/src/std/sumtype.d                   |  22 +-
 62 files changed, 1029 insertions(+), 712 deletions(-)
 create mode 100644 gcc/testsuite/gdc.test/compilable/imports/defines.c
 create mode 100644 gcc/testsuite/gdc.test/compilable/test22626.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23076.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23142.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23174.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/testdefines.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/mixin_template.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/template_decl.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test21477.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test23159.d

Comments

Rainer Orth June 13, 2022, 6:58 p.m. UTC | #1
Hi Iain,

> This patches merges the D front-end with upstream dmd 821ed393d, and the
> standard library with upstream druntime 454471d8 and phobos 1206fc94f.

> libphobos/ChangeLog:
>
> 	* libdruntime/MERGE: Merge upstream druntime 454471d8.
> 	* libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add
> 	core/sync/package.d.
> 	* libdruntime/Makefile.in: Regenerate.
> 	* src/MERGE: Merge upstream phobos 1206fc94f.

unfortunately, you missed core/sync/package.d here, breaking the build:

make[5]: *** No rule to make target 'core/sync/package.d', needed by 'core/sync/package.lo'.  Stop.

I copied the file from upstream libdruntime to fix it.

	Rainer
Iain Buclaw June 13, 2022, 10:10 p.m. UTC | #2
Excerpts from Rainer Orth's message of Juni 13, 2022 8:58 pm:
> Hi Iain,
> 
>> This patches merges the D front-end with upstream dmd 821ed393d, and the
>> standard library with upstream druntime 454471d8 and phobos 1206fc94f.
> 
>> libphobos/ChangeLog:
>>
>> 	* libdruntime/MERGE: Merge upstream druntime 454471d8.
>> 	* libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add
>> 	core/sync/package.d.
>> 	* libdruntime/Makefile.in: Regenerate.
>> 	* src/MERGE: Merge upstream phobos 1206fc94f.
> 
> unfortunately, you missed core/sync/package.d here, breaking the build:
> 
> make[5]: *** No rule to make target 'core/sync/package.d', needed by 'core/sync/package.lo'.  Stop.
> 

Hi Rainer,

Really sorry for that, I've checked the core.sync package module in
r13-1077.

Iain.

---
 libphobos/libdruntime/core/sync/package.d | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/libphobos/libdruntime/core/sync/package.d b/libphobos/libdruntime/core/sync/package.d
new file mode 100644
index 00000000000..fe389a0475d
--- /dev/null
+++ b/libphobos/libdruntime/core/sync/package.d
@@ -0,0 +1,20 @@
+/**
+ * Provides thread synchronization tools such as mutexes, semaphores and barriers.
+ *
+ * License: Distributed under the
+ *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ *    (See accompanying file LICENSE)
+ * Authors:   Sean Kelly, Rainer Schuetze
+ * Source:    $(DRUNTIMESRC core/sync/package.d)
+ */
+
+module core.sync;
+
+public import core.sync.barrier;
+public import core.sync.condition;
+public import core.sync.config;
+public import core.sync.event;
+public import core.sync.exception;
+public import core.sync.mutex;
+public import core.sync.rwmutex;
+public import core.sync.semaphore;
diff mbox series

Patch

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index c37da0585d9..d39658a808e 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-4d07f22f29d098869ad937f0499d8895df089a71
+821ed393d428c7db5a48623e77d43f5647d5c6a2
 
 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/attrib.d b/gcc/d/dmd/attrib.d
index 1e84b55d181..b569a9c3b46 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -1274,14 +1274,14 @@  extern (C++) final class StaticForeachDeclaration : AttribDeclaration
  * declarations.
  */
 
-extern(C++) final class ForwardingAttribDeclaration: AttribDeclaration
+extern(C++) final class ForwardingAttribDeclaration : AttribDeclaration
 {
     ForwardingScopeDsymbol sym = null;
 
     this(Dsymbols* decl)
     {
         super(decl);
-        sym = new ForwardingScopeDsymbol(null);
+        sym = new ForwardingScopeDsymbol();
         sym.symtab = new DsymbolTable();
     }
 
@@ -1298,7 +1298,7 @@  extern(C++) final class ForwardingAttribDeclaration: AttribDeclaration
      */
     override void addMember(Scope* sc, ScopeDsymbol sds)
     {
-        parent = sym.parent = sym.forward = sds;
+        sym.parent = sds;
         return super.addMember(sc, sym);
     }
 
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 344933ace83..62ba889cc13 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -5156,26 +5156,80 @@  final class CParser(AST) : Parser!AST
                 {
                     auto id = n.ident;
                     scan(&n);
-                    if (n.value == TOK.endOfLine)       // #define identifier
-                    {
-                        nextDefineLine();
-                        continue;
-                    }
-                    if (n.value == TOK.int32Literal)
+
+                    AST.Type t;
+
+                    switch (n.value)
                     {
-                        const value = n.intvalue;
-                        scan(&n);
-                        if (n.value == TOK.endOfLine)
-                        {
-                            /* Declare manifest constant:
-                             *  enum id = value;
-                             */
-                            AST.Expression e = new AST.IntegerExp(scanloc, value, AST.Type.tint32);
-                            auto v = new AST.VarDeclaration(scanloc, AST.Type.tint32, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
-                            symbols.push(v);
+                        case TOK.endOfLine:     // #define identifier
                             nextDefineLine();
                             continue;
-                        }
+
+                        case TOK.int32Literal:
+                        case TOK.charLiteral:       t = AST.Type.tint32;    goto Linteger;
+                        case TOK.uns32Literal:      t = AST.Type.tuns32;    goto Linteger;
+                        case TOK.int64Literal:      t = AST.Type.tint64;    goto Linteger;
+                        case TOK.uns64Literal:      t = AST.Type.tuns64;    goto Linteger;
+
+                        Linteger:
+                            const intvalue = n.intvalue;
+                            scan(&n);
+                            if (n.value == TOK.endOfLine)
+                            {
+                                /* Declare manifest constant:
+                                 *  enum id = intvalue;
+                                 */
+                                AST.Expression e = new AST.IntegerExp(scanloc, intvalue, t);
+                                auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
+                                symbols.push(v);
+                                nextDefineLine();
+                                continue;
+                            }
+                            break;
+
+                        case TOK.float32Literal:      t = AST.Type.tfloat32;     goto Lfloat;
+                        case TOK.float64Literal:      t = AST.Type.tfloat64;     goto Lfloat;
+                        case TOK.float80Literal:      t = AST.Type.tfloat80;     goto Lfloat;
+                        case TOK.imaginary32Literal:  t = AST.Type.timaginary32; goto Lfloat;
+                        case TOK.imaginary64Literal:  t = AST.Type.timaginary64; goto Lfloat;
+                        case TOK.imaginary80Literal:  t = AST.Type.timaginary80; goto Lfloat;
+
+                        Lfloat:
+                            const floatvalue = n.floatvalue;
+                            scan(&n);
+                            if (n.value == TOK.endOfLine)
+                            {
+                                /* Declare manifest constant:
+                                 *  enum id = floatvalue;
+                                 */
+                                AST.Expression e = new AST.RealExp(scanloc, floatvalue, t);
+                                auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
+                                symbols.push(v);
+                                nextDefineLine();
+                                continue;
+                            }
+                            break;
+
+                        case TOK.string_:
+                            const str = n.ustring;
+                            const len = n.len;
+                            const postfix = n.postfix;
+                            scan(&n);
+                            if (n.value == TOK.endOfLine)
+                            {
+                                /* Declare manifest constant:
+                                 *  enum id = "string";
+                                 */
+                                AST.Expression e = new AST.StringExp(scanloc, str[0 .. len], len, 1, postfix);
+                                auto v = new AST.VarDeclaration(scanloc, null, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
+                                symbols.push(v);
+                                nextDefineLine();
+                                continue;
+                            }
+                            break;
+
+                        default:
+                            break;
                     }
                 }
                 skipToNextLine();
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index 6235342a4f4..fed83b8f403 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -1318,7 +1318,7 @@  private final class CppMangleVisitor : Visitor
             Type t = fparam.type.merge2();
             if (fparam.isReference())
                 t = t.referenceTo();
-            else if (fparam.storageClass & STC.lazy_)
+            else if (fparam.isLazy())
             {
                 // Mangle as delegate
                 auto tf = new TypeFunction(ParameterList(), t, LINK.d);
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 4607d6fee7c..12051d92215 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -916,7 +916,7 @@  MATCH implicitConvTo(Expression e, Type t)
             if (i - j < nparams)
             {
                 Parameter fparam = tf.parameterList[i - j];
-                if (fparam.storageClass & STC.lazy_)
+                if (fparam.isLazy())
                     return result; // not sure what to do with this
                 Type tparam = fparam.type;
                 if (!tparam)
@@ -1224,7 +1224,7 @@  MATCH implicitConvTo(Expression e, Type t)
                 if (i - j < nparams)
                 {
                     Parameter fparam = tf.parameterList[i - j];
-                    if (fparam.storageClass & STC.lazy_)
+                    if (fparam.isLazy())
                         return MATCH.nomatch; // not sure what to do with this
                     Type tparam = fparam.type;
                     if (!tparam)
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 5e7527d7041..bb25210019f 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -492,7 +492,7 @@  private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
             if (CTFEExp.isCantExp(earg))
                 return earg;
         }
-        else if (fparam.storageClass & STC.lazy_)
+        else if (fparam.isLazy())
         {
         }
         else
@@ -5000,6 +5000,27 @@  public:
             printf("%s CommaExp::interpret() %s\n", e.loc.toChars(), e.toChars());
         }
 
+        bool isNewThrowableHook()
+        {
+            auto de = e.e1.isDeclarationExp();
+            if (de is null)
+                return false;
+
+            auto vd = de.declaration.isVarDeclaration();
+            if (vd is null)
+                return false;
+
+            auto ei = vd._init.isExpInitializer();
+            if (ei is null)
+                return false;
+
+            auto ce = ei.exp.isConstructExp();
+            if (ce is null)
+                return false;
+
+            return isRuntimeHook(ce.e2, Id._d_newThrowable) !is null;
+        }
+
         if (auto ce = isRuntimeHook(e.e1, Id._d_arrayappendcTX))
         {
             // In expressionsem.d `arr ~= elem` was lowered to
@@ -5018,6 +5039,21 @@  public:
             result = interpret(cae, istate);
             return;
         }
+        else if (isNewThrowableHook())
+        {
+            // In expressionsem.d `throw new Exception(args)` was lowered to
+            // `throw (tmp = _d_newThrowable!Exception(), tmp.ctor(args), tmp)`.
+            // The following code will rewrite it back to `throw new Exception(args)`
+            // and then interpret this expression instead.
+            auto ce = e.e2.isCallExp();
+            assert(ce);
+
+            auto ne = new NewExp(e.loc, null, e.type, ce.arguments);
+            ne.type = e.e1.type;
+
+            result = interpret(ne, istate);
+            return;
+        }
 
         // If it creates a variable, and there's no context for
         // the variable to be created in, we need to create one now.
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index b546e372003..9c30978551b 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -754,7 +754,6 @@  struct Scope
             //    assert(0);
         }
     }
-
     /******************************
      */
     structalign_t alignment()
@@ -771,13 +770,13 @@  struct Scope
             return sa;
         }
     }
-
+    @safe @nogc pure nothrow const:
     /**********************************
     * Checks whether the current scope (or any of its parents) is deprecated.
     *
     * Returns: `true` if this or any parent scope is deprecated, `false` otherwise`
     */
-    extern(C++) bool isDeprecated() @safe @nogc pure nothrow const
+    extern(C++) bool isDeprecated()
     {
         for (const(Dsymbol)* sp = &(this.parent); *sp; sp = &(sp.parent))
         {
@@ -799,4 +798,16 @@  struct Scope
         }
         return false;
     }
+    /**
+     * dmd relies on mutation of state during semantic analysis, however
+     * sometimes semantic is being performed in a speculative context that should
+     * not have any visible effect on the rest of the compilation: for example when compiling
+     * a typeof() or __traits(compiles).
+     *
+     * Returns: `true` if this `Scope` is known to be from one of these speculative contexts
+     */
+    extern(C++) bool isFromSpeculativeSemanticContext() scope
+    {
+        return this.intypeof || this.flags & SCOPE.compile;
+    }
 }
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 3b3a527dc52..2b608f6974c 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -2184,20 +2184,13 @@  extern (C++) final class OverloadSet : Dsymbol
  */
 extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
 {
-    /*************************
-     * Symbol to forward insertions to.
-     * Can be `null` before being lazily initialized.
-     */
-    ScopeDsymbol forward;
-    extern (D) this(ScopeDsymbol forward) nothrow
+    extern (D) this() nothrow
     {
-        super(null);
-        this.forward = forward;
+        super();
     }
 
     override Dsymbol symtabInsert(Dsymbol s) nothrow
     {
-        assert(forward);
         if (auto d = s.isDeclaration())
         {
             if (d.storage_class & STC.local)
@@ -2212,6 +2205,8 @@  extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
                 return super.symtabInsert(s); // insert locally
             }
         }
+        auto forward = parent.isScopeDsymbol();
+        assert(forward);
         if (!forward.symtab)
         {
             forward.symtab = new DsymbolTable();
@@ -2228,7 +2223,6 @@  extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
      */
     override Dsymbol symtabLookup(Dsymbol s, Identifier id) nothrow
     {
-        assert(forward);
         // correctly diagnose clashing foreach loop variables.
         if (auto d = s.isDeclaration())
         {
@@ -2243,6 +2237,8 @@  extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
         }
         // Declarations within `static foreach` do not clash with
         // `static foreach` loop variables.
+        auto forward = parent.isScopeDsymbol();
+        assert(forward);
         if (!forward.symtab)
         {
             forward.symtab = new DsymbolTable();
@@ -2252,6 +2248,8 @@  extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
 
     override void importScope(Dsymbol s, Visibility visibility)
     {
+        auto forward = parent.isScopeDsymbol();
+        assert(forward);
         forward.importScope(s, visibility);
     }
 
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 23a2c775d4c..bea4b776ec5 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -391,8 +391,6 @@  public:
 class ForwardingScopeDsymbol final : public ScopeDsymbol
 {
 public:
-    ScopeDsymbol *forward;
-
     Dsymbol *symtabInsert(Dsymbol *s) override;
     Dsymbol *symtabLookup(Dsymbol *s, Identifier *id) override;
     void importScope(Dsymbol *s, Visibility visibility) override;
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index e49127220a0..6dbc129baaf 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -3276,13 +3276,6 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
         if ((funcdecl.storage_class & STC.auto_) && !f.isref && !funcdecl.inferRetType)
             funcdecl.error("storage class `auto` has no effect if return type is not inferred");
 
-        /* Functions can only be 'scope' if they have a 'this'
-         */
-        if (f.isScopeQual && !funcdecl.isNested() && !ad)
-        {
-            funcdecl.error("functions cannot be `scope`");
-        }
-
         if (f.isreturn && !funcdecl.needThis() && !funcdecl.isNested())
         {
             /* Non-static nested functions have a hidden 'this' pointer to which
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index a450ea559ac..c0a8e9f4664 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -1632,7 +1632,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
                             if (farg.op == EXP.error || farg.type.ty == Terror)
                                 return nomatch();
 
-                            if (!(fparam.storageClass & STC.lazy_) && farg.type.ty == Tvoid)
+                            if (!fparam.isLazy() && farg.type.ty == Tvoid)
                                 return nomatch();
 
                             Type tt;
@@ -1837,7 +1837,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
                     }
                     Type argtype = farg.type;
 
-                    if (!(fparam.storageClass & STC.lazy_) && argtype.ty == Tvoid && farg.op != EXP.function_)
+                    if (!fparam.isLazy() && argtype.ty == Tvoid && farg.op != EXP.function_)
                         return nomatch();
 
                     // https://issues.dlang.org/show_bug.cgi?id=12876
@@ -1958,7 +1958,7 @@  extern (C++) final class TemplateDeclaration : ScopeDsymbol
                         if (!farg.type.isMutable()) // https://issues.dlang.org/show_bug.cgi?id=11916
                             return nomatch();
                     }
-                    if (m == MATCH.nomatch && (fparam.storageClass & STC.lazy_) && prmtype.ty == Tvoid && farg.type.ty != Tvoid)
+                    if (m == MATCH.nomatch && fparam.isLazy() && prmtype.ty == Tvoid && farg.type.ty != Tvoid)
                         m = MATCH.convert;
                     if (m != MATCH.nomatch)
                     {
@@ -7723,7 +7723,7 @@  extern (C++) final class TemplateMixin : TemplateInstance
             }
             if (!tempdecl)
             {
-                error("`%s` isn't a template", s.toChars());
+                error("- `%s` is a %s, not a template", s.toChars(), s.kind());
                 return false;
             }
         }
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index cb720271ae7..dcc5b5095ed 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -443,7 +443,7 @@  private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
     }
 
     if (!s)
-        return ue.e1.type.Type.getProperty(sc, loc, ident, 0);
+        return ue.e1.type.getProperty(sc, loc, ident, 0);
 
     FuncDeclaration f = s.isFuncDeclaration();
     if (f)
@@ -1856,7 +1856,7 @@  private bool functionParameters(const ref Loc loc, Scope* sc,
             }
 
         L1:
-            if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
+            if (!(p.isLazy() && p.type.ty == Tvoid))
             {
                 if (ubyte wm = arg.type.deduceWild(p.type, p.isReference()))
                 {
@@ -1953,7 +1953,7 @@  private bool functionParameters(const ref Loc loc, Scope* sc,
             Type targ = arg.type;               // keep original type for isCopyable() because alias this
                                                 // resolution may hide an uncopyable type
 
-            if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
+            if (!(p.isLazy() && p.type.ty == Tvoid))
             {
                 Type tprm = p.type.hasWild()
                     ? p.type.substWildTo(wildmatch)
@@ -2018,7 +2018,7 @@  private bool functionParameters(const ref Loc loc, Scope* sc,
                 }
                 arg = arg.toLvalue(sc, arg);
             }
-            else if (p.storageClass & STC.lazy_)
+            else if (p.isLazy())
             {
                 // Convert lazy argument to a delegate
                 auto t = (p.type.ty == Tvoid) ? p.type : arg.type;
@@ -2050,7 +2050,7 @@  private bool functionParameters(const ref Loc loc, Scope* sc,
             // Turning heap allocations into stack allocations is dangerous without dip1000, since `scope` inference
             // may be unreliable when scope violations only manifest as deprecation warnings.
             // However, existing `@nogc` code may rely on it, so still do it when the parameter is explicitly marked `scope`
-            const explicitScope = (p.storageClass & STC.lazy_) ||
+            const explicitScope = p.isLazy() ||
                 ((p.storageClass & STC.scope_) && !(p.storageClass & STC.scopeinferred));
             if ((pStc & (STC.scope_ | STC.lazy_)) &&
                 ((global.params.useDIP1000 == FeatureState.enabled) || explicitScope) &&
@@ -2261,7 +2261,7 @@  private bool functionParameters(const ref Loc loc, Scope* sc,
             if (arg.type.needsDestruction())
             {
                 Parameter p = (i >= nparams ? null : tf.parameterList[i]);
-                if (!(p && (p.storageClass & (STC.lazy_ | STC.ref_ | STC.out_))))
+                if (!(p && (p.isLazy() || p.isReference())))
                 {
                     if (firstdtor == -1)
                         firstdtor = i;
@@ -2302,7 +2302,7 @@  private bool functionParameters(const ref Loc loc, Scope* sc,
 
             Parameter parameter = (i >= nparams ? null : tf.parameterList[i]);
             const bool isRef = parameter && parameter.isReference();
-            const bool isLazy = (parameter && (parameter.storageClass & STC.lazy_));
+            const bool isLazy = parameter && parameter.isLazy();
 
             /* Skip lazy parameters
              */
@@ -3722,6 +3722,36 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     }
                 }
             }
+
+            // When using `@nogc` exception handling, lower `throw new E(args)` to
+            // `throw (__tmp = _d_newThrowable!E(), __tmp.__ctor(args), __tmp)`.
+            if (global.params.ehnogc && exp.thrownew &&
+                !cd.isCOMclass() && !cd.isCPPclass())
+            {
+                assert(cd.ctor);
+
+                Expression id = new IdentifierExp(exp.loc, Id.empty);
+                id = new DotIdExp(exp.loc, id, Id.object);
+
+                auto tiargs = new Objects();
+                tiargs.push(exp.newtype);
+                id = new DotTemplateInstanceExp(exp.loc, id, Id._d_newThrowable, tiargs);
+                id = new CallExp(exp.loc, id).expressionSemantic(sc);
+
+                Expression idVal;
+                Expression tmp = extractSideEffect(sc, "__tmpThrowable", idVal, id, true);
+                // auto castTmp = new CastExp(exp.loc, tmp, exp.type);
+
+                auto ctor = new DotIdExp(exp.loc, tmp, Id.ctor).expressionSemantic(sc);
+                auto ctorCall = new CallExp(exp.loc, ctor, exp.arguments);
+
+                id = Expression.combine(idVal, exp.argprefix).expressionSemantic(sc);
+                id = Expression.combine(id, ctorCall).expressionSemantic(sc);
+                // id = Expression.combine(id, castTmp).expressionSemantic(sc);
+
+                result = id.expressionSemantic(sc);
+                return;
+            }
         }
         else if (auto ts = tb.isTypeStruct())
         {
@@ -6582,6 +6612,14 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             result = e;
             return;
         }
+        else if (auto ad = exp.var.isAliasDeclaration())
+        {
+            if (auto t = ad.getType())
+            {
+                result = new TypeExp(exp.loc, t).expressionSemantic(sc);
+                return;
+            }
+        }
 
         exp.e1 = exp.e1.addDtorHook(sc);
 
@@ -7006,9 +7044,19 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 /* Because nested functions cannot be overloaded,
                  * mark here that we took its address because castTo()
                  * may not be called with an exact match.
+                 *
+                 * https://issues.dlang.org/show_bug.cgi?id=19285 :
+                 * We also need to make sure we aren't inside a typeof. Ideally the compiler
+                 * would do typeof(...) semantic analysis speculatively then collect information
+                 * about what it used rather than relying on what are effectively semantically-global
+                 * variables but it doesn't.
                  */
-                if (!ve.hasOverloads || (f.isNested() && !f.needThis()))
+                if (!sc.isFromSpeculativeSemanticContext() && (!ve.hasOverloads || (f.isNested() && !f.needThis())))
+                {
+                    // TODO: Refactor to use a proper interface that can keep track of causes.
                     f.tookAddressOf++;
+                }
+
                 if (f.isNested() && !f.needThis())
                 {
                     if (f.isFuncLiteralDeclaration())
@@ -12855,11 +12903,8 @@  Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
 
         if (Declaration v = exp.ti.toAlias().isDeclaration())
         {
-            if (v.isFuncDeclaration() || v.isVarDeclaration())
-            {
-                return new DotVarExp(exp.loc, exp.e1, v)
-                       .expressionSemantic(sc);
-            }
+            return new DotVarExp(exp.loc, exp.e1, v)
+                   .expressionSemantic(sc);
         }
         return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
                .expressionSemantic(sc);
@@ -12966,8 +13011,19 @@  bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
 
         bool visitVar(VarExp e)
         {
-            if (!allowRef && e.var.type.isShared())
+            // https://issues.dlang.org/show_bug.cgi?id=22626
+            // Synchronized functions don't need to use core.atomic
+            // when accessing `this`.
+            if (sc.func && sc.func.isSynchronized())
+            {
+                if (e.var.isThisDeclaration())
+                    return false;
+                else
+                    return sharedError(e);
+            }
+            else if (!allowRef && e.var.type.isShared())
                 return sharedError(e);
+
             return false;
         }
 
@@ -12987,15 +13043,22 @@  bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
             return check(e.e1, false);
         }
 
+        bool visitThis(ThisExp e)
+        {
+            if (sc.func && sc.func.isSynchronized())
+                return false;
+
+            return sharedError(e);
+        }
+
         bool visitDotVar(DotVarExp e)
         {
+            //printf("dotvarexp = %s\n", e.toChars());
             auto fd = e.var.isFuncDeclaration();
             const sharedFunc = fd && fd.type.isShared;
-
-            if (!allowRef && e.type.isShared() && !sharedFunc)
-                return sharedError(e);
-
             // Allow using `DotVarExp` within value types
+            if (!allowRef && e.type.isShared() && !sharedFunc && !(sc.func && sc.func.isSynchronized()))
+                return sharedError(e);
             if (e.e1.type.isTypeSArray() || e.e1.type.isTypeStruct())
                 return check(e.e1, allowRef);
 
@@ -13044,6 +13107,7 @@  bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
             case EXP.star:        return visitPtr(e.isPtrExp());
             case EXP.dotVariable: return visitDotVar(e.isDotVarExp());
             case EXP.index:       return visitIndex(e.isIndexExp());
+            case EXP.this_:       return visitThis(e.isThisExp());
         }
     }
 
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 04039483930..d42925990a9 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -1773,7 +1773,7 @@  extern (C++) class FuncDeclaration : Declaration
             if (!tp)
                 continue;
 
-            if (fparam.storageClass & (STC.lazy_ | STC.out_ | STC.ref_))
+            if (fparam.isLazy() || fparam.isReference())
             {
                 if (!traverseIndirections(tp, t))
                     return false;
@@ -2528,7 +2528,7 @@  extern (C++) class FuncDeclaration : Declaration
             foreach (n, p; parameterList)
             {
                 p = p.syntaxCopy();
-                if (!(p.storageClass & STC.lazy_))
+                if (!p.isLazy())
                     p.storageClass = (p.storageClass | STC.ref_) & ~STC.out_;
                 p.defaultArg = null; // won't be the same with ref
                 result.push(p);
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 4993a9eb1b2..5142daa5137 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -311,6 +311,7 @@  immutable Msgtable[] msgtable =
     { "__ArrayPostblit" },
     { "__ArrayDtor" },
     { "_d_delThrowable" },
+    { "_d_newThrowable" },
     { "_d_assert_fail" },
     { "dup" },
     { "_aaApply" },
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 052c23d4420..6b5389dfebb 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -529,7 +529,6 @@  extern (C++) abstract class Type : ASTNode
      * Returns:
      *     An enum value of either `Covariant.yes` or a reason it's not covariant.
      */
-    extern (D)
     final Covariant covariant(Type t, StorageClass* pstc = null, bool cppCovariant = false)
     {
         version (none)
@@ -4361,7 +4360,7 @@  extern (C++) final class TypeFunction : TypeNext
     {
         foreach (i, fparam; parameterList)
         {
-            if (fparam.storageClass & STC.lazy_)
+            if (fparam.isLazy())
                 return true;
         }
         return false;
@@ -4675,7 +4674,7 @@  extern (C++) final class TypeFunction : TypeNext
             Type tprm = p.type;
             Type targ = arg.type;
 
-            if (!(p.storageClass & STC.lazy_ && tprm.ty == Tvoid && targ.ty != Tvoid))
+            if (!(p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid))
             {
                 const isRef = p.isReference();
                 wildmatch |= targ.deduceWild(tprm, isRef);
@@ -4718,7 +4717,7 @@  extern (C++) final class TypeFunction : TypeNext
                 Type targ = arg.type;
                 Type tprm = wildmatch ? p.type.substWildTo(wildmatch) : p.type;
 
-                if (p.storageClass & STC.lazy_ && tprm.ty == Tvoid && targ.ty != Tvoid)
+                if (p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid)
                     m = MATCH.convert;
                 else
                 {
@@ -6825,6 +6824,12 @@  extern (C++) final class Parameter : ASTNode
         return null;
     }
 
+    /// Returns: Whether the function parameter is lazy
+    bool isLazy() const @safe pure nothrow @nogc
+    {
+        return (this.storageClass & (STC.lazy_)) != 0;
+    }
+
     /// Returns: Whether the function parameter is a reference (out / ref)
     bool isReference() const @safe pure nothrow @nogc
     {
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index 3565913ed27..3e614d88180 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -128,6 +128,14 @@  enum VarArgValues
 };
 typedef unsigned char VarArg;
 
+enum class Covariant
+{
+    distinct = 0, /// types are distinct
+    yes = 1,      /// types are covariant
+    no = 2,       /// arguments match as far as overloading goes, but types are not covariant
+    fwdref = 3,   /// cannot determine covariance because of forward references
+};
+
 class Type : public ASTNode
 {
 public:
@@ -218,6 +226,7 @@  public:
     // kludge for template.isType()
     DYNCAST dyncast() const override final { return DYNCAST_TYPE; }
     size_t getUniqueID() const;
+    Covariant covariant(Type *, StorageClass * = NULL, bool = false);
     const char *toChars() const override;
     char *toPrettyChars(bool QualifyTypes = false);
     static void _init();
@@ -560,6 +569,8 @@  public:
                              Expression *defaultArg, UserAttributeDeclaration *userAttribDecl);
     Parameter *syntaxCopy();
     Type *isLazyArray();
+    bool isLazy() const;
+    bool isReference() const;
     // kludge for template.isType()
     DYNCAST dyncast() const override { return DYNCAST_PARAMETER; }
     void accept(Visitor *v) override { v->visit(this); }
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 15b7658a49a..89f8ae3470f 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -1460,7 +1460,7 @@  class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
 
         if (token.value != TOK.leftCurly)
         {
-            error("members of template declaration expected");
+            error("`{` expected after template parameter list, not `%s`", token.toChars());
             goto Lerr;
         }
         decldefs = parseBlock(null);
diff --git a/gcc/d/dmd/scope.h b/gcc/d/dmd/scope.h
index a163e7577a2..b29c59943f3 100644
--- a/gcc/d/dmd/scope.h
+++ b/gcc/d/dmd/scope.h
@@ -147,4 +147,5 @@  struct Scope
     structalign_t alignment();
 
     bool isDeprecated() const;
+    bool isFromSpeculativeSemanticContext() const;
 };
diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d
index 06546256d17..a519f3b4c4c 100644
--- a/gcc/d/dmd/statement.d
+++ b/gcc/d/dmd/statement.d
@@ -761,7 +761,7 @@  extern (C++) final class ForwardingStatement : Statement
 
     extern (D) this(const ref Loc loc, Statement statement)
     {
-        auto sym = new ForwardingScopeDsymbol(null);
+        auto sym = new ForwardingScopeDsymbol();
         sym.symtab = new DsymbolTable();
         this(loc, sym, statement);
     }
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index ed47b916c0a..06e28a4819d 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -502,10 +502,10 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
     override void visit(ForwardingStatement ss)
     {
         assert(ss.sym);
-        for (Scope* csc = sc; !ss.sym.forward; csc = csc.enclosing)
+        for (Scope* csc = sc; !ss.sym.parent; csc = csc.enclosing)
         {
             assert(csc);
-            ss.sym.forward = csc.scopesym;
+            ss.sym.parent = csc.scopesym;
         }
         sc = sc.push(ss.sym);
         sc.sbreak = ss;
@@ -2891,7 +2891,8 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
             /* Void-return function can have void / noreturn typed expression
              * on return statement.
              */
-            const convToVoid = rs.exp.type.ty == Tvoid || rs.exp.type.ty == Tnoreturn;
+            auto texp = rs.exp.type;
+            const convToVoid = texp.ty == Tvoid || texp.ty == Tnoreturn;
 
             if (tbret && tbret.ty == Tvoid || convToVoid)
             {
@@ -2903,6 +2904,15 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
                     rs.exp = rs.exp.expressionSemantic(sc);
                 }
 
+                // https://issues.dlang.org/show_bug.cgi?id=23063
+                if (texp.isTypeNoreturn() && !rs.exp.isAssertExp() && !rs.exp.isThrowExp() && !rs.exp.isCallExp())
+                {
+                    auto msg = new StringExp(rs.exp.loc, "Accessed expression of type `noreturn`");
+                    msg.type = Type.tstring;
+                    rs.exp = new AssertExp(rs.loc, IntegerExp.literal!0, msg);
+                    rs.exp.type = texp;
+                }
+
                 /* Replace:
                  *      return exp;
                  * with:
@@ -3698,6 +3708,13 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
 
         if (oss.tok != TOK.onScopeExit)
         {
+            // https://issues.dlang.org/show_bug.cgi?id=23159
+            if (!global.params.useExceptions)
+            {
+                oss.error("`%s` cannot be used with -betterC", Token.toChars(oss.tok));
+                return setError();
+            }
+
             // scope(success) and scope(failure) are rewritten to try-catch(-finally) statement,
             // so the generated catch block cannot be placed in finally block.
             // See also Catch::semantic.
@@ -4312,7 +4329,7 @@  public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
         if (!skip && dim == 2)
         {
             // Declare key
-            if (p.storageClass & (STC.out_ | STC.ref_ | STC.lazy_))
+            if (p.isReference() || p.isLazy())
             {
                 fs.error("no storage class for key `%s`", p.ident.toChars());
                 return returnEarly();
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 4c9ca28f2fc..31ecbd246e6 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -64,48 +64,6 @@  import dmd.sideeffect;
 import dmd.target;
 import dmd.tokens;
 
-/**************************
- * This evaluates exp while setting length to be the number
- * of elements in the tuple t.
- */
-private Expression semanticLength(Scope* sc, Type t, Expression exp)
-{
-    if (auto tt = t.isTypeTuple())
-    {
-        ScopeDsymbol sym = new ArrayScopeSymbol(sc, tt);
-        sym.parent = sc.scopesym;
-        sc = sc.push(sym);
-        sc = sc.startCTFE();
-        exp = exp.expressionSemantic(sc);
-        exp = resolveProperties(sc, exp);
-        sc = sc.endCTFE();
-        sc.pop();
-    }
-    else
-    {
-        sc = sc.startCTFE();
-        exp = exp.expressionSemantic(sc);
-        exp = resolveProperties(sc, exp);
-        sc = sc.endCTFE();
-    }
-    return exp;
-}
-
-private Expression semanticLength(Scope* sc, TupleDeclaration tup, Expression exp)
-{
-    ScopeDsymbol sym = new ArrayScopeSymbol(sc, tup);
-    sym.parent = sc.scopesym;
-
-    sc = sc.push(sym);
-    sc = sc.startCTFE();
-    exp = exp.expressionSemantic(sc);
-    exp = resolveProperties(sc, exp);
-    sc = sc.endCTFE();
-    sc.pop();
-
-    return exp;
-}
-
 /*************************************
  * Resolve a tuple index, `s[oindex]`, by figuring out what `s[oindex]` represents.
  * Setting one of pe/pt/ps.
@@ -452,101 +410,6 @@  private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb
         pt = t.merge();
 }
 
-/************************************
- * Transitively search a type for all function types.
- * If any function types with parameters are found that have parameter identifiers
- * or default arguments, remove those and create a new type stripped of those.
- * This is used to determine the "canonical" version of a type which is useful for
- * comparisons.
- * Params:
- *      t = type to scan
- * Returns:
- *      `t` if no parameter identifiers or default arguments found, otherwise a new type that is
- *      the same as t but with no parameter identifiers or default arguments.
- */
-private Type stripDefaultArgs(Type t)
-{
-    static Parameters* stripParams(Parameters* parameters)
-    {
-        static Parameter stripParameter(Parameter p)
-        {
-            Type t = stripDefaultArgs(p.type);
-            return (t != p.type || p.defaultArg || p.ident || p.userAttribDecl)
-                ? new Parameter(p.storageClass, t, null, null, null)
-                : null;
-        }
-
-        if (parameters)
-        {
-            foreach (i, p; *parameters)
-            {
-                Parameter ps = stripParameter(p);
-                if (ps)
-                {
-                    // Replace params with a copy we can modify
-                    Parameters* nparams = new Parameters(parameters.dim);
-
-                    foreach (j, ref np; *nparams)
-                    {
-                        Parameter pj = (*parameters)[j];
-                        if (j < i)
-                            np = pj;
-                        else if (j == i)
-                            np = ps;
-                        else
-                        {
-                            Parameter nps = stripParameter(pj);
-                            np = nps ? nps : pj;
-                        }
-                    }
-                    return nparams;
-                }
-            }
-        }
-        return parameters;
-    }
-
-    if (t is null)
-        return t;
-
-    if (auto tf = t.isTypeFunction())
-    {
-        Type tret = stripDefaultArgs(tf.next);
-        Parameters* params = stripParams(tf.parameterList.parameters);
-        if (tret == tf.next && params == tf.parameterList.parameters)
-            return t;
-        TypeFunction tr = tf.copy().isTypeFunction();
-        tr.parameterList.parameters = params;
-        tr.next = tret;
-        //printf("strip %s\n   <- %s\n", tr.toChars(), t.toChars());
-        return tr;
-    }
-    else if (auto tt = t.isTypeTuple())
-    {
-        Parameters* args = stripParams(tt.arguments);
-        if (args == tt.arguments)
-            return t;
-        TypeTuple tr = t.copy().isTypeTuple();
-        tr.arguments = args;
-        return tr;
-    }
-    else if (t.ty == Tenum)
-    {
-        // TypeEnum::nextOf() may be != NULL, but it's not necessary here.
-        return t;
-    }
-    else
-    {
-        Type tn = t.nextOf();
-        Type n = stripDefaultArgs(tn);
-        if (n == tn)
-            return t;
-        TypeNext tr = cast(TypeNext)t.copy();
-        tr.next = n;
-        return tr;
-    }
-}
-
 /******************************************
  * We've mistakenly parsed `t` as a type.
  * Redo `t` as an Expression only if there are no type modifiers.
@@ -603,53 +466,6 @@  Expression typeToExpression(Type t)
     }
 }
 
-/* Helper function for `typeToExpression`. Contains common code
- * for TypeQualified derived classes.
- */
-Expression typeToExpressionHelper(TypeQualified t, Expression e, size_t i = 0)
-{
-    //printf("toExpressionHelper(e = %s %s)\n", EXPtoString(e.op).ptr, e.toChars());
-    foreach (id; t.idents[i .. t.idents.dim])
-    {
-        //printf("\t[%d] e: '%s', id: '%s'\n", i, e.toChars(), id.toChars());
-
-        final switch (id.dyncast())
-        {
-            // ... '. ident'
-            case DYNCAST.identifier:
-                e = new DotIdExp(e.loc, e, cast(Identifier)id);
-                break;
-
-            // ... '. name!(tiargs)'
-            case DYNCAST.dsymbol:
-                auto ti = (cast(Dsymbol)id).isTemplateInstance();
-                assert(ti);
-                e = new DotTemplateInstanceExp(e.loc, e, ti.name, ti.tiargs);
-                break;
-
-            // ... '[type]'
-            case DYNCAST.type:          // https://issues.dlang.org/show_bug.cgi?id=1215
-                e = new ArrayExp(t.loc, e, new TypeExp(t.loc, cast(Type)id));
-                break;
-
-            // ... '[expr]'
-            case DYNCAST.expression:    // https://issues.dlang.org/show_bug.cgi?id=1215
-                e = new ArrayExp(t.loc, e, cast(Expression)id);
-                break;
-
-            case DYNCAST.object:
-            case DYNCAST.tuple:
-            case DYNCAST.parameter:
-            case DYNCAST.statement:
-            case DYNCAST.condition:
-            case DYNCAST.templateparameter:
-            case DYNCAST.initializer:
-                assert(0);
-        }
-    }
-    return e;
-}
-
 /******************************************
  * Perform semantic analysis on a type.
  * Params:
@@ -1431,7 +1247,7 @@  extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                         errors = true;
                     }
                 }
-                else if (!(fparam.storageClass & STC.lazy_) && t.ty == Tvoid)
+                else if (!fparam.isLazy() && t.ty == Tvoid)
                 {
                     .error(loc, "cannot have parameter of type `%s`", fparam.type.toChars());
                     errors = true;
@@ -2157,47 +1973,6 @@  extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
     }
 }
 
-/******************************************
- * Compile the MixinType, returning the type or expression AST.
- *
- * Doesn't run semantic() on the returned object.
- * Params:
- *      tm = mixin to compile as a type or expression
- *      loc = location for error messages
- *      sc = context
- * Return:
- *      null if error, else RootObject AST as parsed
- */
-RootObject compileTypeMixin(TypeMixin tm, Loc loc, Scope* sc)
-{
-    OutBuffer buf;
-    if (expressionsToString(buf, sc, tm.exps))
-        return null;
-
-    const errors = global.errors;
-    const len = buf.length;
-    buf.writeByte(0);
-    const str = buf.extractSlice()[0 .. len];
-    scope p = new Parser!ASTCodegen(loc, sc._module, str, false);
-    p.nextToken();
-    //printf("p.loc.linnum = %d\n", p.loc.linnum);
-
-    auto o = p.parseTypeOrAssignExp(TOK.endOfFile);
-    if (errors != global.errors)
-    {
-        assert(global.errors != errors); // should have caught all these cases
-        return null;
-    }
-    if (p.token.value != TOK.endOfFile)
-    {
-        .error(loc, "incomplete mixin type `%s`", str.ptr);
-        return null;
-    }
-
-    return o;
-}
-
-
 /************************************
  * If an identical type to `type` is in `type.stringtable`, return
  * the latter one. Otherwise, add it to `type.stringtable`.
@@ -3243,6 +3018,7 @@  void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
         {
             pt = mt.obj.isType();
             ps = mt.obj.isDsymbol();
+            pe = mt.obj.isExpression();
             return;
         }
 
@@ -3310,7 +3086,10 @@  void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
             case EXP.overloadSet:
                 mt.obj = e.isOverExp().type;
                 break;
+            case EXP.error:
+                break;
             default:
+                mt.obj = e;
                 break;
             }
         }
@@ -3318,14 +3097,19 @@  void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
         if (mt.obj)
         {
             if (auto t = mt.obj.isType())
-                returnType(t.addMod(mt.mod));
+            {
+                t = t.addMod(mt.mod);
+                mt.obj = t;
+                returnType(t);
+            }
             else if (auto s = mt.obj.isDsymbol())
                 returnSymbol(s);
-            else
-                assert(0);
+            else if (auto e = mt.obj.isExpression())
+                returnExp(e);
         }
         else
         {
+            assert(global.errors);
             mt.obj = Type.terror;
             return returnError();
         }
@@ -4817,6 +4601,193 @@  extern (C++) Expression defaultInit(Type mt, const ref Loc loc, const bool isCfi
     }
 }
 
+/******************************* Private *****************************************/
+
+private:
+
+/* Helper function for `typeToExpression`. Contains common code
+ * for TypeQualified derived classes.
+ */
+Expression typeToExpressionHelper(TypeQualified t, Expression e, size_t i = 0)
+{
+    //printf("toExpressionHelper(e = %s %s)\n", EXPtoString(e.op).ptr, e.toChars());
+    foreach (id; t.idents[i .. t.idents.dim])
+    {
+        //printf("\t[%d] e: '%s', id: '%s'\n", i, e.toChars(), id.toChars());
+
+        final switch (id.dyncast())
+        {
+            // ... '. ident'
+            case DYNCAST.identifier:
+                e = new DotIdExp(e.loc, e, cast(Identifier)id);
+                break;
+
+            // ... '. name!(tiargs)'
+            case DYNCAST.dsymbol:
+                auto ti = (cast(Dsymbol)id).isTemplateInstance();
+                assert(ti);
+                e = new DotTemplateInstanceExp(e.loc, e, ti.name, ti.tiargs);
+                break;
+
+            // ... '[type]'
+            case DYNCAST.type:          // https://issues.dlang.org/show_bug.cgi?id=1215
+                e = new ArrayExp(t.loc, e, new TypeExp(t.loc, cast(Type)id));
+                break;
+
+            // ... '[expr]'
+            case DYNCAST.expression:    // https://issues.dlang.org/show_bug.cgi?id=1215
+                e = new ArrayExp(t.loc, e, cast(Expression)id);
+                break;
+
+            case DYNCAST.object:
+            case DYNCAST.tuple:
+            case DYNCAST.parameter:
+            case DYNCAST.statement:
+            case DYNCAST.condition:
+            case DYNCAST.templateparameter:
+            case DYNCAST.initializer:
+                assert(0);
+        }
+    }
+    return e;
+}
+
+/**************************
+ * This evaluates exp while setting length to be the number
+ * of elements in the tuple t.
+ */
+Expression semanticLength(Scope* sc, Type t, Expression exp)
+{
+    if (auto tt = t.isTypeTuple())
+    {
+        ScopeDsymbol sym = new ArrayScopeSymbol(sc, tt);
+        sym.parent = sc.scopesym;
+        sc = sc.push(sym);
+        sc = sc.startCTFE();
+        exp = exp.expressionSemantic(sc);
+        exp = resolveProperties(sc, exp);
+        sc = sc.endCTFE();
+        sc.pop();
+    }
+    else
+    {
+        sc = sc.startCTFE();
+        exp = exp.expressionSemantic(sc);
+        exp = resolveProperties(sc, exp);
+        sc = sc.endCTFE();
+    }
+    return exp;
+}
+
+Expression semanticLength(Scope* sc, TupleDeclaration tup, Expression exp)
+{
+    ScopeDsymbol sym = new ArrayScopeSymbol(sc, tup);
+    sym.parent = sc.scopesym;
+
+    sc = sc.push(sym);
+    sc = sc.startCTFE();
+    exp = exp.expressionSemantic(sc);
+    exp = resolveProperties(sc, exp);
+    sc = sc.endCTFE();
+    sc.pop();
+
+    return exp;
+}
+
+/************************************
+ * Transitively search a type for all function types.
+ * If any function types with parameters are found that have parameter identifiers
+ * or default arguments, remove those and create a new type stripped of those.
+ * This is used to determine the "canonical" version of a type which is useful for
+ * comparisons.
+ * Params:
+ *      t = type to scan
+ * Returns:
+ *      `t` if no parameter identifiers or default arguments found, otherwise a new type that is
+ *      the same as t but with no parameter identifiers or default arguments.
+ */
+Type stripDefaultArgs(Type t)
+{
+    static Parameters* stripParams(Parameters* parameters)
+    {
+        static Parameter stripParameter(Parameter p)
+        {
+            Type t = stripDefaultArgs(p.type);
+            return (t != p.type || p.defaultArg || p.ident || p.userAttribDecl)
+                ? new Parameter(p.storageClass, t, null, null, null)
+                : null;
+        }
+
+        if (parameters)
+        {
+            foreach (i, p; *parameters)
+            {
+                Parameter ps = stripParameter(p);
+                if (ps)
+                {
+                    // Replace params with a copy we can modify
+                    Parameters* nparams = new Parameters(parameters.dim);
+
+                    foreach (j, ref np; *nparams)
+                    {
+                        Parameter pj = (*parameters)[j];
+                        if (j < i)
+                            np = pj;
+                        else if (j == i)
+                            np = ps;
+                        else
+                        {
+                            Parameter nps = stripParameter(pj);
+                            np = nps ? nps : pj;
+                        }
+                    }
+                    return nparams;
+                }
+            }
+        }
+        return parameters;
+    }
+
+    if (t is null)
+        return t;
+
+    if (auto tf = t.isTypeFunction())
+    {
+        Type tret = stripDefaultArgs(tf.next);
+        Parameters* params = stripParams(tf.parameterList.parameters);
+        if (tret == tf.next && params == tf.parameterList.parameters)
+            return t;
+        TypeFunction tr = tf.copy().isTypeFunction();
+        tr.parameterList.parameters = params;
+        tr.next = tret;
+        //printf("strip %s\n   <- %s\n", tr.toChars(), t.toChars());
+        return tr;
+    }
+    else if (auto tt = t.isTypeTuple())
+    {
+        Parameters* args = stripParams(tt.arguments);
+        if (args == tt.arguments)
+            return t;
+        TypeTuple tr = t.copy().isTypeTuple();
+        tr.arguments = args;
+        return tr;
+    }
+    else if (t.ty == Tenum)
+    {
+        // TypeEnum::nextOf() may be != NULL, but it's not necessary here.
+        return t;
+    }
+    else
+    {
+        Type tn = t.nextOf();
+        Type n = stripDefaultArgs(tn);
+        if (n == tn)
+            return t;
+        TypeNext tr = cast(TypeNext)t.copy();
+        tr.next = n;
+        return tr;
+    }
+}
 
 /******************************
  * Get the value of the .max/.min property of `ed` as an Expression.
@@ -4829,7 +4800,7 @@  extern (C++) Expression defaultInit(Type mt, const ref Loc loc, const bool isCfi
  * Returns:
  *      corresponding value of .max/.min
  */
-private Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identifier id)
+Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identifier id)
 {
     //printf("EnumDeclaration::getMaxValue()\n");
 
@@ -4935,3 +4906,43 @@  private Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identif
     }
     return ed.errors ? errorReturn() : pvalToResult(*pval, loc);
 }
+
+/******************************************
+ * Compile the MixinType, returning the type or expression AST.
+ *
+ * Doesn't run semantic() on the returned object.
+ * Params:
+ *      tm = mixin to compile as a type or expression
+ *      loc = location for error messages
+ *      sc = context
+ * Return:
+ *      null if error, else RootObject AST as parsed
+ */
+RootObject compileTypeMixin(TypeMixin tm, Loc loc, Scope* sc)
+{
+    OutBuffer buf;
+    if (expressionsToString(buf, sc, tm.exps))
+        return null;
+
+    const errors = global.errors;
+    const len = buf.length;
+    buf.writeByte(0);
+    const str = buf.extractSlice()[0 .. len];
+    scope p = new Parser!ASTCodegen(loc, sc._module, str, false);
+    p.nextToken();
+    //printf("p.loc.linnum = %d\n", p.loc.linnum);
+
+    auto o = p.parseTypeOrAssignExp(TOK.endOfFile);
+    if (errors != global.errors)
+    {
+        assert(global.errors != errors); // should have caught all these cases
+        return null;
+    }
+    if (p.token.value != TOK.endOfFile)
+    {
+        .error(loc, "incomplete mixin type `%s`", str.ptr);
+        return null;
+    }
+
+    return o;
+}
diff --git a/gcc/d/dmd/typinf.d b/gcc/d/dmd/typinf.d
index 21447ae9a3d..b701be38e42 100644
--- a/gcc/d/dmd/typinf.d
+++ b/gcc/d/dmd/typinf.d
@@ -18,6 +18,7 @@  import dmd.dscope;
 import dmd.dclass;
 import dmd.dstruct;
 import dmd.errors;
+import dmd.expression;
 import dmd.globals;
 import dmd.gluelayer;
 import dmd.mtype;
@@ -28,11 +29,12 @@  import core.stdc.stdio;
  * Generates the `TypeInfo` object associated with `torig` if it
  * hasn't already been generated
  * Params:
+ *      e     = if not null, then expression for pretty-printing errors
  *      loc   = the location for reporting line numbers in errors
  *      torig = the type to generate the `TypeInfo` object for
  *      sc    = the scope
  */
-extern (C++) void genTypeInfo(const ref Loc loc, Type torig, Scope* sc)
+extern (C++) void genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc)
 {
     // printf("genTypeInfo() %s\n", torig.toChars());
 
@@ -43,7 +45,10 @@  extern (C++) void genTypeInfo(const ref Loc loc, Type torig, Scope* sc)
     {
         if (!global.params.useTypeInfo)
         {
-            .error(loc, "`TypeInfo` cannot be used with -betterC");
+            if (e)
+                .error(loc, "expression `%s` uses the GC and cannot be used with switch `-betterC`", e.toChars());
+            else
+                .error(loc, "`TypeInfo` cannot be used with -betterC");
             fatal();
         }
     }
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 7edcbc47abc..179f9a5f4fd 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -2238,13 +2238,17 @@  public:
 	    new_call = build_nop (type, build_address (var));
 	    setup_exp = modify_expr (var, aggregate_initializer_decl (cd));
 	  }
+	else if (global.params.ehnogc && e->thrownew)
+	  {
+	    /* Allocating a `@nogc' Exception with `_d_newThrowable' has already
+	       been handled by the front-end.  */
+	    gcc_unreachable ();
+	  }
 	else
 	  {
 	    /* Generate: _d_newclass()  */
 	    tree arg = build_address (get_classinfo_decl (cd));
-	    libcall_fn libcall = (global.params.ehnogc && e->thrownew)
-	      ? LIBCALL_NEWTHROW : LIBCALL_NEWCLASS;
-	    new_call = build_libcall (libcall, tb, 1, arg);
+	    new_call = build_libcall (LIBCALL_NEWCLASS, tb, 1, arg);
 	  }
 
 	/* Set the context pointer for nested classes.  */
diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def
index 1ad0369a75d..459a28386a0 100644
--- a/gcc/d/runtime.def
+++ b/gcc/d/runtime.def
@@ -61,7 +61,6 @@  DEF_D_RUNTIME (ARRAYBOUNDS_INDEXP, "_d_arraybounds_indexp", RT(VOID),
 
 /* Used when calling new on a class.  */
 DEF_D_RUNTIME (NEWCLASS, "_d_newclass", RT(OBJECT), P1(CONST_CLASSINFO), 0)
-DEF_D_RUNTIME (NEWTHROW, "_d_newThrowable", RT(OBJECT), P1(CONST_CLASSINFO), 0)
 
 /* Used when calling delete on a stack-allocated class or interface.  */
 DEF_D_RUNTIME (CALLFINALIZER, "_d_callfinalizer", RT(VOID), P1(VOIDPTR), 0)
diff --git a/gcc/testsuite/gdc.test/compilable/imports/defines.c b/gcc/testsuite/gdc.test/compilable/imports/defines.c
new file mode 100644
index 00000000000..6bd07366544
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/defines.c
@@ -0,0 +1,28 @@ 
+/* */
+
+#define CC 'c'
+_Static_assert(CC == 'c', "1");
+
+#define I32 3
+_Static_assert(I32 == 3, "3");
+
+#define U32 4U
+_Static_assert(U32 == 4U, "4");
+
+#define I64 5L
+_Static_assert(I64 == 5U, "5");
+
+#define U64 6UL
+_Static_assert(U64 == 6UL, "6");
+
+#define F32 7.0f
+_Static_assert(F32 == 7.0f, "7");
+
+#define F64 8.0f
+_Static_assert(F64 == 8.0, "8");
+
+#define F80 9.0f
+_Static_assert(F80 == 9.0L, "9");
+
+#define SSS "hello"
+_Static_assert(SSS[0] == 'h', "10");
diff --git a/gcc/testsuite/gdc.test/compilable/nogc.d b/gcc/testsuite/gdc.test/compilable/nogc.d
index 27518019d6d..6ce5094371f 100644
--- a/gcc/testsuite/gdc.test/compilable/nogc.d
+++ b/gcc/testsuite/gdc.test/compilable/nogc.d
@@ -109,3 +109,12 @@  auto foo13550() @nogc
     }
     return &bar;
 }
+
+// https://issues.dlang.org/show_bug.cgi?id=19285
+
+void f(bool cond, string s) @nogc {
+    auto inner() { return s; }
+    alias Unused1 = typeof(inner); // OK
+    alias Unused2 = typeof(&inner); // (Does not) INFERS GC (anymore)
+    enum Unused3 = __traits(compiles , &inner);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22626.d b/gcc/testsuite/gdc.test/compilable/test22626.d
new file mode 100644
index 00000000000..5f72eb635c0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22626.d
@@ -0,0 +1,23 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=22626
+// REQUIRED_ARGS: -preview=nosharedaccess
+
+shared int k;
+
+class Oops
+{
+    shared int a;
+    shared int* pa;
+    synchronized void oops()
+    {
+        // this should compile since the function is synchronized
+        // and `a` is accessed through `this`.
+        a = 2;
+
+        // this shouldn't compile because synchronized guards
+        // only accesses to the first level of dereferencing
+        static assert (!__traits(compiles, *pa = 2));
+
+        // this shouldn't compile `k` is a field of class `Oops`
+        static assert (!__traits(compiles, k = 2));
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23076.d b/gcc/testsuite/gdc.test/compilable/test23076.d
new file mode 100644
index 00000000000..10a0c2f1601
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23076.d
@@ -0,0 +1,38 @@ 
+/* REQUIRED_ARGS: -O -inline
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=23076
+
+struct S
+{
+    int depthLow = 0;
+    int depthHigh = 30000;
+
+    void fun(int* pixels)
+    {
+        float b = depthLow;
+        int depthA = cast(int)(b);
+        int depthB = cast(short)(cast(float)depthHigh * cast(float)depthLow);
+        pixels[depthA] = depthB;
+    }
+}
+
+/**********************/
+
+float mul3(float a, float b, float t)
+{
+    return t * b * a;
+}
+
+class A
+{
+    ushort depthLow = 0;
+    ushort depthHigh = 30000;
+
+    void fun(short* pixels)
+    {
+        short depthA = (cast(short)(mul3(depthHigh, depthLow, 0)));
+        short depthB = (cast(short)(mul3(depthLow, depthHigh, 0)));
+        pixels[depthA] = depthB;
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23142.d b/gcc/testsuite/gdc.test/compilable/test23142.d
new file mode 100644
index 00000000000..28bb6916978
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23142.d
@@ -0,0 +1,19 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23142
+
+struct Foo
+{
+    int x;
+
+scope:
+    void func()
+    {
+    }
+
+    unittest
+    {
+    }
+
+    static void func2()
+    {
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23174.d b/gcc/testsuite/gdc.test/compilable/test23174.d
new file mode 100644
index 00000000000..9047fd7f8a9
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23174.d
@@ -0,0 +1,58 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23174
+
+alias AliasSeq(T...) = T;
+
+template staticMap(alias fun, args...)
+{
+    alias staticMap = AliasSeq!();
+    static foreach(arg; args)
+        staticMap = AliasSeq!(staticMap, fun!arg);
+}
+
+template Filter(alias pred, args...)
+{
+    alias Filter = AliasSeq!();
+    static foreach (arg; args)
+        static if (pred!arg)
+            Filter = AliasSeq!(Filter, arg);
+}
+
+struct Fields(T)
+{
+    private static alias toField(alias e) = Field!(__traits(identifier, e));
+    alias fields = staticMap!(toField, T.tupleof);
+
+    static alias map(alias F) = staticMap!(F, fields);
+    static alias filter(alias pred) = Filter!(pred, fields);
+}
+
+struct Field(string n)
+{
+    enum name = n;
+}
+
+struct Foo
+{
+    int a;
+}
+
+void test23174()
+{
+    Foo value;
+
+    enum toName(alias e) = e.name;
+    enum pred(alias e) = true;
+
+    alias a = Fields!(Foo).filter!(pred); // works
+    static assert(is(a == AliasSeq!(Field!"a")));
+
+    alias b = Fields!(Foo).map!(toName); // works
+    static assert(b == AliasSeq!("a"));
+
+    alias c = Fields!(Foo).init.filter!(pred); // works
+    static assert(is(c == AliasSeq!(Field!"a")));
+
+    // OK <- Error: alias `d` cannot alias an expression `Fields().tuple("a")`
+    alias d = Fields!(Foo).init.map!(toName);
+    static assert(d == AliasSeq!("a"));
+}
diff --git a/gcc/testsuite/gdc.test/compilable/testdefines.d b/gcc/testsuite/gdc.test/compilable/testdefines.d
new file mode 100644
index 00000000000..4507266c751
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/testdefines.d
@@ -0,0 +1,14 @@ 
+// EXTRA_FILES: imports/defines.c
+import imports.defines;
+
+static assert(CC == 'c');
+static assert(I32 == 3);
+static assert(U32 == 4);
+static assert(I64 == 5);
+static assert(U64 == 6);
+
+static assert(F32 == 7.0f);
+static assert(F64 == 8.0);
+static assert(F80 == 9.0L);
+
+static assert(SSS == "hello");
diff --git a/gcc/testsuite/gdc.test/compilable/testdip1008.d b/gcc/testsuite/gdc.test/compilable/testdip1008.d
index 5e024fe68ec..54d404c993f 100644
--- a/gcc/testsuite/gdc.test/compilable/testdip1008.d
+++ b/gcc/testsuite/gdc.test/compilable/testdip1008.d
@@ -13,9 +13,28 @@  int bar()
     }
 }
 
+void throwQualifiers() @safe @nogc pure
+{
+    throw new Exception("baz");
+}
+
+bool testThrowQualifiers()
+{
+    try
+    {
+        throwQualifiers();
+    } catch (Exception e)
+    {
+        return true;
+    }
+
+    return false;
+}
 
 void foo()
 {
     enum r = bar();
     static assert(r == 7);
+
+    static assert(testThrowQualifiers());
 }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/mixin_template.d b/gcc/testsuite/gdc.test/fail_compilation/mixin_template.d
new file mode 100644
index 00000000000..b088da88e3a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/mixin_template.d
@@ -0,0 +1,10 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/mixin_template.d(10): Error: mixin `mixin_template.f!1` - `f` is a function, not a template
+---
+*/
+string f() {
+    return "int i;";
+}
+mixin f!1;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn.d
index 696081a36b6..d47d44917ba 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/noreturn.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn.d
@@ -118,3 +118,21 @@  enum forceInClassRef = inClassRef();
 */
 
 enum throwEnum = throw new Exception("");
+
+
+/*
+https://issues.dlang.org/show_bug.cgi?id=23063
+
+TEST_OUTPUT:
+---
+fail_compilation/noreturn.d(135): Error: `"Accessed expression of type `noreturn`"`
+fail_compilation/noreturn.d(138):        called from here: `func()`
+---
+*/
+noreturn func()
+{
+    noreturn a;
+    return a;
+}
+
+enum f = func();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/template_decl.d b/gcc/testsuite/gdc.test/fail_compilation/template_decl.d
new file mode 100644
index 00000000000..d986dd65065
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/template_decl.d
@@ -0,0 +1,9 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/template_decl.d(8): Error: `{` expected after template parameter list, not `(`
+fail_compilation/template_decl.d(8): Error: declaration expected, not `(`
+---
+*/
+template b(alias d)() {
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21477.d b/gcc/testsuite/gdc.test/fail_compilation/test21477.d
new file mode 100644
index 00000000000..c9c7c7fcd50
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21477.d
@@ -0,0 +1,16 @@ 
+/* REQUIRED_ARGS: -betterC
+TEST_OUTPUT:
+---
+fail_compilation/test21477.d(103): Error: expression `[1]` uses the GC and cannot be used with switch `-betterC`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=21477
+
+#line 100
+
+int test()
+{
+    int[] foo = [1];
+    return 0;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23159.d b/gcc/testsuite/gdc.test/fail_compilation/test23159.d
new file mode 100644
index 00000000000..cdafc613b59
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test23159.d
@@ -0,0 +1,22 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23159
+
+// REQUIRED_ARGS: -betterC
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test23159.d(14): Error: `scope(failure)` cannot be used with -betterC
+fail_compilation/test23159.d(18): Error: `scope(success)` cannot be used with -betterC
+---
+*/
+
+void main()
+{
+    scope(failure)
+    {
+        int a;
+    }
+    scope(success)
+    {
+        int a;
+    }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/traits.d b/gcc/testsuite/gdc.test/fail_compilation/traits.d
index 8c16afe75b2..21f3f57edd5 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/traits.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/traits.d
@@ -116,3 +116,21 @@  pragma(msg, __traits(hasCopyConstructor));
 pragma(msg, __traits(hasCopyConstructor, S()));
 pragma(msg, __traits(hasPostblit));
 pragma(msg, __traits(hasPostblit, S()));
+
+/********************************************
+https://issues.dlang.org/show_bug.cgi?id=23178
+
+TEST_OUTPUT:
+---
+fail_compilation/traits.d(701): Error: alias `traits.a` cannot alias an expression `true`
+fail_compilation/traits.d(702): Error: alias `traits.b` cannot alias an expression `false`
+fail_compilation/traits.d(703): Error: alias `traits.c` cannot alias an expression `"Object"`
+fail_compilation/traits.d(704):        while evaluating `pragma(msg, a)`
+---
+*/
+#line 700
+
+alias a = __traits(compiles, 1);
+alias b = __traits(isIntegral, 1.1);
+alias c = __traits(identifier, Object);
+pragma(msg, a, b, c);
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index d503bae835c..8b2839da46c 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@ 
-f89da31331ef5df50d3bc7a26efd1b7acdefde8c
+454471d8077d12ec6bf0ae8fcd9571aad1bce7be
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/druntime repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 260bb63340c..d963aa9bd3d 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -200,9 +200,9 @@  DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/stdc/tgmath.d core/stdc/time.d core/stdc/wchar_.d \
 	core/stdc/wctype.d core/sync/barrier.d core/sync/condition.d \
 	core/sync/config.d core/sync/event.d core/sync/exception.d \
-	core/sync/mutex.d core/sync/rwmutex.d core/sync/semaphore.d \
-	core/thread/context.d core/thread/fiber.d core/thread/osthread.d \
-	core/thread/package.d core/thread/threadbase.d \
+	core/sync/mutex.d core/sync/package.d core/sync/rwmutex.d \
+	core/sync/semaphore.d core/thread/context.d core/thread/fiber.d \
+	core/thread/osthread.d core/thread/package.d core/thread/threadbase.d \
 	core/thread/threadgroup.d core/thread/types.d core/time.d \
 	core/vararg.d core/volatile.d gcc/attribute.d gcc/attributes.d \
 	gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index b7e2f347278..45e086a5f0d 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -226,17 +226,18 @@  am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	core/stdc/tgmath.lo core/stdc/time.lo core/stdc/wchar_.lo \
 	core/stdc/wctype.lo core/sync/barrier.lo \
 	core/sync/condition.lo core/sync/config.lo core/sync/event.lo \
-	core/sync/exception.lo core/sync/mutex.lo core/sync/rwmutex.lo \
-	core/sync/semaphore.lo core/thread/context.lo \
-	core/thread/fiber.lo core/thread/osthread.lo \
-	core/thread/package.lo core/thread/threadbase.lo \
-	core/thread/threadgroup.lo core/thread/types.lo core/time.lo \
-	core/vararg.lo core/volatile.lo gcc/attribute.lo \
-	gcc/attributes.lo gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo \
-	gcc/emutls.lo gcc/gthread.lo gcc/sections/common.lo \
-	gcc/sections/elf.lo gcc/sections/macho.lo \
-	gcc/sections/package.lo gcc/sections/pecoff.lo \
-	gcc/unwind/arm.lo gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
+	core/sync/exception.lo core/sync/mutex.lo core/sync/package.lo \
+	core/sync/rwmutex.lo core/sync/semaphore.lo \
+	core/thread/context.lo core/thread/fiber.lo \
+	core/thread/osthread.lo core/thread/package.lo \
+	core/thread/threadbase.lo core/thread/threadgroup.lo \
+	core/thread/types.lo core/time.lo core/vararg.lo \
+	core/volatile.lo gcc/attribute.lo gcc/attributes.lo \
+	gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo gcc/emutls.lo \
+	gcc/gthread.lo gcc/sections/common.lo gcc/sections/elf.lo \
+	gcc/sections/macho.lo gcc/sections/package.lo \
+	gcc/sections/pecoff.lo gcc/unwind/arm.lo \
+	gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
 	gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
 	object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \
 	rt/arrayassign.lo rt/arraycat.lo rt/cast_.lo rt/config.lo \
@@ -866,9 +867,9 @@  DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	core/stdc/tgmath.d core/stdc/time.d core/stdc/wchar_.d \
 	core/stdc/wctype.d core/sync/barrier.d core/sync/condition.d \
 	core/sync/config.d core/sync/event.d core/sync/exception.d \
-	core/sync/mutex.d core/sync/rwmutex.d core/sync/semaphore.d \
-	core/thread/context.d core/thread/fiber.d core/thread/osthread.d \
-	core/thread/package.d core/thread/threadbase.d \
+	core/sync/mutex.d core/sync/package.d core/sync/rwmutex.d \
+	core/sync/semaphore.d core/thread/context.d core/thread/fiber.d \
+	core/thread/osthread.d core/thread/package.d core/thread/threadbase.d \
 	core/thread/threadgroup.d core/thread/types.d core/time.d \
 	core/vararg.d core/volatile.d gcc/attribute.d gcc/attributes.d \
 	gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
@@ -1305,6 +1306,7 @@  core/sync/config.lo: core/sync/$(am__dirstamp)
 core/sync/event.lo: core/sync/$(am__dirstamp)
 core/sync/exception.lo: core/sync/$(am__dirstamp)
 core/sync/mutex.lo: core/sync/$(am__dirstamp)
+core/sync/package.lo: core/sync/$(am__dirstamp)
 core/sync/rwmutex.lo: core/sync/$(am__dirstamp)
 core/sync/semaphore.lo: core/sync/$(am__dirstamp)
 core/thread/$(am__dirstamp):
diff --git a/libphobos/libdruntime/core/attribute.d b/libphobos/libdruntime/core/attribute.d
index 69b20f0bd3c..8a1dc8add89 100644
--- a/libphobos/libdruntime/core/attribute.d
+++ b/libphobos/libdruntime/core/attribute.d
@@ -76,14 +76,14 @@  else
  *      The attribute can only be attached to methods or constructors which
  *      have Objective-C linkage. That is, a method or a constructor in a
  *      class or interface declared as $(D_CODE extern(Objective-C)).
- *  ),
+ *  )
  *
- *  $(LI It cannot be attached to a method or constructor that is a template),
+ *  $(LI It cannot be attached to a method or constructor that is a template)
  *
  *  $(LI
  *      The number of colons in the string need to match the number of
  *      arguments the method accept.
- *  ),
+ *  )
  *
  *  $(LI It can only be used once in a method declaration)
  * )
@@ -181,21 +181,21 @@  version (UdaOptional)
  * $(UL
  *  $(LI
  *      There can only be one such attribute per symbol.
- *  ),
+ *  )
  *  $(LI
  *      The attribute can only be attached to an `extern(C++)` symbol
  *      (`struct`, `class`, `enum`, function, and their templated counterparts).
- *  ),
+ *  )
  *  $(LI
  *      The attribute cannot be applied to C++ namespaces.
  *      This is to prevent confusion with the C++ semantic, which allows it to
  *      be applied to namespaces.
- *  ),
+ *  )
  *  $(LI
  *      The string arguments must only contain valid characters
  *      for C++ name mangling which currently include alphanumerics
  *      and the underscore character.
- *  ),
+ *  )
  * )
  *
  * This UDA is not transitive, and inner scope do not inherit outer scopes'
@@ -252,11 +252,11 @@  version (UdaGNUAbiTag) struct gnuAbiTag
  *  $(LI
  *      the expression is the top-level expression in a statement or the
  *      left-hand expression in a comma expression, and
- *  ),
+ *  )
  *  $(LI
  *      the expression is not an assignment (`=`, `+=`, etc.), increment
  *      (`++`), or decrement (`--`) expression.
- *  ),
+ *  )
  * )
  *
  * If the declaration of a `struct` or `union` type has the `@mustuse`
diff --git a/libphobos/libdruntime/core/internal/array/equality.d b/libphobos/libdruntime/core/internal/array/equality.d
index b12e2f24ccf..d3fdd655796 100644
--- a/libphobos/libdruntime/core/internal/array/equality.d
+++ b/libphobos/libdruntime/core/internal/array/equality.d
@@ -21,8 +21,7 @@  bool __equals(T1, T2)(scope const T1[] lhs, scope const T2[] rhs)
 @nogc nothrow pure @trusted
 if (__traits(isScalar, T1) && __traits(isScalar, T2))
 {
-    if (lhs.length != rhs.length)
-        return false;
+    const length = lhs.length;
 
     static if (T1.sizeof == T2.sizeof
         // Signedness needs to match for types that promote to int.
@@ -31,20 +30,21 @@  if (__traits(isScalar, T1) && __traits(isScalar, T2))
         && (T1.sizeof >= 4 || __traits(isUnsigned, T1) == __traits(isUnsigned, T2))
         && !__traits(isFloating, T1) && !__traits(isFloating, T2))
     {
-        if (!__ctfe)
+        if (__ctfe)
+            return length == rhs.length && isEqual(lhs.ptr, rhs.ptr, length);
+        else
         {
             // This would improperly allow equality of integers and pointers
             // but the CTFE branch will stop this function from compiling then.
             import core.stdc.string : memcmp;
-            return lhs.length == 0 ||
-                0 == memcmp(cast(const void*) lhs.ptr, cast(const void*) rhs.ptr, lhs.length * T1.sizeof);
+            return length == rhs.length &&
+                (!length || 0 == memcmp(cast(const void*) lhs.ptr, cast(const void*) rhs.ptr, length * T1.sizeof));
         }
     }
-
-    foreach (const i; 0 .. lhs.length)
-        if (lhs.ptr[i] != rhs.ptr[i])
-            return false;
-    return true;
+    else
+    {
+        return length == rhs.length && isEqual(lhs.ptr, rhs.ptr, length);
+    }
 }
 
 bool __equals(T1, T2)(scope T1[] lhs, scope T2[] rhs)
@@ -89,6 +89,19 @@  if (!__traits(isScalar, T1) || !__traits(isScalar, T2))
     }
 }
 
+/******************************
+ * Helper function for __equals().
+ * Outlined to enable __equals() to be inlined, as dmd cannot inline loops.
+ */
+private
+bool isEqual(T1, T2)(scope const T1* t1, scope const T2* t2, size_t length)
+{
+    foreach (const i; 0 .. length)
+        if (t1[i] != t2[i])
+            return false;
+    return true;
+}
+
 @safe unittest
 {
     assert(__equals([], []));
diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d
index 6502e595e00..371308def79 100644
--- a/libphobos/libdruntime/core/lifetime.d
+++ b/libphobos/libdruntime/core/lifetime.d
@@ -2648,16 +2648,19 @@  if (!Init.length ||
 }
 
 /**
- * Allocate an exception of type `T` from the exception pool and call its constructor.
- * It has the same interface as `rt.lifetime._d_newclass()`.
- * `T` must be Throwable or derived from it, must declare an explicit ctor
- * and cannot be a COM or C++ class.
+ * Allocate an exception of type `T` from the exception pool.
+ * `T` must be `Throwable` or derived from it and cannot be a COM or C++ class.
+ *
+ * Note:
+ *  This function does not call the constructor of `T` because that would require
+ *  `forward!args`, which causes errors with -dip1008. This inconvenience will be
+ *  removed once -dip1008 works as intended.
+ *
  * Returns:
- *      constructed instance of the type
+ *   allocated instance of type `T`
  */
-T _d_newThrowable(T, Args...)(auto ref Args args) @trusted
-    if (is(T : Throwable) && is(typeof(T.__ctor(forward!args))) &&
-        __traits(getLinkage, T) == "D")
+T _d_newThrowable(T)() @trusted
+    if (is(T : Throwable) && __traits(getLinkage, T) == "D")
 {
     debug(PRINTF) printf("_d_newThrowable(%s)\n", cast(char*) T.stringof);
 
@@ -2687,33 +2690,22 @@  T _d_newThrowable(T, Args...)(auto ref Args args) @trusted
 
     (cast(Throwable) p).refcount() = 1;
 
-    auto t = cast(T) p;
-    t.__ctor(forward!args);
-
-    return t;
+    return cast(T) p;
 }
 
 @system unittest
 {
     class E : Exception
     {
-        int x;
-
-        this(int x, string msg = "", Throwable nextInChain = null)
+        this(string msg = "", Throwable nextInChain = null)
         {
             super(msg, nextInChain);
-            this.x = x;
         }
     }
 
-    auto exc = _d_newThrowable!Exception("Exception");
-    assert(exc.refcount() == 1);
-    assert(exc.msg == "Exception");
-
-    static assert(!__traits(compiles, _d_newThrowable!E()));
+    Throwable exc = _d_newThrowable!Exception();
+    Throwable e = _d_newThrowable!E();
 
-    auto e = _d_newThrowable!E(42, "E", null);
+    assert(exc.refcount() == 1);
     assert(e.refcount() == 1);
-    assert(e.x == 42);
-    assert(e.msg == "E");
 }
diff --git a/libphobos/libdruntime/core/stdcpp/xutility.d b/libphobos/libdruntime/core/stdcpp/xutility.d
index fa61701e1cf..0142d0b9455 100644
--- a/libphobos/libdruntime/core/stdcpp/xutility.d
+++ b/libphobos/libdruntime/core/stdcpp/xutility.d
@@ -23,14 +23,27 @@  else
     enum StdNamespace = "std";
 }
 
+/**
+ * Possible values of the `__cplusplus` macro provided by C++ compilers
+ *
+ * For foolproofness, use ordering comparison, e.g. `__cplusplus >= CppStdRevision.cpp17`.
+ */
 enum CppStdRevision : uint
 {
     cpp98 = 199711,
     cpp11 = 201103,
     cpp14 = 201402,
-    cpp17 = 201703
+    cpp17 = 201703,
+    cpp20 = 202002,
 }
 
+/**
+ * Returns the target C++ version, encoded as C++ compilers do
+ *
+ * C++ compilers provide a `__cplusplus` macro which returns an integer
+ * representing the targetted standard. This manifest provides the same
+ * interface, retrieved from the compiler via a `__traits`.
+ */
 enum __cplusplus = __traits(getTargetInfo, "cppStd");
 
 // wrangle C++ features
diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf32.d b/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf32.d
index 2662fdb0fff..c796cd8fa74 100644
--- a/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf32.d
+++ b/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf32.d
@@ -18,6 +18,16 @@  alias Elf32_Word Elf32_Hashelt;
 alias Elf32_Word Elf32_Size;
 alias Elf32_Sword Elf32_Ssize;
 
+struct Elf32_Dyn
+{
+  Elf32_Sword   d_tag;
+  union _d_un
+  {
+      Elf32_Word d_val;
+      Elf32_Addr d_ptr;
+  } _d_un d_un;
+}
+
 alias Elf_Note Elf32_Nhdr;
 
 struct Elf32_Cap
diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf64.d b/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf64.d
index 6431bd2347a..89e3ca38a89 100644
--- a/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf64.d
+++ b/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf64.d
@@ -18,6 +18,16 @@  alias Elf64_Word Elf64_Hashelt;
 alias Elf64_Xword Elf64_Size;
 alias Elf64_Sxword Elf64_Ssize;
 
+struct Elf64_Dyn
+{
+  Elf64_Sxword  d_tag;
+  union _d_un
+  {
+      Elf64_Xword d_val;
+      Elf64_Addr d_ptr;
+  } _d_un d_un;
+}
+
 extern (D) pure
 {
     auto ELF64_R_TYPE_DATA(I)(I i) { return (cast(Elf64_Xword) i << 32) >> 40; }
diff --git a/libphobos/libdruntime/core/sys/elf/package.d b/libphobos/libdruntime/core/sys/elf/package.d
index 5de897ab420..69e52093dc3 100644
--- a/libphobos/libdruntime/core/sys/elf/package.d
+++ b/libphobos/libdruntime/core/sys/elf/package.d
@@ -617,26 +617,6 @@  enum PF_R =            (1 << 2);
 enum PF_MASKOS =       0x0ff00000;
 enum PF_MASKPROC =     0xf0000000;
 
-struct Elf32_Dyn
-{
-  Elf32_Sword   d_tag;
-  union _d_un
-  {
-      Elf32_Word d_val;
-      Elf32_Addr d_ptr;
-  } _d_un d_un;
-}
-
-struct Elf64_Dyn
-{
-  Elf64_Sxword  d_tag;
-  union _d_un
-  {
-      Elf64_Xword d_val;
-      Elf64_Addr d_ptr;
-  } _d_un d_un;
-}
-
 enum DT_NULL =         0;
 enum DT_NEEDED =       1;
 enum DT_PLTRELSZ =     2;
diff --git a/libphobos/libdruntime/core/sys/freebsd/sys/elf32.d b/libphobos/libdruntime/core/sys/freebsd/sys/elf32.d
index 134cdf0650f..4e8ae2843fb 100644
--- a/libphobos/libdruntime/core/sys/freebsd/sys/elf32.d
+++ b/libphobos/libdruntime/core/sys/freebsd/sys/elf32.d
@@ -18,6 +18,16 @@  alias Elf32_Word Elf32_Hashelt;
 alias Elf32_Word Elf32_Size;
 alias Elf32_Sword Elf32_Ssize;
 
+struct Elf32_Dyn
+{
+  Elf32_Sword   d_tag;
+  union _d_un
+  {
+      Elf32_Word d_val;
+      Elf32_Addr d_ptr;
+  } _d_un d_un;
+}
+
 alias Elf_Note Elf32_Nhdr;
 
 struct Elf32_Cap
diff --git a/libphobos/libdruntime/core/sys/freebsd/sys/elf64.d b/libphobos/libdruntime/core/sys/freebsd/sys/elf64.d
index 69528217941..c56460c123b 100644
--- a/libphobos/libdruntime/core/sys/freebsd/sys/elf64.d
+++ b/libphobos/libdruntime/core/sys/freebsd/sys/elf64.d
@@ -18,6 +18,16 @@  alias Elf64_Word Elf64_Hashelt;
 alias Elf64_Xword Elf64_Size;
 alias Elf64_Sxword Elf64_Ssize;
 
+struct Elf64_Dyn
+{
+  Elf64_Sxword  d_tag;
+  union _d_un
+  {
+      Elf64_Xword d_val;
+      Elf64_Addr d_ptr;
+  } _d_un d_un;
+}
+
 extern (D)
 {
     auto ELF64_R_TYPE_DATA(I)(I i) { return (cast(Elf64_Xword) i << 32) >> 40; }
diff --git a/libphobos/libdruntime/core/sys/linux/elf.d b/libphobos/libdruntime/core/sys/linux/elf.d
index 2cd933170a1..168b936f921 100644
--- a/libphobos/libdruntime/core/sys/linux/elf.d
+++ b/libphobos/libdruntime/core/sys/linux/elf.d
@@ -75,6 +75,26 @@  enum NT_ARM_HW_WATCH = 0x403;
 
 enum NT_VERSION =      1;
 
+struct Elf32_Dyn
+{
+  Elf32_Sword   d_tag;
+  union _d_un
+  {
+      Elf32_Word d_val;
+      Elf32_Addr d_ptr;
+  } _d_un d_un;
+}
+
+struct Elf64_Dyn
+{
+  Elf64_Sxword  d_tag;
+  union _d_un
+  {
+      Elf64_Xword d_val;
+      Elf64_Addr d_ptr;
+  } _d_un d_un;
+}
+
 enum NT_GNU_ABI_TAG =      1;
 enum NT_GNU_HWCAP =        2;
 enum NT_GNU_BUILD_ID =     3;
diff --git a/libphobos/libdruntime/core/sys/netbsd/sys/elf32.d b/libphobos/libdruntime/core/sys/netbsd/sys/elf32.d
index ce7d8bade3f..48386f60212 100644
--- a/libphobos/libdruntime/core/sys/netbsd/sys/elf32.d
+++ b/libphobos/libdruntime/core/sys/netbsd/sys/elf32.d
@@ -18,6 +18,16 @@  alias Elf32_Word Elf32_Hashelt;
 alias Elf32_Word Elf32_Size;
 alias Elf32_Sword Elf32_Ssize;
 
+struct Elf32_Dyn
+{
+  Elf32_Sword   d_tag;
+  union _d_un
+  {
+      Elf32_Word d_val;
+      Elf32_Addr d_ptr;
+  } _d_un d_un;
+}
+
 alias Elf_Note Elf32_Nhdr;
 
 struct Elf32_Cap
diff --git a/libphobos/libdruntime/core/sys/netbsd/sys/elf64.d b/libphobos/libdruntime/core/sys/netbsd/sys/elf64.d
index 7fa9a8b4de4..3eeaa90cf10 100644
--- a/libphobos/libdruntime/core/sys/netbsd/sys/elf64.d
+++ b/libphobos/libdruntime/core/sys/netbsd/sys/elf64.d
@@ -18,6 +18,16 @@  alias Elf64_Word Elf64_Hashelt;
 alias Elf64_Xword Elf64_Size;
 alias Elf64_Sxword Elf64_Ssize;
 
+struct Elf64_Dyn
+{
+  Elf64_Sxword  d_tag;
+  union _d_un
+  {
+      Elf64_Xword d_val;
+      Elf64_Addr d_ptr;
+  } _d_un d_un;
+}
+
 extern (D)
 {
     auto ELF64_R_TYPE_DATA(I)(I i) { return (cast(Elf64_Xword) i << 32) >> 40; }
diff --git a/libphobos/libdruntime/core/sys/openbsd/sys/elf32.d b/libphobos/libdruntime/core/sys/openbsd/sys/elf32.d
index 342282b857b..c56112186aa 100644
--- a/libphobos/libdruntime/core/sys/openbsd/sys/elf32.d
+++ b/libphobos/libdruntime/core/sys/openbsd/sys/elf32.d
@@ -19,6 +19,16 @@  alias Elf32_Word Elf32_Hashelt;
 alias Elf32_Word Elf32_Size;
 alias Elf32_Sword Elf32_Ssize;
 
+struct Elf32_Dyn
+{
+  Elf32_Sword   d_tag;
+  union _d_un
+  {
+      Elf32_Word d_val;
+      Elf32_Addr d_ptr;
+  } _d_un d_un;
+}
+
 alias Elf_Note Elf32_Nhdr;
 
 struct Elf32_Cap
diff --git a/libphobos/libdruntime/core/sys/openbsd/sys/elf64.d b/libphobos/libdruntime/core/sys/openbsd/sys/elf64.d
index b76d669b304..47f84d44daf 100644
--- a/libphobos/libdruntime/core/sys/openbsd/sys/elf64.d
+++ b/libphobos/libdruntime/core/sys/openbsd/sys/elf64.d
@@ -19,6 +19,16 @@  alias Elf64_Word Elf64_Hashelt;
 alias Elf64_Xword Elf64_Size;
 alias Elf64_Sxword Elf64_Ssize;
 
+struct Elf64_Dyn
+{
+  Elf64_Sxword  d_tag;
+  union _d_un
+  {
+      Elf64_Xword d_val;
+      Elf64_Addr d_ptr;
+  } _d_un d_un;
+}
+
 extern (D) pure
 {
     auto ELF64_R_TYPE_DATA(I)(I i) { return (cast(Elf64_Xword) i << 32) >> 40; }
diff --git a/libphobos/libdruntime/core/sys/solaris/sys/elftypes.d b/libphobos/libdruntime/core/sys/solaris/sys/elftypes.d
index a43cc5ad606..fe8cfef3958 100644
--- a/libphobos/libdruntime/core/sys/solaris/sys/elftypes.d
+++ b/libphobos/libdruntime/core/sys/solaris/sys/elftypes.d
@@ -11,18 +11,12 @@  nothrow:
 
 import core.stdc.stdint;
 
-alias uint32_t Elf32_Addr;
-alias uint16_t Elf32_Half;
-alias uint32_t Elf32_Off;
-alias int32_t  Elf32_Sword;
-alias uint32_t Elf32_Word;
+public import core.sys.elf :
+ Elf32_Addr, Elf32_Half, Elf32_Off,
+ Elf32_Sword, Elf32_Word,
+ Elf64_Addr, Elf64_Half, Elf64_Off,
+ Elf64_Sword, Elf64_Sxword,
+ Elf64_Word, Elf64_Xword;
 
-alias uint64_t Elf64_Addr;
-alias uint16_t Elf64_Half;
-alias uint64_t Elf64_Off;
-alias int32_t  Elf64_Sword;
-alias int64_t  Elf64_Sxword;
-alias uint32_t Elf64_Word;
-alias uint64_t Elf64_Xword;
 alias uint64_t Elf64_Lword;
 alias uint64_t Elf32_Lword;
diff --git a/libphobos/libdruntime/core/sys/solaris/sys/link.d b/libphobos/libdruntime/core/sys/solaris/sys/link.d
index d9d47c09142..9176b1794f9 100644
--- a/libphobos/libdruntime/core/sys/solaris/sys/link.d
+++ b/libphobos/libdruntime/core/sys/solaris/sys/link.d
@@ -10,6 +10,7 @@  extern (C):
 nothrow:
 
 public import core.sys.solaris.sys.elftypes;
+public import core.sys.elf;
 import core.stdc.config;
 
 struct Elf32_Dyn
@@ -33,45 +34,8 @@  struct Elf64_Dyn
     } _d_un d_un;
 }
 
-enum DT_NULL         = 0;
-enum DT_NEEDED       = 1;
-enum DT_PLTRELSZ     = 2;
-enum DT_PLTGOT       = 3;
-enum DT_HASH         = 4;
-enum DT_STRTAB       = 5;
-enum DT_SYMTAB       = 6;
-enum DT_RELA         = 7;
-enum DT_RELASZ       = 8;
-enum DT_RELAENT      = 9;
-enum DT_STRSZ        = 10;
-enum DT_SYMENT       = 11;
-enum DT_INIT         = 12;
-enum DT_FINI         = 13;
-enum DT_SONAME       = 14;
-enum DT_RPATH        = 15;
-enum DT_SYMBOLIC     = 16;
-enum DT_REL          = 17;
-enum DT_RELSZ        = 18;
-enum DT_RELENT       = 19;
-enum DT_PLTREL       = 20;
-enum DT_DEBUG        = 21;
-enum DT_TEXTREL      = 22;
-enum DT_JMPREL       = 23;
-enum DT_BIND_NOW     = 24;
-enum DT_INIT_ARRAY   = 25;
-enum DT_FINI_ARRAY   = 26;
-enum DT_INIT_ARRAYSZ = 27;
-enum DT_FINI_ARRAYSZ = 28;
-enum DT_RUNPATH      = 29;
-enum DT_FLAGS        = 30;
-
-enum DT_ENCODING        = 32;
-enum DT_PREINIT_ARRAY   = 32;
-enum DT_PREINIT_ARRAYSZ = 33;
-
 enum DT_MAXPOSTAGS = 34;
 
-enum DT_LOOS           = 0x6000000d;
 enum DT_SUNW_AUXILIARY = 0x6000000d;
 enum DT_SUNW_RTLDINF   = 0x6000000e;
 enum DT_SUNW_FILTER    = 0x6000000f;
@@ -92,205 +56,15 @@  enum DT_SUNW_LDMACH      = 0x6000001b;
 enum DT_SUNW_CAPCHAINENT = 0x6000001d;
 enum DT_SUNW_CAPCHAINSZ  = 0x6000001f;
 
-enum DT_HIOS = 0x6ffff000;
-
 enum DT_DEPRECATED_SPARC_REGISTER = 0x7000001;
 
-enum DT_VALRNGLO = 0x6ffffd00;
-
-enum DT_GNU_PRELINKED  = 0x6ffffdf5;
-enum DT_GNU_CONFLICTSZ = 0x6ffffdf6;
-enum DT_GNU_LIBLISTSZ  = 0x6ffffdf7;
-enum DT_CHECKSUM       = 0x6ffffdf8;
-enum DT_PLTPADSZ       = 0x6ffffdf9;
-enum DT_MOVEENT        = 0x6ffffdfa;
-enum DT_MOVESZ         = 0x6ffffdfb;
-enum DT_FEATURE_1      = 0x6ffffdfc;
-enum DT_POSFLAG_1      = 0x6ffffdfd;
-enum DT_SYMINSZ        = 0x6ffffdfe;
-enum DT_SYMINENT       = 0x6ffffdff;
-enum DT_VALRNGHI       = 0x6ffffdff;
-
-enum DT_ADDRRNGLO = 0x6ffffe00;
-
-enum DT_GNU_HASH     = 0x6ffffef5;
-enum DT_TLSDESC_PLT  = 0x6ffffef6;
-enum DT_TLSDESC_GOT  = 0x6ffffef7;
-enum DT_GNU_CONFLICT = 0x6ffffef8;
-enum DT_GNU_LIBLIST  = 0x6ffffef9;
-
-enum DT_CONFIG    = 0x6ffffefa;
-enum DT_DEPAUDIT  = 0x6ffffefb;
-enum DT_AUDIT     = 0x6ffffefc;
-enum DT_PLTPAD    = 0x6ffffefd;
-enum DT_MOVETAB   = 0x6ffffefe;
-enum DT_SYMINFO   = 0x6ffffeff;
-enum DT_ADDRRNGHI = 0x6ffffeff;
-
-enum DT_VERSYM = 0x6ffffff0;
-
-enum DT_RELACOUNT  = 0x6ffffff9;
-enum DT_RELCOUNT   = 0x6ffffffa;
-enum DT_FLAGS_1    = 0x6ffffffb;
-enum DT_VERDEF     = 0x6ffffffc;
-enum DT_VERDEFNUM  = 0x6ffffffd;
-enum DT_VERNEED    = 0x6ffffffe;
-enum DT_VERNEEDNUM = 0x6fffffff;
-
-enum DT_LOPROC    = 0x70000000;
-enum DT_AUXILIARY = 0x7ffffffd;
 enum DT_USED      = 0x7ffffffe;
-enum DT_FILTER    = 0x7fffffff;
-enum DT_HIPROC    = 0x7fffffff;
 
-enum DF_ORIGIN     = 0x00000001;
-enum DF_SYMBOLIC   = 0x00000002;
-enum DF_TEXTREL    = 0x00000004;
-enum DF_BIND_NOW   = 0x00000008;
-enum DF_STATIC_TLS = 0x00000010;
-
-enum DF_P1_LAZYLOAD  = 0x00000001;
-enum DF_P1_GROUPPERM = 0x00000002;
 enum DF_P1_DEFERRED  = 0x00000004;
 
-enum DF_1_NOW        = 0x00000001;
-enum DF_1_GLOBAL     = 0x00000002;
-enum DF_1_GROUP      = 0x00000004;
-enum DF_1_NODELETE   = 0x00000008;
-enum DF_1_LOADFLTR   = 0x00000010;
-enum DF_1_INITFIRST  = 0x00000020;
-enum DF_1_NOOPEN     = 0x00000040;
-enum DF_1_ORIGIN     = 0x00000080;
-enum DF_1_DIRECT     = 0x00000100;
-enum DF_1_TRANS      = 0x00000200;
-enum DF_1_INTERPOSE  = 0x00000400;
-enum DF_1_NODEFLIB   = 0x00000800;
-enum DF_1_NODUMP     = 0x00001000;
-enum DF_1_CONFALT    = 0x00002000;
-enum DF_1_ENDFILTEE  = 0x00004000;
-enum DF_1_DISPRELDNE = 0x00008000;
-enum DF_1_DISPRELPND = 0x00010000;
-enum DF_1_NODIRECT   = 0x00020000;
-enum DF_1_IGNMULDEF  = 0x00040000;
-enum DF_1_NOKSYMS    = 0x00080000;
-enum DF_1_NOHDR      = 0x00100000;
-enum DF_1_EDITED     = 0x00200000;
-enum DF_1_NORELOC    = 0x00400000;
-enum DF_1_SYMINTPOSE = 0x00800000;
-enum DF_1_GLOBAUDIT  = 0x01000000;
-enum DF_1_SINGLETON  = 0x02000000;
-
-enum DTF_1_PARINIT = 0x00000001;
-enum DTF_1_CONFEXP = 0x00000002;
-
-struct Elf32_Verdef
-{
-    Elf32_Half  vd_version;
-    Elf32_Half  vd_flags;
-    Elf32_Half  vd_ndx;
-    Elf32_Half  vd_cnt;
-    Elf32_Word  vd_hash;
-    Elf32_Word  vd_aux;
-    Elf32_Word  vd_next;
-}
-
-struct Elf32_Verdaux
-{
-    Elf32_Word  vda_name;
-    Elf32_Word  vda_next;
-}
-
-struct Elf32_Verneed
-{
-    Elf32_Half  vn_version;
-    Elf32_Half  vn_cnt;
-    Elf32_Word  vn_file;
-    Elf32_Word  vn_aux;
-    Elf32_Word  vn_next;
-}
-
-struct Elf32_Vernaux
-{
-    Elf32_Word  vna_hash;
-    Elf32_Half  vna_flags;
-    Elf32_Half  vna_other;
-    Elf32_Word  vna_name;
-    Elf32_Word  vna_next;
-}
-
-alias Elf32_Half  Elf32_Versym;
-
-struct Elf32_Syminfo
-{
-    Elf32_Half  si_boundto;
-    Elf32_Half  si_flags;
-}
-
-struct Elf64_Verdef
-{
-    Elf64_Half  vd_version;
-    Elf64_Half  vd_flags;
-    Elf64_Half  vd_ndx;
-    Elf64_Half  vd_cnt;
-    Elf64_Word  vd_hash;
-    Elf64_Word  vd_aux;
-    Elf64_Word  vd_next;
-}
-
-struct Elf64_Verdaux
-{
-    Elf64_Word  vda_name;
-    Elf64_Word  vda_next;
-}
-
-struct Elf64_Verneed
-{
-    Elf64_Half  vn_version;
-    Elf64_Half  vn_cnt;
-    Elf64_Word  vn_file;
-    Elf64_Word  vn_aux;
-    Elf64_Word  vn_next;
-}
-
-struct Elf64_Vernaux
-{
-    Elf64_Word  vna_hash;
-    Elf64_Half  vna_flags;
-    Elf64_Half  vna_other;
-    Elf64_Word  vna_name;
-    Elf64_Word  vna_next;
-}
-
-alias Elf64_Half  Elf64_Versym;
-
-struct Elf64_Syminfo
-{
-    Elf64_Half  si_boundto;
-    Elf64_Half  si_flags;
-}
-
-enum VER_NDX_LOCAL     = 0;
-enum VER_NDX_GLOBAL    = 1;
-enum VER_NDX_LORESERVE = 0xff00;
-enum VER_NDX_ELIMINATE = 0xff01;
-
-enum VER_FLG_BASE = 0x1;
-enum VER_FLG_WEAK = 0x2;
 enum VER_FLG_INFO = 0x4;
 
-enum VER_DEF_NONE    = 0;
-enum VER_DEF_CURRENT = 1;
-enum VER_DEF_NUM     = 2;
-
-enum VER_NEED_NONE    = 0;
-enum VER_NEED_CURRENT = 1;
-enum VER_NEED_NUM     = 2;
-
-enum SYMINFO_FLG_DIRECT      = 0x0001;
 enum SYMINFO_FLG_FILTER      = 0x0002;
-enum SYMINFO_FLG_PASSTHRU    = SYMINFO_FLG_FILTER;
-enum SYMINFO_FLG_COPY        = 0x0004;
-enum SYMINFO_FLG_LAZYLOAD    = 0x0008;
 enum SYMINFO_FLG_DIRECTBIND  = 0x0010;
 enum SYMINFO_FLG_NOEXTDIRECT = 0x0020;
 enum SYMINFO_FLG_AUXILIARY   = 0x0040;
@@ -298,15 +72,8 @@  enum SYMINFO_FLG_INTERPOSE   = 0x0080;
 enum SYMINFO_FLG_CAP         = 0x0100;
 enum SYMINFO_FLG_DEFERRED    = 0x0200;
 
-enum SYMINFO_BT_SELF       = 0xffff;
-enum SYMINFO_BT_PARENT     = 0xfffe;
 enum SYMINFO_BT_NONE       = 0xfffd;
 enum SYMINFO_BT_EXTERN     = 0xfffc;
-enum SYMINFO_BT_LOWRESERVE = 0xff00;
-
-enum SYMINFO_NONE    = 0;
-enum SYMINFO_CURRENT = 1;
-enum SYMINFO_NUM     = 2;
 
 alias link_map Link_map;
 
diff --git a/libphobos/libdruntime/core/thread/threadbase.d b/libphobos/libdruntime/core/thread/threadbase.d
index 505be000c56..217a33a0cf0 100644
--- a/libphobos/libdruntime/core/thread/threadbase.d
+++ b/libphobos/libdruntime/core/thread/threadbase.d
@@ -109,7 +109,7 @@  class ThreadBase
     }
 
     this(void delegate() dg, size_t sz = 0) @trusted pure nothrow @nogc
-    in( cast(void delegate() const) dg)
+    in( cast(const void delegate()) dg)
     {
         this(sz);
         m_call = dg;
diff --git a/libphobos/libdruntime/rt/ehalloc.d b/libphobos/libdruntime/rt/ehalloc.d
index 1dcd69a284f..65f92e3d015 100644
--- a/libphobos/libdruntime/rt/ehalloc.d
+++ b/libphobos/libdruntime/rt/ehalloc.d
@@ -18,51 +18,6 @@  debug(PRINTF)
     import core.stdc.stdio;
 }
 
-/**********************************************
- * Allocate an exception of type `ci` from the exception pool.
- * It has the same interface as `rt.lifetime._d_newclass()`.
- * The class type must be Throwable or derived from it,
- * and cannot be a COM or C++ class. The compiler must enforce
- * this.
- * Returns:
- *      default initialized instance of the type
- */
-
-extern (C) Throwable _d_newThrowable(const TypeInfo_Class ci)
-{
-    debug(PRINTF) printf("_d_newThrowable(ci = %p, %s)\n", ci, cast(char *)ci.name);
-
-    assert(!(ci.m_flags & TypeInfo_Class.ClassFlags.isCOMclass));
-    assert(!(ci.m_flags & TypeInfo_Class.ClassFlags.isCPPclass));
-
-    import core.stdc.stdlib : malloc;
-    auto init = ci.initializer;
-    void* p = malloc(init.length);
-    if (!p)
-    {
-        import core.exception : onOutOfMemoryError;
-        onOutOfMemoryError();
-    }
-
-    debug(PRINTF) printf(" p = %p\n", p);
-
-    // initialize it
-    p[0 .. init.length] = init[];
-
-    if (!(ci.m_flags & TypeInfo_Class.ClassFlags.noPointers))
-    {
-        // Inform the GC about the pointers in the object instance
-        import core.memory : GC;
-
-        GC.addRange(p, init.length, ci);
-    }
-
-    debug(PRINTF) printf("initialization done\n");
-    Throwable t = cast(Throwable)p;
-    t.refcount() = 1;
-    return t;
-}
-
 
 /********************************************
  * Delete exception instance `t` from the exception pool.
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index ddf730ef333..30e9e80092f 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@ 
-d46814c86392007ebb4fb73cb684ef9e8caa605a
+1206fc94f967b0183667a109049cbf596deaa696
 
 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/mmfile.d b/libphobos/src/std/mmfile.d
index e4000d4db27..f8f8a9088b6 100644
--- a/libphobos/src/std/mmfile.d
+++ b/libphobos/src/std/mmfile.d
@@ -71,13 +71,13 @@  class MmFile
      *  - On POSIX, $(REF ErrnoException, std, exception).
      *  - On Windows, $(REF WindowsException, std, windows, syserror).
      */
-    this(string filename)
+    this(string filename) scope
     {
         this(filename, Mode.read, 0, null);
     }
 
     version (linux) this(File file, Mode mode = Mode.read, ulong size = 0,
-            void* address = null, size_t window = 0)
+            void* address = null, size_t window = 0) scope
     {
         // Save a copy of the File to make sure the fd stays open.
         this.file = file;
@@ -85,7 +85,7 @@  class MmFile
     }
 
     version (linux) private this(int fildes, Mode mode, ulong size,
-            void* address, size_t window)
+            void* address, size_t window) scope
     {
         int oflag;
         int fmode;
@@ -169,7 +169,7 @@  class MmFile
      *  - On Windows, $(REF WindowsException, std, windows, syserror).
      */
     this(string filename, Mode mode, ulong size, void* address,
-            size_t window = 0)
+            size_t window = 0) scope
     {
         this.filename = filename;
         this.mMode = mode;
@@ -364,7 +364,7 @@  class MmFile
     /**
      * Flushes pending output and closes the memory mapped file.
      */
-    ~this()
+    ~this() scope
     {
         debug (MMFILE) printf("MmFile.~this()\n");
         unmap();
diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d
index 869c36fdfe8..f3d3152b347 100644
--- a/libphobos/src/std/sumtype.d
+++ b/libphobos/src/std/sumtype.d
@@ -1313,6 +1313,7 @@  version (D_BetterC) {} else
 // Types with invariants
 // Disabled in BetterC due to use of exceptions
 version (D_BetterC) {} else
+version (D_Invariants)
 @system unittest
 {
     import std.exception : assertThrown;
@@ -1330,22 +1331,13 @@  version (D_BetterC) {} else
         invariant { assert(i >= 0); }
     }
 
-    // Only run test if contract checking is enabled
-    try
-    {
-        S probe = S(-1);
-        assert(&probe);
-    }
-    catch (AssertError _)
-    {
-        SumType!S x;
-        x.match!((ref v) { v.i = -1; });
-        assertThrown!AssertError(assert(&x));
+    SumType!S x;
+    x.match!((ref v) { v.i = -1; });
+    assertThrown!AssertError(assert(&x));
 
-        SumType!C y = new C();
-        y.match!((ref v) { v.i = -1; });
-        assertThrown!AssertError(assert(&y));
-    }
+    SumType!C y = new C();
+    y.match!((ref v) { v.i = -1; });
+    assertThrown!AssertError(assert(&y));
 }
 
 // Calls value postblit on self-assignment