[12,committed] d: Merge upstream dmd 76e3b41375, druntime 1462ebd1, phobos 5fef0d28f.

Message ID 20220726214621.1275981-1-ibuclaw@gdcproject.org
State Committed
Headers
Series [12,committed] d: Merge upstream dmd 76e3b41375, druntime 1462ebd1, phobos 5fef0d28f. |

Commit Message

Iain Buclaw July 26, 2022, 9:46 p.m. UTC
  Hi,

This patch merges the D front-end with upstream dmd 76e3b41375, and
standard run-time libraries with druntime 1462ebd1, and phobos
5fef0d28f, updating the D language version to v2.100.1.

D front-end changes:

    - Fix delegate literal with inferred return value that requires
      following alias-this to not use class cast.
    - Fix internal error on variadic template type instantiated with two
      arrays of classes.
    - `scope(failure)' blocks that contain `return' statements are now
      deprecated.
    - Fix regression where wrong cast was inserted for ternary operator
      and non-int enums.
    - Fix internal error in code generation trying to reference
      _d_arraysetctor.
    - Fix memory corruption when array literal is passed to map in
      lambda, then returned from nested function.
    - Generate invariant id on the basis of location rather than a
      global counter.
    - Make `noreturn' conversions work.
    - Fix segfault when `.stringof' of template alias overloaded with
      function accessed by trait.
    - Empty array literal passed to scope param not 'falsey' anymore.

Phobos changes:

    - Avoid copying ranges in std.algorithm.comparison.equal.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and
committed to the releases/gcc-12 branch.

Regards,
Iain.

---
gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 76e3b41375.
	* dmd/VERSION: Bump version to v2.100.1.
	* decl.cc (DeclVisitor::visit (VarDeclaration *)): Evaluate RHS
	  of noreturn declaration expressions first.
	* expr.cc (ExprVisitor::visit (AssignExp *)): Don't generate
	  assignment for noreturn types.

libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime 1462ebd1.
	* src/MERGE: Merge upstream phobos 5fef0d28f.
---
 gcc/d/decl.cc                                 |  7 ++-
 gcc/d/dmd/MERGE                               |  2 +-
 gcc/d/dmd/VERSION                             |  2 +-
 gcc/d/dmd/dcast.d                             | 14 ++++-
 gcc/d/dmd/dsymbolsem.d                        |  3 +
 gcc/d/dmd/expressionsem.d                     | 13 +++--
 gcc/d/dmd/func.d                              | 14 ++++-
 gcc/d/dmd/impcnvtab.d                         | 55 +++++++++++++++++++
 gcc/d/dmd/mtype.d                             |  5 ++
 gcc/d/dmd/statementsem.d                      | 16 +++++-
 gcc/d/expr.cc                                 | 11 ++++
 .../gdc.test/compilable/backendfloatoptim.d   | 10 ++++
 gcc/testsuite/gdc.test/compilable/noreturn1.d | 28 ++++++++++
 gcc/testsuite/gdc.test/compilable/test23082.d | 17 ++++++
 gcc/testsuite/gdc.test/compilable/test23166.d | 22 ++++++++
 gcc/testsuite/gdc.test/compilable/test23172.d | 33 +++++++++++
 gcc/testsuite/gdc.test/compilable/test23258.d | 21 +++++++
 .../gdc.test/fail_compilation/fail23181.d     | 16 ++++++
 .../gdc.test/fail_compilation/fail6889.d      |  2 +-
 .../gdc.test/fail_compilation/fail7848.d      |  8 +--
 .../gdc.test/fail_compilation/test21443.d     | 21 +++++++
 .../gdc.test/fail_compilation/test23170.d     | 12 ++++
 gcc/testsuite/gdc.test/runnable/noreturn1.d   | 32 +++++++++++
 gcc/testsuite/gdc.test/runnable/test20734.d   |  7 +++
 gcc/testsuite/gdc.test/runnable/test23181.d   | 27 +++++++++
 gcc/testsuite/gdc.test/runnable/test23234.d   | 22 ++++++++
 gcc/testsuite/gdc.test/runnable/warning1.d    |  9 ---
 libphobos/libdruntime/MERGE                   |  2 +-
 libphobos/src/MERGE                           |  2 +-
 libphobos/src/std/algorithm/comparison.d      |  2 +-
 libphobos/src/std/typecons.d                  | 10 +++-
 31 files changed, 408 insertions(+), 37 deletions(-)
 create mode 100644 gcc/testsuite/gdc.test/compilable/backendfloatoptim.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23082.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23166.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23172.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test23258.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail23181.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test21443.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test23170.d
 create mode 100644 gcc/testsuite/gdc.test/runnable/test23181.d
 create mode 100644 gcc/testsuite/gdc.test/runnable/test23234.d
  

