https://gcc.gnu.org/g:c8894b681143041205d41e02ede112cef082bf2f

commit r15-6899-gc8894b681143041205d41e02ede112cef082bf2f
Author: Iain Buclaw <ibuc...@gdcproject.org>
Date:   Tue Jan 14 20:51:45 2025 +0100

    d: Merge upstream dmd, druntime d6f693b46a, phobos 336bed6d8.
    
    D front-end changes:
    
            - Import latest fixes from dmd v2.110.0-rc.1.
    
    D runtime changes:
    
            - Import latest fixes from druntime v2.110.0-rc.1.
    
    Phobos changes:
    
            - Import latest fixes from phobos v2.110.0-rc.1.
    
    Included in the merge are fixes for the following PRs:
    
            PR d/118438
            PR d/118448
            PR d/118449
    
    gcc/d/ChangeLog:
    
            * dmd/MERGE: Merge upstream dmd d6f693b46a.
            * d-incpath.cc (add_import_paths): Update for new front-end 
interface.
    
    libphobos/ChangeLog:
    
            * libdruntime/MERGE: Merge upstream druntime d6f693b46a.
            * src/MERGE: Merge upstream phobos 336bed6d8.
            * testsuite/libphobos.init_fini/custom_gc.d: Adjust test.

Diff:
---
 gcc/d/d-incpath.cc                                 |   4 +-
 gcc/d/dmd/MERGE                                    |   2 +-
 gcc/d/dmd/clone.d                                  | 201 ++++++++++++---------
 gcc/d/dmd/ctfeexpr.d                               |  48 +++--
 gcc/d/dmd/dcast.d                                  |  18 +-
 gcc/d/dmd/dimport.d                                |   9 +-
 gcc/d/dmd/dmodule.d                                |  29 ++-
 gcc/d/dmd/doc.d                                    |   6 +-
 gcc/d/dmd/dstruct.d                                |   4 +-
 gcc/d/dmd/dsymbolsem.d                             |  34 +++-
 gcc/d/dmd/dtemplate.d                              |  11 +-
 gcc/d/dmd/dtoh.d                                   |   2 +-
 gcc/d/dmd/errors.d                                 |  20 +-
 gcc/d/dmd/expression.d                             |  13 +-
 gcc/d/dmd/expressionsem.d                          |  16 +-
 gcc/d/dmd/file_manager.d                           |  29 ++-
 gcc/d/dmd/func.d                                   |   4 +-
 gcc/d/dmd/funcsem.d                                |  13 +-
 gcc/d/dmd/globals.d                                |   9 +-
 gcc/d/dmd/globals.h                                |  15 +-
 gcc/d/dmd/hdrgen.d                                 |   4 +-
 gcc/d/dmd/json.d                                   |   2 +-
 gcc/d/dmd/lexer.d                                  |   2 +-
 gcc/d/dmd/mtype.d                                  |   2 +-
 gcc/d/dmd/parse.d                                  |   6 +-
 gcc/d/dmd/pragmasem.d                              |  13 +-
 gcc/d/dmd/semantic3.d                              |   2 +-
 gcc/d/dmd/templateparamsem.d                       |   9 +-
 gcc/d/dmd/traits.d                                 |   3 +-
 gcc/d/dmd/typesem.d                                |   4 +-
 gcc/d/dmd/typinf.d                                 |   1 -
 gcc/testsuite/gdc.test/compilable/copyCtor2.d      |  14 ++
 gcc/testsuite/gdc.test/compilable/cppmangle.d      |   6 +
 gcc/testsuite/gdc.test/compilable/testInference.d  |  20 +-
 .../gdc.test/fail_compilation/failCopyCtor2.d      |  19 --
 .../gdc.test/fail_compilation/retscope2.d          |   2 +-
 .../gdc.test/fail_compilation/retscope3.d          |   4 +-
 .../gdc.test/fail_compilation/retscope6.d          |   2 +-
 .../gdc.test/fail_compilation/test18282.d          |  16 +-
 gcc/testsuite/gdc.test/runnable/rvalue1.d          |  51 ++++++
 libphobos/libdruntime/MERGE                        |   2 +-
 libphobos/libdruntime/core/builtins.d              |  21 ++-
 libphobos/libdruntime/core/demangle.d              |  11 +-
 libphobos/libdruntime/core/internal/gc/os.d        |   4 +-
 libphobos/libdruntime/core/sys/posix/sys/socket.d  |   9 +
 libphobos/src/MERGE                                |   2 +-
 libphobos/src/std/functional.d                     |   6 +-
 libphobos/src/std/socket.d                         |   2 +-
 libphobos/src/std/typecons.d                       |   2 +-
 .../testsuite/libphobos.init_fini/custom_gc.d      |  10 +
 50 files changed, 471 insertions(+), 267 deletions(-)

diff --git a/gcc/d/d-incpath.cc b/gcc/d/d-incpath.cc
index 3f62f437cb98..155dc99c5550 100644
--- a/gcc/d/d-incpath.cc
+++ b/gcc/d/d-incpath.cc
@@ -133,7 +133,7 @@ add_import_paths (const char *iprefix, const char 
*imultilib, bool stdinc)
          bool found = false;
          for (size_t i = 0; i < global.params.imppath.length; i++)
            {
-             if (strcmp (path, global.params.imppath[i]) == 0)
+             if (strcmp (path, global.params.imppath[i].path) == 0)
                {
                  found = true;
                  break;
@@ -160,7 +160,7 @@ add_import_paths (const char *iprefix, const char 
*imultilib, bool stdinc)
   /* Add import search paths.  */
   for (size_t i = 0; i < global.params.imppath.length; i++)
     {
-      const char *path = global.params.imppath[i];
+      const char *path = global.params.imppath[i].path;
       if (path)
        {
          Strings array;
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index b145d1bd6593..33bb398c00d4 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-c7902293d7df9d02546562cb09fc8439004a70d1
+d6f693b46a1565172cac7a1438905141783a164f
 
 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/clone.d b/gcc/d/dmd/clone.d
index 1b838603c7e8..d7658c68ec25 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -269,7 +269,7 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* 
sc)
         return null;
 
     //printf("StructDeclaration::buildOpAssign() %s\n", sd.toChars());
-    StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
+    StorageClass stc = STC.safe;
     Loc declLoc = sd.loc;
     Loc loc; // internal code should have no loc to prevent coverage
 
@@ -1278,7 +1278,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, 
Scope* sc)
     const hasUserDefinedPosblit = sd.postblits.length && 
!sd.postblits[0].isDisabled ? true : false;
 
     // by default, the storage class of the created postblit
-    StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
+    StorageClass stc = STC.safe;
     Loc declLoc = sd.postblits.length ? sd.postblits[0].loc : sd.loc;
     Loc loc; // internal code should have no loc to prevent coverage
 
@@ -1380,6 +1380,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, 
Scope* sc)
         // perform semantic on the member postblit in order to
         // be able to aggregate it later on with the rest of the
         // postblits
+        sdv.postblit.isGenerated = true;
         functionSemantic(sdv.postblit);
 
         stc = mergeFuncAttrs(stc, sdv.postblit);
@@ -1445,6 +1446,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, 
Scope* sc)
          */
         if (sdv.dtor)
         {
+            sdv.dtor.isGenerated = true;
             functionSemantic(sdv.dtor);
 
             // keep a list of fields that need to be destroyed in case
@@ -1545,25 +1547,27 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, 
Scope* sc)
 }
 
 /**
- * Generates a copy constructor declaration with the specified storage
+ * Generates a copy or move constructor declaration with the specified storage
  * class for the parameter and the function.
  *
  * Params:
- *  sd = the `struct` that contains the copy constructor
- *  paramStc = the storage class of the copy constructor parameter
- *  funcStc = the storage class for the copy constructor declaration
+ *  sd = the `struct` that contains the constructor
+ *  paramStc = the storage class of the constructor parameter
+ *  funcStc = the storage class for the constructor declaration
+ *  move = true for move constructor, false for copy constructor
  *
  * Returns:
  *  The copy constructor declaration for struct `sd`.
  */
-private CtorDeclaration generateCopyCtorDeclaration(StructDeclaration sd, 
const StorageClass paramStc, const StorageClass funcStc)
+private CtorDeclaration generateCtorDeclaration(StructDeclaration sd, const 
StorageClass paramStc, const StorageClass funcStc, bool move)
 {
     auto fparams = new Parameters();
     auto structType = sd.type;
-    fparams.push(new Parameter(Loc.initial, paramStc | STC.ref_ | STC.return_ 
| STC.scope_, structType, Id.p, null, null));
+    StorageClass stc = move ? 0 : STC.ref_;     // the only difference between 
copy or move
+    fparams.push(new Parameter(Loc.initial, paramStc | stc, structType, Id.p, 
null, null));
     ParameterList pList = ParameterList(fparams);
     auto tf = new TypeFunction(pList, structType, LINK.d, STC.ref_);
-    auto ccd = new CtorDeclaration(sd.loc, Loc.initial, STC.ref_, tf, true);
+    auto ccd = new CtorDeclaration(sd.loc, Loc.initial, STC.ref_, tf);
     ccd.storage_class |= funcStc;
     ccd.storage_class |= STC.inference;
     ccd.isGenerated = true;
@@ -1571,28 +1575,37 @@ private CtorDeclaration 
generateCopyCtorDeclaration(StructDeclaration sd, const
 }
 
 /**
- * Generates a trivial copy constructor body that simply does memberwise
- * initialization:
+ * Generates a trivial copy or move constructor body that simply does 
memberwise
+ * initialization.
  *
+ * for copy construction:
  *    this.field1 = rhs.field1;
  *    this.field2 = rhs.field2;
  *    ...
+ * for move construction:
+ *    this.field1 = __rvalue(rhs.field1);
+ *    this.field2 = __rvalue(rhs.field2);
+ *    ...
  *
  * Params:
- *  sd = the `struct` declaration that contains the copy constructor
+ *  sd = the `struct` declaration that contains the constructor
+ *  move = true for move constructor, false for copy constructor
  *
  * Returns:
- *  A `CompoundStatement` containing the body of the copy constructor.
+ *  A `CompoundStatement` containing the body of the constructor.
  */
-private Statement generateCopyCtorBody(StructDeclaration sd)
+private Statement generateCtorBody(StructDeclaration sd, bool move)
 {
     Loc loc;
     Expression e;
     foreach (v; sd.fields)
     {
+        Expression rhs = new DotVarExp(loc, new IdentifierExp(loc, Id.p), v);
+        if (move)
+            rhs.rvalue = true;
         auto ec = new AssignExp(loc,
             new DotVarExp(loc, new ThisExp(loc), v),
-            new DotVarExp(loc, new IdentifierExp(loc, Id.p), v));
+            rhs);
         e = Expression.combine(e, ec);
         //printf("e.toChars = %s\n", e.toChars());
     }
@@ -1600,29 +1613,18 @@ private Statement 
generateCopyCtorBody(StructDeclaration sd)
     return new CompoundStatement(loc, s1);
 }
 
