]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
d: Merge upstream dmd, druntime b7e3b3b617
authorIain Buclaw <ibuclaw@gdcproject.org>
Wed, 12 Mar 2025 16:19:49 +0000 (17:19 +0100)
committerIain Buclaw <ibuclaw@gdcproject.org>
Sat, 15 Mar 2025 15:33:00 +0000 (16:33 +0100)
D front-end changes:

- `delete' is no longer a keyword.
- Initializing a field with itself has been deprecated.

D runtime changes:

- Add Windows BCrypt bindings under `core.sys.windows.bcrypt'.

gcc/d/ChangeLog:

* dmd/MERGE: Merge upstream b7e3b3b617.

libphobos/ChangeLog:

* libdruntime/MERGE: Merge upstream b7e3b3b617.
* libdruntime/Makefile.am (DRUNTIME_DSOURCES_WINDOWS): Add
core/sys/windows/bcrypt.d.
* libdruntime/Makefile.in: Regenerate.
* libdruntime/gcc/sections/elf.d (sizeofTLS): Give function the same
mangling as gcc.sections.sizeofTLS.
* libdruntime/gcc/sections/package.d: Import core.internal.traits.
(pinLoadedLibraries): Mangle as function from rt.sections_elf_shared.
(unpinLoadedLibraries): Likewise.
(inheritLoadedLibraries): Likewise.
(cleanupLoadedLibraries): Likewise.
(sizeOfTLS): Add forward declaration.

87 files changed:
gcc/d/dmd/MERGE
gcc/d/dmd/clone.d
gcc/d/dmd/ctfeexpr.d
gcc/d/dmd/dcast.d
gcc/d/dmd/dsymbolsem.d
gcc/d/dmd/dtemplate.d
gcc/d/dmd/expression.d
gcc/d/dmd/expression.h
gcc/d/dmd/expressionsem.d
gcc/d/dmd/func.d
gcc/d/dmd/hdrgen.d
gcc/d/dmd/id.d
gcc/d/dmd/initsem.d
gcc/d/dmd/mangle/cpp.d
gcc/d/dmd/mtype.d
gcc/d/dmd/mustuse.d
gcc/d/dmd/objc.d
gcc/d/dmd/opover.d
gcc/d/dmd/parse.d
gcc/d/dmd/semantic3.d
gcc/d/dmd/tokens.d
gcc/d/dmd/tokens.h
gcc/d/dmd/typesem.d
gcc/testsuite/gdc.test/compilable/interpret3.d
gcc/testsuite/gdc.test/compilable/nogc.d
gcc/testsuite/gdc.test/compilable/test22510.d
gcc/testsuite/gdc.test/fail_compilation/ctor_self_assignment.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/dep_d1_ops.d
gcc/testsuite/gdc.test/fail_compilation/deprecateopdot.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/diag_class_alloc.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/fail10534.d
gcc/testsuite/gdc.test/fail_compilation/fail11445.d
gcc/testsuite/gdc.test/fail_compilation/fail13902.d
gcc/testsuite/gdc.test/fail_compilation/fail14343.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail14486.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/fail17906.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/fail2361.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/fail297.d
gcc/testsuite/gdc.test/fail_compilation/fail3.d
gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d
gcc/testsuite/gdc.test/fail_compilation/faildeleteaa.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/hexstring.d
gcc/testsuite/gdc.test/fail_compilation/ice11968.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/nogc1.d
gcc/testsuite/gdc.test/fail_compilation/test16195.d [deleted file]
gcc/testsuite/gdc.test/runnable/funclit.d
gcc/testsuite/gdc.test/runnable/newdel.d
gcc/testsuite/gdc.test/runnable/opover.d
gcc/testsuite/gdc.test/runnable/xtest46.d
libphobos/libdruntime/MERGE
libphobos/libdruntime/Makefile.am
libphobos/libdruntime/Makefile.in
libphobos/libdruntime/core/internal/abort.d
libphobos/libdruntime/core/internal/array/casting.d
libphobos/libdruntime/core/internal/array/construction.d
libphobos/libdruntime/core/internal/array/duplication.d
libphobos/libdruntime/core/internal/array/utils.d
libphobos/libdruntime/core/internal/gc/bits.d
libphobos/libdruntime/core/internal/gc/blkcache.d
libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
libphobos/libdruntime/core/internal/gc/os.d
libphobos/libdruntime/core/internal/gc/pooltable.d
libphobos/libdruntime/core/internal/parseoptions.d
libphobos/libdruntime/core/internal/qsort.d
libphobos/libdruntime/core/internal/util/array.d
libphobos/libdruntime/core/runtime.d
libphobos/libdruntime/core/stdc/config.d
libphobos/libdruntime/core/sys/windows/bcrypt.d [new file with mode: 0644]
libphobos/libdruntime/core/sys/windows/dll.d
libphobos/libdruntime/core/sys/windows/sdkddkver.d
libphobos/libdruntime/core/sys/windows/threadaux.d
libphobos/libdruntime/core/sys/windows/w32api.d
libphobos/libdruntime/core/sys/windows/winbase.d
libphobos/libdruntime/core/thread/osthread.d
libphobos/libdruntime/gcc/sections/elf.d
libphobos/libdruntime/gcc/sections/package.d
libphobos/libdruntime/rt/adi.d
libphobos/libdruntime/rt/arraycat.d
libphobos/libdruntime/rt/deh.d
libphobos/libdruntime/rt/dmain2.d
libphobos/libdruntime/rt/ehalloc.d
libphobos/libdruntime/rt/lifetime.d
libphobos/libdruntime/rt/minfo.d
libphobos/libdruntime/rt/monitor_.d
libphobos/libdruntime/rt/profilegc.d
libphobos/libdruntime/rt/sections.d
libphobos/libdruntime/rt/tlsgc.d

index 4172630afa08de5c8fbb63f151f71260248bec10..a91f40b6bfce85980b123172edffe39f134f9732 100644 (file)
@@ -1,4 +1,4 @@
-d1157134103a209d36d6ee9c1df1d61d5929ec6d
+b7e3b3b61711bf6c6cad27c7b5b73df0e570c215
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index d7658c68ec255e21719c29b9536bf44c2f9d7952..93b6dc3852e5c8888ab9b492826615c51314c443 100644 (file)
@@ -101,7 +101,7 @@ StorageClass mergeFuncAttrs(StorageClass s1, const FuncDeclaration f) pure @safe
  */
 FuncDeclaration hasIdentityOpAssign(AggregateDeclaration ad, Scope* sc)
 {
-    Dsymbol assign = search_function(ad, Id.assign);
+    Dsymbol assign = search_function(ad, Id.opAssign);
     if (!assign)
         return null;
 
@@ -303,7 +303,7 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc)
     auto fparams = new Parameters();
     fparams.push(new Parameter(loc, STC.nodtor, sd.type, Id.p, null, null));
     auto tf = new TypeFunction(ParameterList(fparams), sd.handleType(), LINK.d, stc | STC.ref_);
-    auto fop = new FuncDeclaration(declLoc, Loc.initial, Id.assign, stc, tf);
+    auto fop = new FuncDeclaration(declLoc, Loc.initial, Id.opAssign, stc, tf);
     fop.storage_class |= STC.inference;
     fop.isGenerated = true;
     Expression e;
@@ -482,7 +482,7 @@ bool needOpEquals(StructDeclaration sd)
 private FuncDeclaration hasIdentityOpEquals(AggregateDeclaration ad, Scope* sc)
 {
     FuncDeclaration f;
-    Dsymbol eq = search_function(ad, Id.eq);
+    Dsymbol eq = search_function(ad, Id.opEquals);
     if (!eq)
         return null;
 
@@ -537,7 +537,7 @@ private FuncDeclaration hasIdentityOpEquals(AggregateDeclaration ad, Scope* sc)
  * opEquals is changed to be never implicitly generated.
  * Now, struct objects comparison s1 == s2 is translated to:
  *      s1.tupleof == s2.tupleof
- * to calculate structural equality. See EqualExp.op_overload.
+ * to calculate structural equality. See `opOverloadEquals`.
  */
 FuncDeclaration buildOpEquals(StructDeclaration sd, Scope* sc)
 {
@@ -564,7 +564,7 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
         return null; // bitwise comparison would work
 
     //printf("StructDeclaration::buildXopEquals() %s\n", sd.toChars());
-    if (Dsymbol eq = search_function(sd, Id.eq))
+    if (Dsymbol eq = search_function(sd, Id.opEquals))
     {
         if (FuncDeclaration fd = eq.isFuncDeclaration())
         {
@@ -639,7 +639,7 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
 FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
 {
     //printf("StructDeclaration::buildXopCmp() %s\n", toChars());
-    if (Dsymbol cmp = search_function(sd, Id.cmp))
+    if (Dsymbol cmp = search_function(sd, Id.opCmp))
     {
         if (FuncDeclaration fd = cmp.isFuncDeclaration())
         {
@@ -667,7 +667,7 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
              * Consider 'alias this', but except opDispatch.
              */
             Expression e = new DsymbolExp(sd.loc, sd);
-            e = new DotIdExp(sd.loc, e, Id.cmp);
+            e = new DotIdExp(sd.loc, e, Id.opCmp);
             Scope* sc2 = sc.push();
             e = e.trySemantic(sc2);
             sc2.pop();
@@ -688,7 +688,7 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
                 default:
                     break;
                 }
-                if (!s || s.ident != Id.cmp)
+                if (!s || s.ident != Id.opCmp)
                     e = null; // there's no valid member 'opCmp'
             }
             if (!e)
@@ -736,7 +736,7 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
     fop.parent = sd;
     Expression e1 = new IdentifierExp(loc, Id.This);
     Expression e2 = new IdentifierExp(loc, Id.p);
-    Expression e = new CallExp(loc, new DotIdExp(loc, e1, Id.cmp), e2);
+    Expression e = new CallExp(loc, new DotIdExp(loc, e1, Id.opCmp), e2);
     fop.fbody = new ReturnStatement(loc, e);
     const errors = global.startGagging(); // Do not report errors
     Scope* sc2 = sc.push();
index a6cfe6e9eafe04e7147e29277f44ac91cc11ca82..6d2a954cb7bab5ba398c1e2990424140d1823716 100644 (file)
@@ -1529,11 +1529,9 @@ Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expres
                                   : tclass.implicitConvTo(to.mutableOf());
         if (match)
             return paint();
-        else
-        {
-            emplaceExp!(NullExp)(pue, loc, to);
-            return pue.exp();
-        }
+
+        emplaceExp!(NullExp)(pue, loc, to);
+        return pue.exp();
     }
 
     // Allow TypeInfo type painting
index 2f33301f0c27687ee7c260974f9d337c5c89a9c0..0d95ad46d380e1e7e5db6eb2d8f95a2ebe9590dd 100644 (file)
@@ -4144,20 +4144,6 @@ Expression typeCombine(BinExp be, Scope* sc)
         return ErrorExp.get();
     }
 
-    Type t1 = be.e1.type.toBasetype();
-    Type t2 = be.e2.type.toBasetype();
-
-    if (be.op == EXP.min || be.op == EXP.add)
-    {
-        // struct+struct, and class+class are errors
-        if (t1.ty == Tstruct && t2.ty == Tstruct)
-            return errorReturn();
-        if (t1.ty == Tclass && t2.ty == Tclass)
-            return errorReturn();
-        if (t1.ty == Taarray && t2.ty == Taarray)
-            return errorReturn();
-    }
-
     if (auto result = typeMerge(sc, be.op, be.e1, be.e2))
     {
         if (be.type is null)
index 0d87f6e26eccdfe801b3aa3dddd2e138fbf1e96b..c7fb26a9da1aa4da8655a5d3b2adc72ed6e685f3 100644 (file)
@@ -3061,7 +3061,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
         if (sd.ctor)
         {
-            Dsymbol scall = sd.search(Loc.initial, Id.call);
+            Dsymbol scall = sd.search(Loc.initial, Id.opCall);
             if (scall)
             {
                 const xerrors = global.startGagging();
index 7f7437cdb1510bb32d4d729ad98580a61e12f5e6..dd9f3dac6b04a41a7bd8becaff0875c095a9e600 100644 (file)
@@ -217,17 +217,12 @@ Dsymbol getDsymbol(RootObject oarg)
             return te.td;
         if (auto te = ea.isScopeExp())
             return te.sds;
-        else
-            return null;
-    }
-    else
-    {
-        // Try to convert Type to symbol
-        if (auto ta = isType(oarg))
-            return ta.toDsymbol(null);
-        else
-            return isDsymbol(oarg); // if already a symbol
+        return null;
     }
+    // Try to convert Type to symbol
+    if (auto ta = isType(oarg))
+        return ta.toDsymbol(null);
+    return isDsymbol(oarg); // if already a symbol
 }
 
 
@@ -5752,8 +5747,8 @@ MATCH matchArg(TemplateParameter tp, Loc instLoc, Scope* sc, Objects* tiargs, si
 
     if (auto ttp = tp.isTemplateTupleParameter())
         return matchArgTuple(ttp);
-    else
-        return matchArgParameter();
+
+    return matchArgParameter();
 }
 
 MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, TemplateParameters* parameters, ref Objects dedtypes, Declaration* psparam)
@@ -6221,8 +6216,8 @@ void printTemplateStats(bool listInstances, ErrorSink eSink)
             auto diff = b.ts.uniqueInstantiations - a.ts.uniqueInstantiations;
             if (diff)
                 return diff;
-            else
-                return b.ts.numInstantiations - a.ts.numInstantiations;
+
+            return b.ts.numInstantiations - a.ts.numInstantiations;
         }
     }
 
index 75d64682aea5455db2e244183ae1b31d4aae68d2..5b8e0107db9fc157bad8a56e30ef2e36113a3b96 100644 (file)
@@ -535,98 +535,6 @@ extern (C++) abstract class Expression : ASTNode
         return false;
     }
 
-    extern (D) final bool checkScalar()
-    {
-        if (op == EXP.error)
-            return true;
-        if (type.toBasetype().ty == Terror)
-            return true;
-        if (!type.isScalar())
-        {
-            error(loc, "`%s` is not a scalar, it is a `%s`", toChars(), type.toChars());
-            return true;
-        }
-        return checkValue();
-    }
-
-    extern (D) final bool checkNoBool()
-    {
-        if (op == EXP.error)
-            return true;
-        if (type.toBasetype().ty == Terror)
-            return true;
-        if (type.toBasetype().ty == Tbool)
-        {
-            error(loc, "operation not allowed on `bool` `%s`", toChars());
-            return true;
-        }
-        return false;
-    }
-
-    extern (D) final bool checkIntegral()
-    {
-        if (op == EXP.error)
-            return true;
-        if (type.toBasetype().ty == Terror)
-            return true;
-        if (!type.isIntegral())
-        {
-            error(loc, "`%s` is not of integral type, it is a `%s`", toChars(), type.toChars());
-            return true;
-        }
-        return checkValue();
-    }
-
-    extern (D) final bool checkArithmetic(EXP op)
-    {
-        if (op == EXP.error)
-            return true;
-        if (type.toBasetype().ty == Terror)
-            return true;
-        if (!type.isIntegral() && !type.isFloating())
-        {
-            // unary aggregate ops error here
-            const char* msg = type.isAggregate() ?
-                "operator `%s` is not defined for `%s` of type `%s`" :
-                "illegal operator `%s` for `%s` of type `%s`";
-            error(loc, msg, EXPtoString(op).ptr, toChars(), type.toChars());
-            return true;
-        }
-        return checkValue();
-    }
-
-    /*******************************
-     * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
-     * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
-     * Returns true if error occurs.
-     */
-    extern (D) final bool checkReadModifyWrite(EXP rmwOp, Expression ex = null)
-    {
-        //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex.toChars() : "");
-        if (!type || !type.isShared() || type.isTypeStruct() || type.isTypeClass())
-            return false;
-
-        // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
-        switch (rmwOp)
-        {
-        case EXP.plusPlus:
-        case EXP.prePlusPlus:
-            rmwOp = EXP.addAssign;
-            break;
-        case EXP.minusMinus:
-        case EXP.preMinusMinus:
-            rmwOp = EXP.minAssign;
-            break;
-        default:
-            break;
-        }
-
-        error(loc, "read-modify-write operations are not allowed for `shared` variables");
-        errorSupplemental(loc, "Use `core.atomic.atomicOp!\"%s\"(%s, %s)` instead",
-                          EXPtoString(rmwOp).ptr, toChars(), ex ? ex.toChars() : "1");
-        return true;
-    }
-
     /******************************
      * Take address of expression.
      */
@@ -3039,8 +2947,6 @@ extern (C++) abstract class BinExp : Expression
 {
     Expression e1;
     Expression e2;
-    Type att1;      // Save alias this type to detect recursion
-    Type att2;      // Save alias this type to detect recursion
 
     extern (D) this(const ref Loc loc, EXP op, Expression e1, Expression e2) scope @safe
     {
@@ -3058,20 +2964,6 @@ extern (C++) abstract class BinExp : Expression
         return e;
     }
 
-    extern (D) final bool checkIntegralBin()
-    {
-        bool r1 = e1.checkIntegral();
-        bool r2 = e2.checkIntegral();
-        return (r1 || r2);
-    }
-
-    extern (D) final bool checkArithmeticBin()
-    {
-        bool r1 = e1.checkArithmetic(this.op);
-        bool r2 = e2.checkArithmetic(this.op);
-        return (r1 || r2);
-    }
-
     /*********************
      * Mark the operands as will never be dereferenced,
      * which is useful info for @safe checks.
index d62aea86d63716fbb7e448ea679e3add668666fd..07b163f1d48178f43128dc5c6b88136b4a11bbaf 100644 (file)
@@ -679,9 +679,6 @@ public:
     Expression *e1;
     Expression *e2;
 
-    Type *att1; // Save alias this type to detect recursion
-    Type *att2; // Save alias this type to detect recursion
-
     BinExp *syntaxCopy() override;
 
     void accept(Visitor *v) override { v->visit(this); }
index eb4a5f884f64f88c65aaa5468fca820829a689dc..fcb47a5398447597edb4d080f6ed54e5d8cabce3 100644 (file)
@@ -663,7 +663,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
     assert(!ae.lengthVar);
     *pe0 = null;
     AggregateDeclaration ad = isAggregate(ae.e1.type);
-    Dsymbol slice = search_function(ad, Id.slice);
+    Dsymbol slice = search_function(ad, Id.opSlice);
     //printf("slice = %s %s\n", slice.kind(), slice.toChars());
     Expression fallback()
     {
@@ -2403,7 +2403,7 @@ private bool checkPostblit(Type t, ref Loc loc, Scope* sc)
 /***************************************
  * Pull out any properties.
  */
-private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null, BinExp saveAtts = null)
+private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null, Type[2]* aliasThisStop = null)
 {
     //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", EXPtoString(e1.op).ptr, e1.toChars(), e2 ? e2.toChars() : null);
     Loc loc = e1.loc;
@@ -2478,11 +2478,9 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
             if (e2)
             {
                 e = new AssignExp(loc, e, e2);
-                if (saveAtts)
-                {
-                    (cast(BinExp)e).att1 = saveAtts.att1;
-                    (cast(BinExp)e).att2 = saveAtts.att2;
-                }
+                if (aliasThisStop)
+                    return e.expressionSemantic(sc, *aliasThisStop);
+                return e.expressionSemantic(sc);
             }
             return e.expressionSemantic(sc);
         }
@@ -2584,11 +2582,8 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
                 if (e2)
                 {
                     e = new AssignExp(loc, e, e2);
-                    if (saveAtts)
-                    {
-                        (cast(BinExp)e).att1 = saveAtts.att1;
-                        (cast(BinExp)e).att2 = saveAtts.att2;
-                    }
+                    if (aliasThisStop)
+                        return e.expressionSemantic(sc, *aliasThisStop);
                 }
                 return e.expressionSemantic(sc);
             }
@@ -3816,6 +3811,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
     Scope* sc;
     Expression result;
 
+    // For binary expressions, stores recursive 'alias this' types of lhs and rhs to prevent endless loops.
+    // See tryAliasThisSemantic
+    Type[2] aliasThisStop;
+
     this(Scope* sc) scope @safe
     {
         this.sc = sc;
@@ -6206,7 +6205,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     return;
                 }
                 // No constructor, look for overload of opCall
-                if (search_function(sd, Id.call))
+                if (search_function(sd, Id.opCall))
                     goto L1;
                 // overload of opCall, therefore it's a call
                 if (exp.e1.op != EXP.type)
@@ -6247,7 +6246,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             {
             L1:
                 // Rewrite as e1.call(arguments)
-                Expression e = new DotIdExp(exp.loc, exp.e1, Id.call);
+                Expression e = new DotIdExp(exp.loc, exp.e1, Id.opCall);
                 e = new CallExp(exp.loc, e, exp.arguments, exp.names);
                 e = e.expressionSemantic(sc);
                 result = e;
@@ -7536,13 +7535,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
     override void visit(BinAssignExp exp)
     {
 
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadBinaryAssign(sc, aliasThisStop))
         {
             result = e;
             return;
         }
 
+        Expression e;
         if (exp.e1.op == EXP.arrayLength)
         {
             // arr.length op= e2;
@@ -7933,7 +7932,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 {
                     const callExpIdent = callExpFunc.ident;
                     isEqualsCallExpression = callExpIdent == Id.__equals ||
-                                             callExpIdent == Id.eq;
+                                             callExpIdent == Id.opEquals;
                 }
             }
             if (op == EXP.equal || op == EXP.notEqual ||
@@ -8777,8 +8776,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             printf("PtrExp::semantic('%s')\n", exp.toChars());
         }
 
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadUnary(sc))
         {
             result = e;
             return;
@@ -8835,8 +8833,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             printf("NegExp::semantic('%s')\n", exp.toChars());
         }
 
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadUnary(sc))
         {
             result = e;
             return;
@@ -8876,8 +8873,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             printf("UAddExp::semantic('%s')\n", exp.toChars());
         }
 
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadUnary(sc))
         {
             result = e;
             return;
@@ -8902,8 +8898,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
     override void visit(ComExp exp)
     {
 
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadUnary(sc))
         {
             result = e;
             return;
@@ -8975,17 +8970,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
     override void visit(DeleteExp exp)
     {
-        // @@@DEPRECATED_2.109@@@
-        // 1. Deprecated since 2.079
-        // 2. Error since 2.099
-        // 3. Removal of keyword, "delete" can be used for other identities
-        if (!exp.isRAII)
-        {
-            error(exp.loc, "the `delete` keyword is obsolete");
-            errorSupplemental(exp.loc, "use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead");
-            return setError();
-        }
-
         Expression e = exp;
 
         if (Expression ex = unaSemantic(exp, sc))
@@ -9176,7 +9160,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (!exp.to.equals(exp.e1.type) && exp.mod == cast(ubyte)~0)
         {
-            if (Expression e = exp.op_overload(sc))
+            if (Expression e = exp.opOverloadCast(sc))
             {
                 result = e.implicitCastTo(sc, exp.to);
                 return;
@@ -9466,8 +9450,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 error(exp.loc, "upper and lower bounds are needed to slice a pointer");
                 if (auto ad = isAggregate(tp.next.toBasetype()))
                 {
-                    auto s = search_function(ad, Id.index);
-                    if (!s) s = search_function(ad, Id.slice);
+                    auto s = search_function(ad, Id.opIndex);
+                    if (!s) s = search_function(ad, Id.opSlice);
                     if (s)
                     {
                         auto fd = s.isFuncDeclaration();
@@ -9710,8 +9694,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (result)
             return;
 
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadArray(sc))
         {
             result = e;
             return;
@@ -10133,13 +10116,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
         exp.e1 = e1x;
 
-        Expression e = exp.op_overload(sc);
-        if (e)
-        {
-            result = e;
-            return;
-        }
-
         if (exp.e1.checkReadModifyWrite(exp.op))
             return setError();
 
@@ -10182,7 +10158,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             // Combine de,ea,eb,ec
             if (de)
                 ea = new CommaExp(exp.loc, de, ea);
-            e = new CommaExp(exp.loc, ea, eb);
+            Expression e = new CommaExp(exp.loc, ea, eb);
             e = new CommaExp(exp.loc, e, ec);
             e = e.expressionSemantic(sc);
             result = e;
@@ -10192,7 +10168,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         exp.e1 = exp.e1.modifiableLvalue(sc);
         exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
 
-        e = exp;
+        Expression e = exp;
         if (exp.e1.checkScalar() ||
             exp.e1.checkSharedAccess(sc))
             return setError();
@@ -10209,15 +10185,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
     override void visit(PreExp exp)
     {
-        Expression e = exp.op_overload(sc);
         // printf("PreExp::semantic('%s')\n", toChars());
-        if (e)
+        if (Expression e = exp.opOverloadUnary(sc))
         {
             result = e;
             return;
         }
 
         // Rewrite as e1+=1 or e1-=1
+        Expression e;
         if (exp.op == EXP.prePlusPlus)
             e = new AddAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
         else
@@ -10328,7 +10304,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 AggregateDeclaration ad = isAggregate(t1b);
                 if (!ad)
                     break;
-                if (search_function(ad, Id.indexass))
+                if (search_function(ad, Id.opIndexAssign))
                 {
                     // Deal with $
                     res = resolveOpDollar(sc, ae, &e0);
@@ -10347,7 +10323,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                      */
                     Expressions* a = ae.arguments.copy();
                     a.insert(0, exp.e2);
-                    res = new DotIdExp(exp.loc, ae.e1, Id.indexass);
+                    res = new DotIdExp(exp.loc, ae.e1, Id.opIndexAssign);
                     res = new CallExp(exp.loc, res, a);
                     if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2)
                         res = res.trySemantic(sc);
@@ -10358,7 +10334,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 }
 
             Lfallback:
-                if (maybeSlice && search_function(ad, Id.sliceass))
+                if (maybeSlice && search_function(ad, Id.opSliceAssign))
                 {
                     // Deal with $
                     res = resolveOpDollar(sc, ae, ie, &e0);
@@ -10381,7 +10357,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                         a.push(ie.lwr);
                         a.push(ie.upr);
                     }
-                    res = new DotIdExp(exp.loc, ae.e1, Id.sliceass);
+                    res = new DotIdExp(exp.loc, ae.e1, Id.opSliceAssign);
                     res = new CallExp(exp.loc, res, a);
                     res = res.expressionSemantic(sc);
                     return setResult(Expression.combine(e0, res));
@@ -10471,7 +10447,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
              * or:
              *      f() = value
              */
-            if (Expression e = resolvePropertiesX(sc, e1x, exp.e2, exp))
+            if (Expression e = resolvePropertiesX(sc, e1x, exp.e2, &aliasThisStop))
                 return setResult(e);
 
             if (e1x.checkRightThis(sc))
@@ -10604,6 +10580,35 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if (exp.op == EXP.assign
             && exp.e1.checkModifiable(sc) == Modifiable.initialization)
         {
+            // Check common mistake of misspelled parameters in constructors,
+            // e.g. `this(int feild) { this.field = field; }`
+            if (auto dve1 = exp.e1.isDotVarExp)
+                if (auto dve2 = exp.e2.isDotVarExp)
+                    if (sc.func && sc.func.parameters && dve1.e1.isThisExp && dve2.e1.isThisExp()
+                        && dve1.var.ident.equals(dve2.var.ident))
+                    {
+                        // @@@DEPRECATED_2.121@@@
+                        // Deprecated in 2.111, make it an error in 2.121
+                        deprecation(exp.e1.loc, "cannot initialize field `%s` with itself", dve1.var.toChars());
+                        auto findParameter(const(char)[] s, ref int cost)
+                        {
+                            foreach (p; *sc.func.parameters)
+                            {
+                                if (p.ident.toString == s)
+                                {
+                                    cost = 1;
+                                    return p.ident.toString;
+                                }
+                            }
+                            return null;
+                        }
+                        import dmd.root.speller : speller;
+                        if (auto s = speller!findParameter(dve1.var.ident.toString))
+                        {
+                            deprecationSupplemental(sc.func.loc, "did you mean to use parameter `%.*s`?\n", s.fTuple.expand);
+                        }
+                    }
+
             //printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars());
             auto t = exp.type;
             exp = new ConstructExp(exp.loc, exp.e1, exp.e2);
@@ -10826,13 +10831,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     if (!e2x.implicitConvTo(t1))
                     {
                         AggregateDeclaration ad2 = isAggregate(e2x.type);
-                        if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type))
+                        if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(aliasThisStop[1], exp.e2.type))
                         {
                             /* Rewrite (e1 op e2) as:
                              *      (e1 op e2.aliasthis)
                              */
                             exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
-                            result = exp.expressionSemantic(sc);
+                            result = exp.expressionSemantic(sc, aliasThisStop);
                             return;
                         }
                     }
@@ -10887,14 +10892,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                         result = e;
                         return;
                     }
-                    if (search_function(sd, Id.call))
+                    if (search_function(sd, Id.opCall))
                     {
                         /* Look for static opCall
                          * https://issues.dlang.org/show_bug.cgi?id=2702
                          * Rewrite as:
                          *  e1 = typeof(e1).opCall(arguments)
                          */
-                        e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call);
+                        e2x = typeDotIdExp(e2x.loc, e1x.type, Id.opCall);
                         e2x = new CallExp(exp.loc, e2x, exp.e2);
 
                         e2x = e2x.expressionSemantic(sc);
@@ -10911,13 +10916,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 else // https://issues.dlang.org/show_bug.cgi?id=11355
                 {
                     AggregateDeclaration ad2 = isAggregate(e2x.type);
-                    if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type))
+                    if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(aliasThisStop[1], exp.e2.type))
                     {
                         /* Rewrite (e1 op e2) as:
                          *      (e1 op e2.aliasthis)
                          */
                         exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
-                        result = exp.expressionSemantic(sc);
+                        result = exp.expressionSemantic(sc, aliasThisStop);
                         return;
                     }
                 }
@@ -10958,8 +10963,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     ae.e1 = ae.e1.expressionSemantic(sc);
                     ae.e1 = ae.e1.optimize(WANTvalue);
                     ae.e2 = ev;
-                    Expression e = ae.op_overload(sc);
-                    if (e)
+                    if (Expression e = ae.opOverloadAssign(sc, aliasThisStop))
                     {
                         Expression ey = null;
                         if (t2.ty == Tstruct && sd == t2.toDsymbol(sc))
@@ -11009,14 +11013,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                         return;
                     }
                 }
-                else
+                else if (Expression e = exp.isAssignExp().opOverloadAssign(sc, aliasThisStop))
                 {
-                    Expression e = exp.op_overload(sc);
-                    if (e)
-                    {
-                        result = e;
-                        return;
-                    }
+                    result = e;
+                    return;
                 }
             }
             else