Patch

diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index f5c21078aad..43c3d87cdd1 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -645,9 +645,12 @@  public:
 	if (!d->isDataseg () && !d->isMember ()
 	    && d->_init && !d->_init->isVoidInitializer ())
 	  {
+	    /* Evaluate RHS for side effects first.  */
+	    Expression *ie = initializerToExpression (d->_init);
+	    add_stmt (build_expr (ie));
+
 	    Expression *e = d->type->defaultInitLiteral (d->loc);
-	    tree exp = build_expr (e);
-	    add_stmt (exp);
+	    add_stmt (build_expr (e));
 	  }
 
 	return;
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index d538621ba83..d79ebfae806 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-a53934d18eecccbf677cd32a4febeff3bc0ee292
+76e3b41375e3e1cb4dbca692b587d8e916c0b49f
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 5ea2ba0d8ec..83a14f57e16 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@ 
-v2.100.0
+v2.100.1
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 83978391e42..6afa1c966b0 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -1107,9 +1107,14 @@  MATCH implicitConvTo(Expression e, Type t)
 
     MATCH visitCond(CondExp e)
     {
-        auto result = visit(e);
-        if (result != MATCH.nomatch)
-            return result;
+        e.econd = e.econd.optimize(WANTvalue);
+        const opt = e.econd.toBool();
+        if (opt.isPresent())
+        {
+            auto result = visit(e);
+            if (result != MATCH.nomatch)
+                return result;
+        }
 
         MATCH m1 = e.e1.implicitConvTo(t);
         MATCH m2 = e.e2.implicitConvTo(t);
@@ -2954,6 +2959,9 @@  Lagain:
 
         t1 = Type.basic[ty1];
         t2 = Type.basic[ty2];
+
+        if (!(t1 && t2))
+            return null;
         e1 = e1.castTo(sc, t1);
         e2 = e2.castTo(sc, t2);
         return Lret(Type.basic[ty]);
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index be8f9150903..c5766787bf0 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -4407,7 +4407,10 @@  private extern(C++) final class DsymbolSemanticVisitor : Visitor
              invd.semanticRun < PASS.semantic &&
              !ad.isUnionDeclaration()           // users are on their own with union fields
            )
+        {
+            invd.fixupInvariantIdent(ad.invs.length);
             ad.invs.push(invd);
+        }
         if (!invd.type)
             invd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, invd.storage_class);
 
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 717420910aa..0617b69ccc9 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -2048,7 +2048,8 @@  private bool functionParameters(const ref Loc loc, Scope* sc,
                 if (global.params.useDIP1000 == FeatureState.enabled)
                     err |= checkParamArgumentEscape(sc, fd, p, arg, false, false);
             }
-            else if (!(pStc & STC.return_))
+            else if (!(pStc & STC.return_) &&
+                ((global.params.useDIP1000 == FeatureState.enabled) || !(p.storageClass & STC.scopeinferred)))
             {
                 /* Argument value cannot escape from the called function.
                  */
@@ -2058,10 +2059,10 @@  private bool functionParameters(const ref Loc loc, Scope* sc,
 
                 ArrayLiteralExp ale;
                 if (p.type.toBasetype().ty == Tarray &&
-                    (ale = a.isArrayLiteralExp()) !is null)
+                    (ale = a.isArrayLiteralExp()) !is null && ale.elements && ale.elements.length > 0)
                 {
                     // allocate the array literal as temporary static array on the stack
-                    ale.type = ale.type.nextOf().sarrayOf(ale.elements ? ale.elements.length : 0);
+                    ale.type = ale.type.nextOf().sarrayOf(ale.elements.length);
                     auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale);
                     auto declareTmp = new DeclarationExp(ale.loc, tmp);
                     auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp),