-/**
- * Determine if a copy constructor is needed for struct sd,
- * if the following conditions are met:
- *
- * 1. sd does not define a copy constructor
- * 2. at least one field of sd defines a copy constructor
- *
+/******************************************
+ * Find root `this` constructor for struct sd.
+ * (root is starting position for overloaded constructors)
  * Params:
- *  sd = the `struct` for which the copy constructor is generated
- *  hasCpCtor = set to true if a copy constructor is already present
- *  hasMoveCtor = set to true if a move constructor is already present
- *
- * Returns:
- *  `true` if one needs to be generated
- *  `false` otherwise
+ *  sd = the `struct` to be searched
+ *  ctor = `this` if found, otherwise null
+ * Result:
+ *  false means `this` found in overload set
  */
-bool needCopyCtor(StructDeclaration sd, out bool hasCpCtor, out bool 
hasMoveCtor)
+private bool findStructConstructorRoot(StructDeclaration sd, out Dsymbol ctor)
 {
-    //printf("needCopyCtor() %s\n", sd.toChars());
-    if (global.errors)
-        return false;
-
-    auto ctor = sd.search(sd.loc, Id.ctor);
+    ctor = sd.search(sd.loc, Id.ctor); // Aggregate.searchCtor() ?
     if (ctor)
     {
         if (ctor.isOverloadSet())
@@ -1630,13 +1632,18 @@ bool needCopyCtor(StructDeclaration sd, out bool 
hasCpCtor, out bool hasMoveCtor
         if (auto td = ctor.isTemplateDeclaration())
             ctor = td.funcroot;
     }
+    return true;
+}
 
-    CtorDeclaration cpCtor;
-    CtorDeclaration rvalueCtor;
-
-    if (!ctor)
-        goto LcheckFields;
-
+/***********************************************
+ * Find move and copy constructors (if any) starting at `ctor`
+ * Params:
+ *      ctor = `this` constructor root
+ *      copyCtor = set to first copy constructor found, or null
+ *      moveCtor = set to first move constructor found, or null
+ */
+private void findMoveAndCopyConstructors(Dsymbol ctor, out CtorDeclaration 
copyCtor, out CtorDeclaration moveCtor)
+{
     overloadApply(ctor, (Dsymbol s)
     {
         if (s.isTemplateDeclaration())
@@ -1645,33 +1652,63 @@ bool needCopyCtor(StructDeclaration sd, out bool 
hasCpCtor, out bool hasMoveCtor
         assert(ctorDecl);
         if (ctorDecl.isCpCtor)
         {
-            if (!cpCtor)
-                cpCtor = ctorDecl;
-            return 0;
+            if (!copyCtor)
+                copyCtor = ctorDecl;
+        }
+        else if (ctorDecl.isMoveCtor)
+        {
+            if (!moveCtor)
+                moveCtor = ctorDecl;
         }
-
-        if (ctorDecl.isMoveCtor)
-            rvalueCtor = ctorDecl;
         return 0;
     });
+}
+
+/**
+ * Determine if a copy constructor is needed for struct sd,
+ * if the following conditions are met:
+ *
+ * 1. sd does not define a copy constructor
+ * 2. at least one field of sd defines a copy constructor
+ *
+ * Params:
+ *  sd = the `struct` for which the copy constructor is generated
+ *  hasCopyCtor = set to true if a copy constructor is already present
+ *  hasMoveCtor = set to true if a move constructor is already present
+ *  needCopyCtor = set to true if a copy constructor is not present, but needed
+ *  needMoveCtor = set to true if a move constructor is not present, but needed
+ *
+ * Returns:
+ *  `true` if one needs to be generated
+ *  `false` otherwise
+ */
+void needCopyOrMoveCtor(StructDeclaration sd, out bool hasCopyCtor, out bool 
hasMoveCtor, out bool needCopyCtor, out bool needMoveCtor)
+{
+    //printf("needCopyOrMoveCtor() %s\n", sd.toChars());
+    if (global.errors)
+        return;
+
+    Dsymbol ctor;
+    if (!findStructConstructorRoot(sd, ctor))
+        return;
+
+    CtorDeclaration copyCtor;
+    CtorDeclaration moveCtor;
+
+    if (ctor)
+        findMoveAndCopyConstructors(ctor, copyCtor, moveCtor);
 
-    if (rvalueCtor)
+    if (moveCtor)
         hasMoveCtor = true;
 
-    if (cpCtor)
-    {
-        if (0 && rvalueCtor)
-        {
-            .error(sd.loc, "`struct %s` may not define both a rvalue 
constructor and a copy constructor", sd.toChars());
-            errorSupplemental(rvalueCtor.loc,"rvalue constructor defined 
here");
-            errorSupplemental(cpCtor.loc, "copy constructor defined here");
-        }
-        hasCpCtor = true;
-        return false;
-    }
+    if (copyCtor)
+        hasCopyCtor = true;
+
+    if (hasMoveCtor && hasCopyCtor)
+        return;
 
-LcheckFields:
     VarDeclaration fieldWithCpCtor;
+    VarDeclaration fieldWithMoveCtor;
     // see if any struct members define a copy constructor
     foreach (v; sd.fields)
     {
@@ -1686,20 +1723,25 @@ LcheckFields:
         if (ts.sym.hasCopyCtor)
         {
             fieldWithCpCtor = v;
-            break;
+        }
+        if (ts.sym.hasMoveCtor)
+        {
+            fieldWithMoveCtor = v;
         }
     }
 
-    if (fieldWithCpCtor && rvalueCtor)
+    if (0 && fieldWithCpCtor && moveCtor)
     {
         .error(sd.loc, "`struct %s` may not define a rvalue constructor and 
have fields with copy constructors", sd.toChars());
-        errorSupplemental(rvalueCtor.loc,"rvalue constructor defined here");
+        errorSupplemental(moveCtor.loc,"rvalue constructor defined here");
         errorSupplemental(fieldWithCpCtor.loc, "field with copy constructor 
defined here");
-        return false;
+        return;
     }
-    else if (!fieldWithCpCtor)
-        return false;
-    return true;
+
+    if (fieldWithCpCtor && !hasCopyCtor)
+        needCopyCtor = true;
+    if (fieldWithMoveCtor && !hasMoveCtor)
+        needMoveCtor = true;
 }
 
 /**
@@ -1713,28 +1755,20 @@ LcheckFields:
  *   }
  *
  * Params:
- *  sd = the `struct` for which the copy constructor is generated
- *  sc = the scope where the copy constructor is generated
- *  hasMoveCtor = set to true when a move constructor is also detected
- *
- * Returns:
- *  `true` if `struct` sd defines a copy constructor (explicitly or generated),
- *  `false` otherwise.
+ *  sd = the `struct` for which the constructor is generated
+ *  sc = the scope where the constructor is generated
+ *  move = true means generate the move constructor, otherwise copy constructor
  * References:
  *   https://dlang.org/spec/struct.html#struct-copy-constructor
  */
-bool buildCopyCtor(StructDeclaration sd, Scope* sc, out bool hasMoveCtor)
+void buildCopyOrMoveCtor(StructDeclaration sd, Scope* sc, bool move)
 {
-    bool hasCpCtor;
-    if (!needCopyCtor(sd, hasCpCtor, hasMoveCtor))
-        return hasCpCtor;
-
-    //printf("generating copy constructor for %s\n", sd.toChars());
+    //printf("buildCopyOrMoveCtor() generating %s constructor for %s\n", move 
? "move".ptr : "copy".ptr, sd.toChars());
     const MOD paramMod = MODFlags.wild;
     const MOD funcMod = MODFlags.wild;
-    auto ccd = generateCopyCtorDeclaration(sd, ModToStc(paramMod), 
ModToStc(funcMod));
-    auto copyCtorBody = generateCopyCtorBody(sd);
-    ccd.fbody = copyCtorBody;
+    auto ccd = generateCtorDeclaration(sd, ModToStc(paramMod), 
ModToStc(funcMod), move);
+    auto ctorBody = generateCtorBody(sd, move);
+    ccd.fbody = ctorBody;
     sd.members.push(ccd);
     ccd.addMember(sc, sd);
     const errors = global.startGagging();
@@ -1751,5 +1785,4 @@ bool buildCopyCtor(StructDeclaration sd, Scope* sc, out 
bool hasMoveCtor)
         ccd.storage_class |= STC.disable;
         ccd.fbody = null;
     }
-    return true;
 }
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index 156c5f8c7e05..a6cfe6e9eafe 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -1226,10 +1226,7 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, 
Expression e2, bool ide
         {
             return 1;   // they are not equal
         }
-        else
-        {
-            return (r1 != r2);
-        }
+        return (r1 != r2);
     }
     else if (e1.type.isComplex())
     {
@@ -1242,33 +1239,30 @@ private int ctfeRawCmp(const ref Loc loc, Expression 
e1, Expression e2, bool ide
         // For structs, we only need to return 0 or 1 (< and > aren't legal).
         if (es1.sd != es2.sd)
             return 1;
-        else if ((!es1.elements || !es1.elements.length) && (!es2.elements || 
!es2.elements.length))
+        if ((!es1.elements || !es1.elements.length) && (!es2.elements || 
!es2.elements.length))
             return 0; // both arrays are empty
-        else if (!es1.elements || !es2.elements)
+        if (!es1.elements || !es2.elements)
             return 1;
-        else if (es1.elements.length != es2.elements.length)
+        if (es1.elements.length != es2.elements.length)
             return 1;
-        else
+        foreach (size_t i; 0 .. es1.elements.length)
         {
-            foreach (size_t i; 0 .. es1.elements.length)
-            {
-                Expression ee1 = (*es1.elements)[i];
-                Expression ee2 = (*es2.elements)[i];
+            Expression ee1 = (*es1.elements)[i];
+            Expression ee2 = (*es2.elements)[i];
 
-                // https://issues.dlang.org/show_bug.cgi?id=16284
-                if (ee1.op == EXP.void_ && ee2.op == EXP.void_) // if both are 
VoidInitExp
-                    continue;
+            // https://issues.dlang.org/show_bug.cgi?id=16284
+            if (ee1.op == EXP.void_ && ee2.op == EXP.void_) // if both are 
VoidInitExp
+                continue;
 
-                if (ee1 == ee2)
-                    continue;
-                if (!ee1 || !ee2)
-                    return 1;
-                const int cmp = ctfeRawCmp(loc, ee1, ee2, identity);
-                if (cmp)
-                    return 1;
-            }
-            return 0; // All elements are equal
+            if (ee1 == ee2)
+                continue;
+            if (!ee1 || !ee2)
+                return 1;
+            const int cmp = ctfeRawCmp(loc, ee1, ee2, identity);
+            if (cmp)
+                return 1;
         }
+        return 0; // All elements are equal
     }
     if (e1.op == EXP.assocArrayLiteral && e2.op == EXP.assocArrayLiteral)
     {
@@ -1361,11 +1355,11 @@ bool ctfeCmp(const ref Loc loc, EXP op, Expression e1, 
Expression e2)
 
     if (t1.isString() && t2.isString())
         return specificCmp(op, ctfeRawCmp(loc, e1, e2));
-    else if (t1.isReal())
+    if (t1.isReal())
         return realCmp(op, e1.toReal(), e2.toReal());
-    else if (t1.isImaginary())
+    if (t1.isImaginary())
         return realCmp(op, e1.toImaginary(), e2.toImaginary());
-    else if (t1.isUnsigned() || t2.isUnsigned())
+    if (t1.isUnsigned() || t2.isUnsigned())
         return intUnsignedCmp(op, e1.toInteger(), e2.toInteger());
     else
         return intSignedCmp(op, e1.toInteger(), e2.toInteger());
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 7c675eba67c2..0c4b469de5d4 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -474,7 +474,7 @@ MATCH implicitConvTo(Expression e, Type t)
         case Tint8:
             if (ty == Tuns64 && value & ~0x7FU)
                 return MATCH.nomatch;
-            else if (cast(byte)value != value)
+            if (cast(byte)value != value)
                 return MATCH.nomatch;
             break;
 
@@ -1499,12 +1499,11 @@ MATCH implicitConvTo(Type from, Type to)
         {
             if (from.mod == to.mod)
                 return MATCH.exact;
-            else if (MODimplicitConv(from.mod, to.mod))
+            if (MODimplicitConv(from.mod, to.mod))
                 return MATCH.constant;
-            else if (!((from.mod ^ to.mod) & MODFlags.shared_)) // for wild 
matching
+            if (!((from.mod ^ to.mod) & MODFlags.shared_)) // for wild matching
                 return MATCH.constant;
-            else
-                return MATCH.convert;
+            return MATCH.convert;
         }
 
         if (from.ty == Tvoid || to.ty == Tvoid)
@@ -4150,9 +4149,9 @@ Expression typeCombine(BinExp be, Scope* sc)
         // struct+struct, and class+class are errors
         if (t1.ty == Tstruct && t2.ty == Tstruct)
             return errorReturn();
-        else if (t1.ty == Tclass && t2.ty == Tclass)
+        if (t1.ty == Tclass && t2.ty == Tclass)
             return errorReturn();
-        else if (t1.ty == Taarray && t2.ty == Taarray)
+        if (t1.ty == Taarray && t2.ty == Taarray)
             return errorReturn();
     }
 
@@ -4399,10 +4398,9 @@ IntRange getIntRange(Expression e)
         VarDeclaration vd = e.var.isVarDeclaration();
         if (vd && vd.range)
             return vd.range._cast(e.type);
-        else if (vd && vd._init && !vd.type.isMutable() && (ie = 
vd.getConstInitializer()) !is null)
+        if (vd && vd._init && !vd.type.isMutable() && (ie = 
vd.getConstInitializer()) !is null)
             return getIntRange(ie);
-        else
-            return visit(e);
+        return visit(e);
     }
 
     IntRange visitComma(CommaExp e)
diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d
index 96e821aea6af..ec7abb558e52 100644
--- a/gcc/d/dmd/dimport.d
+++ b/gcc/d/dmd/dimport.d
@@ -50,16 +50,13 @@ extern (C++) final class Import : Dsymbol
                 // import [aliasId] = std.stdio;
                 return aliasId;
             }
-            else if (packages.length > 0)
+            if (packages.length > 0)
             {
                 // import [std].stdio;
                 return packages[0];
             }
-            else
-            {
-                // import [id];
-                return id;
-            }
+            // import [id];
+            return id;
         }
 
         super(loc, selectIdent());
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 7996d3441934..f26c5812ddf9 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -310,8 +310,9 @@ extern (C++) class Package : ScopeDsymbol
             packages ~= s.ident;
         reverse(packages);
 
-        if (Module.find(getFilename(packages, ident)))
-            Module.load(Loc.initial, packages, this.ident);
+        ImportPathInfo pathThatFoundThis;
+        if (Module.find(getFilename(packages, ident), pathThatFoundThis))
+            Module.load(Loc.initial, packages, this.ident, pathThatFoundThis);
         else
             isPkgMod = PKG.package_;
     }