@@ -11033,8 +11033,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             // Disallow assignment operator overloads for same type
             if (exp.op == EXP.assign && !exp.e2.implicitConvTo(exp.e1.type))
             {
-                Expression e = exp.op_overload(sc);
-                if (e)
+                if (Expression e = exp.isAssignExp().opOverloadAssign(sc, aliasThisStop))
                 {
                     result = e;
                     return;
@@ -11410,7 +11409,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 if (e2x.op == EXP.error && exp.op == EXP.construct && t1.ty == Tstruct)
                 {
                     scope sd = (cast(TypeStruct)t1).sym;
-                    Dsymbol opAssign = search_function(sd, Id.assign);
+                    Dsymbol opAssign = search_function(sd, Id.opAssign);
 
                     // and the struct defines an opAssign
                     if (opAssign)
@@ -11705,9 +11704,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
     override void visit(PowAssignExp exp)
     {
-
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadBinaryAssign(sc, aliasThisStop))
         {
             result = e;
             return;
@@ -11754,7 +11751,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         if ((exp.e1.type.isIntegral() || exp.e1.type.isFloating()) && (exp.e2.type.isIntegral() || exp.e2.type.isFloating()))
         {
             Expression e0 = null;
-            e = exp.reorderSettingAAElem(sc);
+            Expression e = exp.reorderSettingAAElem(sc);
             e = Expression.extractLast(e, e0);
             assert(e == exp);
 
@@ -11786,8 +11783,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
     {
 
         //printf("CatAssignExp::semantic() %s\n", exp.toChars());
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadBinaryAssign(sc, aliasThisStop))
         {
             result = e;
             return;
@@ -11881,49 +11877,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
         else
         {
-            // Try alias this on first operand
-            static Expression tryAliasThisForLhs(BinAssignExp exp, Scope* sc)
-            {
-                AggregateDeclaration ad1 = isAggregate(exp.e1.type);
-                if (!ad1 || !ad1.aliasthis)
-                    return null;
-
-                /* Rewrite (e1 op e2) as:
-                 *      (e1.aliasthis op e2)
-                 */
-                if (isRecursiveAliasThis(exp.att1, exp.e1.type))
-                    return null;
-                //printf("att %s e1 = %s\n", Token.toChars(e.op), e.e1.type.toChars());
-                Expression e1 = new DotIdExp(exp.loc, exp.e1, ad1.aliasthis.ident);
-                BinExp be = cast(BinExp)exp.copy();
-                be.e1 = e1;
-                return be.trySemantic(sc);
-            }
-
-            // Try alias this on second operand
-            static Expression tryAliasThisForRhs(BinAssignExp exp, Scope* sc)
-            {
-                AggregateDeclaration ad2 = isAggregate(exp.e2.type);
-                if (!ad2 || !ad2.aliasthis)
-                    return null;
-                /* Rewrite (e1 op e2) as:
-                 *      (e1 op e2.aliasthis)
-                 */
-                if (isRecursiveAliasThis(exp.att2, exp.e2.type))
-                    return null;
-                //printf("att %s e2 = %s\n", Token.toChars(e.op), e.e2.type.toChars());
-                Expression e2 = new DotIdExp(exp.loc, exp.e2, ad2.aliasthis.ident);
-                BinExp be = cast(BinExp)exp.copy();
-                be.e2 = e2;
-                return be.trySemantic(sc);
-            }
-
     Laliasthis:
-            result = tryAliasThisForLhs(exp, sc);
+            result = checkAliasThisForLhs(isAggregate(exp.e1.type), sc, exp, aliasThisStop);
             if (result)
                 return;
 
-            result = tryAliasThisForRhs(exp, sc);
+            result = checkAliasThisForRhs(isAggregate(exp.e2.type), sc, exp, aliasThisStop);
             if (result)
                 return;
 
@@ -12076,13 +12035,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             printf("AddExp::semantic('%s')\n", exp.toChars());
         }
 
-        if (Expression ex = binSemanticProp(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadBinary(sc, aliasThisStop))
         {
             result = e;
             return;
@@ -12139,6 +12092,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
+        if (exp.checkArithmeticBin())
+            return setError();
+
         tb1 = exp.e1.type.toBasetype();
         if (!target.isVectorOpSupported(tb1, exp.op, tb2))
         {
@@ -12178,13 +12134,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             printf("MinExp::semantic('%s')\n", exp.toChars());
         }
 
-        if (Expression ex = binSemanticProp(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadBinary(sc, aliasThisStop))
         {
             result = e;
             return;
@@ -12217,6 +12167,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (t1.ty == Tpointer)
         {
+            Expression e;
             if (t2.ty == Tpointer)
             {
                 // https://dlang.org/spec/expression.html#add_expressions
@@ -12294,6 +12245,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
+        if (exp.checkArithmeticBin())
+            return setError();
+
         t1 = exp.e1.type.toBasetype();
         t2 = exp.e2.type.toBasetype();
         if (!target.isVectorOpSupported(t1, exp.op, t2))
@@ -12422,14 +12376,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
     {
         // https://dlang.org/spec/expression.html#cat_expressions
         //printf("CatExp.semantic() %s\n", toChars());
-
-        if (Expression ex = binSemanticProp(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadBinary(sc, aliasThisStop))
         {
             result = e;
             return;
@@ -12581,6 +12528,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
         Type t1 = exp.e1.type.toBasetype();
         Type t2 = exp.e2.type.toBasetype();
+        Expression e;
         if ((t1.ty == Tarray || t1.ty == Tsarray) &&
             (t2.ty == Tarray || t2.ty == Tsarray))
         {
@@ -12598,30 +12546,25 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         trySetCatExpLowering(result);
     }
 
-    override void visit(MulExp exp)
+    bool commonBinOpSemantic(BinExp exp)
     {
-        version (none)
-        {
-            printf("MulExp::semantic() %s\n", exp.toChars());
-        }
-
-        if (Expression ex = binSemanticProp(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadBinary(sc, aliasThisStop))
         {
             result = e;
-            return;
+            return true;
         }
 
         if (Expression ex = typeCombine(exp, sc))
         {
             result = ex;
-            return;
+            return true;
         }
+        return false;
+    }
+    bool commonArithBinOpSemantic(BinExp exp)
+    {
+        if (commonBinOpSemantic(exp))
+            return true;
 
         Type tb = exp.type.toBasetype();
         if (tb.ty == Tarray || tb.ty == Tsarray)
@@ -12629,15 +12572,28 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             if (!isArrayOpValid(exp))
             {
                 result = arrayOpInvalidError(exp);
-                return;
+                return true;
             }
             result = exp;
-            return;
+            return true;
         }
 
         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
-            return setError();
+        {
+            setError();
+            return true;
+        }
+        return false;
+    }
+    override void visit(MulExp exp)
+    {
+        version (none)
+        {
+            printf("MulExp::semantic() %s\n", exp.toChars());
+        }
 
+        if (commonArithBinOpSemantic(exp))
+            return;
         if (exp.type.isFloating())
         {
             Type t1 = exp.e1.type;
@@ -12676,7 +12632,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                     // iy * iv = -yv
                     exp.e1.type = exp.type;
                     exp.e2.type = exp.type;
-                    e = new NegExp(exp.loc, exp);
+                    Expression e = new NegExp(exp.loc, exp);
                     e = e.expressionSemantic(sc);
                     result = e;
                     return;
@@ -12689,7 +12645,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 exp.type = t1; // t1 is complex
             }
         }
-        else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
+        else if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
         {
             result = exp.incompatibleTypes();
             return;
@@ -12699,39 +12655,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
     override void visit(DivExp exp)
     {
-
-        if (Expression ex = binSemanticProp(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-        Expression e = exp.op_overload(sc);
-        if (e)
-        {
-            result = e;
-            return;
-        }
-
-        if (Expression ex = typeCombine(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-
-        Type tb = exp.type.toBasetype();
-        if (tb.ty == Tarray || tb.ty == Tsarray)
-        {
-            if (!isArrayOpValid(exp))
-            {
-                result = arrayOpInvalidError(exp);
-                return;
-            }
-            result = exp;
+        if (commonArithBinOpSemantic(exp))
             return;
-        }
-
-        if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
-            return setError();
 
         if (exp.type.isFloating())
         {
@@ -12745,7 +12670,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 {
                     // x/iv = i(-x/v)
                     exp.e2.type = t1;
-                    e = new NegExp(exp.loc, exp);
+                    Expression e = new NegExp(exp.loc, exp);
                     e = e.expressionSemantic(sc);
                     result = e;
                     return;
@@ -12785,7 +12710,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 exp.type = t1; // t1 is complex
             }
         }
-        else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
+        else if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
         {
             result = exp.incompatibleTypes();
             return;
@@ -12795,45 +12720,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
     override void visit(ModExp exp)
     {
-
-        if (Expression ex = binSemanticProp(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-        Expression e = exp.op_overload(sc);
-        if (e)
-        {
-            result = e;
+        if (commonArithBinOpSemantic(exp))
             return;
-        }
 
-        if (Expression ex = typeCombine(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-
-        Type tb = exp.type.toBasetype();
-        if (tb.ty == Tarray || tb.ty == Tsarray)
-        {
-            if (!isArrayOpValid(exp))
-            {
-                result = arrayOpInvalidError(exp);
-                return;
-            }
-            result = exp;
-            return;
-        }
-        if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
+        if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
         {
             result = exp.incompatibleTypes();
             return;
         }
 
-        if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
-            return setError();
-
         if (exp.type.isFloating())
         {
             exp.type = exp.e1.type;
@@ -12848,49 +12743,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
     override void visit(PowExp exp)
     {
-
-        //printf("PowExp::semantic() %s\n", toChars());
-        if (Expression ex = binSemanticProp(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-        Expression e = exp.op_overload(sc);
-        if (e)
-        {
-            result = e;
+        if (commonArithBinOpSemantic(exp))
             return;
-        }
-
-        if (Expression ex = typeCombine(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-
-        Type tb = exp.type.toBasetype();
-        if (tb.ty == Tarray || tb.ty == Tsarray)
-        {
-            if (!isArrayOpValid(exp))
-            {
-                result = arrayOpInvalidError(exp);
-                return;
-            }
-            result = exp;
-            return;
-        }
-
-        if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
-            return setError();
 
-        if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
+        if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
         {
             result = exp.incompatibleTypes();
             return;
         }
 
         // First, attempt to fold the expression.
-        e = exp.optimize(WANTvalue);
+        Expression e = exp.optimize(WANTvalue);
         if (e.op != EXP.pow)
         {
             e = e.expressionSemantic(sc);
@@ -12923,14 +12786,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
     private void visitShift(BinExp exp)
     {
-
-        if (Expression ex = binSemanticProp(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadBinary(sc, aliasThisStop))
         {
             result = e;
             return;
@@ -12971,14 +12827,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
     private void visitBinaryBitOp(BinExp exp)
     {
-
-        if (Expression ex = binSemanticProp(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadBinary(sc, aliasThisStop))
         {
             result = e;
             return;
@@ -13136,57 +12985,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return setError();
         }
 
-
-        EXP cmpop = exp.op;
-        if (auto e = exp.op_overload(sc, &cmpop))
+        if (auto e = exp.opOverloadCmp(sc, aliasThisStop))
         {
-            if (!e.type.isScalar() && e.type.equals(exp.e1.type))
-            {
-                error(exp.loc, "recursive `opCmp` expansion");
-                return setError();
-            }
-            if (e.op == EXP.call)
-            {
-
-                if (t1.ty == Tclass && t2.ty == Tclass)
-                {
-                    // Lower to object.__cmp(e1, e2)
-                    Expression cl = new IdentifierExp(exp.loc, Id.empty);
-                    cl = new DotIdExp(exp.loc, cl, Id.object);
-                    cl = new DotIdExp(exp.loc, cl, Id.__cmp);
-                    cl = cl.expressionSemantic(sc);
-
-                    auto arguments = new Expressions();
-                    // Check if op_overload found a better match by calling e2.opCmp(e1)
-                    // If the operands were swapped, then the result must be reversed
-                    // e1.opCmp(e2) == -e2.opCmp(e1)
-                    // cmpop takes care of this
-                    if (exp.op == cmpop)
-                    {
-                        arguments.push(exp.e1);
-                        arguments.push(exp.e2);
-                    }
-                    else
-                    {
-                        // Use better match found by op_overload
-                        arguments.push(exp.e2);
-                        arguments.push(exp.e1);
-                    }
-
-                    cl = new CallExp(exp.loc, cl, arguments);
-                    cl = new CmpExp(cmpop, exp.loc, cl, new IntegerExp(0));
-                    result = cl.expressionSemantic(sc);
-                    return;
-                }
-
-                e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0);
-                e = e.expressionSemantic(sc);
-            }
             result = e;
             return;
         }
 
-
         if (Expression ex = typeCombine(exp, sc))
         {
             result = ex;
@@ -13284,14 +13088,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
     override void visit(InExp exp)
     {
-
-        if (Expression ex = binSemanticProp(exp, sc))
-        {
-            result = ex;
-            return;
-        }
-        Expression e = exp.op_overload(sc);
-        if (e)
+        if (Expression e = exp.opOverloadBinary(sc, aliasThisStop))
         {
             result = e;
             return;
@@ -13455,13 +13252,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return false;
         }
 
-        if (auto e = exp.op_overload(sc))
+        if (auto e = exp.opOverloadEqual(sc, aliasThisStop))
         {
             result = e;
             return;
         }
 
-
         const isArrayComparison = (t1.ty == Tarray || t1.ty == Tsarray) &&
                                   (t2.ty == Tarray || t2.ty == Tsarray);
         const needsArrayLowering = isArrayComparison && needsDirectEq(t1, t2, sc);
@@ -13931,6 +13727,32 @@ Expression trySemantic(Expression exp, Scope* sc)
     return e;
 }
 
+/**********************************
+ * Try expression semantic on `exp`, gagging semantic errors,
+ * but don't resolve alias this on a BinExp when the lhs or rhs
+ * has the corresponding type in `aliasThisStop` (See `isRecursiveAliasThis`).
+ *
+ * Params:
+ *   exp = expression to try semantic on
+ *   sc = scope
+ *   aliasThisStop = pair of recursive alias this types to stop endless recursion
+ * Returns:
+ *    exp after expression semantic, or `null` on error
+ */
+Expression trySemanticAliasThis(Expression exp, Scope* sc, Type[2] aliasThisStop)
+{
+    if (exp.expressionSemanticDone)
+        return exp;
+
+    const errors = global.startGagging();
+    Expression e = expressionSemantic(exp, sc, aliasThisStop);
+
+    if (global.endGagging(errors))
+        return null;
+
+    return e;
+}
+
 /**************************
  * Helper function for easy error propagation.
  * If error occurs, returns ErrorExp. Otherwise returns NULL.
@@ -14015,6 +13837,18 @@ Expression expressionSemantic(Expression e, Scope* sc)
     return v.result;
 }
 
+// ditto, but passes alias this stop types, see trySemanticAliasThis
+private Expression expressionSemantic(Expression e, Scope* sc, Type[2] aliasThisStop)
+{
+    if (e.expressionSemanticDone)
+        return e;
+
+    scope v = new ExpressionSemanticVisitor(sc);
+    v.aliasThisStop = aliasThisStop;
+    e.accept(v);
+    return v.result;
+}
+
 private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc)
 {
     //printf("dotIdSemanticPropX() %s\n", toChars(exp));
@@ -14849,6 +14683,105 @@ MATCH matchType(FuncExp funcExp, Type to, Scope* sc, FuncExp* presult, ErrorSink
     return m;
 }
 
+private bool checkScalar(Expression e)
+{
+    if (e.op == EXP.error)
+        return true;
+    if (e.type.toBasetype().ty == Terror)
+        return true;
+    if (!e.type.isScalar())
+    {
+        error(e.loc, "`%s` is not a scalar, it is a `%s`", e.toChars(), e.type.toChars());
+        return true;
+    }
+    return e.checkValue();
+}
+
+private bool checkNoBool(Expression e)
+{
+    if (e.op == EXP.error)
+        return true;
+    if (e.type.toBasetype().ty == Terror)
+        return true;
+    if (e.type.toBasetype().ty == Tbool)
+    {
+        error(e.loc, "operation not allowed on `bool` `%s`", e.toChars());
+        return true;
+    }
+    return false;
+}
+
+private bool checkIntegral(Expression e)
+{
+    if (e.op == EXP.error)
+        return true;
+    if (e.type.toBasetype().ty == Terror)
+        return true;
+    if (!e.type.isIntegral())
+    {
+        error(e.loc, "`%s` is not of integral type, it is a `%s`", e.toChars(), e.type.toChars());
+        return true;
+    }
+    return e.checkValue();
+}
+
+private bool checkArithmetic(Expression e, EXP op)
+{
+    if (op == EXP.error)
+        return true;
+    if (e.type.toBasetype().ty == Terror)
+        return true;
+    if (!e.type.isIntegral() && !e.type.isFloating())
+    {
+        // unary aggregate ops error here
+        const char* msg = e.type.isAggregate() ?
+            "operator `%s` is not defined for `%s` of type `%s`" :
+            "illegal operator `%s` for `%s` of type `%s`";
+        error(e.loc, msg, EXPtoString(op).ptr, e.toChars(), e.type.toChars());
+        return true;
+    }
+
+    // FIXME: Existing code relies on adding / subtracting types in typeof() expressions:
+    // alias I = ulong; alias U = typeof(I + 1u);
+    // https://github.com/dlang/dmd/issues/20763
+    if (op == EXP.add || op == EXP.min)
+        return false;
+
+    return e.checkValue();
+}
+
+/*******************************
+ * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
+ * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
+ * Returns true if error occurs.
+ */
+private bool checkReadModifyWrite(Expression e, EXP rmwOp, Expression ex = null)
+{
+    //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex.toChars() : "");
+    if (!e.type || !e.type.isShared() || e.type.isTypeStruct() || e.type.isTypeClass())
+        return false;
+
+    // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
+    switch (rmwOp)
+    {
+    case EXP.plusPlus:
+    case EXP.prePlusPlus:
+        rmwOp = EXP.addAssign;
+        break;
+    case EXP.minusMinus:
+    case EXP.preMinusMinus:
+        rmwOp = EXP.minAssign;
+        break;
+    default:
+        break;
+    }
+
+    error(e.loc, "read-modify-write operations are not allowed for `shared` variables");
+    errorSupplemental(e.loc, "Use `core.atomic.atomicOp!\"%s\"(%s, %s)` instead",
+                        EXPtoString(rmwOp).ptr, e.toChars(), ex ? ex.toChars() : "1");
+    return true;
+}
+
 private bool checkSharedAccessBin(BinExp binExp, Scope* sc)
 {
     const r1 = binExp.e1.checkSharedAccess(sc);
@@ -14856,6 +14789,18 @@ private bool checkSharedAccessBin(BinExp binExp, Scope* sc)
     return (r1 || r2);
 }
 
+private bool checkIntegralBin(BinExp e)
+{
+    bool r1 = e.e1.checkIntegral();
+    bool r2 = e.e2.checkIntegral();
+    return (r1 || r2);
+}
+
+private bool checkArithmeticBin(BinExp e)
+{
+    return (e.e1.checkArithmetic(e.op) || e.e2.checkArithmetic(e.op));
+}
+
 /***************************************
  * If expression is shared, check that we can access it.
  * Give error message if not.
@@ -16451,7 +16396,7 @@ Expression toBoolean(Expression exp, Scope* sc)
                     /* Don't really need to check for opCast first, but by doing so we
                      * get better error messages if it isn't there.
                      */
-                    if (Dsymbol fd = search_function(ad, Id._cast))
+                    if (Dsymbol fd = search_function(ad, Id.opCast))
                     {
                         e = new CastExp(exp.loc, e, Type.tbool);
                         e = e.expressionSemantic(sc);
index 993bce85ee6c49b4b7b71faf5b76e895fc0466c7..70f4c8303a76525b277d60061d373c0c2ba30ce4 100644 (file)
@@ -581,8 +581,7 @@ extern (C++) class FuncDeclaration : Declaration
     {
         if (isMain())
             return "D main";
-        else
-            return Dsymbol.toPrettyChars(QualifyTypes);
+        return Dsymbol.toPrettyChars(QualifyTypes);
     }
 
     /** for diagnostics, e.g. 'int foo(int x, int y) pure' */
index d391bdb581ac57f5a36e28f70afdc1ad1995f6dd..961a0d2c11de4bce2b4206ac1f9c5bdd5f8cabbb 100644 (file)
@@ -2435,7 +2435,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
     void visitSymOff(SymOffExp e)
     {
         if (e.offset)
-            buf.printf("(& %s%+lld)", e.var.toChars(), e.offset);
+            buf.printf("(& %s + %llu)", e.var.toChars(), e.offset);
         else if (e.var.isTypeInfoDeclaration())
             buf.writestring(e.var.toChars());
         else
index ee4214a4c123498935e5643f4381118a10f17941..9833e1980ed98c2042a099b1754ae3feec587c5e 100644 (file)
@@ -223,60 +223,15 @@ immutable Msgtable[] msgtable =
     { "__LOCAL_SIZE" },
 
     // For operator overloads
-    { "uadd",    "opPos" },
-    { "neg",     "opNeg" },
-    { "com",     "opCom" },
-    { "add",     "opAdd" },
-    { "add_r",   "opAdd_r" },
-    { "sub",     "opSub" },
-    { "sub_r",   "opSub_r" },
-    { "mul",     "opMul" },
-    { "mul_r",   "opMul_r" },
-    { "div",     "opDiv" },
-    { "div_r",   "opDiv_r" },
-    { "mod",     "opMod" },
-    { "mod_r",   "opMod_r" },
-    { "eq",      "opEquals" },
-    { "cmp",     "opCmp" },
-    { "iand",    "opAnd" },
-    { "iand_r",  "opAnd_r" },
-    { "ior",     "opOr" },
-    { "ior_r",   "opOr_r" },
-    { "ixor",    "opXor" },
-    { "ixor_r",  "opXor_r" },
-    { "shl",     "opShl" },
-    { "shl_r",   "opShl_r" },
-    { "shr",     "opShr" },
-    { "shr_r",   "opShr_r" },
-    { "ushr",    "opUShr" },
-    { "ushr_r",  "opUShr_r" },
-    { "cat",     "opCat" },
-    { "cat_r",   "opCat_r" },
-    { "assign",  "opAssign" },
-    { "addass",  "opAddAssign" },
-    { "subass",  "opSubAssign" },
-    { "mulass",  "opMulAssign" },
-    { "divass",  "opDivAssign" },
-    { "modass",  "opModAssign" },
-    { "andass",  "opAndAssign" },
-    { "orass",   "opOrAssign" },
-    { "xorass",  "opXorAssign" },
-    { "shlass",  "opShlAssign" },
-    { "shrass",  "opShrAssign" },
-    { "ushrass", "opUShrAssign" },
-    { "catass",  "opCatAssign" },
-    { "postinc", "opPostInc" },
-    { "postdec", "opPostDec" },
-    { "index",   "opIndex" },
-    { "indexass", "opIndexAssign" },
-    { "slice",   "opSlice" },
-    { "sliceass", "opSliceAssign" },
-    { "call",    "opCall" },
-    { "_cast",    "opCast" },
-    { "opIn" },
-    { "opIn_r" },
-    { "opStar" },
-    { "opDot" },
+    { "opEquals" },
+    { "opCmp" },
+    { "opAssign" },
+    { "opIndex" },
+    { "opIndexAssign" },
+    { "opSlice" },
+    { "opSliceAssign" },
+    { "opCall" },
+    { "opCast" },
     { "opDispatch" },
     { "opDollar" },
     { "opUnary" },
@@ -287,9 +242,6 @@ immutable Msgtable[] msgtable =
     { "opOpAssign" },
     { "opIndexOpAssign" },
     { "opSliceOpAssign" },
-    { "pow", "opPow" },
-    { "pow_r", "opPow_r" },
-    { "powass", "opPowAssign" },
 
     { "classNew", "new" },
     { "classDelete", "delete" },
index aec68071ccdcfd23f3a9185bbb488a126f9f9052..c181d53e40720960e784d48bd9e7de4f1b260b6e 100644 (file)
@@ -489,7 +489,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
                 else
                     i.exp = e.optimize(WANTvalue);
             }
-            else if (search_function(sd, Id.call))
+            else if (search_function(sd, Id.opCall))
             {
                 /* https://issues.dlang.org/show_bug.cgi?id=1547
                  *
@@ -499,7 +499,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
                  *  i.exp = typeof(sd).opCall(arguments)
                  */
 
-                Expression e = typeDotIdExp(i.loc, sd.type, Id.call);
+                Expression e = typeDotIdExp(i.loc, sd.type, Id.opCall);
                 e = new CallExp(i.loc, e, i.exp);
                 e = e.expressionSemantic(sc);
                 e = resolveProperties(sc, e);
index 67c9b53f1b6329ebe72b2f0a1dc302123ff07173..4932b01610a533b51f0de5ff9e4914738c1125a9 100644 (file)
@@ -60,11 +60,11 @@ package CppOperator isCppOperator(const scope Identifier id)
 {
     with (Id) with (CppOperator)
     {
-        return (id == _cast)      ? Cast     :
-               (id == assign)     ? Assign   :
-               (id == eq)         ? Eq       :
-               (id == index)      ? Index    :
-               (id == call)       ? Call     :
+        return (id == opCast)     ? Cast     :
+               (id == opAssign)   ? Assign   :
+               (id == opEquals)   ? Eq       :
+               (id == opIndex)    ? Index    :
+               (id == opCall)     ? Call     :
                (id == opUnary)    ? Unary    :
                (id == opBinary)   ? Binary   :
                (id == opOpAssign) ? OpAssign :
@@ -435,10 +435,10 @@ private final class CppMangleVisitor : Visitor
         // 4. null pointer: std::nullptr_t (since C++11)
         if (t.ty == Tvoid || t.ty == Tbool)
             return true;
-        else if (t.ty == Tnull && global.params.cplusplus >= CppStdRevision.cpp11)
+        if (t.ty == Tnull && global.params.cplusplus >= CppStdRevision.cpp11)
             return true;
-        else
-            return t.isTypeBasic() && (t.isIntegral() || t.isReal());
+
+        return t.isTypeBasic() && (t.isIntegral() || t.isReal());
     }
 
     /******************************
@@ -1102,13 +1102,13 @@ private final class CppMangleVisitor : Visitor
                 buf.writestring(ctor.isCpCtor ? "C2" : "C1");
             else if (d.isAggregateDtor())
                 buf.writestring("D1");
-            else if (d.ident && d.ident == Id.assign)
+            else if (d.ident && d.ident == Id.opAssign)
                 buf.writestring("aS");
-            else if (d.ident && d.ident == Id.eq)
+            else if (d.ident && d.ident == Id.opEquals)
                 buf.writestring("eq");
-            else if (d.ident && d.ident == Id.index)
+            else if (d.ident && d.ident == Id.opIndex)
                 buf.writestring("ix");
-            else if (d.ident && d.ident == Id.call)
+            else if (d.ident && d.ident == Id.opCall)
                 buf.writestring("cl");
             else
                 source_name(d, true);
@@ -1939,21 +1939,21 @@ extern(C++):
         //printf("enum id = '%s'\n", id.toChars());
         if (id == Id.__c_long)
             return writeBasicType(t, 0, 'l');
-        else if (id == Id.__c_ulong)
+        if (id == Id.__c_ulong)
             return writeBasicType(t, 0, 'm');
-        else if (id == Id.__c_char)
+        if (id == Id.__c_char)
             return writeBasicType(t, 0, 'c');
-        else if (id == Id.__c_wchar_t)
+        if (id == Id.__c_wchar_t)
             return writeBasicType(t, 0, 'w');
-        else if (id == Id.__c_longlong)
+        if (id == Id.__c_longlong)
             return writeBasicType(t, 0, 'x');
-        else if (id == Id.__c_ulonglong)
+        if (id == Id.__c_ulonglong)
             return writeBasicType(t, 0, 'y');
-        else if (id == Id.__c_complex_float)
+        if (id == Id.__c_complex_float)
             return Type.tcomplex32.accept(this);
-        else if (id == Id.__c_complex_double)
+        if (id == Id.__c_complex_double)
             return Type.tcomplex64.accept(this);
-        else if (id == Id.__c_complex_real)
+        if (id == Id.__c_complex_real)
             return Type.tcomplex80.accept(this);
 
         doSymbol(t);
@@ -2362,8 +2362,7 @@ private bool isNamespaceEqual (CPPNamespaceDeclaration a, Nspace b, size_t idx =
     // We need to see if there's more ident enclosing
     if (auto pb = b.toParent().isNspace())
         return isNamespaceEqual(a.cppnamespace, pb);
-    else
-        return a.cppnamespace is null;
+    return a.cppnamespace is null;
 }
 
 /// Returns:
index f91687b7f39f139b90e6390a74b7cf508b741c25..b270943403213f594e7d6eea69f6098c56647d98 100644 (file)
@@ -1295,17 +1295,15 @@ extern (C++) abstract class Type : ASTNode
             {
                 if (t.isWildConst())
                     return MODFlags.wild;
-                else
-                    return MODFlags.wildconst;
+                return MODFlags.wildconst;
             }
-            else if (isWild())
+            if (isWild())
                 return MODFlags.wild;
-            else if (isConst())
+            if (isConst())
                 return MODFlags.const_;
-            else if (isMutable())
+            if (isMutable())
                 return MODFlags.mutable;
-            else
-                assert(0);
+            assert(0);
         }
         return 0;
     }
index fc7618bfc0ed9378686383ba90bbe51f5447ad1f..4fc117e7e2b12080254970f72da1d82812222c99 100644 (file)
@@ -111,26 +111,13 @@ private bool isAssignmentOpId(Identifier id)
 {
     import dmd.id : Id;
 
-    return id == Id.assign
-        || id == Id.addass
-        || id == Id.subass
-        || id == Id.mulass
-        || id == Id.divass
-        || id == Id.modass
-        || id == Id.andass
-        || id == Id.orass
-        || id == Id.xorass
-        || id == Id.shlass
-        || id == Id.shrass
-        || id == Id.ushrass
-        || id == Id.catass
-        || id == Id.indexass
-        || id == Id.slice
-        || id == Id.sliceass
+    return id == Id.opAssign
+        || id == Id.opIndexAssign
+        || id == Id.opSlice
+        || id == Id.opSliceAssign
         || id == Id.opOpAssign
         || id == Id.opIndexOpAssign
-        || id == Id.opSliceOpAssign
-        || id == Id.powass;
+        || id == Id.opSliceOpAssign;
 }
 
 /**
index c5ee77ae791e53a282dad3919da988240e8e47e0..b6719867581cb80daca14600eba52ee8a7ced9f0 100644 (file)
@@ -714,8 +714,8 @@ extern(C++) private final class Supported : Objc
     {
         if (cd.classKind == ClassKind.objc && fd.isStatic && !cd.objc.isMeta)
             return cd.objc.metaclass;
-        else
-            return cd;
+
+        return cd;
     }
 
     override void addToClassMethodList(FuncDeclaration fd, ClassDeclaration cd) const
@@ -805,11 +805,10 @@ extern(C++) private final class Supported : Objc
         {
             if (classDeclaration.baseClass)
                 return getRuntimeMetaclass(classDeclaration.baseClass);
-            else
-                return classDeclaration;
+
+            return classDeclaration;
         }
-        else
-            return classDeclaration.objc.metaclass;
+        return classDeclaration.objc.metaclass;
     }
 
     override void addSymbols(AttribDeclaration attribDeclaration,
index 56b36010be59967acb26d37bfb2921be7136e2cf..92f3bb2ebd322c2ab6922409e0cb7fdb1edcff10 100644 (file)
@@ -71,84 +71,6 @@ bool isCommutative(EXP op) @safe
     return false;
 }
 
-/***********************************
- * Get Identifier for operator overload.
- */
-private Identifier opId(Expression e)
-{
-    switch (e.op)
-    {
-    case EXP.uadd:                      return Id.uadd;
-    case EXP.negate:                    return Id.neg;
-    case EXP.tilde:                     return Id.com;
-    case EXP.cast_:                     return Id._cast;
-    case EXP.in_:                       return Id.opIn;
-    case EXP.plusPlus:                  return Id.postinc;
-    case EXP.minusMinus:                return Id.postdec;
-    case EXP.add:                       return Id.add;
-    case EXP.min:                       return Id.sub;
-    case EXP.mul:                       return Id.mul;
-    case EXP.div:                       return Id.div;
-    case EXP.mod:                       return Id.mod;
-    case EXP.pow:                       return Id.pow;
-    case EXP.leftShift:                 return Id.shl;
-    case EXP.rightShift:                return Id.shr;
-    case EXP.unsignedRightShift:        return Id.ushr;
-    case EXP.and:                       return Id.iand;
-    case EXP.or:                        return Id.ior;
-    case EXP.xor:                       return Id.ixor;
-    case EXP.concatenate:               return Id.cat;
-    case EXP.assign:                    return Id.assign;
-    case EXP.addAssign:                 return Id.addass;
-    case EXP.minAssign:                 return Id.subass;
-    case EXP.mulAssign:                 return Id.mulass;
-    case EXP.divAssign:                 return Id.divass;
-    case EXP.modAssign:                 return Id.modass;
-    case EXP.powAssign:                 return Id.powass;
-    case EXP.leftShiftAssign:           return Id.shlass;
-    case EXP.rightShiftAssign:          return Id.shrass;
-    case EXP.unsignedRightShiftAssign:  return Id.ushrass;
-    case EXP.andAssign:                 return Id.andass;
-    case EXP.orAssign:                  return Id.orass;
-    case EXP.xorAssign:                 return Id.xorass;
-    case EXP.concatenateAssign:         return Id.catass;
-    case EXP.equal:                     return Id.eq;
-    case EXP.lessThan:
-    case EXP.lessOrEqual:
-    case EXP.greaterThan:
-    case EXP.greaterOrEqual:            return Id.cmp;
-    case EXP.array:                     return Id.index;
-    case EXP.star:                      return Id.opStar;
-    default:                            assert(0);
-    }
-}
-
-/***********************************
- * Get Identifier for reverse operator overload,
- * `null` if not supported for this operator.
- */
-private Identifier opId_r(Expression e)
-{
-    switch (e.op)
-    {
-    case EXP.in_:               return Id.opIn_r;
-    case EXP.add:               return Id.add_r;
-    case EXP.min:               return Id.sub_r;
-    case EXP.mul:               return Id.mul_r;
-    case EXP.div:               return Id.div_r;
-    case EXP.mod:               return Id.mod_r;
-    case EXP.pow:               return Id.pow_r;
-    case EXP.leftShift:         return Id.shl_r;
-    case EXP.rightShift:        return Id.shr_r;
-    case EXP.unsignedRightShift:return Id.ushr_r;
-    case EXP.and:               return Id.iand_r;
-    case EXP.or:                return Id.ior_r;
-    case EXP.xor:               return Id.ixor_r;
-    case EXP.concatenate:       return Id.cat_r;
-    default:                    return null;
-    }
-}
-
 /*******************************************
  * Helper function to turn operator into template argument list
  */
@@ -208,7 +130,7 @@ Objects* opToArg(Scope* sc, EXP op)
 }
 
 // Try alias this on first operand
-private Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinExp e)
+Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinExp e, Type[2] aliasThisStop)
 {
     if (!ad || !ad.aliasthis)
         return null;
@@ -216,7 +138,7 @@ private Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinE
     /* Rewrite (e1 op e2) as:
      *      (e1.aliasthis op e2)
      */
-    if (isRecursiveAliasThis(e.att1, e.e1.type))
+    if (isRecursiveAliasThis(aliasThisStop[0], e.e1.type))
         return null;
     //printf("att %s e1 = %s\n", Token.toChars(e.op), e.e1.type.toChars());
     BinExp be = cast(BinExp)e.copy();
@@ -227,24 +149,18 @@ private Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinE
     if (!be.e1)
         return null;
 
-    Expression result;
-    if (be.op == EXP.concatenateAssign)
-        result = be.op_overload(sc);
-    else
-        result = be.trySemantic(sc);
-
-    return result;
+    return be.trySemanticAliasThis(sc, aliasThisStop);
 }
 
 // Try alias this on second operand
-private Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinExp e)
+Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinExp e, Type[2] aliasThisStop)
 {
     if (!ad || !ad.aliasthis)
         return null;
     /* Rewrite (e1 op e2) as:
      *      (e1 op e2.aliasthis)
      */
-    if (isRecursiveAliasThis(e.att2, e.e2.type))
+    if (isRecursiveAliasThis(aliasThisStop[1], e.e2.type))
         return null;
     //printf("att %s e2 = %s\n", Token.toChars(e.op), e.e2.type.toChars());
     BinExp be = cast(BinExp)e.copy();
@@ -252,189 +168,14 @@ private Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinE
     if (!be.e2)
         return null;
 
-    Expression result;
-    if (be.op == EXP.concatenateAssign)
-        result = be.op_overload(sc);
-    else
-        result = be.trySemantic(sc);
-
-    return result;
+    return be.trySemanticAliasThis(sc, aliasThisStop);
 }
 
-/************************************
- * Operator overload.
- * Check for operator overload, if so, replace
- * with function call.
- * Params:
- *      e = expression with operator
- *      sc = context
- *      pop = if not null, is set to the operator that was actually overloaded,
- *            which may not be `e.op`. Happens when operands are reversed to
- *            match an overload
- * Returns:
- *      `null` if not an operator overload,
- *      otherwise the lowered expression
- */
-Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
+Expression opOverloadUnary(UnaExp e, Scope* sc)
 {
-    Expression visit(Expression e)
-    {
-        assert(0);
-    }
-
-    Expression visitUna(UnaExp e)
-    {
-        //printf("UnaExp::op_overload() (%s)\n", e.toChars());
-        Expression result;
-        if (auto ae = e.e1.isArrayExp())
-        {
-            ae.e1 = ae.e1.expressionSemantic(sc);
-            ae.e1 = resolveProperties(sc, ae.e1);
-            Expression ae1old = ae.e1;
-            const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
-            IntervalExp ie = null;
-            if (maybeSlice && ae.arguments.length)
-            {
-                ie = (*ae.arguments)[0].isIntervalExp();
-            }
-            Type att = null; // first cyclic `alias this` type
-            while (true)
-            {
-                if (ae.e1.op == EXP.error)
-                {
-                    return ae.e1;
-                }
-                Expression e0 = null;
-                Expression ae1save = ae.e1;
-                ae.lengthVar = null;
-                Type t1b = ae.e1.type.toBasetype();
-                AggregateDeclaration ad = isAggregate(t1b);
-                if (!ad)
-                    break;
-                if (search_function(ad, Id.opIndexUnary))
-                {
-                    // Deal with $
-                    result = resolveOpDollar(sc, ae, &e0);
-                    if (!result) // op(a[i..j]) might be: a.opSliceUnary!(op)(i, j)
-                        goto Lfallback;
-                    if (result.op == EXP.error)
-                        return result;
-                    /* Rewrite op(a[arguments]) as:
-                     *      a.opIndexUnary!(op)(arguments)
-                     */
-                    Expressions* a = ae.arguments.copy();
-                    Objects* tiargs = opToArg(sc, e.op);
-                    result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opIndexUnary, tiargs);
-                    result = new CallExp(e.loc, result, a);
-                    if (maybeSlice) // op(a[]) might be: a.opSliceUnary!(op)()
-                        result = result.trySemantic(sc);
-                    else
-                        result = result.expressionSemantic(sc);
-                    if (result)
-                    {
-                        return Expression.combine(e0, result);
-                    }
-                }
-            Lfallback:
-                if (maybeSlice && search_function(ad, Id.opSliceUnary))
-                {
-                    // Deal with $
-                    result = resolveOpDollar(sc, ae, ie, &e0);
-                    if (result.op == EXP.error)
-                        return result;
-                    /* Rewrite op(a[i..j]) as:
-                     *      a.opSliceUnary!(op)(i, j)
-                     */
-                    auto a = new Expressions();
-                    if (ie)
-                    {
-                        a.push(ie.lwr);
-                        a.push(ie.upr);
-                    }
-                    Objects* tiargs = opToArg(sc, e.op);
-                    result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opSliceUnary, tiargs);
-                    result = new CallExp(e.loc, result, a);
-                    result = result.expressionSemantic(sc);
-                    result = Expression.combine(e0, result);
-                    return result;
-                }
-                // Didn't find it. Forward to aliasthis
-                if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
-                {
-                    /* Rewrite op(a[arguments]) as:
-                     *      op(a.aliasthis[arguments])
-                     */
-                    ae.e1 = resolveAliasThis(sc, ae1save, true);
-                    if (ae.e1)
-                        continue;
-                }
-                break;
-            }
-            ae.e1 = ae1old; // recovery
-            ae.lengthVar = null;
-        }
-        e.e1 = e.e1.expressionSemantic(sc);
-        e.e1 = resolveProperties(sc, e.e1);
-        Type att = null; // first cyclic `alias this` type
-        while (1)
-        {
-            if (e.e1.op == EXP.error)
-            {
-                return e.e1;
-            }
-
-            AggregateDeclaration ad = isAggregate(e.e1.type);
-            if (!ad)
-                break;
-
-            Dsymbol fd = null;
-            /* Rewrite as:
-             *      e1.opUnary!(op)()
-             */
-            fd = search_function(ad, Id.opUnary);
-            if (fd)
-            {
-                Objects* tiargs = opToArg(sc, e.op);
-                result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs);
-                result = new CallExp(e.loc, result);
-                result = result.expressionSemantic(sc);
-                return result;
-            }
-            // D1-style operator overloads, deprecated
-            if (e.op != EXP.prePlusPlus && e.op != EXP.preMinusMinus)
-            {
-                auto id = opId(e);
-                fd = search_function(ad, id);
-                if (fd)
-                {
-                    // @@@DEPRECATED_2.110@@@.
-                    // Deprecated in 2.088, made an error in 2.100
-                    error(e.loc, "`%s` is obsolete.  Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
-                    return ErrorExp.get();
-                }
-            }
-            // Didn't find it. Forward to aliasthis
-            if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type))
-            {
-                /* Rewrite op(e1) as:
-                 *      op(e1.aliasthis)
-                 */
-                //printf("att una %s e1 = %s\n", EXPtoString(op).ptr, this.e1.type.toChars());
-                if (auto e1 = resolveAliasThis(sc, e.e1, true))
-                {
-                    e.e1 = e1;
-                    continue;
-                }
-                break;
-            }
-            break;
-        }
-        return result;
-    }
-
-    Expression visitArray(ArrayExp ae)
+    Expression result;
+    if (auto ae = e.e1.isArrayExp())
     {
-        //printf("ArrayExp::op_overload() (%s)\n", ae.toChars());
         ae.e1 = ae.e1.expressionSemantic(sc);
         ae.e1 = resolveProperties(sc, ae.e1);
         Expression ae1old = ae.e1;
@@ -444,7 +185,6 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
         {
             ie = (*ae.arguments)[0].isIntervalExp();
         }
-        Expression result;
         Type att = null; // first cyclic `alias this` type
         while (true)
         {
@@ -458,43 +198,23 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
             Type t1b = ae.e1.type.toBasetype();
             AggregateDeclaration ad = isAggregate(t1b);
             if (!ad)
-            {
-                // If the non-aggregate expression ae.e1 is indexable or sliceable,
-                // convert it to the corresponding concrete expression.
-                if (isIndexableNonAggregate(t1b) || ae.e1.op == EXP.type)
-                {
-                    // Convert to SliceExp
-                    if (maybeSlice)
-                    {
-                        result = new SliceExp(ae.loc, ae.e1, ie);
-                        result = result.expressionSemantic(sc);
-                        return result;
-                    }
-                    // Convert to IndexExp
-                    if (ae.arguments.length == 1)
-                    {
-                        result = new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]);
-                        result = result.expressionSemantic(sc);
-                        return result;
-                    }
-                }
                 break;
-            }
-            if (search_function(ad, Id.index))
+            if (search_function(ad, Id.opIndexUnary))
             {
                 // Deal with $
                 result = resolveOpDollar(sc, ae, &e0);
-                if (!result) // a[i..j] might be: a.opSlice(i, j)
+                if (!result) // op(a[i..j]) might be: a.opSliceUnary!(op)(i, j)
                     goto Lfallback;
                 if (result.op == EXP.error)
                     return result;
-                /* Rewrite e1[arguments] as:
-                 *      e1.opIndex(arguments)
-                 */
+                /* Rewrite op(a[arguments]) as:
+                    *      a.opIndexUnary!(op)(arguments)
+                    */
                 Expressions* a = ae.arguments.copy();
-                result = new DotIdExp(ae.loc, ae.e1, Id.index);
-                result = new CallExp(ae.loc, result, a);
-                if (maybeSlice) // a[] might be: a.opSlice()
+                Objects* tiargs = opToArg(sc, e.op);
+                result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opIndexUnary, tiargs);
+                result = new CallExp(e.loc, result, a);
+                if (maybeSlice) // op(a[]) might be: a.opSliceUnary!(op)()
                     result = result.trySemantic(sc);
                 else
                     result = result.expressionSemantic(sc);
@@ -504,36 +224,24 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
                 }
             }
         Lfallback:
-            if (maybeSlice && ae.e1.op == EXP.type)
-            {
-                result = new SliceExp(ae.loc, ae.e1, ie);
-                result = result.expressionSemantic(sc);
-                result = Expression.combine(e0, result);
-                return result;
-            }
-            if (maybeSlice && search_function(ad, Id.slice))
+            if (maybeSlice && search_function(ad, Id.opSliceUnary))
             {
                 // Deal with $
                 result = resolveOpDollar(sc, ae, ie, &e0);
-
                 if (result.op == EXP.error)
-                {
-                    if (!e0 && !search_function(ad, Id.dollar)) {
-                        ae.loc.errorSupplemental("Aggregate declaration '%s' does not define 'opDollar'", ae.e1.toChars());
-                    }
                     return result;
-                }
-                /* Rewrite a[i..j] as:
-                 *      a.opSlice(i, j)
-                 */
+                /* Rewrite op(a[i..j]) as:
+                    *      a.opSliceUnary!(op)(i, j)
+                    */
                 auto a = new Expressions();
                 if (ie)
                 {
                     a.push(ie.lwr);
                     a.push(ie.upr);
                 }
-                result = new DotIdExp(ae.loc, ae.e1, Id.slice);
-                result = new CallExp(ae.loc, result, a);
+                Objects* tiargs = opToArg(sc, e.op);
+                result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opSliceUnary, tiargs);
+                result = new CallExp(e.loc, result, a);
                 result = result.expressionSemantic(sc);
                 result = Expression.combine(e0, result);
                 return result;
@@ -541,10 +249,9 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
             // Didn't find it. Forward to aliasthis
             if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
             {
-                //printf("att arr e1 = %s\n", this.e1.type.toChars());
                 /* Rewrite op(a[arguments]) as:
-                 *      op(a.aliasthis[arguments])
-                 */
+                    *      op(a.aliasthis[arguments])
+                    */
                 ae.e1 = resolveAliasThis(sc, ae1save, true);
                 if (ae.e1)
                     continue;
@@ -553,846 +260,810 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
         }
         ae.e1 = ae1old; // recovery
         ae.lengthVar = null;
-        return result;
     }
-
-    /***********************************************
-     * This is mostly the same as UnaryExp::op_overload(), but has
-     * a different rewrite.
-     */
-    Expression visitCast(CastExp e, Type att = null)
+    e.e1 = e.e1.expressionSemantic(sc);
+    e.e1 = resolveProperties(sc, e.e1);
+    Type att = null; // first cyclic `alias this` type
+    while (1)
     {
-        //printf("CastExp::op_overload() (%s)\n", e.toChars());
-        Expression result;
-        if (AggregateDeclaration ad = isAggregate(e.e1.type))
+        if (e.e1.op == EXP.error)
         {
-            Dsymbol fd = null;
-            /* Rewrite as:
-             *      e1.opCast!(T)()
+            return e.e1;
+        }
+
+        AggregateDeclaration ad = isAggregate(e.e1.type);
+        if (!ad)
+            break;
+
+        Dsymbol fd = null;
+        /* Rewrite as:
+         *      e1.opUnary!(op)()
+         */
+        fd = search_function(ad, Id.opUnary);
+        if (fd)
+        {
+            Objects* tiargs = opToArg(sc, e.op);
+            result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs);
+            result = new CallExp(e.loc, result);
+            result = result.expressionSemantic(sc);
+            return result;
+        }
+
+        // Didn't find it. Forward to aliasthis
+        if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type))
+        {
+            /* Rewrite op(e1) as:
+             *      op(e1.aliasthis)
              */
-            fd = search_function(ad, Id._cast);
-            if (fd)
-            {
-                version (all)
-                {
-                    // Backwards compatibility with D1 if opCast is a function, not a template
-                    if (fd.isFuncDeclaration())
-                    {
-                        // Rewrite as:  e1.opCast()
-                        return build_overload(e.loc, sc, e.e1, null, fd);
-                    }
-                }
-                auto tiargs = new Objects();
-                tiargs.push(e.to);
-                result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs);
-                result = new CallExp(e.loc, result);
-                result = result.expressionSemantic(sc);
-                return result;
-            }
-            // Didn't find it. Forward to aliasthis
-            if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type))
+            //printf("att una %s e1 = %s\n", EXPtoString(op).ptr, this.e1.type.toChars());
+            if (auto e1 = resolveAliasThis(sc, e.e1, true))
             {
-                /* Rewrite op(e1) as:
-                 *      op(e1.aliasthis)
-                 */
-                if (auto e1 = resolveAliasThis(sc, e.e1, true))
-                {
-                    result = e.copy();
-                    (cast(UnaExp)result).e1 = e1;
-                    result = visitCast(result.isCastExp(), att);
-                    return result;
-                }
+                e.e1 = e1;
+                continue;
             }
+            break;
         }
-        return result;
+        break;
     }
+    return result;
+}
 
-    Expression visitBin(BinExp e)
+Expression opOverloadArray(ArrayExp ae, Scope* sc)
+{
+    ae.e1 = ae.e1.expressionSemantic(sc);
+    ae.e1 = resolveProperties(sc, ae.e1);
+    Expression ae1old = ae.e1;
+    const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
+    IntervalExp ie = null;
+    if (maybeSlice && ae.arguments.length)
     {
-        //printf("BinExp::op_overload() (%s)\n", e.toChars());
-        Identifier id = opId(e);
-        Identifier id_r = opId_r(e);
-        int argsset = 0;
-        AggregateDeclaration ad1 = isAggregate(e.e1.type);
-        AggregateDeclaration ad2 = isAggregate(e.e2.type);
-        if (e.op == EXP.assign && ad1 == ad2)
-        {
-            StructDeclaration sd = ad1.isStructDeclaration();
-            if (sd &&
-                (!sd.hasIdentityAssign ||
-                 /* Do a blit if we can and the rvalue is something like .init,
-                  * where a postblit is not necessary.
-                  */
-                 (sd.hasBlitAssign && !e.e2.isLvalue())))
-            {
-                /* This is bitwise struct assignment. */
-                return null;
-            }
-        }
-        Dsymbol s = null;
-        Dsymbol s_r = null;
-        Objects* tiargs = null;
-        if (e.op == EXP.plusPlus || e.op == EXP.minusMinus)
+        ie = (*ae.arguments)[0].isIntervalExp();
+    }
+    Expression result;
+    Type att = null; // first cyclic `alias this` type
+    while (true)
+    {
+        if (ae.e1.op == EXP.error)
         {
-            // Bug4099 fix
-            if (ad1 && search_function(ad1, Id.opUnary))
-                return null;
+            return ae.e1;
         }
-        if (e.op != EXP.equal && e.op != EXP.notEqual && e.op != EXP.assign && e.op != EXP.plusPlus && e.op != EXP.minusMinus)
+        Expression e0 = null;
+        Expression ae1save = ae.e1;
+        ae.lengthVar = null;
+        Type t1b = ae.e1.type.toBasetype();
+        AggregateDeclaration ad = isAggregate(t1b);
+        if (!ad)
         {
-            /* Try opBinary and opBinaryRight
-             */
-            if (ad1)
+            // If the non-aggregate expression ae.e1 is indexable or sliceable,
+            // convert it to the corresponding concrete expression.
+            if (isIndexableNonAggregate(t1b) || ae.e1.op == EXP.type)
             {
-                s = search_function(ad1, Id.opBinary);
-                if (s && !s.isTemplateDeclaration())
+                // Convert to SliceExp
+                if (maybeSlice)
                 {
-                    error(e.e1.loc, "`%s.opBinary` isn't a template", e.e1.toChars());
-                    return ErrorExp.get();
+                    result = new SliceExp(ae.loc, ae.e1, ie);
+                    result = result.expressionSemantic(sc);
+                    return result;
                 }
-            }
-            if (ad2)
-            {
-                s_r = search_function(ad2, Id.opBinaryRight);
-                if (s_r && !s_r.isTemplateDeclaration())
+                // Convert to IndexExp
+                if (ae.arguments.length == 1)
                 {
-                    error(e.e2.loc, "`%s.opBinaryRight` isn't a template", e.e2.toChars());
-                    return ErrorExp.get();
+                    result = new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]);
+                    result = result.expressionSemantic(sc);
+                    return result;
                 }
-                if (s_r && s_r == s) // https://issues.dlang.org/show_bug.cgi?id=12778
-                    s_r = null;
             }
-            // Set tiargs, the template argument list, which will be the operator string
-            if (s || s_r)
+            break;
+        }
+        if (search_function(ad, Id.opIndex))
+        {
+            // Deal with $
+            result = resolveOpDollar(sc, ae, &e0);
+            if (!result) // a[i..j] might be: a.opSlice(i, j)
+                goto Lfallback;
+            if (result.op == EXP.error)
+                return result;
+            /* Rewrite e1[arguments] as:
+             *      e1.opIndex(arguments)
+             */
+            Expressions* a = ae.arguments.copy();
+            result = new DotIdExp(ae.loc, ae.e1, Id.opIndex);
+            result = new CallExp(ae.loc, result, a);
+            if (maybeSlice) // a[] might be: a.opSlice()
+                result = result.trySemantic(sc);
+            else
+                result = result.expressionSemantic(sc);
+            if (result)
             {
-                id = Id.opBinary;
-                id_r = Id.opBinaryRight;
-                tiargs = opToArg(sc, e.op);
+                return Expression.combine(e0, result);
             }
         }
-        if (!s && !s_r)
+    Lfallback:
+        if (maybeSlice && ae.e1.op == EXP.type)
         {
-            // Try the D1-style operators, deprecated
-            if (ad1 && id)
+            result = new SliceExp(ae.loc, ae.e1, ie);
+            result = result.expressionSemantic(sc);
+            result = Expression.combine(e0, result);
+            return result;
+        }
+        if (maybeSlice && search_function(ad, Id.opSlice))
+        {
+            // Deal with $
+            result = resolveOpDollar(sc, ae, ie, &e0);
+
+            if (result.op == EXP.error)
             {
-                s = search_function(ad1, id);
-                if (s && id != Id.assign)
-                {
-                    // @@@DEPRECATED_2.110@@@.
-                    // Deprecated in 2.088, made an error in 2.100
-                    if (id == Id.postinc || id == Id.postdec)
-                        error(e.loc, "`%s` is obsolete.  Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
-                    else
-                        error(e.loc, "`%s` is obsolete.  Use `opBinary(string op)(...) if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
-                    return ErrorExp.get();
+                if (!e0 && !search_function(ad, Id.dollar)) {
+                    ae.loc.errorSupplemental("Aggregate declaration '%s' does not define 'opDollar'", ae.e1.toChars());
                 }
+                return result;
             }
-            if (ad2 && id_r)
+            /* Rewrite a[i..j] as:
+             *      a.opSlice(i, j)
+             */
+            auto a = new Expressions();
+            if (ie)
             {
-                s_r = search_function(ad2, id_r);
-                // https://issues.dlang.org/show_bug.cgi?id=12778
-                // If both x.opBinary(y) and y.opBinaryRight(x) found,
-                // and they are exactly same symbol, x.opBinary(y) should be preferred.
-                if (s_r && s_r == s)
-                    s_r = null;
-                if (s_r)
-                {
-                    // @@@DEPRECATED_2.110@@@.
-                    // Deprecated in 2.088, made an error in 2.100
-                    error(e.loc, "`%s` is obsolete.  Use `opBinaryRight(string op)(...) if (op == \"%s\")` instead.", id_r.toChars(), EXPtoString(e.op).ptr);
-                    return ErrorExp.get();
-                }
+                a.push(ie.lwr);
+                a.push(ie.upr);
             }
+            result = new DotIdExp(ae.loc, ae.e1, Id.opSlice);
+            result = new CallExp(ae.loc, result, a);
+            result = result.expressionSemantic(sc);
+            result = Expression.combine(e0, result);
+            return result;
         }
-        Expressions* args1 = new Expressions();
-        Expressions* args2 = new Expressions();
-        if (s || s_r)
+        // Didn't find it. Forward to aliasthis
+        if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
         {
-            /* Try:
-             *      a.opfunc(b)
-             *      b.opfunc_r(a)
-             * and see which is better.
+            //printf("att arr e1 = %s\n", this.e1.type.toChars());
+            /* Rewrite op(a[arguments]) as:
+             *      op(a.aliasthis[arguments])
              */
-            args1.setDim(1);
-            (*args1)[0] = e.e1;
-            expandTuples(args1);
-            args2.setDim(1);
-            (*args2)[0] = e.e2;
-            expandTuples(args2);
-            argsset = 1;
-            MatchAccumulator m;
-            if (s)
-            {
-                functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2));
-                if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
-                {
-                    return ErrorExp.get();
-                }
-            }
-            FuncDeclaration lastf = m.lastf;
-            if (s_r)
+            ae.e1 = resolveAliasThis(sc, ae1save, true);
+            if (ae.e1)
+                continue;
+        }
+        break;
+    }
+    ae.e1 = ae1old; // recovery
+    ae.lengthVar = null;
+    return result;
+}
+
+/***********************************************
+ * This is mostly the same as opOverloadUnary but has
+ * a different rewrite.
+ */
+Expression opOverloadCast(CastExp e, Scope* sc, Type att = null)
+{
+    Expression result;
+    if (AggregateDeclaration ad = isAggregate(e.e1.type))
+    {
+        Dsymbol fd = null;
+        /* Rewrite as:
+            *      e1.opCast!(T)()
+            */
+        fd = search_function(ad, Id.opCast);
+        if (fd)
+        {
+            version (all)
             {
-                functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1));
-                if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
+                // Backwards compatibility with D1 if opCast is a function, not a template
+                if (fd.isFuncDeclaration())
                 {
-                    return ErrorExp.get();
+                    // Rewrite as:  e1.opCast()
+                    return build_overload(e.loc, sc, e.e1, null, fd);
                 }
             }
-            if (m.count > 1)
-            {
-                // Error, ambiguous
-                error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
-            }
-            else if (m.last == MATCH.nomatch)
-            {
-                if (tiargs)
-                    goto L1;
-                m.lastf = null;
-            }
-            if (e.op == EXP.plusPlus || e.op == EXP.minusMinus)
-            {
-                // Kludge because operator overloading regards e++ and e--
-                // as unary, but it's implemented as a binary.
-                // Rewrite (e1 ++ e2) as e1.postinc()
-                // Rewrite (e1 -- e2) as e1.postdec()
-                return build_overload(e.loc, sc, e.e1, null, m.lastf ? m.lastf : s);
-            }
-            else if (lastf && m.lastf == lastf || !s_r && m.last == MATCH.nomatch)
-            {
-                // Rewrite (e1 op e2) as e1.opfunc(e2)
-                return build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s);
-            }
-            else
-            {
-                // Rewrite (e1 op e2) as e2.opfunc_r(e1)
-                return build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s_r);
-            }
+            auto tiargs = new Objects();
+            tiargs.push(e.to);
+            result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs);
+            result = new CallExp(e.loc, result);
+            result = result.expressionSemantic(sc);
+            return result;
         }
-    L1:
-        version (all)
+        // Didn't find it. Forward to aliasthis
+        if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type))
         {
-            // Retained for D1 compatibility
-            if (isCommutative(e.op) && !tiargs)
+            /* Rewrite op(e1) as:
+                *      op(e1.aliasthis)
+                */
+            if (auto e1 = resolveAliasThis(sc, e.e1, true))
             {
-                s = null;
-                s_r = null;
-                if (ad1 && id_r)
-                {
-                    s_r = search_function(ad1, id_r);
-                }
-                if (ad2 && id)
-                {
-                    s = search_function(ad2, id);
-                    if (s && s == s_r) // https://issues.dlang.org/show_bug.cgi?id=12778
-                        s = null;
-                }
-                if (s || s_r)
-                {
-                    /* Try:
-                     *  a.opfunc_r(b)
-                     *  b.opfunc(a)
-                     * and see which is better.
-                     */
-                    if (!argsset)
-                    {
-                        args1.setDim(1);
-                        (*args1)[0] = e.e1;
-                        expandTuples(args1);
-                        args2.setDim(1);
-                        (*args2)[0] = e.e2;
-                        expandTuples(args2);
-                    }
-                    MatchAccumulator m;
-                    if (s_r)
-                    {
-                        functionResolve(m, s_r, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2));
-                        if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
-                        {
-                            return ErrorExp.get();
-                        }
-                    }
-                    FuncDeclaration lastf = m.lastf;
-                    if (s)
-                    {
-                        functionResolve(m, s, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1));
-                        if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
-                        {
-                            return ErrorExp.get();
-                        }
-                    }
-                    if (m.count > 1)
-                    {
-                        // Error, ambiguous
-                        error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
-                    }
-                    else if (m.last == MATCH.nomatch)
-                    {
-                        m.lastf = null;
-                    }
-
-                    if (lastf && m.lastf == lastf || !s && m.last == MATCH.nomatch)
-                    {
-                        // Rewrite (e1 op e2) as e1.opfunc_r(e2)
-                        return build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s_r);
-                    }
-                    else
-                    {
-                        // Rewrite (e1 op e2) as e2.opfunc(e1)
-                        Expression result = build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s);
-                        // When reversing operands of comparison operators,
-                        // need to reverse the sense of the op
-                        if (pop)
-                            *pop = reverseRelation(e.op);
-                        return result;
-                    }
-                }
+                result = e.copy();
+                (cast(UnaExp)result).e1 = e1;
+                result = opOverloadCast(result.isCastExp(), sc, att);
+                return result;
             }
         }
+    }
+    return result;
+}
 
-        Expression rewrittenLhs;
-        if (!(e.op == EXP.assign && ad2 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
+// When no operator overload functions are found for `e`, recursively try with `alias this`
+// Returns: `null` when still no overload found, otherwise resolved lowering
+Expression binAliasThis(BinExp e, Scope* sc, Type[2] aliasThisStop)
+{
+    AggregateDeclaration ad1 = isAggregate(e.e1.type);
+    AggregateDeclaration ad2 = isAggregate(e.e2.type);
+    Expression rewrittenLhs;
+    if (!(e.op == EXP.assign && ad2 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
+    {
+        if (Expression result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop))
         {
-            if (Expression result = checkAliasThisForLhs(ad1, sc, e))
-            {
-                /* https://issues.dlang.org/show_bug.cgi?id=19441
-                 *
-                 * alias this may not be used for partial assignment.
-                 * If a struct has a single member which is aliased this
-                 * directly or aliased to a ref getter function that returns
-                 * the mentioned member, then alias this may be
-                 * used since the object will be fully initialised.
-                 * If the struct is nested, the context pointer is considered
-                 * one of the members, hence the `ad1.fields.length == 2 && ad1.vthis`
-                 * condition.
-                 */
-                if (result.op != EXP.assign)
-                    return result;     // i.e: Rewrote `e1 = e2` -> `e1(e2)`
+            /* https://issues.dlang.org/show_bug.cgi?id=19441
+             *
+             * alias this may not be used for partial assignment.
+             * If a struct has a single member which is aliased this
+             * directly or aliased to a ref getter function that returns
+             * the mentioned member, then alias this may be
+             * used since the object will be fully initialised.
+             * If the struct is nested, the context pointer is considered
+             * one of the members, hence the `ad1.fields.length == 2 && ad1.vthis`
+             * condition.
+             */
+            if (result.op != EXP.assign)
+                return result;     // i.e: Rewrote `e1 = e2` -> `e1(e2)`
 
-                auto ae = result.isAssignExp();
-                if (ae.e1.op != EXP.dotVariable)
-                    return result;     // i.e: Rewrote `e1 = e2` -> `e1() = e2`
+            auto ae = result.isAssignExp();
+            if (ae.e1.op != EXP.dotVariable)
+                return result;     // i.e: Rewrote `e1 = e2` -> `e1() = e2`
 
-                auto dve = ae.e1.isDotVarExp();
-                if (auto ad = dve.var.isMember2())
+            auto dve = ae.e1.isDotVarExp();
+            if (auto ad = dve.var.isMember2())
+            {
+                // i.e: Rewrote `e1 = e2` -> `e1.some.var = e2`
+                // Ensure that `var` is the only field member in `ad`
+                if (ad.fields.length == 1 || (ad.fields.length == 2 && ad.vthis))
                 {
-                    // i.e: Rewrote `e1 = e2` -> `e1.some.var = e2`
-                    // Ensure that `var` is the only field member in `ad`
-                    if (ad.fields.length == 1 || (ad.fields.length == 2 && ad.vthis))
-                    {
-                        if (dve.var == ad.aliasthis.sym)
-                            return result;
-                    }
+                    if (dve.var == ad.aliasthis.sym)
+                        return result;
                 }
-                rewrittenLhs = ae.e1;
             }
+            rewrittenLhs = ae.e1;
         }
-        if (!(e.op == EXP.assign && ad1 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
-        {
-            if (Expression result = checkAliasThisForRhs(ad2, sc, e))
-                return result;
-        }
-        if (rewrittenLhs)
-        {
-            error(e.loc, "cannot use `alias this` to partially initialize variable `%s` of type `%s`. Use `%s`",
-                    e.e1.toChars(), ad1.toChars(), rewrittenLhs.toChars());
-            return ErrorExp.get();
-        }
-        return null;
     }
-
-    Expression visitEqual(EqualExp e)
+    if (!(e.op == EXP.assign && ad1 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
     {
-        //printf("EqualExp::op_overload() (%s)\n", e.toChars());
-        Type t1 = e.e1.type.toBasetype();
-        Type t2 = e.e2.type.toBasetype();
+        if (Expression result = checkAliasThisForRhs(ad2, sc, e, aliasThisStop))
+            return result;
+    }
+    if (rewrittenLhs)
+    {
+        error(e.loc, "cannot use `alias this` to partially initialize variable `%s` of type `%s`. Use `%s`",
+                e.e1.toChars(), ad1.toChars(), rewrittenLhs.toChars());
+        return ErrorExp.get();
+    }
+    return null;
+}
 
-        /* Array equality is handled by expressionSemantic() potentially
-         * lowering to object.__equals(), which takes care of overloaded
-         * operators for the element types.
-         */
-        if ((t1.ty == Tarray || t1.ty == Tsarray) &&
-            (t2.ty == Tarray || t2.ty == Tsarray))
+Expression opOverloadAssign(AssignExp e, Scope* sc, Type[2] aliasThisStop)
+{
+    AggregateDeclaration ad1 = isAggregate(e.e1.type);
+    AggregateDeclaration ad2 = isAggregate(e.e2.type);
+    if (ad1 == ad2)
+    {
+        StructDeclaration sd = ad1.isStructDeclaration();
+        if (sd &&
+            (!sd.hasIdentityAssign ||
+                /* Do a blit if we can and the rvalue is something like .init,
+                 * where a postblit is not necessary.
+                 */
+                (sd.hasBlitAssign && !e.e2.isLvalue())))
         {
+            /* This is bitwise struct assignment. */
             return null;
         }
+    }
+    Dsymbol s = search_function(ad1, Id.opAssign);
 
-        /* Check for class equality with null literal or typeof(null).
-         */
-        if (t1.ty == Tclass && e.e2.op == EXP.null_ ||
-            t2.ty == Tclass && e.e1.op == EXP.null_)
-        {
-            error(e.loc, "use `%s` instead of `%s` when comparing with `null`",
-                EXPtoString(e.op == EXP.equal ? EXP.identity : EXP.notIdentity).ptr,
-                EXPtoString(e.op).ptr);
-            return ErrorExp.get();
-        }
-        if (t1.ty == Tclass && t2.ty == Tnull ||
-            t1.ty == Tnull && t2.ty == Tclass)
-        {
-            // Comparing a class with typeof(null) should not call opEquals
-            return null;
-        }
+    bool choseReverse;
+    if (auto result = pickBestBinaryOverload(sc, null, s, null, e, choseReverse))
+        return result;
 
-        /* Check for class equality.
-         */
-        if (t1.ty == Tclass && t2.ty == Tclass)
-        {
-            ClassDeclaration cd1 = t1.isClassHandle();
-            ClassDeclaration cd2 = t2.isClassHandle();
-            if (!(cd1.classKind == ClassKind.cpp || cd2.classKind == ClassKind.cpp))
-            {
-                /* Rewrite as:
-                 *      .object.opEquals(e1, e2)
-                 */
-                if (!ClassDeclaration.object)
-                {
-                    error(e.loc, "cannot compare classes for equality because `object.Object` was not declared");
-                    return null;
-                }
+    return binAliasThis(e, sc, aliasThisStop);
+}
 
-                Expression e1x = e.e1;
-                Expression e2x = e.e2;
+Expression opOverloadBinary(BinExp e, Scope* sc, Type[2] aliasThisStop)
+{
+    if (Expression err = binSemanticProp(e, sc))
+        return err;
 
-                /* The explicit cast is necessary for interfaces
-                 * https://issues.dlang.org/show_bug.cgi?id=4088
-                 */
-                Type to = ClassDeclaration.object.getType();
-                if (cd1.isInterfaceDeclaration())
-                    e1x = new CastExp(e.loc, e.e1, t1.isMutable() ? to : to.constOf());
-                if (cd2.isInterfaceDeclaration())
-                    e2x = new CastExp(e.loc, e.e2, t2.isMutable() ? to : to.constOf());
-
-                Expression result = new IdentifierExp(e.loc, Id.empty);
-                result = new DotIdExp(e.loc, result, Id.object);
-                result = new DotIdExp(e.loc, result, Id.eq);
-                result = new CallExp(e.loc, result, e1x, e2x);
-                if (e.op == EXP.notEqual)
-                    result = new NotExp(e.loc, result);
-                result = result.expressionSemantic(sc);
-                return result;
-            }
-        }
+    AggregateDeclaration ad1 = isAggregate(e.e1.type);
+    AggregateDeclaration ad2 = isAggregate(e.e2.type);
+
+    // Try opBinary and opBinaryRight
+    Dsymbol s = search_function(ad1, Id.opBinary);
+    if (s && !s.isTemplateDeclaration())
+    {
+        error(e.e1.loc, "`%s.opBinary` isn't a template", e.e1.toChars());
+        return ErrorExp.get();
+    }
 
-        if (Expression result = compare_overload(e, sc, Id.eq, null))
+    Dsymbol s_r = search_function(ad2, Id.opBinaryRight);
+    if (s_r && !s_r.isTemplateDeclaration())
+    {
+        error(e.e2.loc, "`%s.opBinaryRight` isn't a template", e.e2.toChars());
+        return ErrorExp.get();
+    }
+    if (s_r && s_r == s) // https://issues.dlang.org/show_bug.cgi?id=12778
+        s_r = null;
+
+    bool choseReverse;
+    if (auto res = pickBestBinaryOverload(sc, opToArg(sc, e.op), s, s_r, e, choseReverse))
+        return res;
+
+    return binAliasThis(e, sc, aliasThisStop);
+}
+
+Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
+{
+    Type t1 = e.e1.type.toBasetype();
+    Type t2 = e.e2.type.toBasetype();
+
+    /* Array equality is handled by expressionSemantic() potentially
+     * lowering to object.__equals(), which takes care of overloaded
+     * operators for the element types.
+     */
+    if ((t1.ty == Tarray || t1.ty == Tsarray) &&
+        (t2.ty == Tarray || t2.ty == Tsarray))
+    {
+        return null;
+    }
+
+    /* Check for class equality with null literal or typeof(null).
+     */
+    if (t1.ty == Tclass && e.e2.op == EXP.null_ ||
+        t2.ty == Tclass && e.e1.op == EXP.null_)
+    {
+        error(e.loc, "use `%s` instead of `%s` when comparing with `null`",
+            EXPtoString(e.op == EXP.equal ? EXP.identity : EXP.notIdentity).ptr,
+            EXPtoString(e.op).ptr);
+        return ErrorExp.get();
+    }
+    if (t1.ty == Tclass && t2.ty == Tnull ||
+        t1.ty == Tnull && t2.ty == Tclass)
+    {
+        // Comparing a class with typeof(null) should not call opEquals
+        return null;
+    }
+
+    /* Check for class equality.
+     */
+    if (t1.ty == Tclass && t2.ty == Tclass)
+    {
+        ClassDeclaration cd1 = t1.isClassHandle();
+        ClassDeclaration cd2 = t2.isClassHandle();
+        if (!(cd1.classKind == ClassKind.cpp || cd2.classKind == ClassKind.cpp))
         {
-            if (lastComma(result).op == EXP.call && e.op == EXP.notEqual)
+            /* Rewrite as:
+             *      .object.opEquals(e1, e2)
+             */
+            if (!ClassDeclaration.object)
             {
-                result = new NotExp(result.loc, result);
-                result = result.expressionSemantic(sc);
+                error(e.loc, "cannot compare classes for equality because `object.Object` was not declared");
+                return null;
             }
+
+            Expression e1x = e.e1;
+            Expression e2x = e.e2;
+
+            /* The explicit cast is necessary for interfaces
+             * https://issues.dlang.org/show_bug.cgi?id=4088
+             */
+            Type to = ClassDeclaration.object.getType();
+            if (cd1.isInterfaceDeclaration())
+                e1x = new CastExp(e.loc, e.e1, t1.isMutable() ? to : to.constOf());
+            if (cd2.isInterfaceDeclaration())
+                e2x = new CastExp(e.loc, e.e2, t2.isMutable() ? to : to.constOf());
+
+            Expression result = new IdentifierExp(e.loc, Id.empty);
+            result = new DotIdExp(e.loc, result, Id.object);
+            result = new DotIdExp(e.loc, result, Id.opEquals);
+            result = new CallExp(e.loc, result, e1x, e2x);
+            if (e.op == EXP.notEqual)
+                result = new NotExp(e.loc, result);
+            result = result.expressionSemantic(sc);
             return result;
         }
+    }
+
+    EXP cmpOp;
+    if (Expression result = compare_overload(e, sc, Id.opEquals, cmpOp, aliasThisStop))
+    {
+        if (lastComma(result).op == EXP.call && e.op == EXP.notEqual)
+        {
+            result = new NotExp(result.loc, result);
+            result = result.expressionSemantic(sc);
+        }
+        return result;
+    }
 
-        /* Check for pointer equality.
+    /* Check for pointer equality.
+     */
+    if (t1.ty == Tpointer || t2.ty == Tpointer)
+    {
+        /* Rewrite:
+         *      ptr1 == ptr2
+         * as:
+         *      ptr1 is ptr2
+         *
+         * This is just a rewriting for deterministic AST representation
+         * as the backend input.
          */
-        if (t1.ty == Tpointer || t2.ty == Tpointer)
+        auto op2 = e.op == EXP.equal ? EXP.identity : EXP.notIdentity;
+        Expression r = new IdentityExp(op2, e.loc, e.e1, e.e2);
+        return r.expressionSemantic(sc);
+    }
+
+    /* Check for struct equality without opEquals.
+     */
+    if (t1.ty == Tstruct && t2.ty == Tstruct)
+    {
+        auto sd = t1.isTypeStruct().sym;
+        if (sd != t2.isTypeStruct().sym)
+            return null;
+
+        import dmd.clone : needOpEquals;
+        if (!sc.previews.fieldwise && !needOpEquals(sd))
         {
-            /* Rewrite:
-             *      ptr1 == ptr2
-             * as:
-             *      ptr1 is ptr2
-             *
-             * This is just a rewriting for deterministic AST representation
-             * as the backend input.
-             */
+            // Use bitwise equality.
             auto op2 = e.op == EXP.equal ? EXP.identity : EXP.notIdentity;
             Expression r = new IdentityExp(op2, e.loc, e.e1, e.e2);
             return r.expressionSemantic(sc);
         }
 
-        /* Check for struct equality without opEquals.
+        /* Do memberwise equality.
+         * https://dlang.org/spec/expression.html#equality_expressions
+         * Rewrite:
+         *      e1 == e2
+         * as:
+         *      e1.tupleof == e2.tupleof
+         *
+         * If sd is a nested struct, and if it's nested in a class, it will
+         * also compare the parent class's equality. Otherwise, compares
+         * the identity of parent context through void*.
          */
-        if (t1.ty == Tstruct && t2.ty == Tstruct)
-        {
-            auto sd = t1.isTypeStruct().sym;
-            if (sd != t2.isTypeStruct().sym)
-                return null;
-
-            import dmd.clone : needOpEquals;
-            if (!sc.previews.fieldwise && !needOpEquals(sd))
-            {
-                // Use bitwise equality.
-                auto op2 = e.op == EXP.equal ? EXP.identity : EXP.notIdentity;
-                Expression r = new IdentityExp(op2, e.loc, e.e1, e.e2);
-                return r.expressionSemantic(sc);
-            }
+        e = e.copy().isEqualExp();
+        e.e1 = new DotIdExp(e.loc, e.e1, Id._tupleof);
+        e.e2 = new DotIdExp(e.loc, e.e2, Id._tupleof);
+
+        auto sc2 = sc.push();
+        sc2.noAccessCheck = true;
+        Expression r = e.expressionSemantic(sc2);
+        sc2.pop();
+        return r;
+    }
 
-            /* Do memberwise equality.
-             * https://dlang.org/spec/expression.html#equality_expressions
-             * Rewrite:
-             *      e1 == e2
-             * as:
-             *      e1.tupleof == e2.tupleof
-             *
-             * If sd is a nested struct, and if it's nested in a class, it will
-             * also compare the parent class's equality. Otherwise, compares
-             * the identity of parent context through void*.
-             */
-            e = e.copy().isEqualExp();
-            e.e1 = new DotIdExp(e.loc, e.e1, Id._tupleof);
-            e.e2 = new DotIdExp(e.loc, e.e2, Id._tupleof);
-
-            auto sc2 = sc.push();
-            sc2.noAccessCheck = true;
-            Expression r = e.expressionSemantic(sc2);
-            sc2.pop();
-            return r;
+    /* Check for tuple equality.
+     */
+    if (e.e1.op == EXP.tuple && e.e2.op == EXP.tuple)
+    {
+        auto tup1 = e.e1.isTupleExp();
+        auto tup2 = e.e2.isTupleExp();
+        size_t dim = tup1.exps.length;
+        if (dim != tup2.exps.length)
+        {
+            error(e.loc, "mismatched sequence lengths, `%d` and `%d`",
+                cast(int)dim, cast(int)tup2.exps.length);
+            return ErrorExp.get();
         }
 
-        /* Check for tuple equality.
-         */
-        if (e.e1.op == EXP.tuple && e.e2.op == EXP.tuple)
+        Expression result;
+        if (dim == 0)
         {
-            auto tup1 = e.e1.isTupleExp();
-            auto tup2 = e.e2.isTupleExp();
-            size_t dim = tup1.exps.length;
-            if (dim != tup2.exps.length)
+            // zero-length tuple comparison should always return true or false.
+            result = IntegerExp.createBool(e.op == EXP.equal);
+        }
+        else
+        {
+            for (size_t i = 0; i < dim; i++)
             {
-                error(e.loc, "mismatched sequence lengths, `%d` and `%d`",
-                    cast(int)dim, cast(int)tup2.exps.length);
-                return ErrorExp.get();
+                auto ex1 = (*tup1.exps)[i];
+                auto ex2 = (*tup2.exps)[i];
+                auto eeq = new EqualExp(e.op, e.loc, ex1, ex2);
+
+                if (!result)
+                    result = eeq;
+                else if (e.op == EXP.equal)
+                    result = new LogicalExp(e.loc, EXP.andAnd, result, eeq);
+                else
+                    result = new LogicalExp(e.loc, EXP.orOr, result, eeq);
             }
+            assert(result);
+        }
+        result = Expression.combine(tup1.e0, tup2.e0, result);
+        result = result.expressionSemantic(sc);
 
-            Expression result;
-            if (dim == 0)
-            {
-                // zero-length tuple comparison should always return true or false.
-                result = IntegerExp.createBool(e.op == EXP.equal);
-            }
-            else
-            {
-                for (size_t i = 0; i < dim; i++)
-                {
-                    auto ex1 = (*tup1.exps)[i];
-                    auto ex2 = (*tup2.exps)[i];
-                    auto eeq = new EqualExp(e.op, e.loc, ex1, ex2);
-
-                    if (!result)
-                        result = eeq;
-                    else if (e.op == EXP.equal)
-                        result = new LogicalExp(e.loc, EXP.andAnd, result, eeq);
-                    else
-                        result = new LogicalExp(e.loc, EXP.orOr, result, eeq);
-                }
-                assert(result);
-            }
-            result = Expression.combine(tup1.e0, tup2.e0, result);
-            result = result.expressionSemantic(sc);
+        return result;
+    }
+    return null;
+}
 
-            return result;
-        }
+Expression opOverloadCmp(CmpExp exp, Scope* sc, Type[2] aliasThisStop)
+{
+    //printf("CmpExp:: () (%s)\n", e.toChars());
+    EXP cmpOp = exp.op;
+    auto e = compare_overload(exp, sc, Id.opCmp, cmpOp, aliasThisStop);
+    if (!e)
         return null;
+
+    if (!e.type.isScalar() && e.type.equals(exp.e1.type))
+    {
+        error(e.loc, "recursive `opCmp` expansion");
+        return ErrorExp.get();
     }
+    if (e.op != EXP.call)
+        return e;
 
-    Expression visitCmp(CmpExp e)
+    Type t1 = exp.e1.type.toBasetype();
+    Type t2 = exp.e2.type.toBasetype();
+    if (t1.ty != Tclass || t2.ty != Tclass)
     {
-        //printf("CmpExp:: () (%s)\n", e.toChars());
-        return compare_overload(e, sc, Id.cmp, pop);
+        return new CmpExp(cmpOp, exp.loc, e, IntegerExp.literal!0).expressionSemantic(sc);
     }
 
-    /*********************************
-     * Operator overloading for op=
-     */
-    Expression visitBinAssign(BinAssignExp e)
+    // Lower to object.__cmp(e1, e2)
+    Expression cl = new IdentifierExp(exp.loc, Id.empty);
+    cl = new DotIdExp(exp.loc, cl, Id.object);
+    cl = new DotIdExp(exp.loc, cl, Id.__cmp);
+    cl = cl.expressionSemantic(sc);
+
+    auto arguments = new Expressions();
+    // Check if op_overload found a better match by calling e2.opCmp(e1)
+    // If the operands were swapped, then the result must be reversed
+    // e1.opCmp(e2) == -e2.opCmp(e1)
+    // cmpop takes care of this
+    if (exp.op == cmpOp)
     {
-        //printf("BinAssignExp::op_overload() (%s)\n", e.toChars());
-        if (auto ae = e.e1.isArrayExp())
+        arguments.push(exp.e1);
+        arguments.push(exp.e2);
+    }
+    else
+    {
+        // Use better match found by op_overload
+        arguments.push(exp.e2);
+        arguments.push(exp.e1);
+    }
+
+    cl = new CallExp(e.loc, cl, arguments);
+    cl = new CmpExp(cmpOp, exp.loc, cl, new IntegerExp(0));
+    return cl.expressionSemantic(sc);
+}
+
+/*********************************
+ * Operator overloading for op=
+ */
+Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisStop)
+{
+    if (auto ae = e.e1.isArrayExp())
+    {
+        ae.e1 = ae.e1.expressionSemantic(sc);
+        ae.e1 = resolveProperties(sc, ae.e1);
+        Expression ae1old = ae.e1;
+        const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
+        IntervalExp ie = null;
+        if (maybeSlice && ae.arguments.length)
         {
-            ae.e1 = ae.e1.expressionSemantic(sc);
-            ae.e1 = resolveProperties(sc, ae.e1);
-            Expression ae1old = ae.e1;
-            const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
-            IntervalExp ie = null;
-            if (maybeSlice && ae.arguments.length)
+            ie = (*ae.arguments)[0].isIntervalExp();
+        }
+        Type att = null; // first cyclic `alias this` type
+        while (true)
+        {
+            if (ae.e1.op == EXP.error)
             {
-                ie = (*ae.arguments)[0].isIntervalExp();
+                return ae.e1;
             }
-            Type att = null; // first cyclic `alias this` type
-            while (true)
+            Expression e0 = null;
+            Expression ae1save = ae.e1;
+            ae.lengthVar = null;
+            Type t1b = ae.e1.type.toBasetype();
+            AggregateDeclaration ad = isAggregate(t1b);
+            if (!ad)
+                break;
+            if (search_function(ad, Id.opIndexOpAssign))
             {
-                if (ae.e1.op == EXP.error)
-                {
-                    return ae.e1;
-                }
-                Expression e0 = null;
-                Expression ae1save = ae.e1;
-                ae.lengthVar = null;
-                Type t1b = ae.e1.type.toBasetype();
-                AggregateDeclaration ad = isAggregate(t1b);
-                if (!ad)
-                    break;
-                if (search_function(ad, Id.opIndexOpAssign))
-                {
-                    // Deal with $
-                    Expression result = resolveOpDollar(sc, ae, &e0);
-                    if (!result) // (a[i..j] op= e2) might be: a.opSliceOpAssign!(op)(e2, i, j)
-                        goto Lfallback;
-                    if (result.op == EXP.error)
-                        return result;
-                    result = e.e2.expressionSemantic(sc);
-                    if (result.op == EXP.error)
-                        return result;
-                    e.e2 = result;
-                    /* Rewrite a[arguments] op= e2 as:
-                     *      a.opIndexOpAssign!(op)(e2, arguments)
-                     */
-                    Expressions* a = ae.arguments.copy();
-                    a.insert(0, e.e2);
-                    Objects* tiargs = opToArg(sc, e.op);
-                    result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opIndexOpAssign, tiargs);
-                    result = new CallExp(e.loc, result, a);
-                    if (maybeSlice) // (a[] op= e2) might be: a.opSliceOpAssign!(op)(e2)
-                        result = result.trySemantic(sc);
-                    else
-                        result = result.expressionSemantic(sc);
-                    if (result)
-                    {
-                        return Expression.combine(e0, result);
-                    }
-                }
-            Lfallback:
-                if (maybeSlice && search_function(ad, Id.opSliceOpAssign))
-                {
-                    // Deal with $
-                    Expression result = resolveOpDollar(sc, ae, ie, &e0);
-                    if (result.op == EXP.error)
-                        return result;
-                    result = e.e2.expressionSemantic(sc);
-                    if (result.op == EXP.error)
-                        return result;
-                    e.e2 = result;
-                    /* Rewrite (a[i..j] op= e2) as:
-                     *      a.opSliceOpAssign!(op)(e2, i, j)
-                     */
-                    auto a = new Expressions();
-                    a.push(e.e2);
-                    if (ie)
-                    {
-                        a.push(ie.lwr);
-                        a.push(ie.upr);
-                    }
-                    Objects* tiargs = opToArg(sc, e.op);
-                    result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opSliceOpAssign, tiargs);
-                    result = new CallExp(e.loc, result, a);
-                    result = result.expressionSemantic(sc);
-                    result = Expression.combine(e0, result);
+                // Deal with $
+                Expression result = resolveOpDollar(sc, ae, &e0);
+                if (!result) // (a[i..j] op= e2) might be: a.opSliceOpAssign!(op)(e2, i, j)
+                    goto Lfallback;
+                if (result.op == EXP.error)
                     return result;
-                }
-                // Didn't find it. Forward to aliasthis
-                if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
+                result = e.e2.expressionSemantic(sc);
+                if (result.op == EXP.error)
+                    return result;
+                e.e2 = result;
+                /* Rewrite a[arguments] op= e2 as:
+                 *      a.opIndexOpAssign!(op)(e2, arguments)
+                 */
+                Expressions* a = ae.arguments.copy();
+                a.insert(0, e.e2);
+                Objects* tiargs = opToArg(sc, e.op);
+                result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opIndexOpAssign, tiargs);
+                result = new CallExp(e.loc, result, a);
+                if (maybeSlice) // (a[] op= e2) might be: a.opSliceOpAssign!(op)(e2)
+                    result = result.trySemantic(sc);
+                else
+                    result = result.expressionSemantic(sc);
+                if (result)
                 {
-                    /* Rewrite (a[arguments] op= e2) as:
-                     *      a.aliasthis[arguments] op= e2
-                     */
-                    ae.e1 = resolveAliasThis(sc, ae1save, true);
-                    if (ae.e1)
-                        continue;
+                    return Expression.combine(e0, result);
                 }
-                break;
             }
-            ae.e1 = ae1old; // recovery
-            ae.lengthVar = null;
-        }
-        Expression result = e.binSemanticProp(sc);
-        if (result)
-            return result;
-        // Don't attempt 'alias this' if an error occurred
-        if (e.e1.type.ty == Terror || e.e2.type.ty == Terror)
-        {
-            return ErrorExp.get();
-        }
-        Identifier id = opId(e);
-        Expressions* args2 = new Expressions();
-        AggregateDeclaration ad1 = isAggregate(e.e1.type);
-        Dsymbol s = null;
-        Objects* tiargs = null;
-        /* Try opOpAssign
-         */
-        if (ad1)
-        {
-            s = search_function(ad1, Id.opOpAssign);
-            if (s && !s.isTemplateDeclaration())
+        Lfallback:
+            if (maybeSlice && search_function(ad, Id.opSliceOpAssign))
             {
-                error(e.loc, "`%s.opOpAssign` isn't a template", e.e1.toChars());
-                return ErrorExp.get();
+                // Deal with $
+                Expression result = resolveOpDollar(sc, ae, ie, &e0);
+                if (result.op == EXP.error)
+                    return result;
+                result = e.e2.expressionSemantic(sc);
+                if (result.op == EXP.error)
+                    return result;
+                e.e2 = result;
+                /* Rewrite (a[i..j] op= e2) as:
+                 *      a.opSliceOpAssign!(op)(e2, i, j)
+                 */
+                auto a = new Expressions();
+                a.push(e.e2);
+                if (ie)
+                {
+                    a.push(ie.lwr);
+                    a.push(ie.upr);
+                }
+                Objects* tiargs = opToArg(sc, e.op);
+                result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opSliceOpAssign, tiargs);
+                result = new CallExp(e.loc, result, a);
+                result = result.expressionSemantic(sc);
+                result = Expression.combine(e0, result);
+                return result;
             }
-        }
-        // Set tiargs, the template argument list, which will be the operator string
-        if (s)
-        {
-            id = Id.opOpAssign;
-            tiargs = opToArg(sc, e.op);
-        }
-
-        // Try D1-style operator overload, deprecated
-        if (!s && ad1 && id)
-        {
-            s = search_function(ad1, id);
-            if (s)
+            // Didn't find it. Forward to aliasthis
+            if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
             {
-                // @@@DEPRECATED_2.110@@@.
-                // Deprecated in 2.088, made an error in 2.100
-                scope char[] op = EXPtoString(e.op).dup;
-                op[$-1] = '\0'; // remove trailing `=`
-                error(e.loc, "`%s` is obsolete.  Use `opOpAssign(string op)(...) if (op == \"%s\")` instead.", id.toChars(), op.ptr);
-                return ErrorExp.get();
+                /* Rewrite (a[arguments] op= e2) as:
+                 *      a.aliasthis[arguments] op= e2
+                 */
+                ae.e1 = resolveAliasThis(sc, ae1save, true);
+                if (ae.e1)
+                    continue;
             }
+            break;
         }
+        ae.e1 = ae1old; // recovery
+        ae.lengthVar = null;
+    }
+    Expression result = e.binSemanticProp(sc);
+    if (result)
+        return result;
+    // Don't attempt 'alias this' if an error occurred
+    if (e.e1.type.ty == Terror || e.e2.type.ty == Terror)
+    {
+        return ErrorExp.get();
+    }
+    AggregateDeclaration ad1 = isAggregate(e.e1.type);
+    Dsymbol s = search_function(ad1, Id.opOpAssign);
+    if (s && !s.isTemplateDeclaration())
+    {
+        error(e.loc, "`%s.opOpAssign` isn't a template", e.e1.toChars());
+        return ErrorExp.get();
+    }
 
-        if (s)
-        {
-            /* Try:
-             *      a.opOpAssign(b)
-             */
-            args2.setDim(1);
-            (*args2)[0] = e.e2;
-            expandTuples(args2);
-            MatchAccumulator m;
-            functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2));
-            if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
-            {
-                return ErrorExp.get();
-            }
-            if (m.count > 1)
-            {
-                // Error, ambiguous
-                error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
-            }
-            else if (m.last == MATCH.nomatch)
-            {
-                if (tiargs)
-                    goto L1;
-                m.lastf = null;
-            }
-            // Rewrite (e1 op e2) as e1.opOpAssign(e2)
-            return build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s);
-        }
-    L1:
-        result = checkAliasThisForLhs(ad1, sc, e);
-        if (result || !s) // no point in trying Rhs alias-this if there's no overload of any kind in lhs
-            return result;
+    bool choseReverse;
+    if (auto res = pickBestBinaryOverload(sc, opToArg(sc, e.op), s, null, e, choseReverse))
+        return res;
 
-        return checkAliasThisForRhs(isAggregate(e.e2.type), sc, e);
-    }
+    result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop);
+    if (result || !s) // no point in trying Rhs alias-this if there's no overload of any kind in lhs
+        return result;
 
-    if (pop)
-        *pop = e.op;
+    return checkAliasThisForRhs(isAggregate(e.e2.type), sc, e, aliasThisStop);
+}
 
-    switch (e.op)
-    {
-        case EXP.cast_         : return visitCast(e.isCastExp());
-        case EXP.array         : return visitArray(e.isArrayExp());
+/**
+Given symbols `s` and `s_r`, try to instantiate `e.e1.s!tiargs(e.e2)` and `e.e2.s_r!tiargs(e.e1)`,
+and return the one with the best match level.
+
+Params:
+    sc = scope
+    tiargs = (optional) template arguments to instantiate symbols with
+    s = (optional) symbol of straightforward template (e.g. opBinary)
+    s_r = (optional) symbol of reversed template (e.g. opBinaryRight)
+    e = binary expression being overloaded, supplying arguments to the function calls
+    choseReverse = set to true when `s_r` was chosen instead of `s`
+Returns:
+    Resulting operator overload function call, or `null` if neither symbol worked
+*/
+private Expression pickBestBinaryOverload(Scope* sc, Objects* tiargs, Dsymbol s, Dsymbol s_r, BinExp e, out bool choseReverse)
+{
+    if (!s && !s_r)
+        return null;
 
-        case EXP.notEqual      :
-        case EXP.equal         : return visitEqual(e.isEqualExp());
+    Expressions* args1 = new Expressions(1);
+    (*args1)[0] = e.e1;
+    expandTuples(args1);
+    Expressions* args2 = new Expressions(1);
+    (*args2)[0] = e.e2;
+    expandTuples(args2);
+    MatchAccumulator m;
 
-        case EXP.lessOrEqual   :
-        case EXP.greaterThan   :
-        case EXP.greaterOrEqual:
-        case EXP.lessThan      : return visitCmp(cast(CmpExp)e);
+    if (s)
+    {
+        functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2));
+        if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
+            return ErrorExp.get();
+    }
+    FuncDeclaration lastf = m.lastf;
+    int count = m.count;
+    if (s_r)
+    {
+        functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1));
+        if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
+            return ErrorExp.get();
+    }
+    if (m.count > 1)
+    {
+        /* The following if says "not ambiguous" if there's one match
+         * from s and one from s_r, in which case we pick s.
+         * This doesn't follow the spec, but is a workaround for the case
+         * where opEquals was generated from templates and we cannot figure
+         * out if both s and s_r came from the same declaration or not.
+         * The test case is:
+         *   import std.typecons;
+         *   void main() {
+         *    assert(tuple("has a", 2u) == tuple("has a", 1));
+         *   }
+         */
+        if (!(m.lastf == lastf && m.count == 2 && count == 1))
+        {
+            // Error, ambiguous
+            error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
+        }
+    }
+    else if (m.last == MATCH.nomatch)
+    {
+        if (tiargs)
+            return null;
+        m.lastf = null;
+    }
 
-        default:
-            if (auto ex = e.isBinAssignExp()) return visitBinAssign(ex);
-            if (auto ex = e.isBinExp())       return visitBin(ex);
-            if (auto ex = e.isUnaExp())       return visitUna(ex);
-            return visit(e);
+    if (lastf && m.lastf == lastf || !s_r && m.last == MATCH.nomatch)
+    {
+        choseReverse = false;
+        // Rewrite (e1 op e2) as e1.opfunc(e2)
+        return build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s);
+    }
+    else
+    {
+        choseReverse = true;
+        // Rewrite (e1 op e2) as e2.opfunc_r(e1)
+        return build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s_r);
     }
 }
 
 /******************************************
  * Common code for overloading of EqualExp and CmpExp
  */
-private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop)
+private Expression compare_overload(BinExp e, Scope* sc, Identifier id, ref EXP cmpOp, Type[2] aliasThisStop)
 {
     //printf("BinExp::compare_overload(id = %s) %s\n", id.toChars(), e.toChars());
     AggregateDeclaration ad1 = isAggregate(e.e1.type);
     AggregateDeclaration ad2 = isAggregate(e.e2.type);
-    Dsymbol s = null;
-    Dsymbol s_r = null;
-    if (ad1)
-    {
-        s = search_function(ad1, id);
-    }
-    if (ad2)
+    Dsymbol s = search_function(ad1, id);
+    Dsymbol s_r = search_function(ad2, id);
+
+    if (s == s_r)
+        s_r = null;
+
+    bool choseReverse;
+    if (auto res = pickBestBinaryOverload(sc, null, s, s_r, e, choseReverse))
     {
-        s_r = search_function(ad2, id);
-        if (s == s_r)
-            s_r = null;
-    }
-    Objects* tiargs = null;
-    if (s || s_r)
-    {
-        /* Try:
-         *      a.opEquals(b)
-         *      b.opEquals(a)
-         * and see which is better.
-         */
-        Expressions* args1 = new Expressions(1);
-        (*args1)[0] = e.e1;
-        expandTuples(args1);
-        Expressions* args2 = new Expressions(1);
-        (*args2)[0] = e.e2;
-        expandTuples(args2);
-        MatchAccumulator m;
-        if (0 && s && s_r)
-        {
-            printf("s  : %s\n", s.toPrettyChars());
-            printf("s_r: %s\n", s_r.toPrettyChars());
-        }
-        if (s)
-        {
-            functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2));
-            if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
-                return ErrorExp.get();
-        }
-        FuncDeclaration lastf = m.lastf;
-        int count = m.count;
-        if (s_r)
-        {
-            functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1));
-            if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
-                return ErrorExp.get();
-        }
-        if (m.count > 1)
-        {
-            /* The following if says "not ambiguous" if there's one match
-             * from s and one from s_r, in which case we pick s.
-             * This doesn't follow the spec, but is a workaround for the case
-             * where opEquals was generated from templates and we cannot figure
-             * out if both s and s_r came from the same declaration or not.
-             * The test case is:
-             *   import std.typecons;
-             *   void main() {
-             *    assert(tuple("has a", 2u) == tuple("has a", 1));
-             *   }
-             */
-            if (!(m.lastf == lastf && m.count == 2 && count == 1))
-            {
-                // Error, ambiguous
-                error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars());
-            }
-        }
-        else if (m.last == MATCH.nomatch)
-        {
-            m.lastf = null;
-        }
-        Expression result;
-        if (lastf && m.lastf == lastf || !s_r && m.last == MATCH.nomatch)
-        {
-            // Rewrite (e1 op e2) as e1.opfunc(e2)
-            result = build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s);
-        }
-        else
-        {
-            // Rewrite (e1 op e2) as e2.opfunc_r(e1)
-            result = build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s_r);
-            // When reversing operands of comparison operators,
-            // need to reverse the sense of the op
-            if (pop)
-                *pop = reverseRelation(e.op);
-        }
-        return result;
+        if (choseReverse)
+            cmpOp = reverseRelation(e.op);
+        return res;
     }