@@ -9926,9 +9927,11 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 ae.e2.type.nextOf &&
                 ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf);
 
+            /* Unlike isArrayCtor above, lower all Rvalues. If the RHS is a literal,
+             * then we do want to make a temporary for it and call its destructor.
+             */
             const isArraySetCtor =
                 (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
-                ae.e2.isLvalue &&
                 (ae.e2.type.ty == Tstruct || ae.e2.type.ty == Tsarray) &&
                 ae.e1.type.nextOf &&
                 ae.e1.type.nextOf.equivalent(ae.e2.type);
@@ -12535,7 +12538,7 @@  Expression semanticY(DotIdExp exp, Scope* sc, int flag)
                     e = new CommaExp(exp.loc, eleft, e);
                     e.type = Type.tvoid; // ambiguous type?
                 }
-                return e;
+                return e.expressionSemantic(sc);
             }
             if (auto o = s.isOverloadSet())
             {
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 55abe4d52e7..aba5d62827a 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -3748,9 +3748,7 @@  extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
             {
                 Expression exp = s.exp;
                 if (exp && !exp.type.equals(tret))
-                {
-                    s.exp = exp.castTo(sc, tret);
-                }
+                    s.exp = exp.implicitCastTo(sc, tret);
             }
         }
 
@@ -4150,6 +4148,7 @@  extern (C++) final class InvariantDeclaration : FuncDeclaration
 {
     extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, Identifier id, Statement fbody)
     {
+        // Make a unique invariant for now; we'll fix it up as we add it to the aggregate invariant list.
         super(loc, endloc, id ? id : Identifier.generateId("__invariant"), stc, null);
         this.fbody = fbody;
     }
@@ -4186,6 +4185,15 @@  extern (C++) final class InvariantDeclaration : FuncDeclaration
     {
         v.visit(this);
     }
+
+    extern (D) void fixupInvariantIdent(size_t offset)
+    {
+        OutBuffer idBuf;
+        idBuf.writestring("__invariant");
+        idBuf.print(offset);
+
+        ident = Identifier.idPool(idBuf[]);
+    }
 }
 
 
diff --git a/gcc/d/dmd/impcnvtab.d b/gcc/d/dmd/impcnvtab.d
index ab46f5eebbd..832c331c314 100644
--- a/gcc/d/dmd/impcnvtab.d
+++ b/gcc/d/dmd/impcnvtab.d
@@ -64,6 +64,57 @@  enum ImpCnvTab impCnvTab = generateImpCnvTab();
 
 ImpCnvTab generateImpCnvTab()
 {
+    TY[TMAX] typeTYs =
+    [
+        Tarray,
+        Tsarray,
+        Taarray,
+        Tpointer,
+        Treference,
+        Tfunction,
+        Tident,
+        Tclass,
+        Tstruct,
+        Tenum,
+        Tdelegate,
+        Tnone,
+        Tvoid,
+        Tint8,
+        Tuns8,
+        Tint16,
+        Tuns16,
+        Tint32,
+        Tuns32,
+        Tint64,
+        Tuns64,
+        Tfloat32,
+        Tfloat64,
+        Tfloat80,
+        Timaginary32,
+        Timaginary64,
+        Timaginary80,
+        Tcomplex32,
+        Tcomplex64,
+        Tcomplex80,
+        Tbool,
+        Tchar,
+        Twchar,
+        Tdchar,
+        Terror,
+        Tinstance,
+        Ttypeof,
+        Ttuple,
+        Tslice,
+        Treturn,
+        Tnull,
+        Tvector,
+        Tint128,
+        Tuns128,
+        Ttraits,
+        Tmixin,
+        Tnoreturn,
+        Ttag,
+    ];
     ImpCnvTab impCnvTab;
 
     // Set conversion tables
@@ -375,5 +426,9 @@  ImpCnvTab generateImpCnvTab()
 
     X(Tcomplex80,Tcomplex80,  Tcomplex80,Tcomplex80, Tcomplex80);
 
+    // "No type is implicitly convertible to noreturn, but noreturn is implicitly convertible to every other type"
+    foreach(convertToTy; typeTYs)
+        X(Tnoreturn, convertToTy, convertToTy, convertToTy, convertToTy);
+
     return impCnvTab;
 }
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 32f57d46773..12608534879 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -6184,6 +6184,11 @@  extern (C++) final class TypeClass : Type
         if (t && t.ty == Tclass)
         {
             ClassDeclaration cd = (cast(TypeClass)t).sym;
+            if (cd.semanticRun < PASS.semanticdone && !cd.isBaseInfoComplete())
+                cd.dsymbolSemantic(null);
+            if (sym.semanticRun < PASS.semanticdone && !sym.isBaseInfoComplete())
+                sym.dsymbolSemantic(null);
+
             if (sym.isBaseOf(cd, poffset))
                 return true;
         }
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 2916bbc38dd..c1c2dc92e12 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -2829,10 +2829,20 @@  package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
             rs.error("`return` statements cannot be in contracts");
             errors = true;
         }