@@ -499,12 +500,18 @@ extern (C++) final class Module : Package
 
     static const(char)* find(const(char)* filename)
     {
-        return find(filename.toDString).ptr;
+        ImportPathInfo pathThatFoundThis; // is this needed? In fact is this 
function needed still???
+        return find(filename.toDString, pathThatFoundThis).ptr;
     }
 
-    extern (D) static const(char)[] find(const(char)[] filename)
+    extern (D) static const(char)[] find(const(char)[] filename, out 
ImportPathInfo pathThatFoundThis)
     {
-        return global.fileManager.lookForSourceFile(filename, global.path[]);
+        ptrdiff_t whichPathFoundThis;
+        const(char)[] ret = global.fileManager.lookForSourceFile(filename, 
global.path[], whichPathFoundThis);
+
+        if (whichPathFoundThis >= 0)
+            pathThatFoundThis = global.path[whichPathFoundThis];
+        return ret;
     }
 
     extern (C++) static Module load(const ref Loc loc, Identifiers* packages, 
Identifier ident)
@@ -512,7 +519,7 @@ extern (C++) final class Module : Package
         return load(loc, packages ? (*packages)[] : null, ident);
     }
 
-    extern (D) static Module load(const ref Loc loc, Identifier[] packages, 
Identifier ident)
+    extern (D) static Module load(const ref Loc loc, Identifier[] packages, 
Identifier ident, ImportPathInfo pathInfo = ImportPathInfo.init)
     {
         //printf("Module::load(ident = '%s')\n", ident.toChars());
         // Build module filename by turning:
@@ -521,11 +528,17 @@ extern (C++) final class Module : Package
         //  foo\bar\baz
         const(char)[] filename = getFilename(packages, ident);
         // Look for the source file
-        if (const result = find(filename))
+        ImportPathInfo importPathThatFindUs;
+        if (const result = find(filename, importPathThatFindUs))
+        {
             filename = result; // leaks
+            pathInfo = importPathThatFindUs;
+        }
 
         auto m = new Module(loc, filename, ident, 0, 0);
 
+        // TODO: apply import path information (pathInfo) on to module
+
         if (!m.read(loc))
             return null;
         if (global.params.v.verbose)
@@ -662,7 +675,7 @@ extern (C++) final class Module : Package
             if (global.path.length)
             {
                 foreach (i, p; global.path[])
-                    fprintf(stderr, "import path[%llu] = %s\n", cast(ulong)i, 
p);
+                    fprintf(stderr, "import path[%llu] = %s\n", cast(ulong)i, 
p.path);
             }
             else
             {
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index 21391dc18388..eba8dddaf988 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -477,7 +477,7 @@ void gendocfile(Module m, const char[] ddoctext, const 
char* datetime, ErrorSink
     auto p = slice.ptr;
     for (size_t j = 0; j < slice.length; j++)
     {
-        char c = p[j];
+        const c = p[j];
         if (c == 0xFF && j + 1 < slice.length)
         {
             j++;
@@ -510,7 +510,7 @@ void escapeDdocString(ref OutBuffer buf, size_t start)
 {
     for (size_t u = start; u < buf.length; u++)
     {
-        char c = buf[u];
+        const c = buf[u];
         switch (c)
         {
         case '$':
@@ -637,7 +637,7 @@ private void escapeStrayParenthesis(Loc loc, ref OutBuffer 
buf, size_t start, bo
         for (size_t u = buf.length; u > start;)
         {
             u--;
-            char c = buf[u];
+            const c = buf[u];
             switch (c)
             {
             case ')':
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index abeffcb39d2d..9a9058f61dc8 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -323,7 +323,9 @@ extern (C++) class StructDeclaration : AggregateDeclaration
 
         bool hasCpCtorLocal;
         bool hasMoveCtorLocal;
-        needCopyCtor(this, hasCpCtorLocal, hasMoveCtorLocal);
+        bool needCopyCtor;
+        bool needMoveCtor;
+        needCopyOrMoveCtor(this, hasCpCtorLocal, hasMoveCtorLocal, 
needCopyCtor, needMoveCtor);
 
         if (enclosing                      || // is nested
             search(this, loc, Id.postblit) || // has postblit
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 1ab646f41382..0d87f6e26ecc 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -2513,10 +2513,12 @@ private extern(C++) final class DsymbolSemanticVisitor 
: Visitor
                 if (param.type.mutableOf().unSharedOf() == 
sd.type.mutableOf().unSharedOf())
                 {
                     //printf("copy constructor %p\n", ctd);
+                    assert(!ctd.isCpCtor && !ctd.isMoveCtor);
                     if (param.storageClass & STC.ref_)
                         ctd.isCpCtor = true;            // copy constructor
                     else
                         ctd.isMoveCtor = true;          // move constructor
+                    assert(!(ctd.isCpCtor && ctd.isMoveCtor));
                 }
             }
         }
@@ -3007,8 +3009,34 @@ private extern(C++) final class DsymbolSemanticVisitor : 
Visitor
 
         buildDtors(sd, sc2);
 
+        bool hasCopyCtor;
         bool hasMoveCtor;
-        sd.hasCopyCtor = buildCopyCtor(sd, sc2, hasMoveCtor);
+        bool needCopyCtor;
+        bool needMoveCtor;
+        needCopyOrMoveCtor(sd, hasCopyCtor, hasMoveCtor, needCopyCtor, 
needMoveCtor);
+        //printf("%s hasCopy %d hasMove %d needCopy %d needMove %d\n", 
sd.toChars(), hasCopyCtor, hasMoveCtor, needCopyCtor, needMoveCtor);
+
+        /* When generating a move ctor, generate a copy ctor too, otherwise
+         *  https://github.com/s-ludwig/taggedalgebraic/issues/75
+         */
+        if (0 && needMoveCtor && !hasCopyCtor)
+        {
+            needCopyCtor = true;
+        }
+
+        if (needCopyCtor)
+        {
+            assert(hasCopyCtor == false);
+            buildCopyOrMoveCtor(sd, sc2, false); // build copy constructor
+            hasCopyCtor = true;
+        }
+        if (needMoveCtor)
+        {
+            assert(hasMoveCtor == false);
+            buildCopyOrMoveCtor(sd, sc2, true); // build move constructor
+            hasMoveCtor = true;
+        }
+        sd.hasCopyCtor = hasCopyCtor;
         sd.hasMoveCtor = hasMoveCtor;
 
         sd.postblit = buildPostBlit(sd, sc2);
@@ -6601,7 +6629,7 @@ private extern(C++) class SearchVisitor : Visitor
             s = b.sym.search(loc, ident, flags);
             if (!s)
                 continue;
-            else if (s == cd) // happens if s is nested in this and derives 
from this
+            if (s == cd) // happens if s is nested in this and derives from 
this
                 s = null;
             else if (!(flags & SearchOpt.ignoreVisibility) && 
!(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(cd, s))
                 s = null;
@@ -7265,7 +7293,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
             fieldState.fieldSize = memsize;
         else
         {
-            auto size = (pastField + 7) / 8;
+            const size = (pastField + 7) / 8;
             fieldState.fieldSize = size;
             //printf(" offset: %d, size: %d\n", offset, size);
             if (isunion)
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 5bb70495bb3d..7f7437cdb151 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -910,7 +910,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
      */
     extern (D) TemplateTupleParameter isVariadic()
     {
-        size_t dim = parameters.length;
+        const dim = parameters.length;
         if (dim == 0)
             return null;
         return (*parameters)[dim - 1].isTemplateTupleParameter();
@@ -6129,14 +6129,13 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, 
RootObject oarg, size_t i, Templ
 
     if (auto ttp = tp.isTemplateTypeParameter())
         return matchArgType(ttp);
-    else if (auto tvp = tp.isTemplateValueParameter())
+    if (auto tvp = tp.isTemplateValueParameter())
         return matchArgValue(tvp);
-    else if (auto tap = tp.isTemplateAliasParameter())
+    if (auto tap = tp.isTemplateAliasParameter())
         return matchArgAlias(tap);
-    else if (auto ttp = tp.isTemplateTupleParameter())
+    if (auto ttp = tp.isTemplateTupleParameter())
         return matchArgTuple(ttp);
-    else
-        assert(0);
+    assert(0);
 }
 
 
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 296e13c63d51..efd0a2f53e20 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -2796,7 +2796,7 @@ public:
     {
         if (vd._init && !vd._init.isVoidInitializer())
             return AST.initializerToExpression(vd._init);
-        else if (auto ts = vd.type.isTypeStruct())
+        if (auto ts = vd.type.isTypeStruct())
         {
             if (!ts.sym.noDefaultCtor && !ts.sym.isUnionDeclaration())
             {
diff --git a/gcc/d/dmd/errors.d b/gcc/d/dmd/errors.d
index 1babb18bcc6b..7faa536dea6f 100644
--- a/gcc/d/dmd/errors.d
+++ b/gcc/d/dmd/errors.d
@@ -197,6 +197,16 @@ else
         va_end(ap);
     }
 
+/// Callback for when the backend wants to report an error
+extern(C++) void errorBackend(const(char)* filename, uint linnum, uint 
charnum, const(char)* format, ...)
+{
+    const loc = Loc(filename, linnum, charnum);
+    va_list ap;
+    va_start(ap, format);
+    verrorReport(loc, format, ap, ErrorKind.error);
+    va_end(ap);
+}
+
 /**
  * Print additional details about an error message.
  * Doesn't increase the error count or print an additional error prefix.
@@ -420,7 +430,10 @@ else
  *      p1          = additional message prefix
  *      p2          = additional message prefix
  */
-extern (C++) void verrorReport(const ref Loc loc, const(char)* format, va_list 
ap, ErrorKind kind, const(char)* p1 = null, const(char)* p2 = null);
+private extern(C++) void verrorReport(const ref Loc loc, const(char)* format, 
va_list ap, ErrorKind kind, const(char)* p1 = null, const(char)* p2 = null);
+
+/// ditto
+private extern(C++) void verrorReport(const SourceLoc loc, const(char)* 
format, va_list ap, ErrorKind kind, const(char)* p1 = null, const(char)* p2 = 
null);
 
 /**
  * Implements $(D errorSupplemental), $(D warningSupplemental), and
@@ -433,7 +446,10 @@ extern (C++) void verrorReport(const ref Loc loc, 
const(char)* format, va_list a
  *      ap          = printf-style variadic arguments
  *      kind        = kind of error being printed
  */
-extern (C++) void verrorReportSupplemental(const ref Loc loc, const(char)* 
format, va_list ap, ErrorKind kind);
+private extern(C++) void verrorReportSupplemental(const ref Loc loc, 
const(char)* format, va_list ap, ErrorKind kind);
+
+/// ditto
+private extern(C++) void verrorReportSupplemental(const SourceLoc loc, 
const(char)* format, va_list ap, ErrorKind kind);
 
 /**
  * The type of the fatal error handler
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 355bdc42468e..2a828d85473f 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -2805,11 +2805,11 @@ extern (C++) final class FuncExp : Expression
     {
         if (td)
             return new FuncExp(loc, td.syntaxCopy(null));
-        else if (fd.semanticRun == PASS.initial)
+        if (fd.semanticRun == PASS.initial)
             return new FuncExp(loc, fd.syntaxCopy(null));
-        else // https://issues.dlang.org/show_bug.cgi?id=13481
-             // Prevent multiple semantic analysis of lambda body.
-            return new FuncExp(loc, fd);
+        // https://issues.dlang.org/show_bug.cgi?id=13481
+        // Prevent multiple semantic analysis of lambda body.
+        return new FuncExp(loc, fd);
     }
 
     override const(char)* toChars() const
@@ -3573,10 +3573,9 @@ TypeFunction calledFunctionType(CallExp ce)
     t = t.toBasetype();
     if (auto tf = t.isTypeFunction())
         return tf;
-    else if (auto td = t.isTypeDelegate())
+    if (auto td = t.isTypeDelegate())
         return td.nextOf().isTypeFunction();
-    else
-        return null;
+    return null;
 }
 
 FuncDeclaration isFuncAddress(Expression e, bool* hasOverloads = null) @safe
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 302038701aff..cd7548ea27cf 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -118,10 +118,9 @@ private bool isNeedThisScope(Scope* sc, Declaration d)
         {
             if (ad2 == ad)
                 return false;
-            else if (ad2.isNested())
+            if (ad2.isNested())
                 continue;
-            else
-                return true;
+            return true;
         }
         if (FuncDeclaration f = s.isFuncDeclaration())
         {
@@ -1521,7 +1520,7 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
     }
     else if (auto oe = e1.isOverExp())
         return handleOverloadSet(oe.vars);
-    else if (auto dti = e1.isDotTemplateInstanceExp())
+    if (auto dti = e1.isDotTemplateInstanceExp())
     {
         if (dti.ti.tempdecl)
             if (auto td = dti.ti.tempdecl.isTemplateDeclaration())
@@ -1529,7 +1528,7 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
     }
     else if (auto dte = e1.isDotTemplateExp())
         return handleTemplateDecl(dte.td);
-    else if (auto se = e1.isScopeExp())
+    if (auto se = e1.isScopeExp())
     {
         Dsymbol s = se.sds;
         TemplateInstance ti = s.isTemplateInstance();
@@ -1539,7 +1538,7 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
     }
     else if (auto et = e1.isTemplateExp())
         return handleTemplateDecl(et.td);
-    else if (e1.isDotVarExp() && e1.type.isTypeFunction())
+    if (e1.isDotVarExp() && e1.type.isTypeFunction())
     {
         DotVarExp dve = e1.isDotVarExp();
         return handleFuncDecl(dve.var.isFuncDeclaration());
@@ -6163,7 +6162,7 @@ private extern (C++) final class 
ExpressionSemanticVisitor : Visitor
                 if (sd.ctor)
                 {
                     auto ctor = sd.ctor.isCtorDeclaration();
-                    if (ctor && ctor.isCpCtor && ctor.isGenerated())
+                    if (ctor && (ctor.isCpCtor || ctor.isMoveCtor) && 
ctor.isGenerated())
                         sd.ctor = null;
                 }
 
@@ -7262,7 +7261,7 @@ private extern (C++) final class 
ExpressionSemanticVisitor : Visitor
                 return no();
             if (e.tok2 == TOK.package_ && p.isModule()) // Note that 
isModule() will return null for package modules because they're not actually 
instances of Module.
                 return no();
-            else if(e.tok2 == TOK.module_ && !(p.isModule() || 
p.isPackageMod()))
+            if (e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod()))
                 return no();
             tded = e.targ;
             return yes();
@@ -17036,6 +17035,7 @@ bool checkDisabled(Declaration d, Loc loc, Scope* sc, 
bool isAliasedDeclaration
 
     if (auto ctor = d.isCtorDeclaration())
     {
+        //printf("checkDisabled() %s %s\n", ctor.toPrettyChars(), 
toChars(ctor.type));
         if (ctor.isCpCtor && ctor.isGenerated())
         {
             .error(loc, "generating an `inout` copy constructor for `struct 
%s` failed, therefore instances of it are uncopyable", 
d.parent.toPrettyChars());
diff --git a/gcc/d/dmd/file_manager.d b/gcc/d/dmd/file_manager.d
index 6ad3d621708d..7f39ec91f023 100644
--- a/gcc/d/dmd/file_manager.d
+++ b/gcc/d/dmd/file_manager.d
@@ -159,16 +159,20 @@ nothrow:
     * Does not open the file.
     * Params:
     *      filename = as supplied by the user
-    *      paths = paths to look for filename
+    *      pathsInfo = pathsInfo to look for filename with metadata
+    *      whichPathFoundThis = Which path from `path` was used in determining 
the output path, or -1 if unknown.
     * Returns:
     *      the found file name or
     *      `null` if it is not different from filename.
     */
-    const(char)[] lookForSourceFile(const char[] filename, const char*[] paths)
+    const(char)[] lookForSourceFile(const char[] filename, const 
ImportPathInfo[] pathsInfo, out ptrdiff_t whichPathFoundThis)
     {
         //printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, 
filename.ptr);
-        /* Search along paths[] for .di file, then .d file.
+        /* Search along pathsInfo[] for .di file, then .d file.
         */
+
+        whichPathFoundThis = -1;
+
         // see if we should check for the module locally.
         bool checkLocal = pathCache.pathExists(filename);
         const sdi = FileName.forceExt(filename, hdr_ext);
@@ -206,11 +210,11 @@ nothrow:
 
         if (FileName.absolute(filename))
             return null;
-        if (!paths.length)
+        if (!pathsInfo.length)
             return null;
-        foreach (entry; paths)
+        foreach (pathIndex, entry; pathsInfo)
         {
-            const p = entry.toDString();
+            const p = entry.path.toDString();
 
             const(char)[] n = FileName.combine(p, sdi);
 
@@ -225,6 +229,7 @@ nothrow:
 
             n = FileName.combine(p, sd);
             if (FileName.exists(n) == 1) {
+                whichPathFoundThis = pathIndex;
                 return n;
             }
             FileName.free(n.ptr);
@@ -236,11 +241,15 @@ nothrow:
             if (pathCache.isExistingPath(n))
             {
                 const n2i = FileName.combine(n, package_di);
-                if (FileName.exists(n2i) == 1)
+                if (FileName.exists(n2i) == 1) {
+                    whichPathFoundThis = pathIndex;
                     return n2i;
+                }
+
                 FileName.free(n2i.ptr);
                 const n2 = FileName.combine(n, package_d);
                 if (FileName.exists(n2) == 1) {
+                    whichPathFoundThis = pathIndex;
                     return n2;
                 }
                 FileName.free(n2.ptr);
@@ -258,18 +267,20 @@ nothrow:
         if (FileName.exists(sc) == 1)
             return sc;
         scope(exit) FileName.free(sc.ptr);
-        foreach (entry; paths)
+        foreach (pathIndex, entry; pathsInfo)
         {
-            const p = entry.toDString();
+            const p = entry.path.toDString();
 
             const(char)[] n = FileName.combine(p, si);
             if (FileName.exists(n) == 1) {
+                whichPathFoundThis = pathIndex;
                 return n;
             }
             FileName.free(n.ptr);
 
             n = FileName.combine(p, sc);
             if (FileName.exists(n) == 1) {
+                whichPathFoundThis = pathIndex;
                 return n;
             }
             FileName.free(n.ptr);
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 40d39aea0ea8..b42ac768b450 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -1373,11 +1373,9 @@ extern (C++) final class CtorDeclaration : 
FuncDeclaration
 {
     bool isCpCtor;    // copy constructor
     bool isMoveCtor;  // move constructor (aka rvalue constructor)
-    extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, 
Type type, bool isCpCtor = false, bool isMoveCtor = false)
+    extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, 
Type type)
     {
         super(loc, endloc, Id.ctor, stc, type);
-        this.isCpCtor = isCpCtor;
-        this.isMoveCtor = isMoveCtor;
         //printf("CtorDeclaration(loc = %s) %s %p\n", loc.toChars(), 
toChars(), this);
     }
 
diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d
index 39da0256eebc..2bd593ed49b2 100644
--- a/gcc/d/dmd/funcsem.d
+++ b/gcc/d/dmd/funcsem.d
@@ -1103,7 +1103,7 @@ Ldone:
         {
             printedMain = true;
             auto name = mod.srcfile.toChars();
-            auto path = FileName.searchPath(global.path, name, true);
+            auto path = FileName.searchPath(global.importPaths, name, true);
             message("entry     %-10s\t%s", type, path ? path : name);
         }
     }
@@ -1536,7 +1536,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* 
sc, Dsymbol s,
 
     version (none)
     {
-        printf("resolveFuncCall('%s')\n", s.toChars());
+        printf("resolveFuncCall() %s)\n", s.toChars());
         if (tthis)
             printf("\tthis: %s\n", tthis.toChars());
         if (fargs)
@@ -1548,7 +1548,6 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* 
sc, Dsymbol s,
                 printf("\t%s: %s\n", arg.toChars(), arg.type.toChars());
             }
         }
-        printf("\tfnames: %s\n", fnames ? fnames.toChars() : "null");
     }
 
     if (tiargs && arrayObjectIsError(*tiargs))
@@ -2270,6 +2269,9 @@ int getLevelAndCheck(FuncDeclaration fd, const ref Loc 
loc, Scope* sc, FuncDecla
 /**********************************
  * Decide if attributes for this function can be inferred from examining
  * the function body.
+ * Params:
+ *      fd = function to infer attributes for
+ *      sc = context
  * Returns:
  *  true if can
  */
@@ -2291,7 +2293,8 @@ bool canInferAttributes(FuncDeclaration fd, Scope* sc)
         (!fd.isMember() || sc.func.isSafeBypassingInference() && 
!fd.isInstantiated()))
         return true;
     if (fd.isFuncLiteralDeclaration() ||               // externs are not 
possible with literals
-        (fd.storage_class & STC.inference) ||           // do attribute 
inference
+        (fd.storage_class & STC.inference) ||          // do attribute 
inference
+        fd.isGenerated ||                              // compiler generated 
function
         (fd.inferRetType && !fd.isCtorDeclaration()))
         return true;
     if (fd.isInstantiated())
@@ -2994,7 +2997,7 @@ extern (D) bool checkNRVO(FuncDeclaration fd)
             auto v = ve.var.isVarDeclaration();
             if (!v || v.isReference())
                 return false;
-            else if (fd.nrvo_var is null)
+            if (fd.nrvo_var is null)
             {
                 // Variables in the data segment (e.g. globals, TLS or not),
                 // parameters and closure variables cannot be NRVOed.
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index 77bb4986e724..4d3c1b9d1970 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -151,6 +151,10 @@ extern(C++) struct Verbose
     }
 }
 
+extern (C++) struct ImportPathInfo {
+    const(char)* path; // char*'s of where to look for import modules
+}
+
 /// Put command line switches in here
 extern (C++) struct Param
 {
@@ -223,7 +227,7 @@ extern (C++) struct Param
 
     const(char)[] argv0;                // program name
     Array!(const(char)*) modFileAliasStrings; // array of char*'s of -I module 
filename alias strings
-    Array!(const(char)*) imppath;       // array of char*'s of where to look 
for import modules
+    Array!(ImportPathInfo) imppath;       // array of import path information 
of where to look for import modules
     Array!(const(char)*) fileImppath;   // array of char*'s of where to look 
for file import modules
     const(char)[] objdir;                // .obj/.lib file output directory
     const(char)[] objname;               // .obj file output name
@@ -291,7 +295,8 @@ extern (C++) struct Global
     string copyright = "Copyright (C) 1999-2024 by The D Language Foundation, 
All Rights Reserved";
     string written = "written by Walter Bright";
 
-    Array!(const(char)*) path;         /// Array of char*'s which form the 
import lookup path
+    Array!(ImportPathInfo) path;       /// Array of path informations which 
form the import lookup path
+    Array!(const(char)*) importPaths;  /// Array of char*'s which form the 
import lookup path without metadata
     Array!(const(char)*) filePath;     /// Array of char*'s which form the 
file import lookup path
 
     private enum string _version = import("VERSION");
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 669f83e2101f..6dd4be4b0a01 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -155,6 +155,14 @@ struct Verbose
     unsigned errorSupplementCount();
 };
 
+struct ImportPathInfo
+{
+    const char* path;
+
+    ImportPathInfo() : path(NULL) { }
+    ImportPathInfo(const char* p) : path(p) { }
+};
+
 // Put command line switches in here
 struct Param
 {
@@ -227,7 +235,7 @@ struct Param
 
     DString  argv0;    // program name
     Array<const char *> modFileAliasStrings; // array of char*'s of -I module 
filename alias strings
-    Array<const char *> imppath;     // array of char*'s of where to look for 
import modules
+    Array<ImportPathInfo> imppath;     // array of import path information of 
where to look for import modules
     Array<const char *> fileImppath; // array of char*'s of where to look for 
file import modules
     DString objdir;    // .obj/.lib file output directory
     DString objname;   // .obj file output name
@@ -315,8 +323,9 @@ struct Global
 
     const DString copyright;
     const DString written;
-    Array<const char *> path;        // Array of char*'s which form the import 
lookup path
-    Array<const char *> filePath;    // Array of char*'s which form the file 
import lookup path
+    Array<ImportPathInfo> path;        // Array of path informations which 
form the import lookup path
+    Array<const char *> importPaths;   // Array of char*'s which form the 
import lookup path without metadata
+    Array<const char *> filePath;      // Array of char*'s which form the file 
import lookup path
 
     char datetime[26];       /// string returned by ctime()
     CompileEnv compileEnv;
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index a5e897d62466..d391bdb581ac 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -2881,9 +2881,9 @@ private void expressionPrettyPrint(Expression e, ref 
OutBuffer buf, ref HdrGenSt
         default:
             if (auto be = e.isBinExp())
                 return visitBin(be);
-            else if (auto ue = e.isUnaExp())
+            if (auto ue = e.isUnaExp())
                 return visitUna(ue);
-            else if (auto de = e.isDefaultInitExp())
+            if (auto de = e.isDefaultInitExp())
                 return visitDefaultInit(e.isDefaultInitExp());
             return visit(e);
 
diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d
index b1b5a4f6cb86..37f8cfdbeac9 100644
--- a/gcc/d/dmd/json.d
+++ b/gcc/d/dmd/json.d
@@ -906,7 +906,7 @@ public:
         arrayStart();
         foreach (importPath; global.params.imppath[])
         {
-            item(importPath.toDString);
+            item(importPath.path.toDString);
         }
         arrayEnd();
 
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index d9f4b1c678f6..7bf32a9ddb8d 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -643,7 +643,7 @@ class Lexer
 
                         if (isidchar(c))
                             continue;
-                        else if (c & 0x80)
+                        if (c & 0x80)
                         {
                             const s = p;
                             const u = decodeUTF();
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 4a4254fcbdd3..b6d44c7f136b 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -1294,7 +1294,7 @@ extern (C++) abstract class Type : ASTNode
         {
             if (isImmutable())
                 return MODFlags.immutable_;
-            else if (isWildConst())
+            if (isWildConst())
             {
                 if (t.isWildConst())
                     return MODFlags.wild;
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index b408f8bffa4f..415d57824d14 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -2146,11 +2146,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         nextToken();
         if (id == Id.Windows)
             return returnLinkage(LINK.windows);
-        else if (id == Id.D)
+        if (id == Id.D)
             return returnLinkage(LINK.d);
-        else if (id == Id.System)
+        if (id == Id.System)
             return returnLinkage(LINK.system);
-        else if (id == Id.Objective) // Looking for tokens "Objective-C"
+        if (id == Id.Objective) // Looking for tokens "Objective-C"
         {
             if (token.value != TOK.min)
                 return invalidLinkage();
diff --git a/gcc/d/dmd/pragmasem.d b/gcc/d/dmd/pragmasem.d
index f2f748500a63..c5d18ef40a5a 100644
--- a/gcc/d/dmd/pragmasem.d
+++ b/gcc/d/dmd/pragmasem.d
@@ -511,10 +511,9 @@ package PINLINE evalPragmaInline(Loc loc, Scope* sc, 
Expressions* args)
     const opt = e.toBool();
     if (opt.isEmpty())
         return PINLINE.default_;
-    else if (opt.get())
+    if (opt.get())
         return PINLINE.always;
-    else
-        return PINLINE.never;
+    return PINLINE.never;
 }
 
 /**
@@ -566,11 +565,9 @@ private bool pragmaMsgSemantic(Loc loc, Scope* sc, 
Expressions* args)
     OutBuffer buf;
     if (expressionsToString(buf, sc, args, loc, "while evaluating `pragma(msg, 
%s)`", false))
         return false;
-    else
-    {
-        buf.writestring("\n");
-        fprintf(stderr, buf.extractChars);
-    }
+
+    buf.writestring("\n");
+    fprintf(stderr, buf.extractChars);
     return true;
 }
 
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index 92e00e8992b9..3553d3dbbf46 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -1333,7 +1333,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
                 // Don't allow D `immutable` and `shared` types to be 
interfaced with C++
                 if (type.isImmutable() || type.isShared())
                     return true;
-                else if (Type cpptype = target.cpp.parameterType(type))
+                if (Type cpptype = target.cpp.parameterType(type))
                     type = cpptype;
 
                 if (origType is null)
diff --git a/gcc/d/dmd/templateparamsem.d b/gcc/d/dmd/templateparamsem.d
index f2dc50ebb702..8a08e7165249 100644
--- a/gcc/d/dmd/templateparamsem.d
+++ b/gcc/d/dmd/templateparamsem.d
@@ -170,7 +170,7 @@ RootObject aliasParameterSemantic(Loc loc, Scope* sc, 
RootObject o, TemplatePara
         Dsymbol s = ta.toDsymbol(sc);
         if (s)
             return s;
-        else if (TypeInstance ti = ta.isTypeInstance())
+        if (TypeInstance ti = ta.isTypeInstance())
         {
             Type t;
             const errors = global.errors;
@@ -183,14 +183,13 @@ RootObject aliasParameterSemantic(Loc loc, Scope* sc, 
RootObject o, TemplatePara
             // see https://issues.dlang.org/show_bug.cgi?id=16472
             if (t)
                 return t.typeSemantic(loc, sc);
-            else if (ea)
+            if (ea)
             {
                 return eaCTFE();
             }
-            else if (s)
+            if (s)
                 return s;
-            else
-                assert(0);
+            assert(0);
         }
         else
             return ta.typeSemantic(loc, sc);
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 34cdf816eb0f..42344c68fd0a 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -726,8 +726,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
 
         if (ClassDeclaration cd = agg.isClassDeclaration())
             return cd.com ? True() : False();
-        else
-            return False();
+        return False();
     }
     if (e.ident == Id.identifier)
     {
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index c631e640815e..dc3f9da89410 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -1050,7 +1050,7 @@ private extern(D) MATCH argumentMatchParameter 
(FuncDeclaration fd, TypeFunction
                     {
                         if (cfd.isCpCtor && !arg.isLvalue())
                             return MATCH.nomatch;       // copy constructor is 
only for lvalues
-                        else if (cfd.isMoveCtor && arg.isLvalue())
+                        if (cfd.isMoveCtor && arg.isLvalue())
                             return MATCH.nomatch;       // move constructor is 
only for rvalues
                     }
                     }
@@ -7470,7 +7470,7 @@ bool isRecursiveAliasThis(ref Type att, Type t)
     auto tb = t.toBasetype();
     if (att && tb.equivalent(att))
         return true;
-    else if (!att && tb.checkAliasThisRec())
+    if (!att && tb.checkAliasThisRec())
         att = tb;
     return false;
 }
diff --git a/gcc/d/dmd/typinf.d b/gcc/d/dmd/typinf.d
index ceff41473e42..35d5ad40bebd 100644
--- a/gcc/d/dmd/typinf.d
+++ b/gcc/d/dmd/typinf.d
@@ -100,7 +100,6 @@ bool genTypeInfo(Expression e, const ref Loc loc, Type 
torig, Scope* sc)
  *      loc = the location for reporting line nunbers in errors
  *      t   = the type to get the type of the `TypeInfo` object for
  *      sc  = the scope
- *      genObjCode = if true, object code will be generated for the obtained 
TypeInfo
  * Returns:
  *      The type of the `TypeInfo` object associated with `t`
  */
diff --git a/gcc/testsuite/gdc.test/compilable/copyCtor2.d 
b/gcc/testsuite/gdc.test/compilable/copyCtor2.d
new file mode 100644
index 000000000000..084ef3b3f25f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/copyCtor2.d
@@ -0,0 +1,14 @@
+/* This used to not be allowed
+ * https://github.com/dlang/dmd/pull/20634
+ */
+
+struct A
+{
+    this (ref shared A a) immutable {}
+}
+
+struct B
+{
+    A a;
+    this(immutable B b) shared {}
+}
diff --git a/gcc/testsuite/gdc.test/compilable/cppmangle.d 
b/gcc/testsuite/gdc.test/compilable/cppmangle.d
index 4b9046e81102..c6c921d7b0cb 100644
--- a/gcc/testsuite/gdc.test/compilable/cppmangle.d
+++ b/gcc/testsuite/gdc.test/compilable/cppmangle.d
@@ -666,6 +666,8 @@ extern (C++) class C18890_2
     Agg s;
 }
 
+void test18890()
+{
 version (CppMangle_Itanium)
 {
     static assert(C18890.__dtor.mangleof == "_ZN6C18890D1Ev");
@@ -690,6 +692,7 @@ version (CppMangle_MSVC)
         static assert(C18890_2.__xdtor.mangleof == 
"??_GC18890_2@@UEAAPEAXI@Z");
     }
 }
+}
 
 /**************************************/
 // https://issues.dlang.org/show_bug.cgi?id=18891
@@ -704,6 +707,8 @@ extern (C++) class C18891
     Agg s;
 }
 
+void test18891()
+{
 version (CppMangle_Itanium)
 {
     static assert(C18891.__dtor.mangleof == "_ZN6C18891D1Ev");
@@ -722,6 +727,7 @@ version (CppMangle_MSVC)
         static assert(C18891.__xdtor.mangleof == "??_GC18891@@UEAAPEAXI@Z");
     }
 }
+}
 
 /**************************************/
 // Test C++ operator mangling
diff --git a/gcc/testsuite/gdc.test/compilable/testInference.d 
b/gcc/testsuite/gdc.test/compilable/testInference.d
index bddbaf429465..5091b99896a1 100644
--- a/gcc/testsuite/gdc.test/compilable/testInference.d
+++ b/gcc/testsuite/gdc.test/compilable/testInference.d
@@ -817,4 +817,22 @@ void test13840() nothrow
     {}
 }
 
-// Add more tests regarding inferences later.
+/***************************************************/
+// https://github.com/dlang/dmd/pull/20685
+
+struct T1
+{
+    int a;
+    inout this(ref inout T1 t) @nogc nothrow pure { a = t.a; }
+}
+
+struct S1
+{
+    T1 t; // generate copy constructor, infer @nogc nothrow pure
+}
+
+void test1() @nogc nothrow pure
+{
+    S1 s;
+    S1 t = s;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/failCopyCtor2.d 
b/gcc/testsuite/gdc.test/fail_compilation/failCopyCtor2.d
deleted file mode 100644
index 5e8f8c40f7da..000000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/failCopyCtor2.d
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/failCopyCtor2.d(15): Error: `struct B` may not define a 
rvalue constructor and have fields with copy constructors
-fail_compilation/failCopyCtor2.d(18):        rvalue constructor defined here
-fail_compilation/failCopyCtor2.d(17):        field with copy constructor 
defined here
----
-*/
-
-struct A
-{
-    this (ref shared A a) immutable {}
-}
-
-struct B
-{
-    A a;
-    this(immutable B b) shared {}
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope2.d 
b/gcc/testsuite/gdc.test/fail_compilation/retscope2.d
index 8e10a7caae78..4638cdc139ab 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope2.d
@@ -296,7 +296,7 @@ fail_compilation/retscope2.d(1024): Error: assigning scope 
variable `p` to non-s
 fail_compilation/retscope2.d(1107): Error: returning scope variable `dg` is 
not allowed in a `@safe` function
 fail_compilation/retscope2.d(1216): Error: returning `s.foo()` escapes a 
reference to local variable `s`
 fail_compilation/retscope2.d(1233): Error: returning `t.foo()` escapes a 
reference to local variable `t`
-fail_compilation/retscope2.d(1306): Error: escaping a reference to local 
variable `i by copying `& i` into allocated memory is not allowed in a `@safe` 
function
+fail_compilation/retscope2.d(1306): Error: escaping a reference to local 
variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` 
function
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope3.d 
b/gcc/testsuite/gdc.test/fail_compilation/retscope3.d
index 59bf11b62683..819071f15d04 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope3.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope3.d
@@ -51,8 +51,8 @@ void bar4()
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/retscope3.d(2008): Error: escaping a reference to local 
variable `i by copying `& i` into allocated memory is not allowed in a `@safe` 
function
-fail_compilation/retscope3.d(2017): Error: escaping a reference to local 
variable `i by copying `S2000(& i)` into allocated memory is not allowed in a 
`@safe` function
+fail_compilation/retscope3.d(2008): Error: escaping a reference to local 
variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` 
function
+fail_compilation/retscope3.d(2017): Error: escaping a reference to local 
variable `i` by copying `S2000(& i)` into allocated memory is not allowed in a 
`@safe` function
 fail_compilation/retscope3.d(4003): Error: escaping a reference to parameter 
`u` by copying `u[]` into allocated memory is not allowed in a `@safe` function
 fail_compilation/retscope3.d(4016): Error: storing reference to outer local 
variable `i` into allocated memory causes it to escape
 fail_compilation/retscope3.d(4025): Error: escaping reference to stack 
allocated value returned by `makeSA()` into allocated memory
diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope6.d 
b/gcc/testsuite/gdc.test/fail_compilation/retscope6.d
index 49751a4b339b..e3b734f03d40 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/retscope6.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/retscope6.d
@@ -5,7 +5,7 @@ REQUIRED_ARGS: -preview=dip1000
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/retscope6.d(6007): Error: escaping a reference to local 
variable `i by copying `& i` into allocated memory is not allowed in a `@safe` 
function
+fail_compilation/retscope6.d(6007): Error: escaping a reference to local 
variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` 
function
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test18282.d 
b/gcc/testsuite/gdc.test/fail_compilation/test18282.d
index 97b2b2b13331..b5db07fd9385 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test18282.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test18282.d
@@ -2,12 +2,12 @@
    TEST_OUTPUT:
 ---
 fail_compilation/test18282.d(25): Error: returning scope variable `aa` is not 
allowed in a `@safe` function
-fail_compilation/test18282.d(34): Error: escaping a reference to local 
variable `i by copying `& i` into allocated memory is not allowed in a `@safe` 
function
-fail_compilation/test18282.d(35): Error: escaping a reference to local 
variable `i by copying `& i` into allocated memory is not allowed in a `@safe` 
function
+fail_compilation/test18282.d(34): Error: escaping a reference to local 
variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` 
function
+fail_compilation/test18282.d(35): Error: escaping a reference to local 
variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` 
function
 fail_compilation/test18282.d(36): Error: returning scope variable `staa` is 
not allowed in a `@safe` function
-fail_compilation/test18282.d(44): Error: escaping a reference to local 
variable `i by copying `S2000(& i)` into allocated memory is not allowed in a 
`@safe` function
-fail_compilation/test18282.d(53): Error: escaping a reference to local 
variable `i by copying `& i` into allocated memory is not allowed in a `@safe` 
function
-fail_compilation/test18282.d(53): Error: escaping a reference to local 
variable `c by copying `& c` into allocated memory is not allowed in a `@safe` 
function
+fail_compilation/test18282.d(44): Error: escaping a reference to local 
variable `i` by copying `S2000(& i)` into allocated memory is not allowed in a 
`@safe` function
+fail_compilation/test18282.d(53): Error: escaping a reference to local 
variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` 
function
+fail_compilation/test18282.d(53): Error: escaping a reference to local 
variable `c` by copying `& c` into allocated memory is not allowed in a `@safe` 
function
 ---
  */
 
@@ -57,9 +57,9 @@ void bar3()
 /******************************
 TEST_OUTPUT:
 ---
-fail_compilation/test18282.d(1007): Error: escaping a reference to local 
variable `foo by copying `& foo` into allocated memory is not allowed in a 
`@safe` function
-fail_compilation/test18282.d(1008): Error: escaping a reference to local 
variable `foo by copying `& foo` into allocated memory is not allowed in a 
`@safe` function
-fail_compilation/test18282.d(1009): Error: escaping a reference to local 
variable `foo by copying `& foo` into allocated memory is not allowed in a 
`@safe` function
+fail_compilation/test18282.d(1007): Error: escaping a reference to local 
variable `foo` by copying `& foo` into allocated memory is not allowed in a 
`@safe` function
+fail_compilation/test18282.d(1008): Error: escaping a reference to local 
variable `foo` by copying `& foo` into allocated memory is not allowed in a 
`@safe` function
+fail_compilation/test18282.d(1009): Error: escaping a reference to local 
variable `foo` by copying `& foo` into allocated memory is not allowed in a 
`@safe` function
 fail_compilation/test18282.d(1016): Error: escaping a reference to parameter 
`this` by copying `&this` into allocated memory is not allowed in a `@safe` 
function
 ---
 */
diff --git a/gcc/testsuite/gdc.test/runnable/rvalue1.d 
b/gcc/testsuite/gdc.test/runnable/rvalue1.d
index f8134f718a9f..2592f2a9e95e 100644
--- a/gcc/testsuite/gdc.test/runnable/rvalue1.d
+++ b/gcc/testsuite/gdc.test/runnable/rvalue1.d
@@ -194,6 +194,56 @@ void test8()
 
 /********************************/
 
+struct T9
+{
+    int i;
+    inout this(ref inout T9 t) { this.i = t.i - 1; printf("this(ref T9)\n"); }
+    inout this(inout T9 t)     { this.i = t.i + 1; printf("this(T9)\n"); }
+}
+
+struct S9
+{
+    T9 t;
+    //inout this(return ref scope inout S9 t);// { this.i = t.i - 1; 
printf("this(ref T9)\n"); }
+    //@system inout this(return scope inout S9 t);//     { this.i = t.i + 1; 
printf("this(T9)\n"); }
+}
+
+void test9()
+{
+    S9 s;
+    s.t.i = 3;
+    S9 u = s;
+    printf("u.t.i = %d\n", u.t.i);
+    assert(u.t.i == 2);
+
+    S9 v = __rvalue(u);
+    printf("v.t.i = %d\n", v.t.i);
+    assert(v.t.i == 3);
+}
+
+/********************************/
+// https://github.com/s-ludwig/taggedalgebraic/issues/75
+
+struct T10
+{
+    string s;
+    this(T10) {}
+    this(string v) { s = v; }
+}
+
+struct S10
+{
+    T10 p;
+}
+
+void test10()
+{
+    S10 s = S10(T10("hello"));
+    assert(s.p.s == "hello");
+}
+
+/********************************/
+
 int main()
 {
     test1();
@@ -204,6 +254,7 @@ int main()
     test6();
     test7();
     test8();
+    test9();
 
     return 0;
 }
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index b145d1bd6593..33bb398c00d4 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-c7902293d7df9d02546562cb09fc8439004a70d1
+d6f693b46a1565172cac7a1438905141783a164f
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/core/builtins.d 
b/libphobos/libdruntime/core/builtins.d
index bc12759e9a18..4e0c6d4d622e 100644
--- a/libphobos/libdruntime/core/builtins.d
+++ b/libphobos/libdruntime/core/builtins.d
@@ -94,6 +94,23 @@ else version (DigitalMars)
 
 /// Provide static branch and value hints for the LDC/GDC compilers.
 /// DMD ignores these hints.
-pragma(inline, true) bool likely(bool b)   { return !!expect(b, true);  }
+pragma(inline, true) bool likely()(bool b)   { return !!expect(b, true);  }
 /// ditto
-pragma(inline, true) bool unlikely(bool b) { return !!expect(b, false); }
+pragma(inline, true) bool unlikely()(bool b) { return !!expect(b, false); }
+
+///
+@nogc nothrow pure @safe unittest
+{
+    int x = 12;
+
+    expect(x, 12);
+
+    if (likely(x > 0))
+    {
+        // ...
+    }
+    else if (unlikely(x == int.min))
+    {
+        // ...
+    }
+}
diff --git a/libphobos/libdruntime/core/demangle.d 
b/libphobos/libdruntime/core/demangle.d
index c9bde27da69e..e7efc8c3ec9a 100644
--- a/libphobos/libdruntime/core/demangle.d
+++ b/libphobos/libdruntime/core/demangle.d
@@ -1758,13 +1758,10 @@ pure @safe:
 
                     if (parseMangledNameArg())
                         continue;
-                    else
-                    {
-                        dst.len = l;
-                        pos = p;
-                        brp = b;
-                        debug(trace) printf( "not a mangled name arg\n" );
-                    }
+                    dst.len = l;
+                    pos = p;
+                    brp = b;
+                    debug(trace) printf( "not a mangled name arg\n" );
                 }
                 if ( isDigit( front ) && isDigit( peek( 1 ) ) )
                 {
diff --git a/libphobos/libdruntime/core/internal/gc/os.d 
b/libphobos/libdruntime/core/internal/gc/os.d
index bde90e952280..9142708a4a4f 100644
--- a/libphobos/libdruntime/core/internal/gc/os.d
+++ b/libphobos/libdruntime/core/internal/gc/os.d
@@ -67,9 +67,9 @@ else version (Posix)
         while (waited_pid == -1 && errno == EINTR);
         if (waited_pid == 0)
             return ChildStatus.running;
-        else if (errno ==  ECHILD)
+        if (errno ==  ECHILD)
             return ChildStatus.done; // someone called posix.syswait
-        else if (waited_pid != pid || status != 0)
+        if (waited_pid != pid || status != 0)
             onForkError();
         return ChildStatus.done;
     }
diff --git a/libphobos/libdruntime/core/sys/posix/sys/socket.d 
b/libphobos/libdruntime/core/sys/posix/sys/socket.d
index 7c6fab6315a4..12824373d586 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/socket.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/socket.d
@@ -30,6 +30,7 @@ else version (WatchOS)
 version (ARM)     version = ARM_Any;
 version (AArch64) version = ARM_Any;
 version (HPPA)    version = HPPA_Any;
+version (HPPA64)  version = HPPA_Any;
 version (MIPS32)  version = MIPS_Any;
 version (MIPS64)  version = MIPS_Any;
 version (PPC)     version = PPC_Any;
@@ -317,6 +318,7 @@ version (linux)
             SO_RCVLOWAT     = 0x1004,
             SO_RCVTIMEO     = 0x1006,
             SO_REUSEADDR    = 0x0004,
+            SO_REUSEPORT    = 0x0200,
             SO_SNDBUF       = 0x1001,
             SO_SNDLOWAT     = 0x1003,
             SO_SNDTIMEO     = 0x1005,
@@ -351,6 +353,7 @@ version (linux)
             SO_RCVLOWAT     = 0x1004,
             SO_RCVTIMEO     = 0x1006,
             SO_REUSEADDR    = 0x0004,
+            SO_REUSEPORT    = 0x0200,
             SO_SNDBUF       = 0x1001,
             SO_SNDLOWAT     = 0x1003,
             SO_SNDTIMEO     = 0x1005,
@@ -385,6 +388,7 @@ version (linux)
             SO_RCVLOWAT     = 16,
             SO_RCVTIMEO     = 18,
             SO_REUSEADDR    = 2,
+            SO_REUSEPORT    = 15,
             SO_SNDBUF       = 7,
             SO_SNDLOWAT     = 17,
             SO_SNDTIMEO     = 19,
@@ -454,6 +458,7 @@ version (linux)
             SO_RCVLOWAT     = 18,
             SO_RCVTIMEO     = 20,
             SO_REUSEADDR    = 2,
+            SO_REUSEPORT    = 15,
             SO_SNDBUF       = 7,
             SO_SNDLOWAT     = 19,
             SO_SNDTIMEO     = 21,
@@ -488,6 +493,7 @@ version (linux)
             SO_RCVLOWAT     = 18,
             SO_RCVTIMEO     = 20,
             SO_REUSEADDR    = 2,
+            SO_REUSEPORT    = 0x0200, //FIXME: the rest appear to be wrong
             SO_SNDBUF       = 7,
             SO_SNDLOWAT     = 19,
             SO_SNDTIMEO     = 21,
@@ -522,6 +528,7 @@ version (linux)
             SO_RCVLOWAT     = 18,
             SO_RCVTIMEO     = 20,
             SO_REUSEADDR    = 2,
+            SO_REUSEPORT    = 15,
             SO_SNDBUF       = 7,
             SO_SNDLOWAT     = 19,
             SO_SNDTIMEO     = 21,
@@ -556,6 +563,7 @@ version (linux)
             SO_RCVLOWAT     = 18,
             SO_RCVTIMEO     = 20,
             SO_REUSEADDR    = 2,
+            SO_REUSEPORT    = 15,
             SO_SNDBUF       = 7,
             SO_SNDLOWAT     = 19,
             SO_SNDTIMEO     = 21,
@@ -1547,6 +1555,7 @@ else version (Solaris)
         SO_RCVLOWAT     = 0x1004,
         SO_RCVTIMEO     = 0x1006,
         SO_REUSEADDR    = 0x0004,
+        SO_REUSEPORT    = 0x100e,
         SO_SNDBUF       = 0x1001,
         SO_SNDLOWAT     = 0x1003,
         SO_SNDTIMEO     = 0x1005,
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index aa35eae57e2e..fdcc058c9035 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-03aeafd2095b563bb66b75342652d2dcea66c9e8
+336bed6d8ffec74d117b755866c5bd22e3d610a1
 
 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/functional.d b/libphobos/src/std/functional.d
index cf7e3ff8cc2e..b1b1382280d7 100644
--- a/libphobos/src/std/functional.d
+++ b/libphobos/src/std/functional.d
@@ -1349,7 +1349,8 @@ template memoize(alias fun)
         alias memoize = impl;
     }
 
-    auto impl(Args...)(Args args) if (is(typeof(fun(args))))
+    auto impl(Args...)(Args args)
+    if (is(typeof(fun(args))))
     {
         import std.typecons : Tuple, tuple;
         import std.traits : Unqual;
@@ -1393,7 +1394,8 @@ template memoize(alias fun, uint maxSize)
         alias memoize = impl;
     }
 
-    auto impl(Args...)(Args args) if (is(typeof(fun(args))))
+    auto impl(Args...)(Args args)
+    if (is(typeof(fun(args))))
     {
         static if (args.length > 0)
         {
diff --git a/libphobos/src/std/socket.d b/libphobos/src/std/socket.d
index 7fa9974189f6..99ac97ac1e3a 100644
--- a/libphobos/src/std/socket.d
+++ b/libphobos/src/std/socket.d
@@ -15,7 +15,7 @@
 
 /**
  * Socket primitives.
- * Example: See $(SAMPLESRC listener.d) and $(SAMPLESRC htmlget.d)
+ * Example: See 
[listener.d](https://github.com/dlang/undeaD/blob/master/dmdsamples/listener.d) 
and 
[htmlget.d](https://github.com/dlang/undeaD/blob/master/dmdsamples/htmlget.d)
  * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
  * Authors: Christopher E. Miller, $(HTTP klickverbot.at, David Nadlinger),
  *      $(HTTP thecybershadow.net, Vladimir Panteleev)
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index bd462f53a5b1..a841e4720b2c 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -3348,7 +3348,7 @@ package(std) Rebindable2!T rebindable2(T)(T value)
 
             this(ref inout S rhs) @safe inout
             {
-                this.i = i;
+                this.i = rhs.i;
                 copied = true;
             }
         }
diff --git a/libphobos/testsuite/libphobos.init_fini/custom_gc.d 
b/libphobos/testsuite/libphobos.init_fini/custom_gc.d
index cb7238409594..bcbd84c844f1 100644
--- a/libphobos/testsuite/libphobos.init_fini/custom_gc.d
+++ b/libphobos/testsuite/libphobos.init_fini/custom_gc.d
@@ -22,6 +22,12 @@ extern (C) void register_default_gcs()
 class MallocGC : GC
 {
 nothrow @nogc:
+    // To make sure all allocations are multiples of 8 bytes for alignment
+    private size_t alignUp(size_t size)
+    {
+        return (size + 7) & ~7LU;
+    }
+
     static GC initialize()
     {
         import core.stdc.string : memcpy;
@@ -81,21 +87,25 @@ nothrow @nogc:
 
     void* malloc(size_t size, uint bits, const TypeInfo ti) nothrow
     {
+        size = alignUp(size);
         return sentinelAdd(.malloc(size + sentinelSize), size);
     }
 
     BlkInfo qalloc(size_t size, uint bits, const scope TypeInfo ti) nothrow
     {
+        size = alignUp(size);
         return BlkInfo(malloc(size, bits, ti), size);
     }
 
     void* calloc(size_t size, uint bits, const TypeInfo ti) nothrow
     {
+        size = alignUp(size);
         return sentinelAdd(.calloc(1, size + sentinelSize), size);
     }
 
     void* realloc(void* p, size_t size, uint bits, const TypeInfo ti) nothrow
     {
+        size = alignUp(size);
         return sentinelAdd(.realloc(p - sentinelSize, size + sentinelSize), 
size);
     }

Reply via email to