+
     /*
      * https://issues.dlang.org/show_bug.cgi?id=16657
      * at this point, no matching opEquals was found for structs,
@@ -1400,8 +1071,8 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop
      */
     if ((e.op == EXP.equal || e.op == EXP.notEqual) && ad1 == ad2)
         return null;
-    Expression result = checkAliasThisForLhs(ad1, sc, e);
-    return result ? result : checkAliasThisForRhs(isAggregate(e.e2.type), sc, e);
+    Expression result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop);
+    return result ? result : checkAliasThisForRhs(isAggregate(e.e2.type), sc, e, aliasThisStop);
 }
 
 /***********************************
@@ -1425,6 +1096,8 @@ Expression build_overload(const ref Loc loc, Scope* sc, Expression ethis, Expres
  */
 Dsymbol search_function(ScopeDsymbol ad, Identifier funcid)
 {
+    if (!ad)
+        return null;
     if (Dsymbol s = ad.search(Loc.initial, funcid))
     {
         //printf("search_function: s = '%s'\n", s.kind());
index b851b9aafe7e673813601e4115c26aa08cb93bfb..2e29762d010c4b4cc48c9d5be36ec77bf1561200 100644 (file)
@@ -2759,35 +2759,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             error("`new` allocator must be annotated with `@disabled`");
         }
         nextToken();
-
-        /* @@@DEPRECATED_2.108@@@
-         * After deprecation period (2.108), remove all code in the version(all) block.
-         */
-        version (all)
-        {
-            auto parameterList = parseParameterList(null);  // parameterList ignored
-            if (parameterList.parameters.length > 0 || parameterList.varargs != VarArg.none)
-                deprecation("`new` allocator with non-empty parameter list is deprecated");
-            auto f = new AST.NewDeclaration(loc, stc);
-            if (token.value != TOK.semicolon)
-            {
-                deprecation("`new` allocator with function definition is deprecated");
-                parseContracts(f);  // body ignored
-                f.fbody = null;
-                f.fensures = null;
-                f.frequires = null;
-            }
-            else
-                nextToken();
-            return f;
-        }
-        else
-        {
-            check(TOK.leftParenthesis);
-            check(TOK.rightParenthesis);
-            check(TOK.semicolon);
-            return new AST.NewDeclaration(loc, stc);
-        }
+        check(TOK.leftParenthesis);
+        check(TOK.rightParenthesis);
+        check(TOK.semicolon);
+        return new AST.NewDeclaration(loc, stc);
     }
 
     /**********************************************
@@ -5844,7 +5819,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         case TOK.plusPlus:
         case TOK.minusMinus:
         case TOK.new_:
-        case TOK.delete_:
         case TOK.delegate_:
         case TOK.function_:
         case TOK.typeid_:
@@ -8713,15 +8687,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             e = new AST.ComExp(loc, e);
             break;
 
-        case TOK.delete_:
-            // @@@DEPRECATED_2.109@@@
-            // Use of `delete` keyword has been an error since 2.099.
-            // Remove from the parser after 2.109.
-            nextToken();
-            e = parseUnaryExp();
-            e = new AST.DeleteExp(loc, e, false);
-            break;
-
         case TOK.cast_: // cast(type) expression
             {
                 nextToken();
@@ -8839,7 +8804,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                         case TOK.dot:
                         case TOK.plusPlus:
                         case TOK.minusMinus:
-                        case TOK.delete_:
                         case TOK.new_:
                         case TOK.leftParenthesis:
                         case TOK.identifier:
index def7d46d3e499c78dddd060f5f18c32bfab97638..89f612c8760b2ccf850d5c5cbbba99cce26ffcd1 100644 (file)
@@ -270,7 +270,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
         //{ static int x; if (++x == 2) *(char*)0=0; }
         //printf("\tlinkage = %d\n", sc.linkage);
 
-        if (funcdecl.ident == Id.assign && !funcdecl.inuse)
+        if (funcdecl.ident == Id.opAssign && !funcdecl.inuse)
         {
             if (funcdecl.storage_class & STC.inference)
             {
index b499c008eab30e608d639d38cd398718b725d39d..e82a582bee3269fb0d4cc39539eaaaf588f64c8a 100644 (file)
@@ -48,7 +48,6 @@ enum TOK : ubyte
     false_,
     throw_,
     new_,
-    delete_,
     variable,
     slice,
     version_,
@@ -459,7 +458,6 @@ private immutable TOK[] keywords =
     TOK.false_,
     TOK.cast_,
     TOK.new_,
-    TOK.delete_,
     TOK.throw_,
     TOK.module_,
     TOK.pragma_,
@@ -680,7 +678,6 @@ extern (C++) struct Token
         TOK.false_: "false",
         TOK.cast_: "cast",
         TOK.new_: "new",
-        TOK.delete_: "delete",
         TOK.throw_: "throw",
         TOK.module_: "module",
         TOK.pragma_: "pragma",
index 2a984b4b7b621cf016dca07b6a428ab2a965ea4f..c12a00b7bb6e673b3e8d3adf682bb9f6bad18b3b 100644 (file)
@@ -54,7 +54,6 @@ enum class TOK : unsigned char
     false_,
     throw_,
     new_,
-    delete_,
     variable,
     slice,
     version_,
index ca10db1a2f5e1e3203b3bfe2861011ed6746043d..65d267f155a3179ccacc4221992acbcb56fc4bb5 100644 (file)
@@ -2025,7 +2025,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
             }
             else if (sd.xeq == sd.xerreq)
             {
-                if (search_function(sd, Id.eq))
+                if (search_function(sd, Id.opEquals))
                 {
                     .error(loc, "%sAA key type `%s` does not have `bool opEquals(ref const %s) const`", s, sd.toChars(), sd.toChars());
                 }
@@ -2037,7 +2037,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
             }
             else if (!sd.xhash)
             {
-                if (search_function(sd, Id.eq))
+                if (search_function(sd, Id.opEquals))
                 {
                     .error(loc, "%sAA key type `%s` should have `extern (D) size_t toHash() const nothrow @safe` if `opEquals` defined", s, sd.toChars());
                 }
@@ -2075,9 +2075,9 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
             __gshared FuncDeclaration fcmp = null;
             __gshared FuncDeclaration fhash = null;
             if (!feq)
-                feq = search_function(ClassDeclaration.object, Id.eq).isFuncDeclaration();
+                feq = search_function(ClassDeclaration.object, Id.opEquals).isFuncDeclaration();
             if (!fcmp)
-                fcmp = search_function(ClassDeclaration.object, Id.cmp).isFuncDeclaration();
+                fcmp = search_function(ClassDeclaration.object, Id.opCmp).isFuncDeclaration();
             if (!fhash)
                 fhash = search_function(ClassDeclaration.object, Id.tohash).isFuncDeclaration();
             assert(fcmp && feq && fhash);
@@ -3417,7 +3417,7 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
 
         if (s)
             error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident.toChars(), mt.toChars(), s.toPrettyChars());
-        else if (ident == Id.call && mt.ty == Tclass)
+        else if (ident == Id.opCall && mt.ty == Tclass)
             error(loc, "no property `%s` for type `%s`, did you mean `new %s`?", ident.toChars(), mt.toChars(), mt.toPrettyChars());
 
         else if (const n = importHint(ident.toString()))
@@ -4883,7 +4883,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
 
     /***************************************
      * `ident` was not found as a member of `mt`.
-     * Attempt to use overloaded opDot(), overloaded opDispatch(), or `alias this`.
+     * Attempt to use overloaded opDispatch() or `alias this`.
      * If that fails, forward to visitType().
      * Params:
      *  mt = class or struct
@@ -4939,21 +4939,6 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag
             ident != Id.postblit &&
             ident != Id.__xpostblit)
         {
-            /* Look for overloaded opDot() to see if we should forward request
-             * to it.
-             */
-            if (auto fd = search_function(sym, Id.opDot))
-            {
-                /* Rewrite e.ident as:
-                 *  e.opDot().ident
-                 */
-                e = build_overload(e.loc, sc, e, null, fd);
-                // @@@DEPRECATED_2.110@@@.
-                // Deprecated in 2.082, made an error in 2.100.
-                error(e.loc, "`opDot` is obsolete. Use `alias this`");
-                return ErrorExp.get();
-            }
-
             /* Look for overloaded opDispatch to see if we should forward request
              * to it.
              */