-        if (sc.os && sc.os.tok != TOK.onScopeFailure)
+        if (sc.os)
         {
-            rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok));
-            errors = true;
+            // @@@DEPRECATED_2.112@@@
+            // Deprecated in 2.100, transform into an error in 2.112
+            if (sc.os.tok == TOK.onScopeFailure)
+            {
+                rs.deprecation("`return` statements cannot be in `scope(failure)` bodies.");
+                deprecationSupplemental(rs.loc, "Use try-catch blocks for this purpose");
+            }
+            else
+            {
+                rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok));
+                errors = true;
+            }
         }
         if (sc.tf)
         {
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 73dab463926..6fba382f0ed 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -916,6 +916,17 @@  public:
 	gcc_unreachable ();
       }
 
+    /* Look for exp = noreturn;  */
+    if (e->e2->type->isTypeNoreturn ())
+      {
+	/* If the RHS is a `noreturn' expression, there is no point generating
+	   any code for the assignment, just evaluate side effects.  */
+	tree t1 = build_expr (e->e1);
+	tree t2 = build_expr (e->e2);
+	this->result_ = compound_expr (t1, t2);
+	return;
+      }
+
     /* Look for array[] = n;  */
     if (e->e1->op == EXP::slice)
       {
diff --git a/gcc/testsuite/gdc.test/compilable/backendfloatoptim.d b/gcc/testsuite/gdc.test/compilable/backendfloatoptim.d
new file mode 100644
index 00000000000..7ec9f614ef8
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/backendfloatoptim.d
@@ -0,0 +1,10 @@ 
+// REQUIRED_ARGS: -O -inline
+
+//https://issues.dlang.org/show_bug.cgi?id=20143
+real fun(int x) { return 0.0; }
+
+double bug()
+{
+    // value passed to fun is irrelevant
+    return 0.0 / fun(420);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/noreturn1.d b/gcc/testsuite/gdc.test/compilable/noreturn1.d
index 5bba9baa72a..e648a56d896 100644
--- a/gcc/testsuite/gdc.test/compilable/noreturn1.d
+++ b/gcc/testsuite/gdc.test/compilable/noreturn1.d
@@ -122,3 +122,31 @@  noreturn testdg(noreturn delegate() dg)
 {
     dg();
 }
+
+noreturn func()
+{
+    while(1)
+    {
+    }
+}
+alias AliasSeq(T...) = T;
+alias Types = AliasSeq!(bool, byte, ubyte, short, ushort, int, uint,
+                        long, ulong, char, wchar, dchar, float, double,
+                        real);
+void noreturnImplicit()
+{
+    /*
+        Testing both ways because, although the underlying table
+        is symmetrical the code that calls into it may be buggy.
+    */
+    {
+        int x = 2 + func();
+        int y = func() + 2;
+    }
+    foreach(T; Types)
+    {
+        T value;
+        auto x = value + throw new Exception("Hello");
+        auto y = (throw new Exception("wow")) + value;
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23082.d b/gcc/testsuite/gdc.test/compilable/test23082.d
new file mode 100644
index 00000000000..9df4e4e7774
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23082.d
@@ -0,0 +1,17 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23082
+
+/*
+TEST_OUTPUT:
+---
+bar
+---
+*/
+
+void foo()() {}
+alias bar = foo;
+void bar() { }
+
+void main()
+{
+    pragma(msg, __traits(parent, main).bar.stringof);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23166.d b/gcc/testsuite/gdc.test/compilable/test23166.d
new file mode 100644
index 00000000000..66da4cd6963
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23166.d
@@ -0,0 +1,22 @@ 
+// REQUIRED_ARGS: -inline
+
+// https://issues.dlang.org/show_bug.cgi?id=23166
+
+// seg fault with -inline
+
+bool __equals(scope const char[] lhs, scope const char[] rhs)
+{
+    if (lhs.length != rhs.length)
+        return false;
+
+    {
+        import core.stdc.string : memcmp;
+        return lhs.length == 0;
+    }
+    return true;
+}
+
+int test(string type)
+{
+    return __equals(type, "as-is");
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23172.d b/gcc/testsuite/gdc.test/compilable/test23172.d
new file mode 100644
index 00000000000..18b6d4ce8c5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23172.d
@@ -0,0 +1,33 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23172
+
+enum E : ubyte { // `ubyte` is needed to trigger the bug
+    A,
+    B,
+}
+
+struct S {
+    E e;
+}
+
+void compiles(bool b, S s) {
+    E e = b ? E.A : s.e;
+}
+
+void errors(bool b, const ref S s) {
+    E e = b ? E.A : s.e;
+}
+
+// from https://issues.dlang.org/show_bug.cgi?id=23188
+
+enum Status : byte
+{
+    A, B, C
+}
+
+Status foo()
+{
+    Status t = Status.A;
+    const Status s = t;
+
+    return (s == Status.A) ? Status.B : s;  // <-- here
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23258.d b/gcc/testsuite/gdc.test/compilable/test23258.d
new file mode 100644
index 00000000000..1e8e91b7795
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test23258.d
@@ -0,0 +1,21 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23258
+
+struct SumType(Types...)
+{
+    this(Types[0])
+    {
+    }
+    this(Types[1])
+    {
+    }
+}
+
+alias A2 = SumType!(C1[], C2[]);
+
+class C1
+{
+}
+
+class C2
+{
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23181.d b/gcc/testsuite/gdc.test/fail_compilation/fail23181.d
new file mode 100644
index 00000000000..519244c1cdf
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail23181.d
@@ -0,0 +1,16 @@ 
+/* https://issues.dlang.org/show_bug.cgi?id=23181
+TEST_OUTPUT:
+---
+$p:druntime/import/core/lifetime.d$($n$): Error: struct `fail23181.fail23181.NoPostblit` is not copyable because it has a disabled postblit
+$p:druntime/import/core/internal/array/construction.d$($n$): Error: template instance `core.lifetime.copyEmplace!(NoPostblit, NoPostblit)` error instantiating
+fail_compilation/fail23181.d(15):        instantiated from here: `_d_arraysetctor!(NoPostblit[], NoPostblit)`
+---
+*/
+void fail23181()
+{
+    struct NoPostblit
+    {
+        @disable this(this);
+    }
+    NoPostblit[4] noblit23181 = NoPostblit();
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail6889.d b/gcc/testsuite/gdc.test/fail_compilation/fail6889.d
index aa189770903..ee84a84ce79 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail6889.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail6889.d
@@ -55,7 +55,7 @@  L1:
     scope(failure) { L2: goto L1; } // OK
     goto L2;                        // NG
 
-    scope(failure) { return; }      // OK
+
 
     foreach (i; 0..1)
     {
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7848.d b/gcc/testsuite/gdc.test/fail_compilation/fail7848.d
index e8371c4f7fe..001c7d75443 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7848.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7848.d
@@ -9,12 +9,12 @@  fail_compilation/fail7848.d(21):        `fail7848.func` is declared here
 fail_compilation/fail7848.d(27): Error: `@nogc` function `fail7848.C.__unittest_L25_C30` cannot call non-@nogc function `fail7848.func`
 fail_compilation/fail7848.d(27): Error: function `fail7848.func` is not `nothrow`
 fail_compilation/fail7848.d(25): Error: function `fail7848.C.__unittest_L25_C30` may throw but is marked as `nothrow`
-fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.__invariant1` cannot call impure function `fail7848.func`
-fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.__invariant1` cannot call `@system` function `fail7848.func`
+fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.__invariant0` cannot call impure function `fail7848.func`
+fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.__invariant0` cannot call `@system` function `fail7848.func`
 fail_compilation/fail7848.d(21):        `fail7848.func` is declared here
-fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.__invariant1` cannot call non-@nogc function `fail7848.func`
+fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.__invariant0` cannot call non-@nogc function `fail7848.func`
 fail_compilation/fail7848.d(32): Error: function `fail7848.func` is not `nothrow`
-fail_compilation/fail7848.d(30): Error: function `fail7848.C.__invariant1` may throw but is marked as `nothrow`
+fail_compilation/fail7848.d(30): Error: function `fail7848.C.__invariant0` may throw but is marked as `nothrow`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21443.d b/gcc/testsuite/gdc.test/fail_compilation/test21443.d
new file mode 100644
index 00000000000..2d99524da35
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test21443.d
@@ -0,0 +1,21 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=21443
+// REQUIRED_ARGS: -de
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test21443.d(14): Deprecation: `return` statements cannot be in `scope(failure)` bodies.
+fail_compilation/test21443.d(14):        Use try-catch blocks for this purpose
+---
+*/
+
+ulong get () @safe nothrow
+{
+    scope (failure) return 10;
+    throw new Error("");
+}
+
+void main () @safe
+{
+    assert(get() == 10);  // passes
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23170.d b/gcc/testsuite/gdc.test/fail_compilation/test23170.d
new file mode 100644
index 00000000000..eb79cd81565
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test23170.d
@@ -0,0 +1,12 @@ 
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test23170.d(10): Error: array literal in `@nogc` delegate `test23170.__lambda5` may cause a GC allocation
+---
+*/
+// https://issues.dlang.org/show_bug.cgi?id=23170
+
+@nogc:
+enum lambda = () => badAlias([1, 2, 3]);
+alias badAlias = (int[] array) => id(array);
+int[] id(int[] array) { return array; }
diff --git a/gcc/testsuite/gdc.test/runnable/noreturn1.d b/gcc/testsuite/gdc.test/runnable/noreturn1.d
index 7d15b54a213..5ed46c16250 100644
--- a/gcc/testsuite/gdc.test/runnable/noreturn1.d
+++ b/gcc/testsuite/gdc.test/runnable/noreturn1.d
@@ -261,6 +261,37 @@  void testThrowDtor()
 
 /*****************************************/
 
+noreturn func()
+{
+    throw new Exception("B");
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=23120
+void test23120()
+{
+    string a;
+    try
+    {
+        noreturn q = throw new Exception ("A");
+    }
+    catch(Exception e)
+    {
+        a ~= e.msg;
+    }
+
+    try
+    {
+        noreturn z = func();
+    }
+    catch(Exception e)
+    {
+        a ~= e.msg;
+    }
+
+    assert(a == "AB");
+}
+
+/*****************************************/
 int main()
 {
     test1();
@@ -269,5 +300,6 @@  int main()
     testThrowExpression();
     testThrowSideEffect();
     testThrowDtor();
+    test23120();
     return 0;
 }
diff --git a/gcc/testsuite/gdc.test/runnable/test20734.d b/gcc/testsuite/gdc.test/runnable/test20734.d
index 264602bccc5..b3c5916ada5 100644
--- a/gcc/testsuite/gdc.test/runnable/test20734.d
+++ b/gcc/testsuite/gdc.test/runnable/test20734.d
@@ -16,6 +16,7 @@  extern(C) int main() nothrow @nogc @safe
 {
     takeScopeSlice([ S(1), S(2) ]); // @nogc => no GC allocation
     (() @trusted { assert(numDtor == 2); })(); // stack-allocated array literal properly destructed
+    assert23100([]);
     return 0;
 }
 
@@ -26,3 +27,9 @@  void test23098() @safe
 {
     f23098([10, 20]);
 }
+
+// https://issues.dlang.org/show_bug.cgi?id=23100
+void assert23100(scope int[] d) @safe nothrow @nogc
+{
+    assert(!d);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test23181.d b/gcc/testsuite/gdc.test/runnable/test23181.d
new file mode 100644
index 00000000000..b961690a2bc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test23181.d
@@ -0,0 +1,27 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23181
+void main()
+{
+    int count;
+    struct HasDtor
+    {
+        ~this() { ++count; }
+    }
+
+    // array[] = elem()
+    // -> creates temporary to construct array and calls destructor.
+    {
+        count = 0;
+        HasDtor[4] dtor1 = HasDtor();
+        assert(count == 1);
+    }
+    assert(count == 5);
+
+    // array[] = array[elem()]
+    // -> constructs array using direct emplacement.
+    {
+        count = 0;
+        HasDtor[2] dtor2 = [HasDtor(), HasDtor()];
+        assert(count == 0);
+    }
+    assert(count == 2);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test23234.d b/gcc/testsuite/gdc.test/runnable/test23234.d
new file mode 100644
index 00000000000..7872aa76dfe
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test23234.d
@@ -0,0 +1,22 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23234
+
+class Bar
+{
+}
+
+class Foo
+{
+    Bar get() { return new Bar; }
+    alias get this;
+}
+
+void main()
+{
+    auto foo = new Foo;
+    void test(Bar delegate() dg)
+    {
+        assert(dg() !is null);
+    }
+
+    test(() => foo);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/warning1.d b/gcc/testsuite/gdc.test/runnable/warning1.d
index 537088e97cc..01ac20c0baf 100644
--- a/gcc/testsuite/gdc.test/runnable/warning1.d
+++ b/gcc/testsuite/gdc.test/runnable/warning1.d
@@ -133,15 +133,6 @@  void test6518()
     }
 }
 
-/******************************************/
-// https://issues.dlang.org/show_bug.cgi?id=7232
-
-bool test7232()
-{
-    scope(failure) return false;
-    return true;
-}
-
 /***************************************************/
 
 struct S9332
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 9bab8ed6395..c96180a3751 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@ 
-9c0d4f914e0817c9ee4eafc5a45c41130aa6b981
+1462ebd188c0ab5181a0a75e3576754bb0b81a16
 
 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/src/MERGE b/libphobos/src/MERGE
index ed9a02e1a0c..f2678185f39 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@ 
-604534d7cb29d49a6474f0aaaa5d166057a44f72
+5fef0d28fc873fb5a0dbfb9149759d76a7b9f1b7
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/algorithm/comparison.d b/libphobos/src/std/algorithm/comparison.d
index 2fcc2bacd5c..b810fbb9258 100644
--- a/libphobos/src/std/algorithm/comparison.d
+++ b/libphobos/src/std/algorithm/comparison.d
@@ -1027,7 +1027,7 @@  template equal(alias pred = "a == b")
         }
     }
 
-    private bool equalLoop(Rs...)(Rs rs)
+    private bool equalLoop(Rs...)(ref Rs rs)
     {
         for (; !rs[0].empty; rs[0].popFront)
             static foreach (r; rs[1 .. $])
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index 1ee7faaee7b..fb15001233a 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -4905,8 +4905,14 @@  if (is(Interface == interface) && is(BaseClass == class))
         // - try default first
         // - only on a failure run & return fallback
         enum fallback = q{
-            scope (failure) return fallback.%1$s(args);
-            return default_.%1$s(args);
+            try
+            {
+                return default_.%1$s(args);
+            }
+            catch (Exception)
+            {
+                return fallback.%1$s(args);
+            }
         }.format(__traits(identifier, func));
     }