index aa88458ad77e685758ad7591966fdce7bb1aceab..f62147a0db4a2c3770a62b74127b2a51ff21b084 100644 (file)
@@ -6240,9 +6240,9 @@ struct Coord13831
 
 struct Chunk13831
 {
-    this(Coord13831)
+    this(Coord13831 coord)
     {
-        coord = coord;
+        this.coord = coord;
     }
 
     Coord13831 coord;
index 959adc499cc0f2b86b76570276fc02d3cfd82b27..5f14339b6137f559d386c0e31a7053fd8fe9a3a6 100644 (file)
@@ -36,9 +36,6 @@ void foo_compiles() {}
     static assert(!__traits(compiles, new Struct()));
     static assert(!__traits(compiles, new Object()));
 
-    int* p;
-    static assert(!__traits(compiles, delete p));
-
     int[int] aa;
     static assert( __traits(compiles, aa[0]));
     static assert(!__traits(compiles, (aa[0] = 10)));
index af5d0a433eb9103a4a7d49288463db221c9f66d7..1207bf0226249ae9322b5b94f7cabf427edf377f 100644 (file)
@@ -7,7 +7,7 @@ struct S
     @disable this(this);
     this (scope ref inout S) inout
     {
-       this.b = b;
+       this.b = 0;
     }
 }
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ctor_self_assignment.d b/gcc/testsuite/gdc.test/fail_compilation/ctor_self_assignment.d
new file mode 100644 (file)
index 0000000..9d424b1
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+REQUIRED_ARGS: -de
+TEST_OUTPUT:
+---
+fail_compilation/ctor_self_assignment.d(17): Deprecation: cannot initialize field `location` with itself
+fail_compilation/ctor_self_assignment.d(15):        did you mean to use parameter `locaction`?
+---
+*/
+// https://forum.dlang.org/post/teghfhpmvkdcfwfeovua@forum.dlang.org
+
+alias Location = int;
+
+struct Node
+{
+    this(Location locaction, uint f)
+    {
+        this.location = location;
+        this.f = f;
+    }
+
+    Location location;
+    uint f;
+}
index 19c64752aaf1148262f10ab064bd51551a4144c4..f8ebc37f80193724aeaa6e9fc069e43e57ee7dc4 100644 (file)
@@ -1,52 +1,93 @@
 /*
-REQUIRED_ARGS: -de
+REQUIRED_ARGS:
 TEST_OUTPUT:
 ---
-fail_compilation/dep_d1_ops.d(105): Error: `opAdd` is obsolete.  Use `opBinary(string op)(...) if (op == "+")` instead.
-fail_compilation/dep_d1_ops.d(106): Error: `opAdd_r` is obsolete.  Use `opBinaryRight(string op)(...) if (op == "+")` instead.
-fail_compilation/dep_d1_ops.d(107): Error: `opSub` is obsolete.  Use `opBinary(string op)(...) if (op == "-")` instead.
-fail_compilation/dep_d1_ops.d(108): Error: `opSub_r` is obsolete.  Use `opBinaryRight(string op)(...) if (op == "-")` instead.
-fail_compilation/dep_d1_ops.d(109): Error: `opMul` is obsolete.  Use `opBinary(string op)(...) if (op == "*")` instead.
-fail_compilation/dep_d1_ops.d(110): Error: `opMul_r` is obsolete.  Use `opBinaryRight(string op)(...) if (op == "*")` instead.
-fail_compilation/dep_d1_ops.d(111): Error: `opDiv` is obsolete.  Use `opBinary(string op)(...) if (op == "/")` instead.
-fail_compilation/dep_d1_ops.d(112): Error: `opDiv_r` is obsolete.  Use `opBinaryRight(string op)(...) if (op == "/")` instead.
-fail_compilation/dep_d1_ops.d(113): Error: `opMod` is obsolete.  Use `opBinary(string op)(...) if (op == "%")` instead.
-fail_compilation/dep_d1_ops.d(114): Error: `opMod_r` is obsolete.  Use `opBinaryRight(string op)(...) if (op == "%")` instead.
-fail_compilation/dep_d1_ops.d(116): Error: `opAnd` is obsolete.  Use `opBinary(string op)(...) if (op == "&")` instead.
-fail_compilation/dep_d1_ops.d(117): Error: `opOr` is obsolete.  Use `opBinary(string op)(...) if (op == "|")` instead.
-fail_compilation/dep_d1_ops.d(118): Error: `opXor` is obsolete.  Use `opBinary(string op)(...) if (op == "^")` instead.
-fail_compilation/dep_d1_ops.d(120): Error: `opShl` is obsolete.  Use `opBinary(string op)(...) if (op == "<<")` instead.
-fail_compilation/dep_d1_ops.d(121): Error: `opShl_r` is obsolete.  Use `opBinaryRight(string op)(...) if (op == "<<")` instead.
-fail_compilation/dep_d1_ops.d(122): Error: `opShr` is obsolete.  Use `opBinary(string op)(...) if (op == ">>")` instead.
-fail_compilation/dep_d1_ops.d(123): Error: `opShr_r` is obsolete.  Use `opBinaryRight(string op)(...) if (op == ">>")` instead.
-fail_compilation/dep_d1_ops.d(124): Error: `opUShr` is obsolete.  Use `opBinary(string op)(...) if (op == ">>>")` instead.
-fail_compilation/dep_d1_ops.d(125): Error: `opUShr_r` is obsolete.  Use `opBinaryRight(string op)(...) if (op == ">>>")` instead.
-fail_compilation/dep_d1_ops.d(127): Error: `opCat` is obsolete.  Use `opBinary(string op)(...) if (op == "~")` instead.
-fail_compilation/dep_d1_ops.d(128): Error: `opCat_r` is obsolete.  Use `opBinaryRight(string op)(...) if (op == "~")` instead.
-fail_compilation/dep_d1_ops.d(130): Error: `opNeg` is obsolete.  Use `opUnary(string op)() if (op == "-")` instead.
-fail_compilation/dep_d1_ops.d(131): Error: `opCom` is obsolete.  Use `opUnary(string op)() if (op == "~")` instead.
-fail_compilation/dep_d1_ops.d(132): Error: `opPostInc` is obsolete.  Use `opUnary(string op)() if (op == "++")` instead.
-fail_compilation/dep_d1_ops.d(133): Error: `opPostDec` is obsolete.  Use `opUnary(string op)() if (op == "--")` instead.
-fail_compilation/dep_d1_ops.d(134): Error: `opStar` is obsolete.  Use `opUnary(string op)() if (op == "*")` instead.
-fail_compilation/dep_d1_ops.d(136): Error: `opIn` is obsolete.  Use `opBinary(string op)(...) if (op == "in")` instead.
-fail_compilation/dep_d1_ops.d(137): Error: `opIn_r` is obsolete.  Use `opBinaryRight(string op)(...) if (op == "in")` instead.
-fail_compilation/dep_d1_ops.d(139): Error: `opAddAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == "+")` instead.
-fail_compilation/dep_d1_ops.d(140): Error: `opSubAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == "-")` instead.
-fail_compilation/dep_d1_ops.d(141): Error: `opMulAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == "*")` instead.
-fail_compilation/dep_d1_ops.d(142): Error: `opDivAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == "/")` instead.
-fail_compilation/dep_d1_ops.d(143): Error: `opModAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == "%")` instead.
-fail_compilation/dep_d1_ops.d(144): Error: `opAndAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == "&")` instead.
-fail_compilation/dep_d1_ops.d(145): Error: `opOrAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == "|")` instead.
-fail_compilation/dep_d1_ops.d(146): Error: `opXorAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == "^")` instead.
-fail_compilation/dep_d1_ops.d(147): Error: `opShlAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == "<<")` instead.
-fail_compilation/dep_d1_ops.d(148): Error: `opShrAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == ">>")` instead.
-fail_compilation/dep_d1_ops.d(149): Error: `opUShrAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == ">>>")` instead.
-fail_compilation/dep_d1_ops.d(150): Error: `opCatAssign` is obsolete.  Use `opOpAssign(string op)(...) if (op == "~")` instead.
-fail_compilation/dep_d1_ops.d(158): Error: `opCom` is obsolete.  Use `opUnary(string op)() if (op == "~")` instead.
+fail_compilation/dep_d1_ops.d(198): Error: incompatible types for `(s) + (1)`: `S` and `int`
+fail_compilation/dep_d1_ops.d(199): Error: incompatible types for `(1) + (s)`: `int` and `S`
+fail_compilation/dep_d1_ops.d(200): Error: incompatible types for `(s) - (1)`: `S` and `int`
+fail_compilation/dep_d1_ops.d(201): Error: incompatible types for `(1) - (s)`: `int` and `S`
+fail_compilation/dep_d1_ops.d(202): Error: incompatible types for `(s) * (1)`: `S` and `int`
+fail_compilation/dep_d1_ops.d(203): Error: incompatible types for `(1) * (s)`: `int` and `S`
+fail_compilation/dep_d1_ops.d(204): Error: incompatible types for `(s) / (1)`: `S` and `int`
+fail_compilation/dep_d1_ops.d(205): Error: incompatible types for `(1) / (s)`: `int` and `S`
+fail_compilation/dep_d1_ops.d(206): Error: incompatible types for `(s) % (1)`: `S` and `int`
+fail_compilation/dep_d1_ops.d(207): Error: incompatible types for `(1) % (s)`: `int` and `S`
+fail_compilation/dep_d1_ops.d(209): Error: incompatible types for `(s) & (1)`: `S` and `int`
+fail_compilation/dep_d1_ops.d(210): Error: incompatible types for `(s) | (1)`: `S` and `int`
+fail_compilation/dep_d1_ops.d(211): Error: incompatible types for `(s) ^ (1)`: `S` and `int`
+fail_compilation/dep_d1_ops.d(213): Error: `s` is not of integral type, it is a `S`
+fail_compilation/dep_d1_ops.d(214): Error: `s` is not of integral type, it is a `S`
+fail_compilation/dep_d1_ops.d(215): Error: `s` is not of integral type, it is a `S`
+fail_compilation/dep_d1_ops.d(216): Error: `s` is not of integral type, it is a `S`
+fail_compilation/dep_d1_ops.d(217): Error: `s` is not of integral type, it is a `S`
+fail_compilation/dep_d1_ops.d(218): Error: `s` is not of integral type, it is a `S`
+fail_compilation/dep_d1_ops.d(220): Error: incompatible types for `(s) ~ (1)`: `S` and `int`
+fail_compilation/dep_d1_ops.d(221): Error: incompatible types for `(1) ~ (s)`: `int` and `S`
+fail_compilation/dep_d1_ops.d(223): Error: operator `+` is not defined for `s` of type `S`
+fail_compilation/dep_d1_ops.d(224): Error: operator `-` is not defined for `s` of type `S`
+fail_compilation/dep_d1_ops.d(225): Error: `s` is not of integral type, it is a `S`
+fail_compilation/dep_d1_ops.d(226): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(227): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(228): Error: can only `*` a pointer, not a `S`
+fail_compilation/dep_d1_ops.d(230): Error: incompatible types for `(s) in (1)`: `S` and `int`
+fail_compilation/dep_d1_ops.d(231): Error: incompatible types for `(1) in (s)`: `int` and `S`
+fail_compilation/dep_d1_ops.d(233): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(234): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(235): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(236): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(237): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(238): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(239): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(240): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(241): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(242): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(243): Error: `s` is not a scalar, it is a `S`
+fail_compilation/dep_d1_ops.d(244): Error: cannot append type `int` to type `S`
+fail_compilation/dep_d1_ops.d(248): Error: incompatible types for `(c) + (1)`: `dep_d1_ops.C` and `int`
+fail_compilation/dep_d1_ops.d(249): Error: incompatible types for `(1) + (c)`: `int` and `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(250): Error: incompatible types for `(c) - (1)`: `dep_d1_ops.C` and `int`
+fail_compilation/dep_d1_ops.d(251): Error: incompatible types for `(1) - (c)`: `int` and `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(252): Error: incompatible types for `(c) * (1)`: `dep_d1_ops.C` and `int`
+fail_compilation/dep_d1_ops.d(253): Error: incompatible types for `(1) * (c)`: `int` and `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(254): Error: incompatible types for `(c) / (1)`: `dep_d1_ops.C` and `int`
+fail_compilation/dep_d1_ops.d(255): Error: incompatible types for `(1) / (c)`: `int` and `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(256): Error: incompatible types for `(c) % (1)`: `dep_d1_ops.C` and `int`
+fail_compilation/dep_d1_ops.d(257): Error: incompatible types for `(1) % (c)`: `int` and `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(259): Error: incompatible types for `(c) & (1)`: `dep_d1_ops.C` and `int`
+fail_compilation/dep_d1_ops.d(260): Error: incompatible types for `(c) | (1)`: `dep_d1_ops.C` and `int`
+fail_compilation/dep_d1_ops.d(261): Error: incompatible types for `(c) ^ (1)`: `dep_d1_ops.C` and `int`
+fail_compilation/dep_d1_ops.d(263): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(264): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(265): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(266): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(267): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(268): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(270): Error: incompatible types for `(c) ~ (1)`: `dep_d1_ops.C` and `int`
+fail_compilation/dep_d1_ops.d(271): Error: incompatible types for `(1) ~ (c)`: `int` and `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(273): Error: operator `+` is not defined for `c` of type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(274): Error: operator `-` is not defined for `c` of type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(275): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(276): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(277): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(278): Error: can only `*` a pointer, not a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(280): Error: incompatible types for `(c) in (1)`: `dep_d1_ops.C` and `int`
+fail_compilation/dep_d1_ops.d(281): Error: incompatible types for `(1) in (c)`: `int` and `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(283): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(284): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(285): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(286): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(287): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(288): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(289): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(290): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(291): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(292): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(293): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(294): Error: cannot append type `int` to type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(303): Error: `nd` is not of integral type, it is a `dep_d1_ops.NoDeprecation`
 ---
 */
 
-#line 50
 struct S
 {
     int opAdd(int i) { return 0; }
@@ -74,6 +115,58 @@ struct S
     int opCat(int i) { return 0; }
     int opCat_r(int i) { return 0; }
 
+    int opPos() { return 0; }
+    int opNeg() { return 0; }
+    int opCom() { return 0; }
+    int opPostInc() { return 0; }
+    int opPostDec() { return 0; }
+    int opStar() { return 0; }
+
+    int opIn(int i) { return 0; }
+    int opIn_r(int i) { return 0; }
+
+    int opAddAssign(int i) { return 0; }
+    int opSubAssign(int i) { return 0; }
+    int opMulAssign(int i) { return 0; }
+    int opDivAssign(int i) { return 0; }
+    int opModAssign(int i) { return 0; }
+    int opAndAssign(int i) { return 0; }
+    int opOrAssign(int i) { return 0; }
+    int opXorAssign(int i) { return 0; }
+    int opShlAssign(int i) { return 0; }
+    int opShrAssign(int i) { return 0; }
+    int opUShrAssign(int i) { return 0; }
+    int opCatAssign(int i) { return 0; }
+}
+
+class C
+{
+    int opAdd(int i) { return 0; }
+    int opAdd_r(int i) { return 0; }
+    int opSub(int i) { return 0; }
+    int opSub_r(int i) { return 0; }
+    int opMul(int i) { return 0; }
+    int opMul_r(int i) { return 0; }
+    int opDiv(int i) { return 0; }
+    int opDiv_r(int i) { return 0; }
+    int opMod(int i) { return 0; }
+    int opMod_r(int i) { return 0; }
+
+    int opAnd(int i) { return 0; }
+    int opOr(int i) { return 0; }
+    int opXor(int i) { return 0; }
+
+    int opShl(int i) { return 0; }
+    int opShl_r(int i) { return 0; }
+    int opShr(int i) { return 0; }
+    int opShr_r(int i) { return 0; }
+    int opUShr(int i) { return 0; }
+    int opUShr_r(int i) { return 0; }
+
+    int opCat(int i) { return 0; }
+    int opCat_r(int i) { return 0; }
+
+    int opPos() { return 0; }
     int opNeg() { return 0; }
     int opCom() { return 0; }
     int opPostInc() { return 0; }
@@ -99,55 +192,107 @@ struct S
 
 void main()
 {
-    S s;
     int i;
+    {
+        S s;
+        i = s + 1;
+        i = 1 + s;
+        i = s - 1;
+        i = 1 - s;
+        i = s * 1;
+        i = 1 * s;
+        i = s / 1;
+        i = 1 / s;
+        i = s % 1;
+        i = 1 % s;
+
+        i = s & 1;
+        i = s | 1;
+        i = s ^ 1;
+
+        i = s << 1;
+        i = 1 << s;
+        i = s >> 1;
+        i = 1 >> s;
+        i = s >>> 1;
+        i = 1 >>> s;
+
+        i = s ~ 1;
+        i = 1 ~ s;
+
+        i = +s;
+        i = -s;
+        i = ~s;
+        s++;
+        s--;
+        i = *s;
+
+        i = s in 1;
+        i = 1 in s;
+
+        s += 1;
+        s -= 1;
+        s *= 1;
+        s /= 1;
+        s %= 1;
+        s &= 1;
+        s |= 1;
+        s ^= 1;
+        s <<= 1;
+        s >>= 1;
+        s >>>= 1;
+        s ~= 1;
+    }
+    {
+        C c;
+        i = c + 1;
+        i = 1 + c;
+        i = c - 1;
+        i = 1 - c;
+        i = c * 1;
+        i = 1 * c;
+        i = c / 1;
+        i = 1 / c;
+        i = c % 1;
+        i = 1 % c;
+
+        i = c & 1;
+        i = c | 1;
+        i = c ^ 1;
+
+        i = c << 1;
+        i = 1 << c;
+        i = c >> 1;
+        i = 1 >> c;
+        i = c >>> 1;
+        i = 1 >>> c;
 
-    i = s + 1;
-    i = 1 + s;
-    i = s - 1;
-    i = 1 - s;
-    i = s * 1;
-    i = 1 * s;
-    i = s / 1;
-    i = 1 / s;
-    i = s % 1;
-    i = 1 % s;
-
-    i = s & 1;
-    i = s | 1;
-    i = s ^ 1;
-
-    i = s << 1;
-    i = 1 << s;
-    i = s >> 1;
-    i = 1 >> s;
-    i = s >>> 1;
-    i = 1 >>> s;
-
-    i = s ~ 1;
-    i = 1 ~ s;
-
-    i = -s;
-    i = ~s;
-    s++;
-    s--;
-    i = *s;
-
-    i = s in 1;
-    i = 1 in s;
-
-    s += 1;
-    s -= 1;
-    s *= 1;
-    s /= 1;
-    s %= 1;
-    s &= 1;
-    s |= 1;
-    s ^= 1;
-    s <<= 1;
-    s >>= 1;
-    s >>>= 1;
-    s ~= 1;
+        i = c ~ 1;
+        i = 1 ~ c;
+
+        i = +c;
+        i = -c;
+        i = ~c;
+        c++;
+        c--;
+        i = *c;
+
+        i = c in 1;
+        i = 1 in c;
+
+        c += 1;
+        c -= 1;
+        c *= 1;
+        c /= 1;
+        c %= 1;
+        c &= 1;
+        c |= 1;
+        c ^= 1;
+        c <<= 1;
+        c >>= 1;
+        c >>>= 1;
+        c ~= 1;
+    }
 
     scope nd = new NoDeprecation;
     assert((42 in nd) == 0);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/deprecateopdot.d b/gcc/testsuite/gdc.test/fail_compilation/deprecateopdot.d
deleted file mode 100644 (file)
index 46c9493..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-REQUIRED_ARGS: -de
-TEST_OUTPUT:
----
-fail_compilation/deprecateopdot.d(27): Error: `opDot` is obsolete. Use `alias this`
-fail_compilation/deprecateopdot.d(28): Error: `opDot` is obsolete. Use `alias this`
-fail_compilation/deprecateopdot.d(29): Error: `opDot` is obsolete. Use `alias this`
----
-*/
-struct S6
-{
-    int a, b;
-}
-struct T6
-{
-    S6 s;
-
-    S6* opDot() return
-    {
-        return &s;
-    }
-}
-
-void test6()
-{
-    T6 t;
-    t.a = 4;
-    assert(t.a == 4);
-    t.b = 5;
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag_class_alloc.d b/gcc/testsuite/gdc.test/fail_compilation/diag_class_alloc.d
deleted file mode 100644 (file)
index 326d82e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/diag_class_alloc.d(15): Error: `new` allocator must be annotated with `@disabled`
-fail_compilation/diag_class_alloc.d(16): Deprecation: `new` allocator with non-empty parameter list is deprecated
-fail_compilation/diag_class_alloc.d(16): Deprecation: `new` allocator with function definition is deprecated
----
-*/
-
-// This test exists to ensure class allocators and deallocators emit an appropriate error message.
-// This test can be deleted when class allocators and deallocators are removed from the language.
-
-class C
-{
-    new(size_t size)         // error message
-    {
-        return malloc(size);
-    }
-}
index b5bb67c26786e5e01e653a93de5dc559737a477d..f0e0b855b718e62dc5ff596997a99fafc7464f4d 100644 (file)
@@ -1,22 +1,18 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail10534.d(28): Error: illegal operator `+` for `a` of type `int delegate()`
-fail_compilation/fail10534.d(28): Error: illegal operator `+` for `b` of type `int delegate()`
-fail_compilation/fail10534.d(29): Error: illegal operator `-` for `a` of type `int delegate()`
-fail_compilation/fail10534.d(29): Error: illegal operator `-` for `b` of type `int delegate()`
-fail_compilation/fail10534.d(30): Error: illegal operator `/` for `a` of type `int delegate()`
-fail_compilation/fail10534.d(30): Error: illegal operator `/` for `b` of type `int delegate()`
-fail_compilation/fail10534.d(31): Error: illegal operator `*` for `a` of type `int delegate()`
-fail_compilation/fail10534.d(31): Error: illegal operator `*` for `b` of type `int delegate()`
-fail_compilation/fail10534.d(36): Error: illegal operator `+` for `a` of type `int function()`
-fail_compilation/fail10534.d(36): Error: illegal operator `+` for `b` of type `int function()`
-fail_compilation/fail10534.d(37): Error: illegal operator `-` for `a` of type `int function()`
-fail_compilation/fail10534.d(37): Error: illegal operator `-` for `b` of type `int function()`
-fail_compilation/fail10534.d(38): Error: illegal operator `/` for `a` of type `int function()`
-fail_compilation/fail10534.d(38): Error: illegal operator `/` for `b` of type `int function()`
-fail_compilation/fail10534.d(39): Error: illegal operator `*` for `a` of type `int function()`
-fail_compilation/fail10534.d(39): Error: illegal operator `*` for `b` of type `int function()`
+fail_compilation/fail10534.d(24): Error: illegal operator `+` for `a` of type `int delegate()`
+fail_compilation/fail10534.d(24): Error: illegal operator `+` for `b` of type `int delegate()`
+fail_compilation/fail10534.d(25): Error: illegal operator `-` for `a` of type `int delegate()`
+fail_compilation/fail10534.d(25): Error: illegal operator `-` for `b` of type `int delegate()`
+fail_compilation/fail10534.d(26): Error: illegal operator `/` for `a` of type `int delegate()`
+fail_compilation/fail10534.d(27): Error: illegal operator `*` for `a` of type `int delegate()`
+fail_compilation/fail10534.d(32): Error: illegal operator `+` for `a` of type `int function()`
+fail_compilation/fail10534.d(32): Error: illegal operator `+` for `b` of type `int function()`
+fail_compilation/fail10534.d(33): Error: illegal operator `-` for `a` of type `int function()`
+fail_compilation/fail10534.d(33): Error: illegal operator `-` for `b` of type `int function()`
+fail_compilation/fail10534.d(34): Error: illegal operator `/` for `a` of type `int function()`
+fail_compilation/fail10534.d(35): Error: illegal operator `*` for `a` of type `int function()`
 ---
 */
 
index 3295b243815a29155a3000798578674d95f10f09..e4105b8d9241b8b778d35cc63331bf3794820e21 100644 (file)
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail11445.d(11): Error: incompatible types for `(a) + (b)`: both operands are of type `double[string]`
+fail_compilation/fail11445.d(11): Error: illegal operator `+` for `a` of type `double[string]`
 ---
 */
 
index 9c82b2c28153ac4ae1ef1b7cab1963ba8ae5a2ff..a1c1bab986bfc1c32a25f10a92cd0ef49576aafe 100644 (file)
@@ -14,7 +14,7 @@ fail_compilation/fail13902.d(33): Error: returning `&s1.v` escapes a reference t
 fail_compilation/fail13902.d(38): Error: returning `& sa1` escapes a reference to local variable `sa1`
 fail_compilation/fail13902.d(39): Error: returning `& sa2` escapes a reference to local variable `sa2`
 fail_compilation/fail13902.d(40): Error: returning `& x` escapes a reference to local variable `x`
-fail_compilation/fail13902.d(41): Error: returning `(& x+4)` escapes a reference to local variable `x`
+fail_compilation/fail13902.d(41): Error: returning `(& x + 4)` escapes a reference to local variable `x`
 fail_compilation/fail13902.d(42): Error: returning `& x + cast(long)x * 4L` escapes a reference to local variable `x`
 fail_compilation/fail13902.d(45): Error: returning `& y` escapes a reference to local variable `y`
 ---
@@ -59,7 +59,7 @@ fail_compilation/fail13902.d(76): Error: returning `&s1.v` escapes a reference t
 fail_compilation/fail13902.d(81): Error: returning `& sa1` escapes a reference to parameter `sa1`
 fail_compilation/fail13902.d(82): Error: returning `& sa2` escapes a reference to parameter `sa2`
 fail_compilation/fail13902.d(83): Error: returning `& x` escapes a reference to parameter `x`
-fail_compilation/fail13902.d(84): Error: returning `(& x+4)` escapes a reference to parameter `x`
+fail_compilation/fail13902.d(84): Error: returning `(& x + 4)` escapes a reference to parameter `x`
 fail_compilation/fail13902.d(85): Error: returning `& x + cast(long)x * 4L` escapes a reference to parameter `x`
 fail_compilation/fail13902.d(88): Error: returning `& y` escapes a reference to parameter `y`
 ---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail14343.d b/gcc/testsuite/gdc.test/fail_compilation/fail14343.d
new file mode 100644 (file)
index 0000000..d644ec9
--- /dev/null
@@ -0,0 +1,25 @@
+// https://issues.dlang.org/show_bug.cgi?id=14343
+/* TEST_OUTPUT:
+---
+fail_compilation/fail14343.d(21): Error: cannot modify struct instance `s` of type `S14343b` because it contains `const` or `immutable` members
+fail_compilation/fail14343.d(23): Error: cannot modify struct instance `s` of type `S14343b` because it contains `const` or `immutable` members
+---
+*/
+
+struct S14343b
+{
+    int i;
+    immutable(Object) o;
+
+    void opAddAssign(int j) { i += j; }
+    void opAssign(S14343b other) {}
+}
+
+void test14343()
+{
+    S14343b s;
+    ++s;
+    assert(s.i == 1);
+    s++;
+    assert(s.i == 2);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail14486.d b/gcc/testsuite/gdc.test/fail_compilation/fail14486.d
deleted file mode 100644 (file)
index 3531245..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-// REQUIRED_ARGS: -o-
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail14486.d(47): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(47):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/fail14486.d(48): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(48):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/fail14486.d(53): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(53):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/fail14486.d(54): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(54):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/fail14486.d(59): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(59):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/fail14486.d(60): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(60):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/fail14486.d(65): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(65):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/fail14486.d(66): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(66):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/fail14486.d(71): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(71):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/fail14486.d(72): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(72):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/fail14486.d(77): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(77):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/fail14486.d(78): Error: the `delete` keyword is obsolete
-fail_compilation/fail14486.d(78):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
----
-*/
-
-class  C0a { }
-class  C1a {                  ~this() {} }
-
-class  C0b { }
-class  C1b {                  ~this() {} }
-
-struct S0a { }
-struct S1a {                  ~this() {} }
-
-struct S0b { }
-struct S1b {                  ~this() {} }
-
-void test1a() @nogc pure @safe
-{
-    C0a   c0;  delete c0;   // error
-    C1a   c1;  delete c1;   // error
-}
-
-void test1b() nothrow
-{
-    C0b   c0;  delete c0;    // no error
-    C1b   c1;  delete c1;    // error
-}
-
-void test2a() @nogc pure @safe
-{
-    S0a*  s0;  delete s0;   // error
-    S1a*  s1;  delete s1;   // error
-}
-
-void test2b() nothrow
-{
-    S0b*  s0;  delete s0;    // no error
-    S1b*  s1;  delete s1;    // error
-}
-
-void test3a() @nogc pure @safe
-{
-    S0a[] a0;  delete a0;   // error
-    S1a[] a1;  delete a1;   // error
-}
-
-void test3b() nothrow
-{
-    S0b[] a0;  delete a0;    // no error
-    S1b[] a1;  delete a1;    // error
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17906.d b/gcc/testsuite/gdc.test/fail_compilation/fail17906.d
deleted file mode 100644 (file)
index 41f7465..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// REQUIRED_ARGS: -de
-/* TEST_OUTPUT:
----
-fail_compilation/fail17906.d(12): Error: the `delete` keyword is obsolete
-fail_compilation/fail17906.d(12):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
----
-*/
-// https://issues.dlang.org/show_bug.cgi?id=18647
-deprecated void main ()
-{
-    Object o = new Object;
-    delete o;
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail2361.d b/gcc/testsuite/gdc.test/fail_compilation/fail2361.d
deleted file mode 100644 (file)
index ffc12f1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail2361.d(14): Error: the `delete` keyword is obsolete
-fail_compilation/fail2361.d(14):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
----
-*/
-
-class C {}
-
-void main()
-{
-    immutable c = new immutable(C);
-    delete c;
-}
index 5fc3bbf8e575e4d205595a8feed79be6fbddfad0..3bb25dd0fae483eeaf2e75994a46c0b2bc1ecaf8 100644 (file)
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail297.d(30): Error: incompatible types for `(Bar()) + (baz())`: `Bar` and `const(Bar)`
+fail_compilation/fail297.d(30): Error: operator `+` is not defined for `Bar()` of type `Bar`
 ---
 */
 
index 5c1ea9178bdf613c463a5d800818108b36a3f3dd..1c40c4f93c7696015fb0dfbc05b602ce4ae4be34 100644 (file)
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail3.d(41): Error: incompatible types for `(a) + (b)`: both operands are of type `vec2`
+fail_compilation/fail3.d(41): Error: operator `+` is not defined for `a` of type `vec2`
 ---
 */
 
index 0db6a45c9a285c1f6133e7b5371678280625e1dd..a8b53f1e95f9cd02cddc1df36b86659214207a9b 100644 (file)
@@ -209,8 +209,6 @@ fail_compilation/fail_arrayop2.d(269): Error: array operation `"abc"[] + '\x01'`
 fail_compilation/fail_arrayop2.d(272): Error: array operation `[1] * 6` without destination memory not allowed
 fail_compilation/fail_arrayop2.d(275): Error: cannot take address of expression `([1] * 6)[0..2]` because it is not an lvalue
 fail_compilation/fail_arrayop2.d(278): Error: can only `*` a pointer, not a `int[]`
-fail_compilation/fail_arrayop2.d(281): Error: the `delete` keyword is obsolete
-fail_compilation/fail_arrayop2.d(281):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
 fail_compilation/fail_arrayop2.d(284): Error: array operation `da[] * 6` without destination memory not allowed
 fail_compilation/fail_arrayop2.d(287): Error: array operation `da[] * 6` without destination memory not allowed
 fail_compilation/fail_arrayop2.d(290): Error: cannot modify expression `[1] * 6` because it is not an lvalue
@@ -235,6 +233,8 @@ fail_compilation/fail_arrayop2.d(321): Error: array operation `[1] * 6` without
 fail_compilation/fail_arrayop2.d(321): Error: array operation `[1] * 6` without destination memory not allowed
 ---
 */
+
+
 // Test all expressions, which can take arrays as their operands but cannot be a part of array operation.
 void test15407exp()
 {
@@ -277,8 +277,8 @@ void test15407exp()
     // PtrExp, *([1] * 6).ptr is also invalid -> show better diagnostic
     { auto r = *([1] * 6); }
 
-    // DeleteExp - e1
-    delete ([1] * 6);
+
+
 
     // TypeDArray.dotExp, cannot check in ArrayLengthExp.semantic()
     { auto r = (6 * da[]).length; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/faildeleteaa.d b/gcc/testsuite/gdc.test/fail_compilation/faildeleteaa.d
deleted file mode 100644 (file)
index ed640fb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/faildeleteaa.d(12): Error: the `delete` keyword is obsolete
-fail_compilation/faildeleteaa.d(12):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
----
-*/
-
-void main()
-{
-    int[int] aa = [1 : 2];
-    delete aa[1];
-}
index edbb4e67bc0daf0f08cf608f5d920cc9391423ab..2c6191e7f959df8bd4d07a8cfa7f7ff989f1911f 100644 (file)
@@ -1,21 +1,24 @@
 /**
 TEST_OUTPUT:
 ---
-fail_compilation/hexstring.d(29): Error: cannot implicitly convert expression `"123F"` of type `string` to `immutable(ubyte[])`
-fail_compilation/hexstring.d(33): Error: hex string length 1 must be a multiple of 2 to cast to `immutable(ushort[])`
-fail_compilation/hexstring.d(34): Error: hex string length 3 must be a multiple of 4 to cast to `immutable(uint[])`
-fail_compilation/hexstring.d(35): Error: hex string length 5 must be a multiple of 8 to cast to `immutable(ulong[])`
-fail_compilation/hexstring.d(36): Error: array cast from `wstring` to `immutable(ulong[])` is not supported at compile time
-fail_compilation/hexstring.d(36):        perhaps remove postfix `w` from hex string
-fail_compilation/hexstring.d(37): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time
-fail_compilation/hexstring.d(38): Error: array cast from `string` to `immutable(ushort[])` is not supported at compile time
-fail_compilation/hexstring.d(39): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time
-fail_compilation/hexstring.d(39):        perhaps remove postfix `c` from hex string
-fail_compilation/hexstring.d(40): Error: hex string with `dstring` type needs to be multiple of 4 bytes, not 5
-fail_compilation/hexstring.d(41): Error: cannot implicitly convert expression `x"11223344"d` of type `dstring` to `immutable(float[])`
-fail_compilation/hexstring.d(42): Error: cannot implicitly convert expression `x"1122"w` of type `wstring` to `immutable(ubyte[])`
-fail_compilation/hexstring.d(50): Error: array cast from `string` to `S[]` is not supported at compile time
-fail_compilation/hexstring.d(28): Error: cannot implicitly convert expression `x"123F"` of type `string` to `ubyte[]`
+fail_compilation/hexstring.d(30): Error: array cast from `string` to `ubyte[3][1]` is not supported at compile time
+fail_compilation/hexstring.d(33): Error: cannot implicitly convert expression `"123F"` of type `string` to `immutable(ubyte[])`
+fail_compilation/hexstring.d(37): Error: hex string length 1 must be a multiple of 2 to cast to `immutable(ushort[])`
+fail_compilation/hexstring.d(38): Error: hex string length 3 must be a multiple of 4 to cast to `immutable(uint[])`
+fail_compilation/hexstring.d(39): Error: hex string length 5 must be a multiple of 8 to cast to `immutable(ulong[])`
+fail_compilation/hexstring.d(40): Error: array cast from `wstring` to `immutable(ulong[])` is not supported at compile time
+fail_compilation/hexstring.d(40):        perhaps remove postfix `w` from hex string
+fail_compilation/hexstring.d(41): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time
+fail_compilation/hexstring.d(42): Error: array cast from `string` to `immutable(ushort[])` is not supported at compile time
+fail_compilation/hexstring.d(43): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time
+fail_compilation/hexstring.d(43):        perhaps remove postfix `c` from hex string
+fail_compilation/hexstring.d(44): Error: hex string with `dstring` type needs to be multiple of 4 bytes, not 5
+fail_compilation/hexstring.d(45): Error: cannot implicitly convert expression `x"11223344"d` of type `dstring` to `immutable(float[])`
+fail_compilation/hexstring.d(46): Error: cannot implicitly convert expression `x"1122"w` of type `wstring` to `immutable(ubyte[])`
+fail_compilation/hexstring.d(47): Error: array cast from `string` to `ubyte[3][1]` is not supported at compile time
+fail_compilation/hexstring.d(48): Error: array cast from `string` to `ubyte[3][1][1]` is not supported at compile time
+fail_compilation/hexstring.d(56): Error: array cast from `string` to `S[]` is not supported at compile time
+fail_compilation/hexstring.d(32): Error: cannot implicitly convert expression `x"123F"` of type `string` to `ubyte[]`
 ---
 */
 immutable ubyte[] s0 = x"123F";
@@ -24,6 +27,7 @@ static assert(s0[1] == 0x3F);
 immutable byte[] s1 = x"123F";
 enum E(X) = cast(X[]) x"AABBCCDD";
 static assert(E!int[0] == 0xAABBCCDD);
+immutable ubyte[3] s2 = cast(ubyte[3][1])x"FFAAFF";
 
 ubyte[] f1 = x"123F";
 immutable ubyte[] f2 = "123F";
@@ -40,6 +44,8 @@ immutable uint[] f11 = cast(immutable uint[]) x"AABBCCDD"c;
 immutable uint[] f12 = x"1122334455"d;
 immutable float[] f13 = x"11223344"d;
 immutable ubyte[] f14 = x"1122"w;
+immutable ubyte[3][1] f16 = cast(ubyte[3][1])x"FFBBFF";
+immutable ubyte[3][1][1] f17 = cast(ubyte[3][1][1])x"FFCCFF";
 
 // https://issues.dlang.org/show_bug.cgi?id=24832
 struct S
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11968.d b/gcc/testsuite/gdc.test/fail_compilation/ice11968.d
deleted file mode 100644 (file)
index 1d50b66..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
-TEST_OUTPUT:
-----
-fail_compilation/ice11968.d(9): Error: the `delete` keyword is obsolete
-fail_compilation/ice11968.d(9):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-----
-*/
-
-void main() {  delete __FILE__  ; }
index b2bea5be8e8fcdb7431bc879429c83afecf149b9..ba6956e1bd0a2e155ae4baed67f38c7e3193e941 100644 (file)
@@ -57,23 +57,3 @@ fail_compilation/nogc1.d(55): Error: allocating with `new` causes a GC allocatio
     scope Object o1 = new Object();     // no error
     scope o2 = new Object();            // no error
 }
-
-/***************** DeleteExp *******************/
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/nogc1.d(76): Error: the `delete` keyword is obsolete
-fail_compilation/nogc1.d(76):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/nogc1.d(77): Error: the `delete` keyword is obsolete
-fail_compilation/nogc1.d(77):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
-fail_compilation/nogc1.d(78): Error: the `delete` keyword is obsolete
-fail_compilation/nogc1.d(78):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
----
-*/
-@nogc void testDelete(int* p, Object o, S1* s)
-{
-    delete p;
-    delete o;
-    delete s;
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16195.d b/gcc/testsuite/gdc.test/fail_compilation/test16195.d
deleted file mode 100644 (file)
index 018ab0d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * TEST_OUTPUT:
----
-fail_compilation/test16195.d(14): Error: the `delete` keyword is obsolete
-fail_compilation/test16195.d(14):        use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead
----
- */
-
-
-// https://issues.dlang.org/show_bug.cgi?id=16195
-
-@safe pure nothrow @nogc void test(int* p)
-{
-    delete p;
-}
index 253df8feec11f62941817bcb717f0ac907f526e0..bce4e9aacb2af6bfb8bd3e4715c3074fc4f66bba 100644 (file)
@@ -383,16 +383,6 @@ void test6714()
     assert(bar6714y((a, b){ return a;    }) == 2);
 }
 
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=7193
-
-void test7193()
-{
-    static assert(!__traits(compiles, {
-        delete a => a;
-    }));
-}
-
 /***************************************************/
 // https://issues.dlang.org/show_bug.cgi?id=7207
 // on CastExp
@@ -1331,7 +1321,6 @@ int main()
     test11();
     test3235();
     test6714();
-    test7193();
     test7202();
     test7288();
     test7499();
index 8ba7a0c44c261a936d17b56024521b12eefd71dd..8888c751ca128585106f7009811c437798695920 100644 (file)
@@ -41,11 +41,30 @@ void test1()
     assert(Foo.flags == 1);
 }
 
+/*********************************************/
+// delete is no longer a keyword and can be used as an identifier
+
+enum E
+{
+    add, delete
+}
+
+E delete()
+{
+    return E.delete;
+}
+
+void test2()
+{
+    assert(delete() == E.delete);
+}
+
 /*********************************************/
 
 int main()
 {
     test1();
+    test2();
 
     printf("Success\n");
     return 0;
index 253a7a54ceb193e33d7a9650a53f073366a962fa..4e34e52223df355dc378b6e4923af1184d075138 100644 (file)
@@ -2,29 +2,13 @@
 RUN_OUTPUT:
 ---
 i = 1
-Writer.opShl(char[])
-BinaryWriter.opShl(int)
-a + 1 = 2
-1 + a = 2
-a + b = 3
-b + a = 3
 i = 64
 12
 534
-A::opShl(int 4)
-4A::opShl(char[])
- A::opShl(int 12)
-12A::opShl(char[])
-
-B::opShl_r(A)
 Success
 ---
 */
 
-// Test operator overloading
-// Ignore deprecation warnings for D1 style operator overloading
-// TRANSFORM_OUTPUT: remove_lines("Deprecation: `op")
-
 import core.stdc.stdio;
 
 /**************************************/
@@ -996,20 +980,11 @@ struct S14343b
 
 void test14343()
 {
-    {
-        S14343a s, t;
+    S14343a s, t;
 
-        t = s;  // OK
-        ++s;    // OK
-        s++;    // OK <- Error: cannot modify struct s S with immutable members
-    }
-    {
-        S14343b s;
-        ++s;
-        assert(s.i == 1);
-        s++;
-        assert(s.i == 2);
-    }
+    t = s;  // OK
+    ++s;    // OK
+    s++;    // OK <- Error: cannot modify struct s S with immutable members
 }
 
 /**************************************/
@@ -1081,20 +1056,13 @@ void test20475()
 /**************************************/
 int main()
 {
-    test1();
-    test2();
-    test3();
     test4();
     test5();
     test6();
     test7();
-    test8();
     test9();
-    test10();
     test11();
     test12();
-    test13();
-    test14();
     test15();
     test1547();
     test4953a();
index cbcbd1a97f1abc91dd23fbb36e9794a04f18ffb7..5893560a62263c02bd6f9058274d9f7b978cd814 100644 (file)
@@ -4091,30 +4091,30 @@ void test4258() {
 
 struct Foo4258 {
     // binary ++/--
-    int opPostInc()() if (false) { return 0; }
+    int opUnary(string op)() if (false) { return 0; }
 
     // binary 1st
-    int opAdd(R)(R rhs) if (false) { return 0; }
-    int opAdd_r(R)(R rhs) if (false) { return 0; }
+    int opBinary(string op, R)(R rhs) if (false) { return 0; }
+    int opBinaryRight(string op, R)(R rhs) if (false) { return 0; }
 
     // compare
-    int opCmp(R)(R rhs) if (false) { return 0; }
+    int opCmp(R)(const(R) rhs) const if (false) { return 0; }
 
     // binary-op assign
-    int opAddAssign(R)(R rhs) if (false) { return 0; }
+    int opOpAssign(string op, R)(R rhs) if (false) { return 0; }
 }
 struct Bar4258 {
     // binary commutive 1
-    int opAdd_r(R)(R rhs) if (false) { return 0; }
+    int opBinary(string op, R)(R rhs) if (false) { return 0; }
 
     // binary-op assign
     int opOpAssign(string op, R)(R rhs) if (false) { return 0; }
 }
 struct Baz4258 {
     // binary commutive 2
-    int opAdd(R)(R rhs) if (false) { return 0; }
+    int opBinaryRight(string op, R)(R rhs) if (false) { return 0; }
 }
-static assert(!is(typeof(Foo4258.init++)));
+static assert(!is(typeof(++Foo4258.init)));
 static assert(!is(typeof(Foo4258.init + 1)));
 static assert(!is(typeof(1 + Foo4258.init)));
 static assert(!is(typeof(Foo4258.init < Foo4258.init)));
index 4172630afa08de5c8fbb63f151f71260248bec10..a91f40b6bfce85980b123172edffe39f134f9732 100644 (file)
@@ -1,4 +1,4 @@
-d1157134103a209d36d6ee9c1df1d61d5929ec6d
+b7e3b3b61711bf6c6cad27c7b5b73df0e570c215
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index efdae4c57861bd030bcd0b2cca78fe42c0585dfa..595e3f974c0c00585656ac1ae7335fc6637568b3 100644 (file)
@@ -361,13 +361,14 @@ DRUNTIME_DSOURCES_SOLARIS = core/sys/solaris/dlfcn.d \
 DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \
        core/sys/windows/aclapi.d core/sys/windows/aclui.d \
        core/sys/windows/basetsd.d core/sys/windows/basetyps.d \
-       core/sys/windows/cderr.d core/sys/windows/cguid.d \
-       core/sys/windows/com.d core/sys/windows/comcat.d \
-       core/sys/windows/commctrl.d core/sys/windows/commdlg.d \
-       core/sys/windows/core.d core/sys/windows/cpl.d \
-       core/sys/windows/cplext.d core/sys/windows/custcntl.d \
-       core/sys/windows/dbghelp.d core/sys/windows/dbghelp_types.d \
-       core/sys/windows/dbt.d core/sys/windows/dde.d core/sys/windows/ddeml.d \
+       core/sys/windows/bcrypt.d core/sys/windows/cderr.d \
+       core/sys/windows/cguid.d core/sys/windows/com.d \
+       core/sys/windows/comcat.d core/sys/windows/commctrl.d \
+       core/sys/windows/commdlg.d core/sys/windows/core.d \
+       core/sys/windows/cpl.d core/sys/windows/cplext.d \
+       core/sys/windows/custcntl.d core/sys/windows/dbghelp.d \
+       core/sys/windows/dbghelp_types.d core/sys/windows/dbt.d \
+       core/sys/windows/dde.d core/sys/windows/ddeml.d \
        core/sys/windows/dhcpcsdk.d core/sys/windows/dlgs.d \
        core/sys/windows/dll.d core/sys/windows/docobj.d \
        core/sys/windows/errorrep.d core/sys/windows/exdisp.d \
index 1227c59b4854bfc179ea154a0184da8a153fe4f8..4832fd15c40845581a63ea4ffa0c9a3687a1bc53 100644 (file)
@@ -392,88 +392,88 @@ am__objects_19 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \
 am__objects_21 = core/sys/windows/accctrl.lo \
        core/sys/windows/aclapi.lo core/sys/windows/aclui.lo \
        core/sys/windows/basetsd.lo core/sys/windows/basetyps.lo \
-       core/sys/windows/cderr.lo core/sys/windows/cguid.lo \
-       core/sys/windows/com.lo core/sys/windows/comcat.lo \
-       core/sys/windows/commctrl.lo core/sys/windows/commdlg.lo \
-       core/sys/windows/core.lo core/sys/windows/cpl.lo \
-       core/sys/windows/cplext.lo core/sys/windows/custcntl.lo \
-       core/sys/windows/dbghelp.lo core/sys/windows/dbghelp_types.lo \
-       core/sys/windows/dbt.lo core/sys/windows/dde.lo \
-       core/sys/windows/ddeml.lo core/sys/windows/dhcpcsdk.lo \
-       core/sys/windows/dlgs.lo core/sys/windows/dll.lo \
-       core/sys/windows/docobj.lo core/sys/windows/errorrep.lo \
-       core/sys/windows/exdisp.lo core/sys/windows/exdispid.lo \
-       core/sys/windows/httpext.lo core/sys/windows/idispids.lo \
-       core/sys/windows/imagehlp.lo core/sys/windows/imm.lo \
-       core/sys/windows/intshcut.lo core/sys/windows/ipexport.lo \
-       core/sys/windows/iphlpapi.lo core/sys/windows/ipifcons.lo \
-       core/sys/windows/iprtrmib.lo core/sys/windows/iptypes.lo \
-       core/sys/windows/isguids.lo core/sys/windows/lm.lo \
-       core/sys/windows/lmaccess.lo core/sys/windows/lmalert.lo \
-       core/sys/windows/lmapibuf.lo core/sys/windows/lmat.lo \
-       core/sys/windows/lmaudit.lo core/sys/windows/lmbrowsr.lo \
-       core/sys/windows/lmchdev.lo core/sys/windows/lmconfig.lo \
-       core/sys/windows/lmcons.lo core/sys/windows/lmerr.lo \
-       core/sys/windows/lmerrlog.lo core/sys/windows/lmmsg.lo \
-       core/sys/windows/lmremutl.lo core/sys/windows/lmrepl.lo \
-       core/sys/windows/lmserver.lo core/sys/windows/lmshare.lo \
-       core/sys/windows/lmsname.lo core/sys/windows/lmstats.lo \
-       core/sys/windows/lmsvc.lo core/sys/windows/lmuse.lo \
-       core/sys/windows/lmuseflg.lo core/sys/windows/lmwksta.lo \
-       core/sys/windows/lzexpand.lo core/sys/windows/mapi.lo \
-       core/sys/windows/mciavi.lo core/sys/windows/mcx.lo \
-       core/sys/windows/mgmtapi.lo core/sys/windows/mmsystem.lo \
-       core/sys/windows/msacm.lo core/sys/windows/mshtml.lo \
-       core/sys/windows/mswsock.lo core/sys/windows/nb30.lo \
-       core/sys/windows/nddeapi.lo core/sys/windows/nspapi.lo \
-       core/sys/windows/ntdef.lo core/sys/windows/ntdll.lo \
-       core/sys/windows/ntldap.lo core/sys/windows/ntsecapi.lo \
-       core/sys/windows/ntsecpkg.lo core/sys/windows/oaidl.lo \
-       core/sys/windows/objbase.lo core/sys/windows/objfwd.lo \
-       core/sys/windows/objidl.lo core/sys/windows/objsafe.lo \
-       core/sys/windows/ocidl.lo core/sys/windows/odbcinst.lo \
-       core/sys/windows/ole.lo core/sys/windows/ole2.lo \
-       core/sys/windows/ole2ver.lo core/sys/windows/oleacc.lo \
-       core/sys/windows/oleauto.lo core/sys/windows/olectl.lo \
-       core/sys/windows/olectlid.lo core/sys/windows/oledlg.lo \
-       core/sys/windows/oleidl.lo core/sys/windows/pbt.lo \
-       core/sys/windows/powrprof.lo core/sys/windows/prsht.lo \
-       core/sys/windows/psapi.lo core/sys/windows/rapi.lo \
-       core/sys/windows/ras.lo core/sys/windows/rasdlg.lo \
-       core/sys/windows/raserror.lo core/sys/windows/rassapi.lo \
-       core/sys/windows/reason.lo core/sys/windows/regstr.lo \
-       core/sys/windows/richedit.lo core/sys/windows/richole.lo \
-       core/sys/windows/rpc.lo core/sys/windows/rpcdce.lo \
-       core/sys/windows/rpcdce2.lo core/sys/windows/rpcdcep.lo \
-       core/sys/windows/rpcndr.lo core/sys/windows/rpcnsi.lo \
-       core/sys/windows/rpcnsip.lo core/sys/windows/rpcnterr.lo \
-       core/sys/windows/schannel.lo core/sys/windows/sdkddkver.lo \
-       core/sys/windows/secext.lo core/sys/windows/security.lo \
-       core/sys/windows/servprov.lo core/sys/windows/setupapi.lo \
-       core/sys/windows/shellapi.lo core/sys/windows/shldisp.lo \
-       core/sys/windows/shlguid.lo core/sys/windows/shlobj.lo \
-       core/sys/windows/shlwapi.lo core/sys/windows/snmp.lo \
-       core/sys/windows/sql.lo core/sys/windows/sqlext.lo \
-       core/sys/windows/sqltypes.lo core/sys/windows/sqlucode.lo \
-       core/sys/windows/sspi.lo core/sys/windows/stacktrace.lo \
-       core/sys/windows/stat.lo core/sys/windows/stdc/malloc.lo \
-       core/sys/windows/stdc/time.lo core/sys/windows/subauth.lo \
-       core/sys/windows/threadaux.lo core/sys/windows/tlhelp32.lo \
-       core/sys/windows/tmschema.lo core/sys/windows/unknwn.lo \
-       core/sys/windows/uuid.lo core/sys/windows/vfw.lo \
-       core/sys/windows/w32api.lo core/sys/windows/winbase.lo \
-       core/sys/windows/winber.lo core/sys/windows/wincon.lo \
-       core/sys/windows/wincrypt.lo core/sys/windows/windef.lo \
-       core/sys/windows/windows.lo core/sys/windows/winerror.lo \
-       core/sys/windows/wingdi.lo core/sys/windows/winhttp.lo \
-       core/sys/windows/wininet.lo core/sys/windows/winioctl.lo \
-       core/sys/windows/winldap.lo core/sys/windows/winnetwk.lo \
-       core/sys/windows/winnls.lo core/sys/windows/winnt.lo \
-       core/sys/windows/winperf.lo core/sys/windows/winreg.lo \
-       core/sys/windows/winsock2.lo core/sys/windows/winspool.lo \
-       core/sys/windows/winsvc.lo core/sys/windows/winuser.lo \
-       core/sys/windows/winver.lo core/sys/windows/wtsapi32.lo \
-       core/sys/windows/wtypes.lo
+       core/sys/windows/bcrypt.lo core/sys/windows/cderr.lo \
+       core/sys/windows/cguid.lo core/sys/windows/com.lo \
+       core/sys/windows/comcat.lo core/sys/windows/commctrl.lo \
+       core/sys/windows/commdlg.lo core/sys/windows/core.lo \
+       core/sys/windows/cpl.lo core/sys/windows/cplext.lo \
+       core/sys/windows/custcntl.lo core/sys/windows/dbghelp.lo \
+       core/sys/windows/dbghelp_types.lo core/sys/windows/dbt.lo \
+       core/sys/windows/dde.lo core/sys/windows/ddeml.lo \
+       core/sys/windows/dhcpcsdk.lo core/sys/windows/dlgs.lo \
+       core/sys/windows/dll.lo core/sys/windows/docobj.lo \
+       core/sys/windows/errorrep.lo core/sys/windows/exdisp.lo \
+       core/sys/windows/exdispid.lo core/sys/windows/httpext.lo \
+       core/sys/windows/idispids.lo core/sys/windows/imagehlp.lo \
+       core/sys/windows/imm.lo core/sys/windows/intshcut.lo \
+       core/sys/windows/ipexport.lo core/sys/windows/iphlpapi.lo \
+       core/sys/windows/ipifcons.lo core/sys/windows/iprtrmib.lo \
+       core/sys/windows/iptypes.lo core/sys/windows/isguids.lo \
+       core/sys/windows/lm.lo core/sys/windows/lmaccess.lo \
+       core/sys/windows/lmalert.lo core/sys/windows/lmapibuf.lo \
+       core/sys/windows/lmat.lo core/sys/windows/lmaudit.lo \
+       core/sys/windows/lmbrowsr.lo core/sys/windows/lmchdev.lo \
+       core/sys/windows/lmconfig.lo core/sys/windows/lmcons.lo \
+       core/sys/windows/lmerr.lo core/sys/windows/lmerrlog.lo \
+       core/sys/windows/lmmsg.lo core/sys/windows/lmremutl.lo \
+       core/sys/windows/lmrepl.lo core/sys/windows/lmserver.lo \
+       core/sys/windows/lmshare.lo core/sys/windows/lmsname.lo \
+       core/sys/windows/lmstats.lo core/sys/windows/lmsvc.lo \
+       core/sys/windows/lmuse.lo core/sys/windows/lmuseflg.lo \
+       core/sys/windows/lmwksta.lo core/sys/windows/lzexpand.lo \
+       core/sys/windows/mapi.lo core/sys/windows/mciavi.lo \
+       core/sys/windows/mcx.lo core/sys/windows/mgmtapi.lo \
+       core/sys/windows/mmsystem.lo core/sys/windows/msacm.lo \
+       core/sys/windows/mshtml.lo core/sys/windows/mswsock.lo \
+       core/sys/windows/nb30.lo core/sys/windows/nddeapi.lo \
+       core/sys/windows/nspapi.lo core/sys/windows/ntdef.lo \
+       core/sys/windows/ntdll.lo core/sys/windows/ntldap.lo \
+       core/sys/windows/ntsecapi.lo core/sys/windows/ntsecpkg.lo \
+       core/sys/windows/oaidl.lo core/sys/windows/objbase.lo \
+       core/sys/windows/objfwd.lo core/sys/windows/objidl.lo \
+       core/sys/windows/objsafe.lo core/sys/windows/ocidl.lo \
+       core/sys/windows/odbcinst.lo core/sys/windows/ole.lo \
+       core/sys/windows/ole2.lo core/sys/windows/ole2ver.lo \
+       core/sys/windows/oleacc.lo core/sys/windows/oleauto.lo \
+       core/sys/windows/olectl.lo core/sys/windows/olectlid.lo \
+       core/sys/windows/oledlg.lo core/sys/windows/oleidl.lo \
+       core/sys/windows/pbt.lo core/sys/windows/powrprof.lo \
+       core/sys/windows/prsht.lo core/sys/windows/psapi.lo \
+       core/sys/windows/rapi.lo core/sys/windows/ras.lo \
+       core/sys/windows/rasdlg.lo core/sys/windows/raserror.lo \
+       core/sys/windows/rassapi.lo core/sys/windows/reason.lo \
+       core/sys/windows/regstr.lo core/sys/windows/richedit.lo \
+       core/sys/windows/richole.lo core/sys/windows/rpc.lo \
+       core/sys/windows/rpcdce.lo core/sys/windows/rpcdce2.lo \
+       core/sys/windows/rpcdcep.lo core/sys/windows/rpcndr.lo \
+       core/sys/windows/rpcnsi.lo core/sys/windows/rpcnsip.lo \
+       core/sys/windows/rpcnterr.lo core/sys/windows/schannel.lo \
+       core/sys/windows/sdkddkver.lo core/sys/windows/secext.lo \
+       core/sys/windows/security.lo core/sys/windows/servprov.lo \
+       core/sys/windows/setupapi.lo core/sys/windows/shellapi.lo \
+       core/sys/windows/shldisp.lo core/sys/windows/shlguid.lo \
+       core/sys/windows/shlobj.lo core/sys/windows/shlwapi.lo \
+       core/sys/windows/snmp.lo core/sys/windows/sql.lo \
+       core/sys/windows/sqlext.lo core/sys/windows/sqltypes.lo \
+       core/sys/windows/sqlucode.lo core/sys/windows/sspi.lo \
+       core/sys/windows/stacktrace.lo core/sys/windows/stat.lo \
+       core/sys/windows/stdc/malloc.lo core/sys/windows/stdc/time.lo \
+       core/sys/windows/subauth.lo core/sys/windows/threadaux.lo \
+       core/sys/windows/tlhelp32.lo core/sys/windows/tmschema.lo \
+       core/sys/windows/unknwn.lo core/sys/windows/uuid.lo \
+       core/sys/windows/vfw.lo core/sys/windows/w32api.lo \
+       core/sys/windows/winbase.lo core/sys/windows/winber.lo \
+       core/sys/windows/wincon.lo core/sys/windows/wincrypt.lo \
+       core/sys/windows/windef.lo core/sys/windows/windows.lo \
+       core/sys/windows/winerror.lo core/sys/windows/wingdi.lo \
+       core/sys/windows/winhttp.lo core/sys/windows/wininet.lo \
+       core/sys/windows/winioctl.lo core/sys/windows/winldap.lo \
+       core/sys/windows/winnetwk.lo core/sys/windows/winnls.lo \
+       core/sys/windows/winnt.lo core/sys/windows/winperf.lo \
+       core/sys/windows/winreg.lo core/sys/windows/winsock2.lo \
+       core/sys/windows/winspool.lo core/sys/windows/winsvc.lo \
+       core/sys/windows/winuser.lo core/sys/windows/winver.lo \
+       core/sys/windows/wtsapi32.lo core/sys/windows/wtypes.lo
 @DRUNTIME_OS_MINGW_TRUE@am__objects_22 = $(am__objects_21) \
 @DRUNTIME_OS_MINGW_TRUE@       config/mingw/libgdruntime_la-msvc.lo
 am__objects_23 = core/sys/solaris/dlfcn.lo core/sys/solaris/elf.lo \
@@ -1041,13 +1041,14 @@ DRUNTIME_DSOURCES_SOLARIS = core/sys/solaris/dlfcn.d \
 DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \
        core/sys/windows/aclapi.d core/sys/windows/aclui.d \
        core/sys/windows/basetsd.d core/sys/windows/basetyps.d \
-       core/sys/windows/cderr.d core/sys/windows/cguid.d \
-       core/sys/windows/com.d core/sys/windows/comcat.d \
-       core/sys/windows/commctrl.d core/sys/windows/commdlg.d \
-       core/sys/windows/core.d core/sys/windows/cpl.d \
-       core/sys/windows/cplext.d core/sys/windows/custcntl.d \
-       core/sys/windows/dbghelp.d core/sys/windows/dbghelp_types.d \
-       core/sys/windows/dbt.d core/sys/windows/dde.d core/sys/windows/ddeml.d \
+       core/sys/windows/bcrypt.d core/sys/windows/cderr.d \
+       core/sys/windows/cguid.d core/sys/windows/com.d \
+       core/sys/windows/comcat.d core/sys/windows/commctrl.d \
+       core/sys/windows/commdlg.d core/sys/windows/core.d \
+       core/sys/windows/cpl.d core/sys/windows/cplext.d \
+       core/sys/windows/custcntl.d core/sys/windows/dbghelp.d \
+       core/sys/windows/dbghelp_types.d core/sys/windows/dbt.d \
+       core/sys/windows/dde.d core/sys/windows/ddeml.d \
        core/sys/windows/dhcpcsdk.d core/sys/windows/dlgs.d \
        core/sys/windows/dll.d core/sys/windows/docobj.d \
        core/sys/windows/errorrep.d core/sys/windows/exdisp.d \
@@ -1767,6 +1768,7 @@ core/sys/windows/aclapi.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/aclui.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/basetsd.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/basetyps.lo: core/sys/windows/$(am__dirstamp)
+core/sys/windows/bcrypt.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/cderr.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/cguid.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/com.lo: core/sys/windows/$(am__dirstamp)
index 6942f7e37d2283e44521400837252141ecac6037..c0adde99dd2b1195a7f552742ca551ebde06fa00 100644 (file)
@@ -6,7 +6,7 @@ module core.internal.abort;
  */
 void abort(scope string msg, scope string filename = __FILE__, size_t line = __LINE__) @nogc nothrow @safe
 {
-    import core.stdc.stdlib: c_abort = abort;
+    import core.stdc.stdlib : c_abort = abort;
     // use available OS system calls to print the message to stderr
     version (Posix)
     {
index 4366da829c982518149b204a3acd418ab4260559..54e7463ca495d840dd29567dd3cd0323a61c22aa 100644 (file)
@@ -136,7 +136,7 @@ TTo[] __ArrayCast(TFrom, TTo)(return scope TFrom[] from) @nogc pure @trusted
 
     if (msg != expected)
     {
-        import core.stdc.stdio;
+        import core.stdc.stdio : printf;
         printf("Expected: |%.*s|\n", cast(int) expected.length, expected.ptr);
         printf("Actual  : |%.*s|\n", cast(int) msg.length, msg.ptr);
         assert(false);
index c5d8c79bfbc7d823243d524687ccce50bd74f77a..45a1ce5629ddfcd4238df7356a5fc9810489fc84 100644 (file)
@@ -13,7 +13,7 @@ import core.internal.traits : Unqual;
 
 debug(PRINTF)
 {
-    import core.stdc.stdio;
+    import core.stdc.stdio : printf;
 }
 
 /**
@@ -46,7 +46,6 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma
     import core.lifetime : copyEmplace;
     import core.stdc.string : memcpy;
     import core.stdc.stdint : uintptr_t;
-    debug(PRINTF) import core.stdc.stdio : printf;
 
     debug(PRINTF) printf("_d_arrayctor(from = %p,%zd) size = %zd\n", from.ptr, from.length, T.sizeof);
 
index 9df84893bb9e0a08b738846f7cc8d9b7aba5a98e..b5222b3b1751f318222be9324ba47634d0dbc99d 100644 (file)
@@ -327,7 +327,7 @@ U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
         {
             if (l != 0xDEADBEEF)
             {
-                import core.stdc.stdio;
+                import core.stdc.stdio : fflush, printf, stdout;
                 printf("Unexpected value: %lld\n", l);
                 fflush(stdout);
                 assert(false);
index 03d414471ad695a5e8b213c178da28b4230ffbea..e7a661a0f2a0c7975a5546ddad16043802e2d013 100644 (file)
@@ -55,7 +55,7 @@ version (D_ProfileGC)
             // FIXME: use rt.tracegc.accumulator when it is accessable in the future.
             version (tracegc)
         } ~ "{\n" ~ q{
-                import core.stdc.stdio;
+                import core.stdc.stdio : printf;
 
                 printf("%sTrace file = '%.*s' line = %d function = '%.*s' type = %.*s\n",
                 } ~ "\"" ~ Hook ~ "\".ptr," ~ q{
index a060e65c8e14ba203362aa30255c4c1e909fe3eb..7aeb2e2d24ad1d87e89bea074ba69d4c16faeffe 100644 (file)
@@ -10,9 +10,9 @@ module core.internal.gc.bits;
 import core.internal.gc.os : os_mem_map, os_mem_unmap, HaveFork;
 
 import core.bitop;
-import core.stdc.string;
-import core.stdc.stdlib;
 import core.exception : onOutOfMemoryError;
+import core.stdc.stdlib : calloc, free;
+import core.stdc.string : memcpy, memset;
 
 // use version gcbitsSingleBitOperation to disable optimizations that use
 //  word operands on bulk operation copyRange, setRange, clrRange, etc.
index b141a6959f7707256f600130b294a89f6e7a5e82..07027f56eb6cdd850675e74623595e9f21e544b5 100644 (file)
@@ -44,8 +44,7 @@ else
 {
     if (!__blkcache_storage)
     {
-        import core.stdc.stdlib;
-        import core.stdc.string;
+        import core.stdc.stdlib : calloc;
         import core.thread.threadbase;
         auto tBase = ThreadBase.getThis();
         if (tBase is null)
@@ -68,7 +67,7 @@ else
 {
     if (__blkcache_storage)
     {
-        import core.stdc.stdlib;
+        import core.stdc.stdlib : free;
         import core.thread.threadbase;
         auto tBase = ThreadBase.getThis();
         if (tBase !is null)
index b5d9802db3f04c8241cf5096d21d06d6fd398577..4cb7b57a6f4d50e58e2fa8d20458057d30b17b0b 100644 (file)
@@ -15,7 +15,7 @@ module core.internal.gc.impl.conservative.gc;
 //debug = PARALLEL_PRINTF;      // turn on printf's
 //debug = COLLECT_PRINTF;       // turn on printf's
 //debug = MARK_PRINTF;          // turn on printf's
-//debug = PRINTF_TO_FILE;       // redirect printf's ouptut to file "gcx.log"
+//debug = PRINTF_TO_FILE;       // redirect printf's output to file "gcx.log"
 //debug = LOGGING;              // log allocations / frees
 //debug = MEMSTOMP;             // stomp on memory
 //debug = SENTINEL;             // add underrun/overrrun protection
@@ -43,7 +43,7 @@ import core.internal.spinlock;
 import core.internal.gc.pooltable;
 import core.internal.gc.blkcache;
 
-import cstdlib = core.stdc.stdlib : calloc, free, malloc, realloc;
+import cstdlib = core.stdc.stdlib;
 import core.stdc.string : memcpy, memset, memmove;
 import core.bitop;
 import core.thread;
@@ -4800,7 +4800,7 @@ debug(PRINTF_TO_FILE)
         }
         len += fprintf(gcx_fh, fmt, args);
         fflush(gcx_fh);
-        import core.stdc.string;
+        import core.stdc.string : strlen;
         hadNewline = fmt && fmt[0] && fmt[strlen(fmt) - 1] == '\n';
         return len;
     }
@@ -5266,8 +5266,8 @@ version (D_LP64) unittest
             catch (OutOfMemoryError)
             {
                 // ignore if the system still doesn't have enough virtual memory
-                import core.stdc.stdio;
-                printf("%s(%d): out-of-memory execption ignored, phys_mem = %zd",
+                import core.stdc.stdio : printf;
+                printf("%s(%d): out-of-memory exception ignored, phys_mem = %zd",
                        __FILE__.ptr, __LINE__, phys_mem);
             }
         }
@@ -5321,7 +5321,7 @@ unittest
 unittest
 {
     import core.memory;
-    import core.stdc.stdio;
+    import core.stdc.stdio : printf;
 
     // allocate from large pool
     auto o = GC.malloc(10);
index 9142708a4a4f01d0bec4357843612795a9a966df..d5431d4ed97af8697ae9fe9f2f72ee9f09d65ea8 100644 (file)
@@ -33,8 +33,10 @@ else version (Posix)
     else version (WatchOS)
         version = Darwin;
 
-    import core.stdc.stdlib;
+    public import core.sys.posix.unistd : fork, pid_t;
+    import core.stdc.errno : ECHILD, EINTR, errno;
     import core.sys.posix.sys.mman : MAP_ANON, MAP_FAILED, MAP_PRIVATE, MAP_SHARED, mmap, munmap, PROT_READ, PROT_WRITE;
+    import core.sys.posix.sys.wait : waitpid, WNOHANG;
 
 
     /// Possible results for the wait_pid() function.
@@ -74,15 +76,11 @@ else version (Posix)
         return ChildStatus.done;
     }
 
-    public import core.sys.posix.unistd : fork, pid_t;
-    import core.stdc.errno : ECHILD, EINTR, errno;
-    import core.sys.posix.sys.wait : waitpid, WNOHANG;
-
     //version = GC_Use_Alloc_MMap;
 }
 else
 {
-    import core.stdc.stdlib;
+    import core.stdc.stdlib : free, malloc;
 
     //version = GC_Use_Alloc_Malloc;
 }
index f9ec3d2a22b64f53a6cce708cdbb82457b9d9766..412ade4290b11804acec05af36e7390f50fa6a7a 100644 (file)
@@ -7,7 +7,7 @@
  */
 module core.internal.gc.pooltable;
 
-static import cstdlib=core.stdc.stdlib;
+static import cstdlib = core.stdc.stdlib;
 
 struct PoolTable(Pool)
 {
index 2dd3ec8375b2bba484344ba8b53febee6aa6b73a..bc4755517ed58b675cf974b3bdc999a835c4e120 100644 (file)
@@ -9,12 +9,10 @@
 
 module core.internal.parseoptions;
 
-import core.stdc.stdlib;
-import core.stdc.stdio;
-import core.stdc.ctype;
-import core.stdc.string;
-import core.vararg;
 import core.internal.traits : externDFunc, hasUDA;
+import core.stdc.ctype : isdigit, isspace;
+import core.stdc.stdio : fprintf, snprintf, sscanf, stderr;
+import core.vararg;
 
 
 @nogc nothrow:
index fce1067812cf46ce4630552d378fdc8213b028d9..8938a445babd02423914f6d296fc7f14f8962c1c 100644 (file)
@@ -10,8 +10,6 @@ module core.internal.qsort;
 
 //debug=qsort;
 
-import core.stdc.stdlib;
-
 debug (qsort) import core.stdc.stdio : printf;
 
 version (OSX)
@@ -150,6 +148,8 @@ else version (CRuntime_UClibc)
 }
 else
 {
+    import core.stdc.stdlib : qsort;
+
     private TypeInfo tiglobal;
 
     extern (C) void[] _adSort(return scope void[] a, TypeInfo ti)
@@ -166,7 +166,6 @@ else
 
 unittest
 {
-    debug(qsort) import core.stdc.stdio;
     debug(qsort) printf("array.sort.unittest()\n");
 
     int[] a = new int[10];
index 066ee7e72db91e63510cb7b4f2ce02843df06745..1a5c41bd8ec1cfdd59eeaa2ebf1e955ec2850358 100644 (file)
@@ -10,7 +10,7 @@ module core.internal.util.array;
 
 
 import core.internal.string;
-import core.stdc.stdint;
+import core.stdc.stdint : uintptr_t;
 
 
 // TLS storage shared for all error messages.
index ff1df7ffad13bfd42bfbf1f0014b0180a5f39eec..d76e14ae49336b887549fde4d5ea7eb332fe33c1 100644 (file)
@@ -29,10 +29,12 @@ version (GNU)
     // It does however prevent the unittest SEGV handler to be installed,
     // which is desireable as it uses backtrace directly.
     private enum hasExecinfo = false;
+    version = LibBacktrace_TraceHandler;
 }
 else version (DRuntime_Use_Libunwind)
 {
-    import core.internal.backtrace.libunwind;
+    version = DefineBacktrace_using_UnwindBacktrace;
+
     // This shouldn't be necessary but ensure that code doesn't get mixed
     // It does however prevent the unittest SEGV handler to be installed,
     // which is desireable as it uses backtrace directly.
@@ -611,7 +613,9 @@ extern (C) UnitTestResult runModuleUnitTests()
     }
     else static if (hasExecinfo)
     {
-        import core.sys.posix.signal; // segv handler
+        // segv handler
+        import core.sys.posix.signal : SA_RESETHAND, SA_SIGINFO, sigaction, sigaction_t, SIGBUS, sigfillset, siginfo_t,
+            SIGSEGV;
 
         static extern (C) void unittestSegvHandler( int signum, siginfo_t* info, void* ptr ) nothrow
         {
@@ -717,6 +721,44 @@ extern (C) UnitTestResult runModuleUnitTests()
     return results;
 }
 
+version (DefineBacktrace_using_UnwindBacktrace)
+{
+    import core.internal.backtrace.unwind;
+
+    private int backtrace(void** buffer, int maxSize) nothrow
+    {
+        if (maxSize < 0) return 0;
+
+        struct State
+        {
+            void** buffer;
+            int maxSize;
+            int entriesWritten = 0;
+        }
+
+        static extern(C) int handler(_Unwind_Context* context, void* statePtr)
+        {
+            auto state = cast(State*)statePtr;
+            if (state.entriesWritten >= state.maxSize) return _URC_END_OF_STACK;
+
+            auto instructionPtr = _Unwind_GetIP(context);
+            if (!instructionPtr) return _URC_END_OF_STACK;
+
+            state.buffer[state.entriesWritten] = cast(void*)instructionPtr;
+            ++state.entriesWritten;
+
+            return _URC_NO_REASON;
+        }
+
+        State state;
+        state.buffer = buffer;
+        state.maxSize = maxSize;
+        _Unwind_Backtrace(&handler, &state);
+
+        return state.entriesWritten;
+    }
+}
+
 /**
  * Get the default `Throwable.TraceInfo` implementation for the platform
  *
@@ -833,14 +875,11 @@ void defaultTraceDeallocator(Throwable.TraceInfo info) nothrow
     free(cast(void *)obj);
 }
 
-version (DRuntime_Use_Libunwind)
+version (LibBacktrace_TraceHandler)
 {
-    import core.internal.backtrace.handler;
-
-    alias DefaultTraceInfo = LibunwindHandler;
 }
 /// Default implementation for most POSIX systems
-else static if (hasExecinfo) private class DefaultTraceInfo : Throwable.TraceInfo
+else version (Posix) private class DefaultTraceInfo : Throwable.TraceInfo
 {
     import core.demangle;
     import core.stdc.stdlib : free;
@@ -907,30 +946,100 @@ else static if (hasExecinfo) private class DefaultTraceInfo : Throwable.TraceInf
         else version (Darwin) enum enableDwarf = true;
         else enum enableDwarf = false;
 
-        const framelist = backtrace_symbols( callstack.ptr, numframes );
-        scope(exit) free(cast(void*) framelist);
-
-        static if (enableDwarf)
+        static if (hasExecinfo)
         {
-            import core.internal.backtrace.dwarf;
-            return traceHandlerOpApplyImpl(numframes,
-                i => callstack[i],
-                (i) { auto str = framelist[i][0 .. strlen(framelist[i])]; return getMangledSymbolName(str); },
-                dg);
+            const framelist = backtrace_symbols( callstack.ptr, numframes );
+            scope(exit) free(cast(void*) framelist);
+
+            static if (enableDwarf)
+            {
+                import core.internal.backtrace.dwarf;
+                return traceHandlerOpApplyImpl(numframes,
+                    i => callstack[i],
+                    (i) { auto str = framelist[i][0 .. strlen(framelist[i])]; return getMangledSymbolName(str); },
+                    dg);
+            }
+            else
+            {
+                int ret = 0;
+                for (size_t pos = 0; pos < numframes; ++pos)
+                {
+                    char[4096] fixbuf = void;
+                    auto buf = framelist[pos][0 .. strlen(framelist[pos])];
+                    buf = fixline( buf, fixbuf );
+                    ret = dg( pos, buf );
+                    if ( ret )
+                        break;
+                }
+                return ret;
+            }
         }
         else
         {
-            int ret = 0;
-            for (size_t pos = 0; pos < numframes; ++pos)
+            // https://code.woboq.org/userspace/glibc/debug/backtracesyms.c.html
+            // The logic that glibc's backtrace use is to check for for `dli_fname`,
+            // the file name, and error if not present, then check for `dli_sname`.
+            // In case `dli_fname` is present but not `dli_sname`, the address is
+            // printed related to the file. We just print the file.
+            static const(char)[] getFrameName (const(void)* ptr)
+            {
+                import core.sys.posix.dlfcn;
+                Dl_info info = void;
+                // Note: See the module documentation about `-L--export-dynamic`
+                if (dladdr(ptr, &info))
+                {
+                    // Return symbol name if possible
+                    if (info.dli_sname !is null && info.dli_sname[0] != '\0')
+                        return info.dli_sname[0 .. strlen(info.dli_sname)];
+
+                    // Fall back to file name
+                    if (info.dli_fname !is null && info.dli_fname[0] != '\0')
+                        return info.dli_fname[0 .. strlen(info.dli_fname)];
+                }
+
+                // `dladdr` failed
+                return "<ERROR: Unable to retrieve function name>";
+            }
+
+            static if (enableDwarf)
             {
-                char[4096] fixbuf = void;
-                auto buf = framelist[pos][0 .. strlen(framelist[pos])];
-                buf = fixline( buf, fixbuf );
-                ret = dg( pos, buf );
-                if ( ret )
-                    break;
+                import core.internal.backtrace.dwarf;
+                return traceHandlerOpApplyImpl(numframes,
+                    i => callstack[i],
+                    i => getFrameName(callstack[i]),
+                    dg);
+            }
+            else
+            {
+                // Poor man solution. Does not show line numbers, but does (potentially) show a backtrace of function names.
+                import core.internal.container.array;
+                Array!(const(char)[]) frameNames;
+                frameNames.length = numframes;
+                size_t startIdx;
+                foreach (idx; 0 .. numframes)
+                {
+                    frameNames[idx] = getFrameName(callstack[idx]);
+
+                    // NOTE: The first few frames with the current implementation are
+                    //       inside core.runtime and the object code, so eliminate
+                    //       these for readability.
+                    // They also might depend on build parameters, which would make
+                    // using a fixed number of frames otherwise brittle.
+                    version (LDC) enum BaseExceptionFunctionName = "_d_throw_exception";
+                    else          enum BaseExceptionFunctionName = "_d_throwdwarf";
+                    if (!startIdx && frameNames[idx] == BaseExceptionFunctionName)
+                        startIdx = idx + 1;
+                }
+
+                int ret = 0;
+                foreach (idx; startIdx .. numframes)
+                {
+                    ret = dg( idx, frameNames[idx] );
+                    if ( ret )
+                        break;
+                }
+                return ret;
             }
-            return ret;
         }
     }
 
@@ -948,40 +1057,43 @@ private:
     void*[MAXFRAMES]  callstack = void;
 
 private:
-    const(char)[] fixline( const(char)[] buf, return ref char[4096] fixbuf ) const
+    static if (hasExecinfo)
     {
-        size_t symBeg, symEnd;
-
-        getMangledSymbolName(buf, symBeg, symEnd);
-
-        enum min = (size_t a, size_t b) => a <= b ? a : b;
-        if (symBeg == symEnd || symBeg >= fixbuf.length)
-        {
-            immutable len = min(buf.length, fixbuf.length);
-            fixbuf[0 .. len] = buf[0 .. len];
-            return fixbuf[0 .. len];
-        }
-        else
+        const(char)[] fixline( const(char)[] buf, return ref char[4096] fixbuf ) const
         {
-            fixbuf[0 .. symBeg] = buf[0 .. symBeg];
+            size_t symBeg, symEnd;
 
-            auto sym = demangle(buf[symBeg .. symEnd], fixbuf[symBeg .. $], getCXXDemangler());
+            getMangledSymbolName(buf, symBeg, symEnd);
 
-            if (sym.ptr !is fixbuf.ptr + symBeg)
+            enum min = (size_t a, size_t b) => a <= b ? a : b;
+            if (symBeg == symEnd || symBeg >= fixbuf.length)
             {
-                // demangle reallocated the buffer, copy the symbol to fixbuf
-                immutable len = min(fixbuf.length - symBeg, sym.length);
-                memmove(fixbuf.ptr + symBeg, sym.ptr, len);
-                if (symBeg + len == fixbuf.length)
-                    return fixbuf[];
+                immutable len = min(buf.length, fixbuf.length);
+                fixbuf[0 .. len] = buf[0 .. len];
+                return fixbuf[0 .. len];
             }
+            else
+            {
+                fixbuf[0 .. symBeg] = buf[0 .. symBeg];
+
+                auto sym = demangle(buf[symBeg .. symEnd], fixbuf[symBeg .. $], getCXXDemangler());
+
+                if (sym.ptr !is fixbuf.ptr + symBeg)
+                {
+                    // demangle reallocated the buffer, copy the symbol to fixbuf
+                    immutable len = min(fixbuf.length - symBeg, sym.length);
+                    memmove(fixbuf.ptr + symBeg, sym.ptr, len);
+                    if (symBeg + len == fixbuf.length)
+                        return fixbuf[];
+                }
 
-            immutable pos = symBeg + sym.length;
-            assert(pos < fixbuf.length);
-            immutable tail = buf.length - symEnd;
-            immutable len = min(fixbuf.length - pos, tail);
-            fixbuf[pos .. pos + len] = buf[symEnd .. symEnd + len];
-            return fixbuf[0 .. pos + len];
+                immutable pos = symBeg + sym.length;
+                assert(pos < fixbuf.length);
+                immutable tail = buf.length - symEnd;
+                immutable len = min(fixbuf.length - pos, tail);
+                fixbuf[pos .. pos + len] = buf[symEnd .. symEnd + len];
+                return fixbuf[0 .. pos + len];
+            }
         }
     }
 }
index ca833eaac33083ce8e7f871993a31d8748e2a9bd..c95fe6514070d9f582aac75a42cad37c5aa0553a 100644 (file)
@@ -11,9 +11,6 @@
  * Standards: ISO/IEC 9899:1999 (E)
  */
 
-/* NOTE: This file has been patched from the original DMD distribution to
- * work with the GDC compiler.
- */
 module core.stdc.config;
 
 version (StdDdoc)
diff --git a/libphobos/libdruntime/core/sys/windows/bcrypt.d b/libphobos/libdruntime/core/sys/windows/bcrypt.d
new file mode 100644 (file)
index 0000000..6edf0df
--- /dev/null
@@ -0,0 +1,900 @@
+/**
+ * Cryptographic primitives
+ *
+ * Translated from MinGW-w64 Windows headers
+ *
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Authors: Aya Partridge
+ * Source: $(DRUNTIMESRC core/sys/windows/_bcrypt.d)
+ */
+module core.sys.windows.bcrypt;
+version (Windows):
+
+pragma(lib, "bcrypt");
+
+import core.sys.windows.ntdef, core.sys.windows.sdkddkver, core.sys.windows.winbase, core.sys.windows.windef, core.sys.windows.winnt;
+
+pragma(inline, true)
+bool BCRYPT_SUCCESS(NTSTATUS Status) @nogc nothrow pure @safe => Status >= 0;
+
+enum BCRYPT_OBJECT_ALIGNMENT = 16;
+
+enum {
+       BCRYPT_KDF_HASH = "HASH"w,
+       BCRYPT_KDF_HMAC = "HMAC"w,
+       BCRYPT_KDF_TLS_PRF = "TLS_PRF"w,
+       BCRYPT_KDF_SP80056A_CONCAT = "SP800_56A_CONCAT"w,
+}
+static if (NTDDI_VERSION >= NTDDI_WINBLUE)
+enum {
+       BCRYPT_KDF_RAW_SECRET = "TRUNCATE"w,
+}
+static if (NTDDI_VERSION >= NTDDI_WIN10_RS4)
+enum {
+       BCRYPT_KDF_HKDF = "HKDF"w,
+}
+
+enum {
+       KDF_HASH_ALGORITHM = 0x0,
+       KDF_SECRET_PREPEND = 0x1,
+       KDF_SECRET_APPEND = 0x2,
+       KDF_HMAC_KEY = 0x3,
+       KDF_TLS_PRF_LABEL = 0x4,
+       KDF_TLS_PRF_SEED = 0x5,
+       KDF_SECRET_HANDLE = 0x6,
+}
+static if (NTDDI_VERSION >= NTDDI_WIN7)
+enum {
+       KDF_TLS_PRF_PROTOCOL = 0x7,
+       KDF_ALGORITHMID = 0x8,
+       KDF_PARTYUINFO = 0x9,
+       KDF_PARTYVINFO = 0xA,
+       KDF_SUPPPUBINFO = 0xB,
+       KDF_SUPPPRIVINFO = 0xC,
+}
+static if (NTDDI_VERSION >= NTDDI_WIN8)
+enum {
+       KDF_LABEL = 0xD,
+       KDF_CONTEXT = 0xE,
+       KDF_SALT = 0xF,
+       KDF_ITERATION_COUNT = 0x10,
+       KDF_GENERIC_PARAMETER = 0x11,
+       KDF_KEYBITLENGTH = 0x12,
+}
+static if (NTDDI_VERSION >= NTDDI_WIN10_RS4)
+enum {
+       KDF_HKDF_SALT = 0x13,
+       KDF_HKDF_INFO = 0x14,
+}
+
+enum KDF_USE_SECRET_AS_HMAC_KEY_FLAG = 1;
+
+enum BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION = 1;
+
+enum {
+       BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG = 0x00000001,
+       BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG = 0x00000002,
+}
+
+pragma(inline, true)
+void BCRYPT_INIT_AUTH_MODE_INFO(ref BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO _AUTH_INFO_STRUCT_) @nogc nothrow pure @safe {
+       (() @trusted => RtlZeroMemory(&_AUTH_INFO_STRUCT_, _AUTH_INFO_STRUCT_.sizeof))();
+       _AUTH_INFO_STRUCT_.cbSize = _AUTH_INFO_STRUCT_.sizeof;
+       _AUTH_INFO_STRUCT_.dwInfoVersion = BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION;
+}
+
+enum {
+       BCRYPT_OPAQUE_KEY_BLOB = "OpaqueKeyBlob"w,
+       BCRYPT_KEY_DATA_BLOB = "KeyDataBlob"w,
+}
+static if (NTDDI_VERSION >= NTDDI_WIN7)
+enum {
+       BCRYPT_AES_WRAP_KEY_BLOB = "Rfc3565KeyWrapBlob"w,
+}
+
+enum {
+       BCRYPT_ALGORITHM_NAME = "AlgorithmName"w,
+       BCRYPT_AUTH_TAG_LENGTH = "AuthTagLength"w,
+       BCRYPT_BLOCK_LENGTH = "BlockLength"w,
+       BCRYPT_BLOCK_SIZE_LIST = "BlockSizeList"w,
+       BCRYPT_CHAINING_MODE = "ChainingMode"w,
+       BCRYPT_CHAIN_MODE_CBC = "ChainingModeCBC"w,
+       BCRYPT_CHAIN_MODE_CCM = "ChainingModeCCM"w,
+       BCRYPT_CHAIN_MODE_CFB = "ChainingModeCFB"w,
+       BCRYPT_CHAIN_MODE_ECB = "ChainingModeECB"w,
+       BCRYPT_CHAIN_MODE_GCM = "ChainingModeGCM"w,
+       BCRYPT_CHAIN_MODE_NA = "ChainingModeN/A"w,
+       BCRYPT_EFFECTIVE_KEY_LENGTH = "EffectiveKeyLength"w,
+       BCRYPT_HASH_BLOCK_LENGTH = "HashBlockLength"w,
+       BCRYPT_HASH_LENGTH = "HashDigestLength"w,
+       BCRYPT_HASH_OID_LIST = "HashOIDList"w,
+       BCRYPT_INITIALIZATION_VECTOR = "IV"w,
+       BCRYPT_IS_KEYED_HASH = "IsKeyedHash"w,
+       BCRYPT_IS_REUSABLE_HASH = "IsReusableHash"w,
+       BCRYPT_KEY_LENGTH = "KeyLength"w,
+       BCRYPT_KEY_LENGTHS = "KeyLengths"w,
+       BCRYPT_KEY_OBJECT_LENGTH = "KeyObjectLength"w,
+       BCRYPT_KEY_STRENGTH = "KeyStrength"w,
+       BCRYPT_MESSAGE_BLOCK_LENGTH = "MessageBlockLength"w,
+       BCRYPT_OBJECT_LENGTH = "ObjectLength"w,
+       BCRYPT_PADDING_SCHEMES = "PaddingSchemes"w,
+       BCRYPT_PCP_PLATFORM_TYPE_PROPERTY = "PCP_PLATFORM_TYPE"w,
+       BCRYPT_PCP_PROVIDER_VERSION_PROPERTY = "PCP_PROVIDER_VERSION"w,
+       BCRYPT_PRIMITIVE_TYPE = "PrimitiveType"w,
+       BCRYPT_PROVIDER_HANDLE = "ProviderHandle"w,
+       BCRYPT_PUBLIC_KEY_LENGTH = "PublicKeyLength"w,
+       BCRYPT_SIGNATURE_LENGTH = "SignatureLength"w,
+}
+static if (NTDDI_VERSION >= NTDDI_WINBLUE)
+enum {
+       BCRYPT_MULTI_OBJECT_LENGTH = "MultiObjectLength"w,
+}
+static if (NTDDI_VERSION >= NTDDI_WIN10_RS4)
+enum {
+       BCRYPT_IS_IFX_TPM_WEAK_KEY = "IsIfxTpmWeakKey"w,
+       BCRYPT_HKDF_HASH_ALGORITHM = "HkdfHashAlgorithm"w,
+       BCRYPT_HKDF_SALT_AND_FINALIZE = "HkdfSaltAndFinalize"w,
+       BCRYPT_HKDF_PRK_AND_FINALIZE = "HkdfPrkAndFinalize"w,
+}
+static if (NTDDI_VERSION >= NTDDI_WIN11_ZN)
+enum {
+       BCRYPT_FUNCTION_NAME_STRING = "FunctionNameString"w,
+       BCRYPT_CUSTOMIZATION_STRING = "CustomizationString"w,
+}
+static if (NTDDI_VERSION >= NTDDI_WIN11_GA)
+enum {
+       BCRYPT_CHAIN_MODE_KWP = "ChainingModeKWP"w,
+}
+
+enum {
+       BCRYPT_SUPPORTED_PAD_ROUTER = 0x00000001,
+       BCRYPT_SUPPORTED_PAD_PKCS1_ENC = 0x00000002,
+       BCRYPT_SUPPORTED_PAD_PKCS1_SIG = 0x00000004,
+       BCRYPT_SUPPORTED_PAD_OAEP = 0x00000008,
+       BCRYPT_SUPPORTED_PAD_PSS = 0x00000010,
+}
+
+enum BCRYPT_PROV_DISPATCH = 0x00000001;
+
+enum BCRYPT_BLOCK_PADDING = 0x00000001;
+
+static if (NTDDI_VERSION >= NTDDI_WIN10_CO)
+enum BCRYPT_GENERATE_IV = 0x00000020;
+
+enum {
+       BCRYPT_PAD_NONE = 0x00000001,
+       BCRYPT_PAD_PKCS1 = 0x00000002,
+       BCRYPT_PAD_OAEP = 0x00000004,
+       BCRYPT_PAD_PSS = 0x00000008,
+}
+static if (NTDDI_VERSION >= NTDDI_WINBLUE)
+enum {
+       BCRYPT_PAD_PKCS1_OPTIONAL_HASH_OID = 0x00000010,
+}
+
+enum BCRYPTBUFFER_VERSION = 0;
+
+struct BCRYPT_KEY_LENGTHS_STRUCT {
+       ULONG dwMinLength;
+       ULONG dwMaxLength;
+       ULONG dwIncrement;
+}
+
+alias BCRYPT_AUTH_TAG_LENGTHS_STRUCT = BCRYPT_KEY_LENGTHS_STRUCT;
+
+struct BCRYPT_OID {
+       ULONG cbOID;
+       PUCHAR pbOID;
+}
+
+struct BCRYPT_OID_LIST {
+       ULONG dwOIDCount;
+       BCRYPT_OID* pOIDs;
+}
+
+struct BCRYPT_PKCS1_PADDING_INFO {
+       LPCWSTR pszAlgId;
+}
+
+struct BCRYPT_PSS_PADDING_INFO {
+       LPCWSTR pszAlgId;
+       ULONG cbSalt;
+}
+
+struct BCRYPT_OAEP_PADDING_INFO {
+       LPCWSTR pszAlgId;
+       PUCHAR pbLabel;
+       ULONG cbLabel;
+}
+
+struct BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO {
+       ULONG cbSize;
+       ULONG dwInfoVersion;
+       PUCHAR pbNonce;
+       ULONG cbNonce;
+       PUCHAR pbAuthData;
+       ULONG cbAuthData;
+       PUCHAR pbTag;
+       ULONG cbTag;
+       PUCHAR pbMacContext;
+       ULONG cbMacContext;
+       ULONG cbAAD;
+       ULONGLONG cbData;
+       ULONG dwFlags;
+}
+alias PBCRYPT_AUTHENTICATED_CIPHER_MODE_INFO = BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO*;
+
+struct BCryptBuffer {
+       ULONG cbBuffer;
+       ULONG BufferType;
+       PVOID pvBuffer;
+}
+alias PBCryptBuffer = BCryptBuffer*;
+
+struct BCryptBufferDesc {
+       ULONG ulVersion;
+       ULONG cBuffers;
+       PBCryptBuffer pBuffers;
+}
+alias PBCryptBufferDesc = BCryptBufferDesc*;
+
+enum {
+       BCRYPT_PUBLIC_KEY_BLOB = "PUBLICBLOB"w,
+       BCRYPT_PRIVATE_KEY_BLOB = "PRIVATEBLOB"w,
+}
+
+enum {
+       BCRYPT_RSAPUBLIC_BLOB = "RSAPUBLICBLOB"w,
+       BCRYPT_RSAPRIVATE_BLOB = "RSAPRIVATEBLOB"w,
+       LEGACY_RSAPUBLIC_BLOB = "CAPIPUBLICBLOB"w,
+       LEGACY_RSAPRIVATE_BLOB = "CAPIPRIVATEBLOB"w,
+}
+
+enum {
+       BCRYPT_RSAPUBLIC_MAGIC = 0x31415352,
+       BCRYPT_RSAPRIVATE_MAGIC = 0x32415352,
+}
+
+enum BCRYPT_RSAFULLPRIVATE_BLOB = "RSAFULLPRIVATEBLOB"w;
+
+enum BCRYPT_RSAFULLPRIVATE_MAGIC = 0x33415352;
+
+static if (NTDDI_VERSION >= NTDDI_WIN8) {
+       enum BCRYPT_GLOBAL_PARAMETERS = "SecretAgreementParam"w;
+       enum BCRYPT_PRIVATE_KEY = "PrivKeyVal"w;
+}
+
+enum {
+       BCRYPT_ECCPUBLIC_BLOB = "ECCPUBLICBLOB"w,
+       BCRYPT_ECCPRIVATE_BLOB = "ECCPRIVATEBLOB"w,
+}
+static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
+enum {
+       BCRYPT_ECCFULLPUBLIC_BLOB = "ECCFULLPUBLICBLOB"w,
+       BCRYPT_ECCFULLPRIVATE_BLOB = "ECCFULLPRIVATEBLOB"w,
+}
+
+static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
+enum SSL_ECCPUBLIC_BLOB = "SSLECCPUBLICBLOB"w;
+
+enum TLS_13_PRE_SHARED_KEY = "TLS13PRESHAREDKEY"w;
+
+enum {
+       BCRYPT_ECDH_PUBLIC_P256_MAGIC = 0x314B4345,
+       BCRYPT_ECDH_PRIVATE_P256_MAGIC = 0x324B4345,
+       BCRYPT_ECDH_PUBLIC_P384_MAGIC = 0x334B4345,
+       BCRYPT_ECDH_PRIVATE_P384_MAGIC = 0x344B4345,
+       BCRYPT_ECDH_PUBLIC_P521_MAGIC = 0x354B4345,
+       BCRYPT_ECDH_PRIVATE_P521_MAGIC = 0x364B4345,
+}
+static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
+enum {
+       BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC = 0x504B4345,
+       BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC = 0x564B4345,
+}
+
+enum {
+       BCRYPT_ECDSA_PUBLIC_P256_MAGIC = 0x31534345,
+       BCRYPT_ECDSA_PRIVATE_P256_MAGIC = 0x32534345,
+       BCRYPT_ECDSA_PUBLIC_P384_MAGIC = 0x33534345,
+       BCRYPT_ECDSA_PRIVATE_P384_MAGIC = 0x34534345,
+       BCRYPT_ECDSA_PUBLIC_P521_MAGIC = 0x35534345,
+       BCRYPT_ECDSA_PRIVATE_P521_MAGIC = 0x36534345,
+}
+static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
+enum {
+       BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC = 0x50444345,
+       BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC = 0x56444345,
+}
+
+enum {
+       BCRYPT_DH_PUBLIC_BLOB = "DHPUBLICBLOB"w,
+       BCRYPT_DH_PRIVATE_BLOB = "DHPRIVATEBLOB"w,
+       LEGACY_DH_PUBLIC_BLOB = "CAPIDHPUBLICBLOB"w,
+       LEGACY_DH_PRIVATE_BLOB = "CAPIDHPRIVATEBLOB"w,
+}
+
+enum {
+       BCRYPT_DH_PUBLIC_MAGIC = 0x42504844,
+       BCRYPT_DH_PRIVATE_MAGIC = 0x56504844,
+}
+
+enum {
+       BCRYPT_DH_PARAMETERS = "DHParameters"w,
+       BCRYPT_DH_PARAMETERS_MAGIC = 0x4D504844,
+}
+
+enum {
+       BCRYPT_DSA_PUBLIC_BLOB = "DSAPUBLICBLOB"w,
+       BCRYPT_DSA_PRIVATE_BLOB = "DSAPRIVATEBLOB"w,
+       LEGACY_DSA_PUBLIC_BLOB = "CAPIDSAPUBLICBLOB"w,
+       LEGACY_DSA_PRIVATE_BLOB = "CAPIDSAPRIVATEBLOB"w,
+       LEGACY_DSA_V2_PUBLIC_BLOB = "V2CAPIDSAPUBLICBLOB"w,
+       LEGACY_DSA_V2_PRIVATE_BLOB = "V2CAPIDSAPRIVATEBLOB"w,
+}
+
+enum {
+       BCRYPT_DSA_PUBLIC_MAGIC = 0x42505344,
+       BCRYPT_DSA_PRIVATE_MAGIC = 0x56505344,
+       BCRYPT_DSA_PUBLIC_MAGIC_V2 = 0x32425044,
+       BCRYPT_DSA_PRIVATE_MAGIC_V2 = 0x32565044,
+}
+
+enum {
+       BCRYPT_KEY_DATA_BLOB_MAGIC = 0x4D42444B,
+       BCRYPT_KEY_DATA_BLOB_VERSION1 = 0x1,
+}
+
+enum {
+       BCRYPT_DSA_PARAMETERS = "DSAParameters"w,
+       BCRYPT_DSA_PARAMETERS_MAGIC = 0x4D505344,
+       BCRYPT_DSA_PARAMETERS_MAGIC_V2 = 0x324D5044,
+}
+
+enum {
+       MS_PRIMITIVE_PROVIDER = "Microsoft Primitive Provider"w,
+       MS_PLATFORM_CRYPTO_PROVIDER = "Microsoft Platform Crypto Provider"w,
+}
+
+enum {
+       BCRYPT_RSA_ALGORITHM = "RSA"w,
+       BCRYPT_RSA_SIGN_ALGORITHM = "RSA_SIGN"w,
+       BCRYPT_DH_ALGORITHM = "DH"w,
+       BCRYPT_DSA_ALGORITHM = "DSA"w,
+       BCRYPT_RC2_ALGORITHM = "RC2"w,
+       BCRYPT_RC4_ALGORITHM = "RC4"w,
+       BCRYPT_AES_ALGORITHM = "AES"w,
+       BCRYPT_DES_ALGORITHM = "DES"w,
+       BCRYPT_DESX_ALGORITHM = "DESX"w,
+       BCRYPT_3DES_ALGORITHM = "3DES"w,
+       BCRYPT_3DES_112_ALGORITHM = "3DES_112"w,
+       BCRYPT_MD2_ALGORITHM = "MD2"w,
+       BCRYPT_MD4_ALGORITHM = "MD4"w,
+       BCRYPT_MD5_ALGORITHM = "MD5"w,
+       BCRYPT_SHA1_ALGORITHM = "SHA1"w,
+       BCRYPT_SHA256_ALGORITHM = "SHA256"w,
+       BCRYPT_SHA384_ALGORITHM = "SHA384"w,
+       BCRYPT_SHA512_ALGORITHM = "SHA512"w,
+       BCRYPT_AES_GMAC_ALGORITHM = "AES-GMAC"w,
+       BCRYPT_AES_CMAC_ALGORITHM = "AES-CMAC"w,
+       BCRYPT_ECDSA_P256_ALGORITHM = "ECDSA_P256"w,
+       BCRYPT_ECDSA_P384_ALGORITHM = "ECDSA_P384"w,
+       BCRYPT_ECDSA_P521_ALGORITHM = "ECDSA_P521"w,
+       BCRYPT_ECDH_P256_ALGORITHM = "ECDH_P256"w,
+       BCRYPT_ECDH_P384_ALGORITHM = "ECDH_P384"w,
+       BCRYPT_ECDH_P521_ALGORITHM = "ECDH_P521"w,
+       BCRYPT_RNG_ALGORITHM = "RNG"w,
+       BCRYPT_RNG_FIPS186_DSA_ALGORITHM = "FIPS186DSARNG"w,
+       BCRYPT_RNG_DUAL_EC_ALGORITHM = "DUALECRNG"w,
+       BCRYPT_SP800108_CTR_HMAC_ALGORITHM = "SP800_108_CTR_HMAC"w,
+       BCRYPT_SP80056A_CONCAT_ALGORITHM = "SP800_56A_CONCAT"w,
+       BCRYPT_PBKDF2_ALGORITHM = "PBKDF2"w,
+       BCRYPT_CAPI_KDF_ALGORITHM = "CAPI_KDF"w,
+}
+
+enum {
+       BCRYPT_CIPHER_INTERFACE = 0x00000001,
+       BCRYPT_HASH_INTERFACE = 0x00000002,
+       BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE = 0x00000003,
+       BCRYPT_SECRET_AGREEMENT_INTERFACE = 0x00000004,
+       BCRYPT_SIGNATURE_INTERFACE = 0x00000005,
+       BCRYPT_RNG_INTERFACE = 0x00000006,
+       BCRYPT_KEY_DERIVATION_INTERFACE = 0x00000007,
+}
+
+static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
+enum : BCRYPT_ALG_HANDLE {
+       BCRYPT_MD2_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000001,
+       BCRYPT_MD4_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000011,
+       BCRYPT_MD5_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000021,
+       BCRYPT_SHA1_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000031,
+       BCRYPT_SHA256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000041,
+       BCRYPT_SHA384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000051,
+       BCRYPT_SHA512_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000061,
+       BCRYPT_RC4_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000071,
+       BCRYPT_RNG_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000081,
+       BCRYPT_HMAC_MD5_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000091,
+       BCRYPT_HMAC_SHA1_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000A1,
+       BCRYPT_HMAC_SHA256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000B1,
+       BCRYPT_HMAC_SHA384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000C1,
+       BCRYPT_HMAC_SHA512_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000D1,
+       BCRYPT_RSA_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000E1,
+       BCRYPT_ECDSA_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000F1,
+
+       BCRYPT_AES_CMAC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000101,
+       BCRYPT_AES_GMAC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000111,
+       BCRYPT_HMAC_MD2_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000121,
+       BCRYPT_HMAC_MD4_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000131,
+
+       BCRYPT_3DES_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000141,
+       BCRYPT_3DES_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000151,
+       BCRYPT_3DES_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000161,
+       BCRYPT_3DES_112_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000171,
+       BCRYPT_3DES_112_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000181,
+       BCRYPT_3DES_112_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000191,
+       BCRYPT_AES_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001A1,
+       BCRYPT_AES_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001B1,
+       BCRYPT_AES_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001C1,
+       BCRYPT_AES_CCM_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001D1,
+       BCRYPT_AES_GCM_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001E1,
+       BCRYPT_DES_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001F1,
+       BCRYPT_DES_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000201,
+       BCRYPT_DES_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000211,
+       BCRYPT_DESX_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000221,
+       BCRYPT_DESX_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000231,
+       BCRYPT_DESX_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000241,
+       BCRYPT_RC2_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000251,
+       BCRYPT_RC2_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000261,
+       BCRYPT_RC2_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000271,
+
+       BCRYPT_DH_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000281,
+       BCRYPT_ECDH_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000291,
+       BCRYPT_ECDH_P256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002A1,
+       BCRYPT_ECDH_P384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002B1,
+       BCRYPT_ECDH_P521_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002C1,
+       BCRYPT_DSA_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002D1,
+       BCRYPT_ECDSA_P256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002E1,
+       BCRYPT_ECDSA_P384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002F1,
+       BCRYPT_ECDSA_P521_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000301,
+       BCRYPT_RSA_SIGN_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000311,
+
+       BCRYPT_CAPI_KDF_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000321,
+       BCRYPT_PBKDF2_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000331,
+
+       BCRYPT_SP800108_CTR_HMAC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000341,
+       BCRYPT_SP80056A_CONCAT_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000351,
+
+       BCRYPT_TLS1_1_KDF_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000361,
+       BCRYPT_TLS1_2_KDF_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000371,
+
+       BCRYPT_XTS_AES_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000381,
+
+       BCRYPT_HKDF_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000391,
+}
+static if (NTDDI_VERSION >= NTDDI_WIN10_FE)
+enum {
+       BCRYPT_CHACHA20_POLY1305_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003A1,
+}
+static if (NTDDI_VERSION >= NTDDI_WIN11_ZN)
+enum {
+       BCRYPT_SHA3_256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003B1,
+       BCRYPT_SHA3_384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003C1,
+       BCRYPT_SHA3_512_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003D1,
+       BCRYPT_HMAC_SHA3_256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003E1,
+       BCRYPT_HMAC_SHA3_384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003F1,
+       BCRYPT_HMAC_SHA3_512_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000401,
+       BCRYPT_CSHAKE128_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000411,
+       BCRYPT_CSHAKE256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000421,
+       BCRYPT_KMAC128_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000431,
+       BCRYPT_KMAC256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000441,
+}
+static if (NTDDI_VERSION >= NTDDI_WIN11_GA)
+enum {
+       BCRYPT_AES_KWP_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000451,
+}
+
+enum {
+       BCRYPT_ALG_HANDLE_HMAC_FLAG = 0x00000008,
+       BCRYPT_CAPI_AES_FLAG = 0x00000010,
+       BCRYPT_HASH_REUSABLE_FLAG = 0x00000020,
+
+       BCRYPT_BUFFERS_LOCKED_FLAG = 0x00000040,
+}
+
+enum {
+       BCRYPT_CIPHER_OPERATION = 0x00000001,
+       BCRYPT_HASH_OPERATION = 0x00000002,
+       BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION = 0x00000004,
+       BCRYPT_SECRET_AGREEMENT_OPERATION = 0x00000008,
+       BCRYPT_SIGNATURE_OPERATION = 0x00000010,
+       BCRYPT_RNG_OPERATION = 0x00000020,
+       BCRYPT_KEY_DERIVATION_OPERATION = 0x00000040,
+}
+
+enum {
+       BCRYPT_PUBLIC_KEY_FLAG = 0x00000001,
+       BCRYPT_PRIVATE_KEY_FLAG = 0x00000002,
+}
+
+enum BCRYPT_NO_KEY_VALIDATION = 0x00000008;
+
+enum {
+       BCRYPT_RNG_USE_ENTROPY_IN_BUFFER = 0x00000001,
+       BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002,
+}
+
+pragma(inline, true) @nogc nothrow pure @safe {
+       BCRYPT_INTERFACE_VERSION BCRYPT_MAKE_INTERFACE_VERSION(int major, int minor) =>
+               BCRYPT_INTERFACE_VERSION(MajorVersion: cast(USHORT)major, MinorVersion: cast(USHORT)minor);
+       bool BCRYPT_IS_INTERFACE_VERSION_COMPATIBLE(BCRYPT_INTERFACE_VERSION loader, BCRYPT_INTERFACE_VERSION provider) =>
+               loader.MajorVersion <= provider.MajorVersion;
+}
+
+enum {
+       BCRYPT_CIPHER_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0),
+       BCRYPT_HASH_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0),
+       BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0),
+       BCRYPT_SECRET_AGREEMENT_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0),
+       BCRYPT_SIGNATURE_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0),
+       BCRYPT_RNG_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0),
+}
+
+enum {
+       CRYPT_MIN_DEPENDENCIES = 0x00000001,
+       CRYPT_PROCESS_ISOLATE = 0x00010000,
+}
+
+enum {
+       CRYPT_UM = 0x00000001,
+       CRYPT_KM = 0x00000002,
+       CRYPT_MM = 0x00000003,
+       CRYPT_ANY = 0x00000004,
+}
+
+enum CRYPT_OVERWRITE = 0x00000001;
+
+enum {
+       CRYPT_LOCAL = 0x00000001,
+       CRYPT_DOMAIN = 0x00000002,
+}
+
+enum {
+       CRYPT_EXCLUSIVE = 0x00000001,
+       CRYPT_OVERRIDE = 0x00010000,
+}
+
+enum {
+       CRYPT_ALL_FUNCTIONS = 0x00000001,
+       CRYPT_ALL_PROVIDERS = 0x00000002,
+}
+
+enum {
+       CRYPT_PRIORITY_TOP = 0x00000000,
+       CRYPT_PRIORITY_BOTTOM = 0xFFFFFFFF,
+}
+
+enum CRYPT_DEFAULT_CONTEXT = "Default"w;
+
+alias BCRYPT_HANDLE = PVOID;
+alias BCRYPT_ALG_HANDLE = PVOID;
+alias BCRYPT_KEY_HANDLE = PVOID;
+alias BCRYPT_HASH_HANDLE = PVOID;
+alias BCRYPT_SECRET_HANDLE = PVOID;
+
+struct BCRYPT_KEY_BLOB {
+       ULONG Magic;
+}
+
+struct BCRYPT_RSAKEY_BLOB {
+       ULONG Magic;
+       ULONG BitLength;
+       ULONG cbPublicExp;
+       ULONG cbModulus;
+       ULONG cbPrime1;
+       ULONG cbPrime2;
+}
+
+struct BCRYPT_ECCKEY_BLOB {
+       ULONG dwMagic;
+       ULONG cbKey;
+}
+alias PBCRYPT_ECCKEY_BLOB = BCRYPT_ECCKEY_BLOB*;
+
+static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) {
+       struct SSL_ECCKEY_BLOB {
+               ULONG dwCurveType;
+               ULONG cbKey;
+       }
+       alias PSSL_ECCKEY_BLOB = SSL_ECCKEY_BLOB*;
+
+       enum BCRYPT_ECC_FULLKEY_BLOB_V1 = 0x1;
+
+       alias ECC_CURVE_TYPE_ENUM = int;
+       enum : ECC_CURVE_TYPE_ENUM {
+               BCRYPT_ECC_PRIME_SHORT_WEIERSTRASS_CURVE = 0x1,
+               BCRYPT_ECC_PRIME_TWISTED_EDWARDS_CURVE = 0x2,
+               BCRYPT_ECC_PRIME_MONTGOMERY_CURVE = 0x3
+       }
+
+       alias ECC_CURVE_ALG_ID_ENUM = int;
+       enum : ECC_CURVE_ALG_ID_ENUM {
+               BCRYPT_NO_CURVE_GENERATION_ALG_ID = 0x0,
+       }
+
+       struct BCRYPT_ECCFULLKEY_BLOB {
+               ULONG dwMagic;
+               ULONG dwVersion;
+               ECC_CURVE_TYPE_ENUM dwCurveType;
+               ECC_CURVE_ALG_ID_ENUM dwCurveGenerationAlgId;
+               ULONG cbFieldLength;
+               ULONG cbSubgroupOrder;
+               ULONG cbCofactor;
+               ULONG cbSeed;
+       }
+       alias PBCRYPT_ECCFULLKEY_BLOB = BCRYPT_ECCFULLKEY_BLOB*;
+}
+
+struct BCRYPT_DH_KEY_BLOB {
+       ULONG dwMagic;
+       ULONG cbKey;
+}
+alias PBCRYPT_DH_KEY_BLOB = BCRYPT_DH_KEY_BLOB*;
+
+struct BCRYPT_DH_PARAMETER_HEADER {
+       ULONG cbLength;
+       ULONG dwMagic;
+       ULONG cbKeyLength;
+}
+
+struct BCRYPT_DSA_KEY_BLOB {
+       ULONG dwMagic;
+       ULONG cbKey;
+       UCHAR[4] Count;
+       UCHAR[20] Seed;
+       UCHAR[20] q;
+}
+alias PBCRYPT_DSA_KEY_BLOB = BCRYPT_DSA_KEY_BLOB*;
+
+alias HASHALGORITHM_ENUM = int;
+enum : HASHALGORITHM_ENUM {
+       DSA_HASH_ALGORITHM_SHA1,
+       DSA_HASH_ALGORITHM_SHA256,
+       DSA_HASH_ALGORITHM_SHA512,
+}
+
+alias DSAFIPSVERSION_ENUM = int;
+enum : DSAFIPSVERSION_ENUM {
+       DSA_FIPS186_2,
+       DSA_FIPS186_3,
+}
+
+struct BCRYPT_DSA_KEY_BLOB_V2 {
+       ULONG dwMagic;
+       ULONG cbKey;
+       HASHALGORITHM_ENUM hashAlgorithm;
+       DSAFIPSVERSION_ENUM standardVersion;
+       ULONG cbSeedLength;
+       ULONG cbGroupSize;
+       UCHAR[4] Count;
+}
+alias PBCRYPT_DSA_KEY_BLOB_V2 = BCRYPT_DSA_KEY_BLOB_V2*;
+
+struct BCRYPT_KEY_DATA_BLOB_HEADER {
+       ULONG dwMagic;
+       ULONG dwVersion;
+       ULONG cbKeyData;
+}
+alias PBCRYPT_KEY_DATA_BLOB_HEADER = BCRYPT_KEY_DATA_BLOB_HEADER*;
+
+struct BCRYPT_DSA_PARAMETER_HEADER {
+       ULONG cbLength;
+       ULONG dwMagic;
+       ULONG cbKeyLength;
+       UCHAR[4] Count;
+       UCHAR[20] Seed;
+       UCHAR[20] q;
+}
+
+struct BCRYPT_DSA_PARAMETER_HEADER_V2 {
+       ULONG cbLength;
+       ULONG dwMagic;
+       ULONG cbKeyLength;
+       HASHALGORITHM_ENUM hashAlgorithm;
+       DSAFIPSVERSION_ENUM standardVersion;
+       ULONG cbSeedLength;
+       ULONG cbGroupSize;
+       UCHAR[4] Count;
+}
+
+struct BCRYPT_ECC_CURVE_NAMES {
+       ULONG dwEccCurveNames;
+       LPWSTR* pEccCurveNames;
+}
+
+alias BCRYPT_HASH_OPERATION_TYPE = int;
+enum : BCRYPT_HASH_OPERATION_TYPE {
+       BCRYPT_HASH_OPERATION_HASH_DATA = 1,
+       BCRYPT_HASH_OPERATION_FINISH_HASH = 2,
+}
+
+struct BCRYPT_MULTI_HASH_OPERATION {
+       ULONG iHash;
+       BCRYPT_HASH_OPERATION_TYPE hashOperation;
+       PUCHAR pbBuffer;
+       ULONG cbBuffer;
+}
+
+alias BCRYPT_MULTI_OPERATION_TYPE = int;
+enum : BCRYPT_MULTI_OPERATION_TYPE {
+       BCRYPT_OPERATION_TYPE_HASH = 1,
+}
+
+struct BCRYPT_MULTI_OBJECT_LENGTH_STRUCT {
+       ULONG cbPerObject;
+       ULONG cbPerElement;
+}
+
+struct BCRYPT_ALGORITHM_IDENTIFIER {
+       LPWSTR pszName;
+       ULONG dwClass;
+       ULONG dwFlags;
+}
+
+struct BCRYPT_PROVIDER_NAME {
+       LPWSTR pszProviderName;
+}
+
+struct BCRYPT_INTERFACE_VERSION {
+       USHORT MajorVersion;
+       USHORT MinorVersion;
+}
+alias PBCRYPT_INTERFACE_VERSION = BCRYPT_INTERFACE_VERSION*;
+
+struct CRYPT_INTERFACE_REG {
+       ULONG dwInterface;
+       ULONG dwFlags;
+       ULONG cFunctions;
+       PWSTR* rgpszFunctions;
+}
+alias PCRYPT_INTERFACE_REG = CRYPT_INTERFACE_REG*;
+
+struct CRYPT_IMAGE_REG {
+       PWSTR pszImage;
+       ULONG cInterfaces;
+       PCRYPT_INTERFACE_REG* rgpInterfaces;
+}
+alias PCRYPT_IMAGE_REG = CRYPT_IMAGE_REG*;
+
+struct CRYPT_PROVIDER_REG {
+       ULONG cAliases;
+       PWSTR* rgpszAliases;
+       PCRYPT_IMAGE_REG pUM;
+       PCRYPT_IMAGE_REG pKM;
+}
+alias PCRYPT_PROVIDER_REG = CRYPT_PROVIDER_REG*;
+
+struct CRYPT_PROVIDERS {
+       ULONG cProviders;
+       PWSTR* rgpszProviders;
+}
+alias PCRYPT_PROVIDERS = CRYPT_PROVIDERS*;
+
+struct CRYPT_CONTEXT_CONFIG {
+       ULONG dwFlags;
+       ULONG dwReserved;
+}
+alias PCRYPT_CONTEXT_CONFIG = CRYPT_CONTEXT_CONFIG*;
+
+struct CRYPT_CONTEXT_FUNCTION_CONFIG {
+       ULONG dwFlags;
+       ULONG dwReserved;
+}
+alias PCRYPT_CONTEXT_FUNCTION_CONFIG = CRYPT_CONTEXT_FUNCTION_CONFIG*;
+
+struct CRYPT_CONTEXTS {
+       ULONG cContexts;
+       PWSTR* rgpszContexts;
+}
+alias PCRYPT_CONTEXTS = CRYPT_CONTEXTS*;
+
+struct CRYPT_CONTEXT_FUNCTIONS {
+       ULONG cFunctions;
+       PWSTR* rgpszFunctions;
+}
+alias PCRYPT_CONTEXT_FUNCTIONS = CRYPT_CONTEXT_FUNCTIONS*;
+
+struct CRYPT_CONTEXT_FUNCTION_PROVIDERS {
+       ULONG cProviders;
+       PWSTR* rgpszProviders;
+}
+alias PCRYPT_CONTEXT_FUNCTION_PROVIDERS = CRYPT_CONTEXT_FUNCTION_PROVIDERS*;
+
+struct CRYPT_PROPERTY_REF {
+       PWSTR pszProperty;
+       ULONG cbValue;
+       PUCHAR pbValue;
+}
+alias PCRYPT_PROPERTY_REF = CRYPT_PROPERTY_REF*;
+
+struct CRYPT_IMAGE_REF {
+       PWSTR pszImage;
+       ULONG dwFlags;
+}
+alias PCRYPT_IMAGE_REF = CRYPT_IMAGE_REF*;
+
+struct CRYPT_PROVIDER_REF {
+       ULONG dwInterface;
+       PWSTR pszFunction;
+       PWSTR pszProvider;
+       ULONG cProperties;
+       PCRYPT_PROPERTY_REF* rgpProperties;
+       PCRYPT_IMAGE_REF pUM;
+       PCRYPT_IMAGE_REF pKM;
+}
+alias PCRYPT_PROVIDER_REF = CRYPT_PROVIDER_REF*;
+
+struct CRYPT_PROVIDER_REFS {
+       ULONG cProviders;
+       PCRYPT_PROVIDER_REF* rgpProviders;
+}
+alias PCRYPT_PROVIDER_REFS = CRYPT_PROVIDER_REFS*;
+
+extern(Windows) @nogc nothrow {
+       NTSTATUS BCryptOpenAlgorithmProvider(scope BCRYPT_ALG_HANDLE* phAlgorithm, scope LPCWSTR pszAlgId, scope LPCWSTR pszImplementation, ULONG dwFlags);
+       NTSTATUS BCryptEnumAlgorithms(ULONG dwAlgOperations, scope ULONG* pAlgCount, scope BCRYPT_ALGORITHM_IDENTIFIER** ppAlgList, ULONG dwFlags);
+       NTSTATUS BCryptEnumProviders(scope LPCWSTR pszAlgId, scope ULONG* pImplCount, scope BCRYPT_PROVIDER_NAME** ppImplList, ULONG dwFlags);
+       NTSTATUS BCryptGetProperty(BCRYPT_HANDLE hObject, scope LPCWSTR pszProperty, scope PUCHAR pbOutput, ULONG cbOutput, scope ULONG* pcbResult, ULONG dwFlags);
+       NTSTATUS BCryptSetProperty(BCRYPT_HANDLE hObject, scope LPCWSTR pszProperty, scope PUCHAR pbInput, ULONG cbInput, ULONG dwFlags);
+       NTSTATUS BCryptCloseAlgorithmProvider(BCRYPT_ALG_HANDLE hAlgorithm, ULONG dwFlags);
+       VOID BCryptFreeBuffer(PVOID pvBuffer);
+       NTSTATUS BCryptGenerateSymmetricKey(BCRYPT_ALG_HANDLE hAlgorithm, scope BCRYPT_KEY_HANDLE* phKey, scope PUCHAR pbKeyObject, ULONG cbKeyObject, scope PUCHAR pbSecret, ULONG cbSecret, ULONG dwFlags);
+       NTSTATUS BCryptGenerateKeyPair(BCRYPT_ALG_HANDLE hAlgorithm, scope BCRYPT_KEY_HANDLE* phKey, ULONG dwLength, ULONG dwFlags);
+       NTSTATUS BCryptEncrypt(BCRYPT_KEY_HANDLE hKey, scope PUCHAR pbInput, ULONG cbInput, scope VOID* pPaddingInfo, scope PUCHAR pbIV, ULONG cbIV, scope PUCHAR pbOutput, ULONG cbOutput, scope ULONG* pcbResult, ULONG dwFlags);
+       NTSTATUS BCryptDecrypt(BCRYPT_KEY_HANDLE hKey, scope PUCHAR pbInput, ULONG cbInput, scope VOID* pPaddingInfo, scope PUCHAR pbIV, ULONG cbIV, scope PUCHAR pbOutput, ULONG cbOutput, scope ULONG* pcbResult, ULONG dwFlags);
+       NTSTATUS BCryptExportKey(BCRYPT_KEY_HANDLE hKey, BCRYPT_KEY_HANDLE hExportKey, scope LPCWSTR pszBlobType, scope PUCHAR pbOutput, ULONG cbOutput, scope ULONG* pcbResult, ULONG dwFlags);
+       NTSTATUS BCryptImportKey(BCRYPT_ALG_HANDLE hAlgorithm, BCRYPT_KEY_HANDLE hImportKey, scope LPCWSTR pszBlobType, scope BCRYPT_KEY_HANDLE* phKey, scope PUCHAR pbKeyObject, ULONG cbKeyObject, scope PUCHAR pbInput, ULONG cbInput, ULONG dwFlags);
+       NTSTATUS BCryptImportKeyPair(BCRYPT_ALG_HANDLE hAlgorithm, BCRYPT_KEY_HANDLE hImportKey, scope LPCWSTR pszBlobType, scope BCRYPT_KEY_HANDLE* phKey, scope PUCHAR pbInput, ULONG cbInput, ULONG dwFlags);
+       NTSTATUS BCryptDuplicateKey(BCRYPT_KEY_HANDLE hKey, scope BCRYPT_KEY_HANDLE* phNewKey, scope PUCHAR pbKeyObject, ULONG cbKeyObject, ULONG dwFlags);
+       NTSTATUS BCryptFinalizeKeyPair(BCRYPT_KEY_HANDLE hKey, ULONG dwFlags);
+       NTSTATUS BCryptDestroyKey(BCRYPT_KEY_HANDLE hKey);
+       NTSTATUS BCryptDestroySecret(BCRYPT_SECRET_HANDLE hSecret);
+       NTSTATUS BCryptSignHash(BCRYPT_KEY_HANDLE hKey, scope VOID* pPaddingInfo, scope PUCHAR pbInput, ULONG cbInput, scope PUCHAR pbOutput, ULONG cbOutput, scope ULONG* pcbResult, ULONG dwFlags);
+       NTSTATUS BCryptVerifySignature(BCRYPT_KEY_HANDLE hKey, scope VOID* pPaddingInfo, scope PUCHAR pbHash, ULONG cbHash, scope PUCHAR pbSignature, ULONG cbSignature, ULONG dwFlags);
+       NTSTATUS BCryptSecretAgreement(BCRYPT_KEY_HANDLE hPrivKey, BCRYPT_KEY_HANDLE hPubKey, scope BCRYPT_SECRET_HANDLE* phAgreedSecret, ULONG dwFlags);
+       NTSTATUS BCryptDeriveKey(BCRYPT_SECRET_HANDLE hSharedSecret, LPCWSTR pwszKDF, scope BCryptBufferDesc* pParameterList, scope PUCHAR pbDerivedKey, ULONG cbDerivedKey, scope ULONG* pcbResult, ULONG dwFlags);
+       NTSTATUS BCryptKeyDerivation(BCRYPT_KEY_HANDLE hKey, scope BCryptBufferDesc* pParameterList, scope PUCHAR pbDerivedKey, ULONG cbDerivedKey, scope ULONG* pcbResult, ULONG dwFlags);
+       NTSTATUS BCryptCreateHash(BCRYPT_ALG_HANDLE hAlgorithm, scope BCRYPT_HASH_HANDLE* phHash, scope PUCHAR pbHashObject, ULONG cbHashObject, scope PUCHAR pbSecret, ULONG cbSecret, ULONG dwFlags);
+       NTSTATUS BCryptHashData(BCRYPT_HASH_HANDLE hHash, scope PUCHAR pbInput, ULONG cbInput, ULONG dwFlags);
+       NTSTATUS BCryptFinishHash(BCRYPT_HASH_HANDLE hHash, scope PUCHAR pbOutput, ULONG cbOutput, ULONG dwFlags);
+       static if (NTDDI_VERSION >= NTDDI_WINBLUE) {
+               NTSTATUS BCryptCreateMultiHash(BCRYPT_ALG_HANDLE hAlgorithm, scope BCRYPT_HASH_HANDLE* phHash, ULONG nHashes, scope PUCHAR pbHashObject, ULONG cbHashObject, scope PUCHAR pbSecret, ULONG cbSecret, ULONG dwFlags);
+               NTSTATUS BCryptProcessMultiOperations(BCRYPT_HANDLE hObject, BCRYPT_MULTI_OPERATION_TYPE operationType, scope PVOID pOperations, ULONG cbOperations, ULONG dwFlags);
+       }
+       NTSTATUS BCryptDuplicateHash(BCRYPT_HASH_HANDLE hHash, scope BCRYPT_HASH_HANDLE* phNewHash, scope PUCHAR pbHashObject, ULONG cbHashObject, ULONG dwFlags);
+       NTSTATUS BCryptDestroyHash(BCRYPT_HASH_HANDLE hHash);
+       static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) {
+               NTSTATUS BCryptHash(BCRYPT_ALG_HANDLE hAlgorithm, scope PUCHAR pbSecret, ULONG cbSecret, scope PUCHAR pbInput, ULONG cbInput, scope PUCHAR pbOutput, ULONG cbOutput);
+       }
+       NTSTATUS BCryptGenRandom(BCRYPT_ALG_HANDLE hAlgorithm, scope PUCHAR pbBuffer, ULONG cbBuffer, ULONG dwFlags);
+       NTSTATUS BCryptDeriveKeyCapi(BCRYPT_HASH_HANDLE hHash, BCRYPT_ALG_HANDLE hTargetAlg, scope PUCHAR pbDerivedKey, ULONG cbDerivedKey, ULONG dwFlags);
+       NTSTATUS BCryptDeriveKeyPBKDF2(BCRYPT_ALG_HANDLE hPrf, scope PUCHAR pbPassword, ULONG cbPassword, scope PUCHAR pbSalt, ULONG cbSalt, ULONGLONG cIterations, scope PUCHAR pbDerivedKey, ULONG cbDerivedKey, ULONG dwFlags);
+       NTSTATUS BCryptResolveProviders(scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, scope LPCWSTR pszProvider, ULONG dwMode, ULONG dwFlags, scope ULONG* pcbBuffer, scope PCRYPT_PROVIDER_REFS* ppBuffer);
+       NTSTATUS BCryptGetFipsAlgorithmMode(scope BOOLEAN* pfEnabled);
+       NTSTATUS BCryptQueryProviderRegistration(scope LPCWSTR pszProvider, ULONG dwMode, ULONG dwInterface, scope ULONG* pcbBuffer, scope PCRYPT_PROVIDER_REG* ppBuffer);
+       NTSTATUS BCryptEnumRegisteredProviders(scope ULONG* pcbBuffer, scope PCRYPT_PROVIDERS* ppBuffer);
+       NTSTATUS BCryptCreateContext(ULONG dwTable, scope LPCWSTR pszContext, PCRYPT_CONTEXT_CONFIG pConfig);
+       NTSTATUS BCryptDeleteContext(ULONG dwTable, scope LPCWSTR pszContext);
+       NTSTATUS BCryptEnumContexts(ULONG dwTable, scope ULONG* pcbBuffer, scope PCRYPT_CONTEXTS* ppBuffer);
+       NTSTATUS BCryptConfigureContext(ULONG dwTable, scope LPCWSTR pszContext, PCRYPT_CONTEXT_CONFIG pConfig);
+       NTSTATUS BCryptQueryContextConfiguration(ULONG dwTable, scope LPCWSTR pszContext, scope ULONG* pcbBuffer, scope PCRYPT_CONTEXT_CONFIG* ppBuffer);
+       NTSTATUS BCryptAddContextFunction(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, ULONG dwPosition);
+       NTSTATUS BCryptRemoveContextFunction(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction);
+       NTSTATUS BCryptEnumContextFunctions(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope ULONG* pcbBuffer, scope PCRYPT_CONTEXT_FUNCTIONS* ppBuffer);
+       NTSTATUS BCryptConfigureContextFunction(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, PCRYPT_CONTEXT_FUNCTION_CONFIG pConfig);
+       NTSTATUS BCryptQueryContextFunctionConfiguration(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, scope ULONG* pcbBuffer, scope PCRYPT_CONTEXT_FUNCTION_CONFIG* ppBuffer);
+       NTSTATUS BCryptEnumContextFunctionProviders(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, scope ULONG* pcbBuffer, scope PCRYPT_CONTEXT_FUNCTION_PROVIDERS* ppBuffer);
+       NTSTATUS BCryptSetContextFunctionProperty(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, LPCWSTR pszProperty, ULONG cbValue, scope PUCHAR pbValue);
+       NTSTATUS BCryptQueryContextFunctionProperty(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, LPCWSTR pszProperty, ULONG* pcbValue, scope PUCHAR* ppbValue);
+       deprecated NTSTATUS BCryptRegisterConfigChangeNotify(scope HANDLE* phEvent);
+       NTSTATUS BCryptUnregisterConfigChangeNotify(HANDLE hEvent);
+}
index 7c601bb2e3fadd4564d83083390d1472dc45dbd1..06f01f3f6d48dcaa1514a6762ce02471b60641eb 100644 (file)
@@ -9,9 +9,6 @@
  * Source: $(DRUNTIMESRC core/sys/windows/_dll.d)
  */
 
-/* NOTE: This file has been patched from the original DMD distribution to
- * work with the GDC compiler.
- */
 module core.sys.windows.dll;
 version (Windows):
 
@@ -405,36 +402,29 @@ private bool isWindows8OrLater() nothrow @nogc
 int dll_getRefCount( HINSTANCE hInstance ) nothrow @nogc
 {
     void** peb;
-    version (Win64)
+    version (D_InlineAsm_X86_64)
     {
-        version (GNU_InlineAsm)
+        asm pure nothrow @nogc
         {
-            asm pure nothrow @nogc { "movq %%gs:0x60, %0;" : "=r" (peb); }
+            mov RAX, 0x60;
+            mov RAX,GS:[RAX];
+            mov peb, RAX;
         }
-        else
+    }
+    else version (D_InlineAsm_X86)
+    {
+        asm pure nothrow @nogc
         {
-            asm pure nothrow @nogc
-            {
-                mov RAX, 0x60;
-                mov RAX,GS:[RAX];
-                mov peb, RAX;
-            }
+            mov EAX,FS:[0x30];
+            mov peb, EAX;
         }
     }
-    else version (Win32)
+    else version (GNU_InlineAsm)
     {
-        version (GNU_InlineAsm)
-        {
+        version (X86_64)
+            asm pure nothrow @nogc { "movq %%gs:0x60, %0;" : "=r" (peb); }
+        else version (X86)
             asm pure nothrow @nogc { "movl %%fs:0x30, %0;" : "=r" (peb); }
-        }
-        else
-        {
-            asm pure nothrow @nogc
-            {
-                mov EAX,FS:[0x30];
-                mov peb, EAX;
-            }
-        }
     }
     dll_aux.LDR_MODULE *ldrMod = dll_aux.findLdrModule( hInstance, peb );
     if ( !ldrMod )
index 3f5c01be1489ba7c4fafd239c3221a496fbcb2c4..bdaaa81d6dda90643c4d5dc7d71b10da3e6908c6 100644 (file)
@@ -7,9 +7,10 @@
  * Source: $(DRUNTIMESRC core/sys/windows/sdkddkver.d)
  */
 module core.sys.windows.sdkddkver;
-
 version (Windows):
 
+import core.sys.windows.w32api;
+
 enum _WIN32_WINNT_NT4                    = 0x0400;
 enum _WIN32_WINNT_WIN2K                  = 0x0500;
 enum _WIN32_WINNT_WINXP                  = 0x0501;
@@ -21,6 +22,7 @@ enum _WIN32_WINNT_LONGHORN               = 0x0600;
 enum _WIN32_WINNT_WIN7                   = 0x0601;
 enum _WIN32_WINNT_WIN8                   = 0x0602;
 enum _WIN32_WINNT_WINBLUE                = 0x0603;
+enum _WIN32_WINNT_WINTHRESHOLD           = 0x0A00;
 enum _WIN32_WINNT_WIN10                  = 0x0A00;
 
 enum _WIN32_IE_IE20                      = 0x0200;
@@ -38,6 +40,7 @@ enum _WIN32_IE_IE70                      = 0x0700;
 enum _WIN32_IE_IE80                      = 0x0800;
 enum _WIN32_IE_IE90                      = 0x0900;
 enum _WIN32_IE_IE100                     = 0x0A00;
+enum _WIN32_IE_IE110                     = 0x0A00;
 
 enum _WIN32_IE_NT4                    =  _WIN32_IE_IE20;
 enum _WIN32_IE_NT4SP1                 =  _WIN32_IE_IE20;
@@ -64,6 +67,8 @@ enum _WIN32_IE_LONGHORN               =  _WIN32_IE_IE70;
 enum _WIN32_IE_WIN7                   =  _WIN32_IE_IE80;
 enum _WIN32_IE_WIN8                   =  _WIN32_IE_IE100;
 enum _WIN32_IE_WINBLUE                =  _WIN32_IE_IE100;
+enum _WIN32_IE_WINTHRESHOLD           =  _WIN32_IE_IE110;
+enum _WIN32_IE_WIN10                  =  _WIN32_IE_IE110;
 
 
 enum NTDDI_WIN2K                         = 0x05000000;
@@ -106,12 +111,45 @@ enum NTDDI_WS08SP4                     = NTDDI_WIN6SP4;
 enum NTDDI_WIN7                          = 0x06010000;
 enum NTDDI_WIN8                          = 0x06020000;
 enum NTDDI_WINBLUE                       = 0x06030000;
-
-enum OSVERSION_MASK      = 0xFFFF0000;
+enum NTDDI_WINTHRESHOLD                  = 0x0A000000;
+enum NTDDI_WIN10                         = 0x0A000000;
+enum NTDDI_WIN10_TH2                     = 0x0A000001;
+enum NTDDI_WIN10_RS1                     = 0x0A000002;
+enum NTDDI_WIN10_RS2                     = 0x0A000003;
+enum NTDDI_WIN10_RS3                     = 0x0A000004;
+enum NTDDI_WIN10_RS4                     = 0x0A000005;
+enum NTDDI_WIN10_RS5                     = 0x0A000006;
+enum NTDDI_WIN10_19H1                    = 0x0A000007;
+enum NTDDI_WIN10_VB                      = 0x0A000008;
+enum NTDDI_WIN10_MN                      = 0x0A000009;
+enum NTDDI_WIN10_FE                      = 0x0A00000A;
+enum NTDDI_WIN10_CO                      = 0x0A00000B;
+enum NTDDI_WIN10_NI                      = 0x0A00000C;
+enum NTDDI_WIN10_CU                      = 0x0A00000D;
+enum NTDDI_WIN11_ZN                      = 0x0A00000E;
+enum NTDDI_WIN11_GA                      = 0x0A00000F;
+enum NTDDI_WIN11_GE                      = 0x0A000010;
+
+enum WDK_NTDDI_VERSION = NTDDI_WIN11_GE;
+
+enum OSVERSION_MASK      = 0xFFFF0000U;
 enum SPVERSION_MASK      = 0x0000FF00;
 enum SUBVERSION_MASK     = 0x000000FF;
 
-enum _WIN32_WINNT    = 0x0603;
+pragma(inline, true) @nogc nothrow pure @safe {
+    uint OSVER(uint Version) => Version & OSVERSION_MASK;
+    uint SPVER(uint Version) => (Version & SPVERSION_MASK) >> 8;
+    uint SUBVER(uint Version) => Version & SUBVERSION_MASK;
+
+    uint NTDDI_VERSION_FROM_WIN32_WINNT2(uint Version) => Version * 0x10000;
+    alias NTDDI_VERSION_FROM_WIN32_WINNT = NTDDI_VERSION_FROM_WIN32_WINNT2;
+}
+
+
+static if (_WIN32_WINNT < _WIN32_WINNT_WIN10) {
+    enum NTDDI_VERSION = NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT);
+} else {
+    enum NTDDI_VERSION = WDK_NTDDI_VERSION;
+}
 
-enum NTDDI_VERSION   = 0x06030000;
-enum WINVER          =  _WIN32_WINNT;
+enum WINVER = _WIN32_WINNT;
index 92bd1c6752ae6bde7cae95773b3095c87f6f59fb..dae8896d4b08795fa4edbc03790827a28bb299f8 100644 (file)
@@ -9,9 +9,6 @@
  * Authors:   Rainer Schuetze
  */
 
-/* NOTE: This file has been patched from the original DMD distribution to
- * work with the GDC compiler.
- */
 module core.sys.windows.threadaux;
 version (Windows):
 
@@ -166,42 +163,35 @@ struct thread_aux
     // get linear address of TEB of current thread
     static void** getTEB() nothrow @nogc
     {
-        version (Win32)
+        version (D_InlineAsm_X86)
         {
-            version (GNU_InlineAsm)
+            asm pure nothrow @nogc
             {
-                void** teb;
-                asm pure nothrow @nogc { "movl %%fs:0x18, %0;" : "=r" (teb); }
-                return teb;
+                naked;
+                mov EAX,FS:[0x18];
+                ret;
             }
-            else
+        }
+        else version (D_InlineAsm_X86_64)
+        {
+            asm pure nothrow @nogc
             {
-                asm pure nothrow @nogc
-                {
-                    naked;
-                    mov EAX,FS:[0x18];
-                    ret;
-                }
+                naked;
+                mov RAX,0x30;
+                mov RAX,GS:[RAX]; // immediate value causes fixup
+                ret;
             }
         }
-        else version (Win64)
+        else version (GNU_InlineAsm)
         {
-            version (GNU_InlineAsm)
-            {
-                void** teb;
+            void** teb;
+            version (X86)
+                asm pure nothrow @nogc { "movl %%fs:0x18, %0;" : "=r" (teb); }
+            else version (X86_64)
                 asm pure nothrow @nogc { "movq %%gs:0x30, %0;" : "=r" (teb); }
-                return teb;
-            }
             else
-            {
-                asm pure nothrow @nogc
-                {
-                    naked;
-                    mov RAX,0x30;
-                    mov RAX,GS:[RAX]; // immediate value causes fixup
-                    ret;
-                }
-            }
+                static assert(false);
+            return teb;
         }
         else
         {
index a5aa975b20806501bd57b73194be90aa3bfbee00..bf841953805d5fd5e533832386d7415da41a7d21 100644 (file)
 module core.sys.windows.w32api;
 version (Windows):
 
+import core.sys.windows.sdkddkver;
+
 version (ANSI) {} else version = Unicode;
 
 enum __W32API_VERSION = 3.17;
 enum __W32API_MAJOR_VERSION = 3;
 enum __W32API_MINOR_VERSION = 17;
 
+enum Windows95 = 0x0400;
+enum Windows98 = 0x0410;
+enum WindowsME = 0x0500;
+
+enum WindowsNT4   = 0x0400;
+enum Windows2000  = 0x0500;
+enum WindowsXP    = 0x0501;
+enum Windows2003  = 0x0502;
+enum WindowsVista = 0x0600;
+enum Windows7     = 0x0601;
+enum Windows8     = 0x0602;
+
+enum IE3   = 0x0300;
+enum IE301 = 0x0300;
+enum IE302 = 0x0300;
+enum IE4   = 0x0400;
+enum IE401 = 0x0401;
+enum IE5   = 0x0500;
+enum IE5a  = 0x0500;
+enum IE5b  = 0x0500;
+enum IE501 = 0x0501;
+enum IE55  = 0x0501;
+enum IE56  = 0x0560;
+enum IE6   = 0x0600;
+enum IE601 = 0x0601;
+enum IE602 = 0x0603;
+enum IE7   = 0x0700;
+enum IE8   = 0x0800;
+enum IE9   = 0x0900;
+enum IE10  = 0x0A00;
+
 /*  These version identifiers are used to specify the minimum version of Windows that an
  *  application will support.
  *
@@ -23,62 +56,64 @@ enum __W32API_MINOR_VERSION = 17;
  *  Windows 9x is no longer supported, either by Microsoft or by DMD, this distinction has been
  *  removed in order to simplify the bindings.
  */
- version (Windows10) {
-    enum uint _WIN32_WINNT = 0xA00;
+version (Windows11) {
+    enum uint _WIN32_WINNT = _WIN32_WINNT_WIN10;
+} else version (Windows10) {
+    enum uint _WIN32_WINNT = _WIN32_WINNT_WIN10;
 } else version (Windows8_1) {    // also Windows2012R2
-    enum uint _WIN32_WINNT = 0x603;
+    enum uint _WIN32_WINNT = _WIN32_WINNT_WINBLUE;
 } else version (Windows8) {      // also Windows2012
-    enum uint _WIN32_WINNT = 0x602;
+    enum uint _WIN32_WINNT = _WIN32_WINNT_WIN8;
 } else version (Windows7) {      // also Windows2008R2
-    enum uint _WIN32_WINNT = 0x601;
+    enum uint _WIN32_WINNT = _WIN32_WINNT_WIN7;
 } else version (WindowsVista) {  // also Windows2008
-    enum uint _WIN32_WINNT = 0x600;
+    enum uint _WIN32_WINNT = _WIN32_WINNT_VISTA;
 } else version (Windows2003) {   // also WindowsHomeServer, WindowsXP64
-    enum uint _WIN32_WINNT = 0x502;
+    enum uint _WIN32_WINNT = _WIN32_WINNT_WS03;
 } else version (WindowsXP) {
-    enum uint _WIN32_WINNT = 0x501;
+    enum uint _WIN32_WINNT = _WIN32_WINNT_WINXP;
 } else version (Windows2000) {
     // Current DMD doesn't support any version of Windows older than XP,
     // but third-party compilers could use this
-    enum uint _WIN32_WINNT = 0x500;
+    enum uint _WIN32_WINNT = _WIN32_WINNT_WIN2K;
 } else {
-    enum uint _WIN32_WINNT = 0x601;
+    enum uint _WIN32_WINNT = _WIN32_WINNT_WIN7;
 }
 
 version (IE11) {
-    enum uint _WIN32_IE = 0xA00;
+    enum uint _WIN32_IE = _WIN32_IE_IE110;
 } else version (IE10) {
-    enum uint _WIN32_IE = 0xA00;
+    enum uint _WIN32_IE = _WIN32_IE_IE100;
 } else version (IE9) {
-    enum uint _WIN32_IE = 0x900;
+    enum uint _WIN32_IE = _WIN32_IE_IE90;
 } else version (IE8) {
-    enum uint _WIN32_IE = 0x800;
+    enum uint _WIN32_IE = _WIN32_IE_IE80;
 } else version (IE7) {
-    enum uint _WIN32_IE = 0x700;
+    enum uint _WIN32_IE = _WIN32_IE_IE70;
 } else version (IE602) {
-    enum uint _WIN32_IE = 0x603;
+    enum uint _WIN32_IE = _WIN32_IE_IE60SP2;
 } else version (IE601) {
-    enum uint _WIN32_IE = 0x601;
+    enum uint _WIN32_IE = _WIN32_IE_IE60SP1;
 } else version (IE6) {
-    enum uint _WIN32_IE = 0x600;
+    enum uint _WIN32_IE = _WIN32_IE_IE60;
 } else version (IE56) {
-    enum uint _WIN32_IE = 0x560;
+    enum uint _WIN32_IE = _WIN32_IE_IE60;
 } else version (IE55) {
-    enum uint _WIN32_IE = 0x550;
+    enum uint _WIN32_IE = _WIN32_IE_IE55;
 } else version (IE501) {
-    enum uint _WIN32_IE = 0x501;
+    enum uint _WIN32_IE = _WIN32_IE_IE501;
 } else version (IE5) {
-    enum uint _WIN32_IE = 0x500;
+    enum uint _WIN32_IE = _WIN32_IE_IE50;
 } else version (IE401) {
-    enum uint _WIN32_IE = 0x401;
+    enum uint _WIN32_IE = _WIN32_IE_IE401;
 } else version (IE4) {
-    enum uint _WIN32_IE = 0x400;
+    enum uint _WIN32_IE = _WIN32_IE_IE40;
 } else version (IE3) {
-    enum uint _WIN32_IE = 0x300;
-} else static if (_WIN32_WINNT >= 0x500) {
-    enum uint _WIN32_IE = 0x600;
-} else static if (_WIN32_WINNT >= 0x410) {
-    enum uint _WIN32_IE = 0x400;
+    enum uint _WIN32_IE = _WIN32_IE_IE30;
+} else static if (_WIN32_WINNT >= _WIN32_WINNT_WIN2K) {
+    enum uint _WIN32_IE = _WIN32_IE_IE60;
+} else static if (_WIN32_WINNT >= Windows98) { //NOTE: _WIN32_WINNT will never be set this low
+    enum uint _WIN32_IE = _WIN32_IE_IE40;
 } else {
     enum uint _WIN32_IE = 0;
 }
index a30035c0accc66786f9e12695d72fca48ab24c19..935c7c432cfdf87737f962687214f3becd783423 100644 (file)
@@ -1789,8 +1789,8 @@ extern (Windows) nothrow @nogc {
 
     alias RtlMoveMemory = memmove;
     alias RtlCopyMemory = memcpy;
-    pragma(inline, true) void RtlFillMemory(PVOID Destination, SIZE_T Length, BYTE Fill) { memset(Destination, Fill, Length); }
-    pragma(inline, true) void RtlZeroMemory(PVOID Destination, SIZE_T Length) { memset(Destination, 0, Length); }
+    pragma(inline, true) void RtlFillMemory(PVOID Destination, SIZE_T Length, BYTE Fill) pure { memset(Destination, Fill, Length); }
+    pragma(inline, true) void RtlZeroMemory(PVOID Destination, SIZE_T Length) pure { memset(Destination, 0, Length); }
     alias MoveMemory = RtlMoveMemory;
     alias CopyMemory = RtlCopyMemory;
     alias FillMemory = RtlFillMemory;
index e08e4a113eb4543edd7ec9b81736572bb1f9d31c..c1cd42b852e7c702e2e96bcdcb16daedebfdc8ef 100644 (file)
@@ -10,9 +10,6 @@
  * Source:    $(DRUNTIMESRC core/thread/osthread.d)
  */
 
-/* NOTE: This file has been patched from the original DMD distribution to
- * work with the GDC compiler.
- */
 module core.thread.osthread;
 
 import core.atomic;
@@ -37,10 +34,6 @@ else version (TVOS)
 else version (WatchOS)
     version = Darwin;
 
-version (Shared)
-    version (GNU)
-        version = GNUShared;
-
 version (D_InlineAsm_X86)
 {
     version (Windows)
@@ -482,16 +475,8 @@ class Thread : ThreadBase
 
                 version (Shared)
                 {
-                    version (GNU)
-                    {
-                        auto libs = externDFunc!("gcc.sections.pinLoadedLibraries",
-                                                 void* function() @nogc nothrow)();
-                    }
-                    else
-                    {
-                        auto libs = externDFunc!("rt.sections_elf_shared.pinLoadedLibraries",
-                                                 void* function() @nogc nothrow)();
-                    }
+                    auto libs = externDFunc!("rt.sections_elf_shared.pinLoadedLibraries",
+                                             void* function() @nogc nothrow)();
 
                     auto ps = cast(void**).malloc(2 * size_t.sizeof);
                     if (ps is null) onOutOfMemoryError();
@@ -499,16 +484,8 @@ class Thread : ThreadBase
                     ps[1] = cast(void*)libs;
                     if ( pthread_create( &m_addr, &attr, &thread_entryPoint, ps ) != 0 )
                     {
-                        version (GNU)
-                        {
-                            externDFunc!("gcc.sections.unpinLoadedLibraries",
-                                         void function(void*) @nogc nothrow)(libs);
-                        }
-                        else
-                        {
-                            externDFunc!("rt.sections_elf_shared.unpinLoadedLibraries",
-                                         void function(void*) @nogc nothrow)(libs);
-                        }
+                        externDFunc!("rt.sections_elf_shared.unpinLoadedLibraries",
+                                     void function(void*) @nogc nothrow)(libs);
                         .free(ps);
                         onThreadError( "Error creating thread" );
                     }
@@ -1562,7 +1539,7 @@ private extern(D) void* getStackBottom() nothrow @nogc
             else version (X86_64)
                 asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" (bottom); }
             else
-                static assert(false, "Platform not supported.");
+                static assert(false, "Architecture not supported.");
 
             return bottom;
         }
@@ -2232,12 +2209,7 @@ else version (Posix)
 
             // loadedLibraries need to be inherited from parent thread
             // before initilizing GC for TLS (rt_tlsgc_init)
-            version (GNUShared)
-            {
-                externDFunc!("gcc.sections.inheritLoadedLibraries",
-                             void function(void*) @nogc nothrow)(loadedLibraries);
-            }
-            else version (Shared)
+            version (Shared)
             {
                 externDFunc!("rt.sections_elf_shared.inheritLoadedLibraries",
                              void function(void*) @nogc nothrow)(loadedLibraries);
@@ -2319,12 +2291,7 @@ else version (Posix)
                     append( t );
                 }
                 rt_moduleTlsDtor();
-                version (GNUShared)
-                {
-                    externDFunc!("gcc.sections.cleanupLoadedLibraries",
-                                 void function() @nogc nothrow)();
-                }
-                else version (Shared)
+                version (Shared)
                 {
                     externDFunc!("rt.sections_elf_shared.cleanupLoadedLibraries",
                                  void function() @nogc nothrow)();
@@ -2801,16 +2768,8 @@ private size_t adjustStackSize(size_t sz) nothrow @nogc
     version (CRuntime_Glibc)
     {
         // On glibc, TLS uses the top of the stack, so add its size to the requested size
-        version (GNU)
-        {
-            sz += externDFunc!("gcc.sections.elf.sizeOfTLS",
-                               size_t function() @nogc nothrow)();
-        }
-        else
-        {
-            sz += externDFunc!("rt.sections_elf_shared.sizeOfTLS",
-                               size_t function() @nogc nothrow)();
-        }
+        sz += externDFunc!("rt.sections_elf_shared.sizeOfTLS",
+                           size_t function() @nogc nothrow)();
     }
 
     // stack size must be a multiple of pageSize
index bbebedf345ecbb6ed293f83e45d988ba18a7fe8d..6d8b843b2d9bedf2eae7dc8f66b44a0805929244 100644 (file)
@@ -181,7 +181,7 @@ alias ScanDG = void delegate(void* pbeg, void* pend) nothrow;
 version (Shared)
 {
     import gcc.sections : pinLoadedLibraries, unpinLoadedLibraries,
-           inheritLoadedLibraries, cleanupLoadedLibraries;
+           inheritLoadedLibraries, cleanupLoadedLibraries, sizeOfTLS;
 
     /***
      * Called once per thread; returns array of thread local storage ranges
@@ -213,6 +213,7 @@ version (Shared)
         }
     }
 
+    pragma(mangle, gcc.sections.sizeOfTLS.mangleof)
     size_t sizeOfTLS() nothrow @nogc
     {
         auto tdsos = initTLSRanges();
@@ -295,6 +296,8 @@ version (Shared)
 }
 else
 {
+    import gcc.sections : sizeOfTLS;
+
     /***
      * Called once per thread; returns array of thread local storage ranges
      */
@@ -328,6 +331,7 @@ else
         }
     }
 
+    pragma(mangle, gcc.sections.sizeOfTLS.mangleof)
     size_t sizeOfTLS() nothrow @nogc
     {
         auto rngs = initTLSRanges();
index b003c3125a907ed1682f1ec7f11ef040eb207eff..b41cb28a86d09c8e009541f94277a8a7b8f90be5 100644 (file)
@@ -42,11 +42,32 @@ else version (SectionsPeCoff)
 else
     static assert(0, "unimplemented");
 
+import core.internal.traits : externDFunc;
+
 version (Shared)
 {
-    // interface for core.thread to inherit loaded libraries
-    void* pinLoadedLibraries() nothrow @nogc;
-    void unpinLoadedLibraries(void* p) nothrow @nogc;
-    void inheritLoadedLibraries(void* p) nothrow @nogc;
-    void cleanupLoadedLibraries() nothrow @nogc;
+    // interface for core.thread.osthread to inherit loaded libraries
+    pragma(mangle, externDFunc!("rt.sections_elf_shared.pinLoadedLibraries",
+                                void* function() @nogc nothrow).mangleof)
+    void* pinLoadedLibraries() @nogc nothrow;
+
+    pragma(mangle, externDFunc!("rt.sections_elf_shared.unpinLoadedLibraries",
+                                void function(void*) @nogc nothrow).mangleof)
+    void unpinLoadedLibraries(void* p) @nogc nothrow;
+
+    pragma(mangle, externDFunc!("rt.sections_elf_shared.inheritLoadedLibraries",
+                                void function(void*) @nogc nothrow).mangleof)
+    void inheritLoadedLibraries(void* p) @nogc nothrow;
+
+    pragma(mangle, externDFunc!("rt.sections_elf_shared.cleanupLoadedLibraries",
+                                void function() @nogc nothrow).mangleof)
+    void cleanupLoadedLibraries() @nogc nothrow;
+}
+
+version (SectionsElf)
+{
+    // interface for core.thread.osthread to adjust stack size
+    pragma(mangle, externDFunc!("rt.sections_elf_shared.sizeOfTLS",
+                                size_t function() @nogc nothrow).mangleof)
+    size_t sizeOfTLS() @nogc nothrow;
 }
index ece0f4b9f2e7d002b9902177efc22b9e90abd297..02e4d7719aac9f4086210b2fcc4fc1f2e60652cd 100644 (file)
 
 module rt.adi;
 
-//debug=adi;            // uncomment to turn on debugging printf's
+// debug = adi; // uncomment to turn on debugging printf's
 
-private
-{
-    debug(adi) import core.stdc.stdio;
-}
+debug (adi) import core.stdc.stdio : printf;
 
 /***************************************
  * Support for array equality test.
index 0ab785ba3b97df511c0b6d370d4bda4ce77deea8..a443c9b620d8eec6b8e2b29e47bd57703d70def3 100644 (file)
 
 module rt.arraycat;
 
-private
-{
-    import core.stdc.string;
-    import core.internal.util.array;
-    debug(PRINTF) import core.stdc.stdio;
-}
+// debug = PRINTF;
+
+import core.internal.util.array;
+import core.stdc.string : memcpy;
+
+debug(PRINTF) import core.stdc.stdio : printf;
 
 extern (C) @trusted nothrow:
 
index 0a44be3e31f5b6ac0ab4d267bf9a0abd419bc4de..cb80c769c6deb103a5127a5621ea16031f203f22 100644 (file)
  * Authors:   Walter Bright
  * Source: $(DRUNTIMESRC rt/deh.d)
  */
-
-/* NOTE: This file has been patched from the original DMD distribution to
- * work with the GDC compiler.
- */
 module rt.deh;
 
 extern (C)
index a1ddba513957bc6e61e0d4a5fd03e1172afc21a2..f1e94913da5a217984996aac2b80a380928c6004 100644 (file)
@@ -9,27 +9,26 @@
  * Source: $(DRUNTIMESRC rt/_dmain2.d)
  */
 
-/* NOTE: This file has been patched from the original DMD distribution to
- * work with the GDC compiler.
- */
 module rt.dmain2;
 
-import rt.memory;
-import rt.sections;
 import core.atomic;
-import core.stdc.stddef;
-import core.stdc.stdlib;
-import core.stdc.string;
-import core.stdc.stdio;   // for printf()
+import core.internal.parseoptions : rt_parseOption;
 import core.stdc.errno : errno;
+import core.stdc.stdio : fflush, fprintf, fwrite, stderr, stdout;
+import core.stdc.stdlib : alloca, EXIT_FAILURE, EXIT_SUCCESS, free, malloc, realloc;
+import core.stdc.string : strerror;
+import rt.config : rt_cmdline_enabled, rt_configOption;
+import rt.memory;
+import rt.sections;
 
 version (Windows)
 {
-    import core.stdc.wchar_;
+    import core.stdc.stdio : fileno;
+    import core.stdc.wchar_ : wcslen;
     import core.sys.windows.basetsd : HANDLE;
     import core.sys.windows.shellapi : CommandLineToArgvW;
-    import core.sys.windows.winbase : FreeLibrary, GetCommandLineW, GetProcAddress,
-        IsDebuggerPresent, LoadLibraryW, LocalFree, WriteFile;
+    import core.sys.windows.winbase : FreeLibrary, GetCommandLineW, GetProcAddress, IsDebuggerPresent, LoadLibraryW,
+        LocalFree, WriteFile;
     import core.sys.windows.wincon : CONSOLE_SCREEN_BUFFER_INFO, GetConsoleOutputCP,
         GetConsoleScreenBufferInfo;
     import core.sys.windows.winnls : CP_UTF8, MultiByteToWideChar, WideCharToMultiByte;
@@ -37,19 +36,12 @@ version (Windows)
     import core.sys.windows.winuser : MB_ICONERROR, MessageBoxW;
 
     pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW
-}
 
-version (FreeBSD)
-{
-    import core.stdc.fenv;
-}
-version (NetBSD)
-{
-    import core.stdc.fenv;
+    import core.stdc.stdio : _get_osfhandle;
 }
-version (DragonFlyBSD)
+else version (Posix)
 {
-    import core.stdc.fenv;
+    import core.stdc.string : strlen;
 }
 
 // not sure why we can't define this in one place, but this is to keep this
@@ -447,7 +439,6 @@ private extern (C) int _d_run_main2(char[][] args, size_t totalArgsLength, MainF
         char[][] argsCopy = buff[0 .. args.length];
         auto argBuff = cast(char*) (buff + args.length);
         size_t j = 0;
-        import rt.config : rt_cmdline_enabled;
         bool parseOpts = rt_cmdline_enabled!();
         foreach (arg; args)
         {
@@ -590,8 +581,6 @@ private void formatThrowable(Throwable t, scope void delegate(in char[] s) nothr
 
 private auto parseExceptionOptions()
 {
-    import rt.config : rt_configOption;
-    import core.internal.parseoptions : rt_parseOption;
     const optName = "trapExceptions";
     auto option = rt_configOption(optName);
     auto trap = rt_trapExceptions;
index 65f92e3d015a5b7f2961589b1342910889665ab9..7c3f06c33c147ecd1fa41b273da13919639c5b96 100644 (file)
@@ -13,10 +13,7 @@ module rt.ehalloc;
 
 //debug = PRINTF;
 
-debug(PRINTF)
-{
-    import core.stdc.stdio;
-}
+debug (PRINTF) import core.stdc.stdio : printf;
 
 
 /********************************************
index 71ed51bf05c0c0095c6e036668dcd90719627694..3558674482836c1e93aa78f491fbf3da70d4e89d 100644 (file)
 module rt.lifetime;
 
 import core.attribute : weak;
-import core.memory;
+import core.checkedint : mulu;
+import core.exception : onFinalizeError, onOutOfMemoryError, onUnicodeError;
 import core.internal.gc.blockmeta : PAGESIZE;
-debug(PRINTF) import core.stdc.stdio;
+import core.memory;
+import core.stdc.stdlib : malloc;
+import core.stdc.string : memcpy, memset;
 static import rt.tlsgc;
 
+debug (PRINTF) import core.stdc.stdio : printf;
+debug (VALGRIND) import etc.valgrind.valgrind;
+
 alias BlkInfo = GC.BlkInfo;
 alias BlkAttr = GC.BlkAttr;
 
@@ -81,8 +87,6 @@ Returns: newly created object
 */
 extern (C) Object _d_newclass(const ClassInfo ci) @weak
 {
-    import core.stdc.stdlib;
-    import core.exception : onOutOfMemoryError;
     void* p;
     auto init = ci.initializer;
 
@@ -268,7 +272,6 @@ extern(C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow
             }
             catch (Exception e)
             {
-                import core.exception : onFinalizeError;
                 onFinalizeError(sti, e);
             }
         }
@@ -336,9 +339,6 @@ in
 }
 do
 {
-    import core.stdc.string;
-    import core.exception : onOutOfMemoryError;
-
     auto isshared = typeid(ti) is typeid(TypeInfo_Shared);
     auto tinext = unqualify(ti.next);
     auto size = tinext.tsize;
@@ -368,8 +368,6 @@ do
     }
     else
     {
-        import core.checkedint : mulu;
-
         bool overflow = false;
         size_t reqsize = mulu(size, newcapacity, overflow);
         if (!overflow)
@@ -444,8 +442,6 @@ Returns: newly allocated array
 */
 extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow @weak
 {
-    import core.exception : onOutOfMemoryError;
-
     auto tinext = unqualify(ti.next);
     auto size = tinext.tsize;
 
@@ -475,8 +471,6 @@ extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure noth
     }
     else
     {
-        import core.checkedint : mulu;
-
         bool overflow = false;
         size = mulu(size, length, overflow);
         if (!overflow)
@@ -497,8 +491,6 @@ Lcontinue:
 /// ditto
 extern (C) void[] _d_newarrayT(const TypeInfo ti, size_t length) pure nothrow @weak
 {
-    import core.stdc.string;
-
     void[] result = _d_newarrayU(ti, length);
     auto tinext = unqualify(ti.next);
     auto size = tinext.tsize;
@@ -533,7 +525,6 @@ extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length) pure nothrow @
 
     default:
     {
-        import core.stdc.string;
         immutable sz = init.length;
         for (size_t u = 0; u < size * length; u += sz)
             memcpy(result.ptr + u, init.ptr, sz);
@@ -650,8 +641,6 @@ extern (C) int rt_hasFinalizerInSegment(void* p, size_t size, uint attr, scope c
     return false;
 }
 
-debug (VALGRIND) import etc.valgrind.valgrind;
-
 void finalize_array(void* p, size_t size, const TypeInfo_Struct si)
 {
     // Due to the fact that the delete operator calls destructors
@@ -676,7 +665,6 @@ void finalize_struct(void* p, TypeInfo_Struct ti) nothrow
     }
     catch (Exception e)
     {
-        import core.exception : onFinalizeError;
         onFinalizeError(ti, e);
     }
 }
@@ -717,7 +705,6 @@ extern (C) void rt_finalize2(void* p, bool det = true, bool resetMemory = true)
     }
     catch (Exception e)
     {
-        import core.exception : onFinalizeError;
         onFinalizeError(*pc, e);
     }
     finally
@@ -760,7 +747,6 @@ extern (C) void rt_finalizeFromGC(void* p, size_t size, uint attr) nothrow
         }
         catch (Exception e)
         {
-            import core.exception : onFinalizeError;
             onFinalizeError(si, e);
         }
     }
@@ -801,9 +787,6 @@ in
 }
 do
 {
-    import core.stdc.string;
-    import core.exception : onOutOfMemoryError;
-
     debug(PRINTF)
     {
         //printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength);
@@ -848,7 +831,6 @@ do
     }
     else
     {
-        import core.checkedint : mulu;
         const size_t newsize = mulu(sizeelem, newlength, overflow);
     }
     if (overflow)
@@ -911,9 +893,6 @@ in
 }
 do
 {
-    import core.stdc.string;
-    import core.exception : onOutOfMemoryError;
-
     debug(PRINTF)
     {
         //printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength);
@@ -958,7 +937,6 @@ do
     }
     else
     {
-        import core.checkedint : mulu;
         const size_t newsize = mulu(sizeelem, newlength, overflow);
     }
     if (overflow)
@@ -1111,8 +1089,6 @@ Returns: `px` after being appended to
 extern (C)
 byte[] _d_arrayappendcTX(const TypeInfo ti, return scope ref byte[] px, size_t n) @weak
 {
-    import core.stdc.string;
-    import core.exception : onOutOfMemoryError;
     // This is a cut&paste job from _d_arrayappendT(). Should be refactored.
 
     // Short circuit if no data is being appended.
@@ -1218,7 +1194,6 @@ extern (C) void[] _d_arrayappendcd(ref byte[] x, dchar c) @weak
     }
     else
     {
-        import core.exception : onUnicodeError;
         onUnicodeError("Invalid UTF-8 sequence", 0);      // invalid utf character
     }
 
index 9bc105589816099192b5fe5942eed9880dd1e3ab..6e9cd1c8fe1487cc00b757da077d671f47c184cc 100644 (file)
 
 module rt.minfo;
 
-import core.stdc.stdlib;  // alloca
-import core.stdc.string;  // memcpy
+import core.stdc.stdio : fprintf, stderr;
+import core.stdc.stdlib : free, malloc, realloc;
+import core.stdc.string : memcpy, memset;
 import rt.sections;
 
+debug (printModuleDependencies) import core.stdc.stdio : printf;
+
 enum
 {
     MIctorstart  = 0x1,   // we've started constructing it
@@ -179,7 +182,6 @@ struct ModuleGroup
         switch (cycleHandling) with(OnCycle)
         {
         case "deprecate":
-            import core.stdc.stdio : fprintf, stderr;
             // Option deprecated in 2.101, remove in 2.111
             fprintf(stderr, "`--DRT-oncycle=deprecate` is no longer supported, using `abort` instead\n");
             break;
@@ -202,8 +204,6 @@ struct ModuleGroup
 
         debug (printModuleDependencies)
         {
-            import core.stdc.stdio : printf;
-
             foreach (_m; _modules)
             {
                 printf("%s%s%s:", _m.name.ptr, (_m.flags & MIstandalone)
@@ -375,7 +375,6 @@ struct ModuleGroup
                                 case print:
                                     // print the message
                                     buildCycleMessage(idx, midx, (string x) {
-                                                      import core.stdc.stdio : fprintf, stderr;
                                                       fprintf(stderr, "%.*s", cast(int) x.length, x.ptr);
                                                       });
                                     // continue on as if this is correct.
@@ -518,7 +517,6 @@ struct ModuleGroup
             !doSort(MItlsctor | MItlsdtor, _tlsctors))
         {
             // print a warning
-            import core.stdc.stdio : fprintf, stderr;
             fprintf(stderr, "Deprecation 16211 warning:\n"
                 ~ "A cycle has been detected in your program that was undetected prior to DMD\n"
                 ~ "2.072. This program will continue, but will not operate when using DMD 2.074\n"
index 5d6c2f8c148394db778d450ccfb638661eb8f700..1d4ed2ea8fc4dae8fe1493a288d12984619ea1c9 100644 (file)
@@ -8,7 +8,26 @@
  */
 module rt.monitor_;
 
-import core.atomic, core.stdc.stdlib, core.stdc.string;
+import core.atomic;
+import core.stdc.stdlib : calloc, free, realloc;
+import core.stdc.string : memmove;
+
+version (Windows)
+{
+    import core.sys.windows.winbase /+: CRITICAL_SECTION, DeleteCriticalSection,
+        EnterCriticalSection, InitializeCriticalSection, LeaveCriticalSection+/;
+}
+else version (Posix)
+{
+    import core.sys.posix.pthread : pthread_mutex_destroy, pthread_mutex_init, pthread_mutex_lock,
+        PTHREAD_MUTEX_RECURSIVE, pthread_mutex_unlock, pthread_mutexattr_destroy, pthread_mutexattr_init,
+        pthread_mutexattr_settype;
+    import core.sys.posix.sys.types : pthread_mutex_t, pthread_mutexattr_t;
+}
+else
+{
+    static assert(0, "Unsupported platform");
+}
 
 // NOTE: The dtor callback feature is only supported for monitors that are not
 //       supplied by the user.  The assumption is that any object with a user-
@@ -173,9 +192,6 @@ alias DEvent = void delegate(Object);
 
 version (Windows)
 {
-    import core.sys.windows.winbase /+: CRITICAL_SECTION, DeleteCriticalSection,
-        EnterCriticalSection, InitializeCriticalSection, LeaveCriticalSection+/;
-
     alias Mutex = CRITICAL_SECTION;
 
     alias initMutex = InitializeCriticalSection;
@@ -185,11 +201,6 @@ version (Windows)
 }
 else version (Posix)
 {
-    import core.sys.posix.pthread : pthread_mutex_destroy, pthread_mutex_init, pthread_mutex_lock,
-        PTHREAD_MUTEX_RECURSIVE, pthread_mutex_unlock, pthread_mutexattr_destroy, pthread_mutexattr_init,
-        pthread_mutexattr_settype;
-    import core.sys.posix.sys.types : pthread_mutex_t, pthread_mutexattr_t;
-
 @nogc:
     alias Mutex = pthread_mutex_t;
     __gshared pthread_mutexattr_t gattr;
@@ -214,10 +225,6 @@ else version (Posix)
         pthread_mutex_unlock(mtx) && assert(0);
     }
 }
-else
-{
-    static assert(0, "Unsupported platform");
-}
 
 struct Monitor
 {
@@ -229,6 +236,8 @@ struct Monitor
 
 private:
 
+__gshared Mutex gmtx;
+
 @property ref shared(Monitor*) monitor(return scope Object h) pure nothrow @nogc
 {
     return *cast(shared Monitor**)&h.__monitor;
@@ -244,8 +253,6 @@ void setMonitor(Object h, shared(Monitor)* m) pure @nogc
     atomicStore!(MemoryOrder.rel)(h.monitor, m);
 }
 
-__gshared Mutex gmtx;
-
 shared(Monitor)* ensureMonitor(Object h)
 {
     if (auto m = getMonitor(h))
index b97a5c5437b0dfac9e3ca496c6ea6ef77bdecef8..e7d4f03e53ad56b674715087b3eec00518eab1ed 100644 (file)
@@ -15,10 +15,9 @@ module rt.profilegc;
 
 private:
 
-import core.stdc.errno;
-import core.stdc.stdio;
-import core.stdc.stdlib;
-import core.stdc.string;
+import core.stdc.errno : errno;
+import core.stdc.stdio : fclose, FILE, fopen, fprintf, snprintf, stderr, stdout;
+import core.stdc.stdlib : free, malloc, qsort, realloc;
 
 import core.exception : onOutOfMemoryError;
 import core.internal.container.hashtab;
index a7b75d4ba81e793c4ecafa916373e09f758b496b..ce5a6682dfecb3fa0b1f69355e08f22a9df904d2 100644 (file)
@@ -8,9 +8,6 @@
  * Source: $(DRUNTIMESRC rt/_sections.d)
  */
 
-/* NOTE: This file has been patched from the original DMD distribution to
- * work with the GDC compiler.
- */
 module rt.sections;
 
 version (OSX)
index f1dcc598d7964971fa8d9552659debf6a5307aae..2b21d1e0e15be88b893509e9f37c411a49b2b6b0 100644 (file)
@@ -13,9 +13,9 @@
  */
 module rt.tlsgc;
 
-import core.stdc.stdlib;
-
-static import rt.lifetime, rt.sections;
+import core.exception : onOutOfMemoryError;
+import core.stdc.stdlib : free, malloc;
+static import rt.sections;
 
 /**
  * Per thread record to store thread associated data for garbage collection.
@@ -32,8 +32,7 @@ struct Data
 void* init() nothrow @nogc
 {
     auto data = cast(Data*).malloc(Data.sizeof);
-    import core.exception;
-    if ( data is null ) core.exception.onOutOfMemoryError();
+    if ( data is null ) onOutOfMemoryError();
     *data = Data.init;
 
     // do module specific initialization