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

- Error messages related to operator overloading have been improved.

D runtime changes:

- Import latest fixes from druntime.

gcc/d/ChangeLog:

* dmd/MERGE: Merge upstream dmd d29e3eca45.
* d-codegen.cc (can_elide_copy_p): Update for new front-end interface.
* d-lang.cc (d_handle_option): Likewise.
* expr.cc (class ExprVisitor): Likewise.

libphobos/ChangeLog:

* libdruntime/MERGE: Merge upstream druntime d29e3eca45.

82 files changed:
gcc/d/d-codegen.cc
gcc/d/d-lang.cc
gcc/d/dmd/MERGE
gcc/d/dmd/access.d
gcc/d/dmd/aggregate.d
gcc/d/dmd/arrayop.d
gcc/d/dmd/attrib.d
gcc/d/dmd/attrib.h
gcc/d/dmd/cond.d
gcc/d/dmd/cond.h
gcc/d/dmd/cparse.d
gcc/d/dmd/ctfe.h
gcc/d/dmd/ctfeexpr.d
gcc/d/dmd/cxxfrontend.d
gcc/d/dmd/dcast.d
gcc/d/dmd/declaration.d
gcc/d/dmd/declaration.h
gcc/d/dmd/dinterpret.d
gcc/d/dmd/dmodule.d
gcc/d/dmd/doc.d
gcc/d/dmd/dsymbol.d
gcc/d/dmd/dsymbol.h
gcc/d/dmd/dsymbolsem.d
gcc/d/dmd/dtemplate.d
gcc/d/dmd/dversion.d
gcc/d/dmd/errors.d
gcc/d/dmd/escape.d
gcc/d/dmd/expression.d
gcc/d/dmd/expression.h
gcc/d/dmd/expressionsem.d
gcc/d/dmd/func.d
gcc/d/dmd/globals.d
gcc/d/dmd/globals.h
gcc/d/dmd/hdrgen.d
gcc/d/dmd/iasm.d
gcc/d/dmd/iasmgcc.d
gcc/d/dmd/identifier.d
gcc/d/dmd/importc.d
gcc/d/dmd/initsem.d
gcc/d/dmd/intrange.d
gcc/d/dmd/json.d
gcc/d/dmd/location.d
gcc/d/dmd/module.h
gcc/d/dmd/mtype.d
gcc/d/dmd/ob.d
gcc/d/dmd/opover.d
gcc/d/dmd/parse.d
gcc/d/dmd/statementsem.d
gcc/d/dmd/template.h
gcc/d/dmd/templatesem.d
gcc/d/dmd/typesem.d
gcc/d/dmd/version.h
gcc/d/expr.cc
gcc/testsuite/gdc.test/fail_compilation/b17285.d
gcc/testsuite/gdc.test/fail_compilation/bug9631.d
gcc/testsuite/gdc.test/fail_compilation/dep_d1_ops.d
gcc/testsuite/gdc.test/fail_compilation/diag12063.d
gcc/testsuite/gdc.test/fail_compilation/diag13320.d
gcc/testsuite/gdc.test/fail_compilation/diag16499.d
gcc/testsuite/gdc.test/fail_compilation/fail10964.d
gcc/testsuite/gdc.test/fail_compilation/fail10968.d
gcc/testsuite/gdc.test/fail_compilation/fail18143.d
gcc/testsuite/gdc.test/fail_compilation/fail18985.d
gcc/testsuite/gdc.test/fail_compilation/fail20.d
gcc/testsuite/gdc.test/fail_compilation/fail20616.d
gcc/testsuite/gdc.test/fail_compilation/fail297.d
gcc/testsuite/gdc.test/fail_compilation/fail3.d
gcc/testsuite/gdc.test/fail_compilation/fail3672.d
gcc/testsuite/gdc.test/fail_compilation/fail4421.d
gcc/testsuite/gdc.test/fail_compilation/fail6107.d
gcc/testsuite/gdc.test/fail_compilation/fail7848.d
gcc/testsuite/gdc.test/fail_compilation/fail_arrayexp.d
gcc/testsuite/gdc.test/fail_compilation/fail_opover.d
gcc/testsuite/gdc.test/fail_compilation/ice10624.d
gcc/testsuite/gdc.test/fail_compilation/ice12902.d
gcc/testsuite/gdc.test/fail_compilation/ice9545.d
gcc/testsuite/gdc.test/fail_compilation/operator_undefined.d
gcc/testsuite/gdc.test/fail_compilation/test20763.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test22329.d
libphobos/libdruntime/MERGE
libphobos/libdruntime/core/bitop.d
libphobos/libdruntime/core/sys/windows/ntdef.d

index 50362e6f8f53a23fa46a59cbe66390b5e587fad8..4d8ed65536b1d1c0407b5ca15150a9f63df45e8b 100644 (file)
@@ -637,7 +637,7 @@ static bool
 can_elide_copy_p (Expression *exp)
 {
   /* Explicit `__rvalue(exp)'.  */
-  if (exp->rvalue)
+  if (exp->rvalue ())
     return true;
 
   /* Look for variable expression.  */
index a4cde584f43f0539877687127621c853c3f7f9ba..585737b4d533e8855d53d54a51064af4cb408041 100644 (file)
@@ -450,7 +450,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       break;
 
     case OPT_fdebug:
-      global.params.debuglevel = value ? 1 : 0;
+      global.params.debugEnabled = value ? true : false;
       break;
 
     case OPT_fdebug_:
index a91f40b6bfce85980b123172edffe39f134f9732..c81fccbb902eff24cfb95d7f71dab77f1d5d9877 100644 (file)
@@ -1,4 +1,4 @@
-b7e3b3b61711bf6c6cad27c7b5b73df0e570c215
+d29e3eca45edaeef63b31f78c9846fc6e2870c49
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index e778ed92cae8149212567d6b063ee67acbbc40ae..b3e98f8f18d45614bb03c8691c4e0c78f99f7a45 100644 (file)
@@ -142,7 +142,7 @@ private bool hasPackageAccess(Module mod, Dsymbol s)
 /****************************************
  * Determine if scope sc has protected level access to cd.
  */
-private bool hasProtectedAccess(Scope *sc, Dsymbol s)
+private bool hasProtectedAccess(Scopesc, Dsymbol s)
 {
     if (auto cd = s.isClassMember()) // also includes interfaces
     {
@@ -273,7 +273,7 @@ bool symbolIsVisible(Dsymbol origin, Dsymbol s)
  *  s = symbol to check for visibility
  * Returns: true if s is visible by origin
  */
-bool symbolIsVisible(Scope *sc, Dsymbol s)
+bool symbolIsVisible(Scopesc, Dsymbol s)
 {
     s = mostVisibleOverload(s);
     return checkSymbolAccess(sc, s);
@@ -288,7 +288,7 @@ bool symbolIsVisible(Scope *sc, Dsymbol s)
  *  s = symbol to check for visibility
  * Returns: true if s is visible by origin
  */
-bool checkSymbolAccess(Scope *sc, Dsymbol s)
+bool checkSymbolAccess(Scopesc, Dsymbol s)
 {
     final switch (s.visible().kind)
     {
index 25f54b57c91d29e0e94a4895576a8d0768275a30..20bcafeb675e37dd3d5daf5484755b51f3ea586c 100644 (file)
@@ -447,7 +447,8 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
                   s.isTemplateDeclaration() ||
                   s.isOverloadSet()))
             {
-                .error(s.loc, "%s `%s` is not a constructor; identifiers starting with `__` are reserved for the implementation", s.kind(), s.toPrettyChars());
+                error(s.loc, "%s name `__ctor` is not allowed", s.kind);
+                errorSupplemental(s.loc, "identifiers starting with `__` are reserved for internal use");
                 errors = true;
                 s = null;
             }
index 5fe5273d5add6f823cdb55fce4263fd31372cdc6..e1aefdb6d39bb3dcf0797d354de94f0e76964a95 100644 (file)
@@ -44,12 +44,12 @@ bool isArrayOpValid(Expression e)
     if (e.op == EXP.arrayLiteral)
     {
         Type t = e.type.toBasetype();
-        while (t.ty == Tarray || t.ty == Tsarray)
+        while (t.isStaticOrDynamicArray())
             t = t.nextOf().toBasetype();
         return (t.ty != Tvoid);
     }
     Type tb = e.type.toBasetype();
-    if (tb.ty == Tarray || tb.ty == Tsarray)
+    if (tb.isStaticOrDynamicArray())
     {
         if (isUnaArrayOp(e.op))
         {
@@ -80,7 +80,7 @@ bool isNonAssignmentArrayOp(Expression e)
         return isNonAssignmentArrayOp(e.isSliceExp().e1);
 
     Type tb = e.type.toBasetype();
-    if (tb.ty == Tarray || tb.ty == Tsarray)
+    if (tb.isStaticOrDynamicArray())
     {
         return (isUnaArrayOp(e.op) || isBinArrayOp(e.op));
     }
@@ -119,7 +119,7 @@ Expression arrayOp(BinExp e, Scope* sc)
 {
     //printf("BinExp.arrayOp() %s\n", e.toChars());
     Type tb = e.type.toBasetype();
-    assert(tb.ty == Tarray || tb.ty == Tsarray);
+    assert(tb.isStaticOrDynamicArray());
     Type tbn = tb.nextOf().toBasetype();
     if (tbn.ty == Tvoid)
     {
@@ -346,7 +346,7 @@ bool isArrayOpOperand(Expression e)
     if (e.op == EXP.arrayLiteral)
     {
         Type t = e.type.toBasetype();
-        while (t.ty == Tarray || t.ty == Tsarray)
+        while (t.isStaticOrDynamicArray())
             t = t.nextOf().toBasetype();
         return (t.ty != Tvoid);
     }
index 5da4721bba5c77e4e640efd0f5a26281a83f1def..7a60ecbd4086871a3b1b7a167fbcefbfa0a78fe1 100644 (file)
@@ -271,17 +271,6 @@ extern (C++) final class LinkDeclaration : AttribDeclaration
         return new LinkDeclaration(loc, linkage, Dsymbol.arraySyntaxCopy(decl));
     }
 
-
-    override const(char)* toChars() const
-    {
-        return toString().ptr;
-    }
-
-    extern(D) override const(char)[] toString() const
-    {
-        return "extern ()";
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -313,16 +302,6 @@ extern (C++) final class CPPMangleDeclaration : AttribDeclaration
         return new CPPMangleDeclaration(loc, cppmangle, Dsymbol.arraySyntaxCopy(decl));
     }
 
-    override const(char)* toChars() const
-    {
-        return toString().ptr;
-    }
-
-    extern(D) override const(char)[] toString() const
-    {
-        return "extern ()";
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -383,16 +362,6 @@ extern (C++) final class CPPNamespaceDeclaration : AttribDeclaration
             this.loc, this.ident, this.exp, Dsymbol.arraySyntaxCopy(this.decl), this.cppnamespace);
     }
 
-    override const(char)* toChars() const
-    {
-        return toString().ptr;
-    }
-
-    extern(D) override const(char)[] toString() const
-    {
-        return "extern (C++, `namespace`)";
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
index ef01d0f9538f6794557000d15a32ee345438fb56..1c9bd96fa9c24c4bf04ddb0111a441c810139c40 100644 (file)
@@ -67,7 +67,6 @@ public:
 
     static LinkDeclaration *create(const Loc &loc, LINK p, Dsymbols *decl);
     LinkDeclaration *syntaxCopy(Dsymbol *s) override;
-    const char *toChars() const override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -77,7 +76,6 @@ public:
     CPPMANGLE cppmangle;
 
     CPPMangleDeclaration *syntaxCopy(Dsymbol *s) override;
-    const char *toChars() const override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -87,7 +85,6 @@ public:
     Expression *exp;
 
     CPPNamespaceDeclaration *syntaxCopy(Dsymbol *s) override;
-    const char *toChars() const override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
index f66f14af5b91c601dbc08244db6944d740987f9d..186efb072825aadd9616d81a9e7be93545a69967 100644 (file)
@@ -166,7 +166,7 @@ extern (C++) final class StaticForeach : RootObject
             return;
         }
 
-        Expressions *es;
+        Expressionses;
         if (auto ale = aggr.isArrayLiteralExp())
         {
             // Directly use the elements of the array for the TupleExp creation
@@ -493,15 +493,13 @@ extern (C++) final class StaticForeach : RootObject
  */
 extern (C++) class DVCondition : Condition
 {
-    uint level;
     Identifier ident;
     Module mod;
 
-    extern (D) this(const ref Loc loc, Module mod, uint level, Identifier ident) @safe
+    extern (D) this(const ref Loc loc, Module mod, Identifier ident) @safe
     {
         super(loc);
         this.mod = mod;
-        this.level = level;
         this.ident = ident;
     }
 
@@ -556,15 +554,13 @@ extern (C++) final class DebugCondition : DVCondition
      *
      * Params:
      *   mod = Module this node belongs to
-     *   level = Minimum global level this condition needs to pass.
-     *           Only used if `ident` is `null`.
      *   ident = Identifier required for this condition to pass.
      *           If `null`, this conditiion will use an integer level.
      *  loc = Location in the source file
      */
-    extern (D) this(const ref Loc loc, Module mod, uint level, Identifier ident) @safe
+    extern (D) this(const ref Loc loc, Module mod, Identifier ident) @safe
     {
-        super(loc, mod, level, ident);
+        super(loc, mod, ident);
     }
 
     override int include(Scope* sc)
@@ -592,8 +588,9 @@ extern (C++) final class DebugCondition : DVCondition
                 mod.debugidsNot.push(ident);
             }
         }
-        else if (level <= global.params.debuglevel || level <= mod.debuglevel)
+        else if (global.params.debugEnabled)
             inc = Include.yes;
+
         if (!definedInModule)
             printDepsConditional(sc, this, "depsDebug ");
         return (inc == Include.yes);
@@ -608,11 +605,6 @@ extern (C++) final class DebugCondition : DVCondition
     {
         v.visit(this);
     }
-
-    override const(char)* toChars() const
-    {
-        return ident ? ident.toChars() : "debug".ptr;
-    }
 }
 
 /**
@@ -837,15 +829,13 @@ extern (C++) final class VersionCondition : DVCondition
      *
      * Params:
      *   mod = Module this node belongs to
-     *   level = Minimum global level this condition needs to pass.
-     *           Only used if `ident` is `null`.
      *   ident = Identifier required for this condition to pass.
      *           If `null`, this conditiion will use an integer level.
      *  loc = Location in the source file
      */
-    extern (D) this(const ref Loc loc, Module mod, uint level, Identifier ident) @safe
+    extern (D) this(const ref Loc loc, Module mod, Identifier ident) @safe
     {
-        super(loc, mod, level, ident);
+        super(loc, mod, ident);
     }
 
     override int include(Scope* sc)
@@ -875,8 +865,6 @@ extern (C++) final class VersionCondition : DVCondition
                 mod.versionidsNot.push(ident);
             }
         }
-        else if (level <= global.params.versionlevel || level <= mod.versionlevel)
-            inc = Include.yes;
         if (!definedInModule &&
             (!ident || (!isReserved(ident.toString()) && ident != Id._unittest && ident != Id._assert)))
         {
@@ -894,11 +882,6 @@ extern (C++) final class VersionCondition : DVCondition
     {
         v.visit(this);
     }
-
-    override const(char)* toChars() const
-    {
-        return ident ? ident.toChars() : "version".ptr;
-    }
 }
 
 /***********************************************************
@@ -968,11 +951,6 @@ extern (C++) final class StaticIfCondition : Condition
     {
         return this;
     }
-
-    override const(char)* toChars() const
-    {
-        return exp ? exp.toChars() : "static if".ptr;
-    }
 }
 
 
@@ -1010,7 +988,5 @@ private void printDepsConditional(Scope* sc, DVCondition condition, const(char)[
     ob.writestring(") : ");
     if (condition.ident)
         ob.writestring(condition.ident.toString());
-    else
-        ob.print(condition.level);
     ob.writeByte('\n');
 }
index fc3ebd4625d49c8066201c46d584f4c921847d36..ec68d19c04a1c6e2fa67d6a93e64b4d78c04cb28 100644 (file)
@@ -58,7 +58,6 @@ public:
 class DVCondition : public Condition
 {
 public:
-    unsigned level;
     Identifier *ident;
     Module *mod;
 
index 354d83bd4ba4493264f691ee1c44e54c45dc5339..bef1ec96c99e8e31e21c1be3a37fed1c41d6c2d3 100644 (file)
@@ -2990,7 +2990,7 @@ final class CParser(AST) : Parser!AST
                             if (isStatic || mod)
                                 error("static or type qualifier used outside of function prototype");
                         }
-                        if (ts.isTypeSArray() || ts.isTypeDArray())
+                        if (ts.isStaticOrDynamicArray())
                         {
                             /* C11 6.7.6.2-1: type qualifiers and 'static' shall only appear
                              * in the outermost array type derivation.
index 72d895c715096a64f3b6c5fd4dbc8fc26a2e28d9..73f1939490aaa850446dd0b223df9e9345056035 100644 (file)
@@ -48,7 +48,6 @@ class ThrownExceptionExp final : public Expression
 {
 public:
     ClassReferenceExp *thrown; // the thing being tossed
-    const char *toChars() const override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -58,6 +57,4 @@ public:
 
 class CTFEExp final : public Expression
 {
-public:
-    const char *toChars() const override;
 };
index 6d2a954cb7bab5ba398c1e2990424140d1823716..9a927810fe84fb17afb9816cb5aba2570d93bf08 100644 (file)
@@ -688,7 +688,7 @@ Expression getAggregateFromPointer(Expression e, dinteger_t* ofs)
     if (auto ie = e.isIndexExp())
     {
         // Note that each AA element is part of its own memory block
-        if ((ie.e1.type.ty == Tarray || ie.e1.type.ty == Tsarray || ie.e1.op == EXP.string_ || ie.e1.op == EXP.arrayLiteral) && ie.e2.op == EXP.int64)
+        if ((ie.e1.type.isStaticOrDynamicArray() || ie.e1.op == EXP.string_ || ie.e1.op == EXP.arrayLiteral) && ie.e2.op == EXP.int64)
         {
             *ofs = ie.e2.toInteger();
             return ie.e1;
@@ -697,7 +697,7 @@ Expression getAggregateFromPointer(Expression e, dinteger_t* ofs)
     if (auto se = e.isSliceExp())
     {
         if (se && e.type.toBasetype().ty == Tsarray &&
-           (se.e1.type.ty == Tarray || se.e1.type.ty == Tsarray || se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral) && se.lwr.op == EXP.int64)
+           (se.e1.type.isStaticOrDynamicArray() || se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral) && se.lwr.op == EXP.int64)
         {
             *ofs = se.lwr.toInteger();
             return se.e1;
@@ -1841,7 +1841,7 @@ bool isCtfeValueValid(Expression newval)
             const SliceExp se = newval.isSliceExp();
             assert(se.lwr && se.lwr.op == EXP.int64);
             assert(se.upr && se.upr.op == EXP.int64);
-            return (tb.ty == Tarray || tb.ty == Tsarray) && (se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral);
+            return tb.isStaticOrDynamicArray() && (se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral);
         }
 
         case EXP.void_:
index b74b11b67341b7a8f2c31dfffea9568f365bdc06..3807c1dfa995a17b626b71f121971ed7777ab78f 100644 (file)
@@ -338,13 +338,13 @@ const(char)* parametersTypeToChars(ParameterList pl)
 /***********************************************************
  * iasm.d
  */
-Statement asmSemantic(AsmStatement s, Scope *sc)
+Statement asmSemantic(AsmStatement s, Scopesc)
 {
     import dmd.iasm;
     return dmd.iasm.asmSemantic(s, sc);
 }
 
-void asmSemantic(CAsmDeclaration d, Scope *sc)
+void asmSemantic(CAsmDeclaration d, Scopesc)
 {
     import dmd.iasm;
     return dmd.iasm.asmSemantic(d, sc);
@@ -353,13 +353,13 @@ void asmSemantic(CAsmDeclaration d, Scope *sc)
 /***********************************************************
  * iasmgcc.d
  */
-Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
+Statement gccAsmSemantic(GccAsmStatement s, Scopesc)
 {
     import dmd.iasmgcc;
     return dmd.iasmgcc.gccAsmSemantic(s, sc);
 }
 
-void gccAsmSemantic(CAsmDeclaration d, Scope *sc)
+void gccAsmSemantic(CAsmDeclaration d, Scopesc)
 {
     import dmd.iasmgcc;
     return dmd.iasmgcc.gccAsmSemantic(d, sc);
index 0d95ad46d380e1e7e5db6eb2d8f95a2ebe9590dd..bb85318c44eed15c77e3c55e435b7987233f2bc2 100644 (file)
@@ -626,7 +626,7 @@ MATCH implicitConvTo(Expression e, Type t)
         if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
             return MATCH.nomatch;
 
-        if (!(e.type.ty == Tsarray || e.type.ty == Tarray || e.type.ty == Tpointer))
+        if (!(e.type.isStaticOrDynamicArray() || e.type.ty == Tpointer))
             return visit(e);
 
         TY tyn = e.type.nextOf().ty;
@@ -758,8 +758,7 @@ MATCH implicitConvTo(Expression e, Type t)
         Type typeb = e.type.toBasetype();
 
         auto result = MATCH.nomatch;
-        if ((tb.ty == Tarray || tb.ty == Tsarray) &&
-            (typeb.ty == Tarray || typeb.ty == Tsarray))
+        if (tb.isStaticOrDynamicArray() && typeb.isStaticOrDynamicArray())
         {
             result = MATCH.exact;
             Type typen = typeb.nextOf().toBasetype();
@@ -802,7 +801,7 @@ MATCH implicitConvTo(Expression e, Type t)
 
             return result;
         }
-        else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray || typeb.ty == Tpointer))
+        else if (tb.ty == Tvector && (typeb.isStaticOrDynamicArray() || typeb.ty == Tpointer))
         {   // Tpointer because ImportC eagerly converts Tsarray to Tpointer
             result = MATCH.exact;
             // Convert array literal to vector type
@@ -2724,8 +2723,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
         }
         Type typeb = e.type.toBasetype();
 
-        if ((tb.ty == Tarray || tb.ty == Tsarray) &&
-            (typeb.ty == Tarray || typeb.ty == Tsarray))
+        if (tb.isStaticOrDynamicArray() && typeb.isStaticOrDynamicArray())
         {
             if (tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)
             {
@@ -2768,7 +2766,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
                 ae.type = tp;
             }
         }
-        else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray || typeb.ty == Tpointer))
+        else if (tb.ty == Tvector && (typeb.isStaticOrDynamicArray() || typeb.ty == Tpointer))
         {
             // Convert array literal to vector type
             // The Tpointer case comes from C eagerly converting Tsarray to Tpointer
@@ -3140,7 +3138,7 @@ Expression inferType(Expression e, Type t, int flag = 0)
     Expression visitAle(ArrayLiteralExp ale)
     {
         Type tb = t.toBasetype();
-        if (tb.ty == Tarray || tb.ty == Tsarray)
+        if (tb.isStaticOrDynamicArray())
         {
             Type tn = tb.nextOf();
             if (ale.basis)
@@ -3284,7 +3282,7 @@ private bool isVoidArrayLiteral(Expression e, Type other)
     {
         auto ale = e.isArrayLiteralExp();
         e = ale[0];
-        if (other.ty == Tsarray || other.ty == Tarray)
+        if (other.isStaticOrDynamicArray())
             other = other.nextOf();
         else
             return false;
@@ -3550,7 +3548,7 @@ Lagain:
         return null;
     }
 
-    if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == EXP.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == EXP.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && t2.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
+    if (t1.isStaticOrDynamicArray() && (e2.op == EXP.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == EXP.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && t2.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
     {
         /*  (T[n] op void*)   => T[]
          *  (T[]  op void*)   => T[]
@@ -3562,7 +3560,9 @@ Lagain:
         return coerce(t1.nextOf().arrayOf());
     }
 
-    if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == EXP.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == EXP.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && t1.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
+    if (t2.isStaticOrDynamicArray() &&
+        (e1.op == EXP.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == EXP.arrayLiteral
+        && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && t1.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
     {
         /*  (void*   op T[n]) => T[]
          *  (void*   op T[])  => T[]
@@ -3574,7 +3574,7 @@ Lagain:
         return coerce(t2.nextOf().arrayOf());
     }
 
-    if ((t1.ty == Tsarray || t1.ty == Tarray) && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
+    if (t1.isStaticOrDynamicArray() && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
     {
         // https://issues.dlang.org/show_bug.cgi?id=7285
         // Tsarray op [x, y, ...] should to be Tsarray
@@ -3590,7 +3590,7 @@ Lagain:
         return convert(e1, t2);
     }
 
-    if ((t2.ty == Tsarray || t2.ty == Tarray) && t2.implicitConvTo(t1))
+    if (t2.isStaticOrDynamicArray() && t2.implicitConvTo(t1))
     {
         // https://issues.dlang.org/show_bug.cgi?id=7285
         // https://issues.dlang.org/show_bug.cgi?id=14737
@@ -3599,7 +3599,8 @@ Lagain:
         return convert(e2, t1);
     }
 
-    if ((t1.ty == Tsarray || t1.ty == Tarray || t1.ty == Tpointer) && (t2.ty == Tsarray || t2.ty == Tarray || t2.ty == Tpointer) && t1.nextOf().mod != t2.nextOf().mod)
+    if ((t1.isStaticOrDynamicArray() || t1.ty == Tpointer) && (t2.isStaticOrDynamicArray() || t2.ty == Tpointer)
+        && t1.nextOf().mod != t2.nextOf().mod)
     {
         /* If one is mutable and the other immutable, then retry
          * with both of them as const
@@ -3919,7 +3920,7 @@ LmodCompare:
         return convert(e1, t2);
 
     /// Covers array operations for user-defined types
-    Type checkArrayOpType(Expression e1, Expression e2, EXP op, Scope *sc)
+    Type checkArrayOpType(Expression e1, Expression e2, EXP op, Scopesc)
     {
         // scalar op scalar - we shouldn't be here
         if (e1.type.ty != Tarray && e1.type.ty != Tsarray && e2.type.ty != Tarray && e2.type.ty != Tsarray)
@@ -4138,7 +4139,7 @@ Expression typeCombine(BinExp be, Scope* sc)
 {
     Expression errorReturn()
     {
-        Expression ex = be.incompatibleTypes();
+        Expression ex = be.incompatibleTypes(sc);
         if (ex.op == EXP.error)
             return ex;
         return ErrorExp.get();
@@ -4240,7 +4241,7 @@ extern (D) bool arrayTypeCompatibleWithoutCasting(Type t1, Type t2)
     t1 = t1.toBasetype();
     t2 = t2.toBasetype();
 
-    if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && t2.ty == t1.ty)
+    if ((t1.isStaticOrDynamicArray() || t1.ty == Tpointer) && t2.ty == t1.ty)
     {
         if (t1.nextOf().implicitConvTo(t2.nextOf()) >= MATCH.constant || t2.nextOf().implicitConvTo(t1.nextOf()) >= MATCH.constant)
             return true;
index e6fb1ed65cd9ef981e9c3579807ef267e1c60efd..c94443de396922053e48ca21601900596c373600 100644 (file)
@@ -1379,16 +1379,6 @@ extern (C++) class TypeInfoDeclaration : VarDeclaration
         assert(0); // should never be produced by syntax
     }
 
-    override final const(char)* toChars() const
-    {
-        //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
-        OutBuffer buf;
-        buf.writestring("typeid(");
-        buf.writestring(tinfo.toChars());
-        buf.writeByte(')');
-        return buf.extractChars();
-    }
-
     override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
     {
         return this;
index 7f37f89d22411d77578d4c1f43eb94cbad98439b..e2ac13ee04a14727d90e8cb94c01e507b76418cd 100644 (file)
@@ -342,7 +342,6 @@ public:
 
     static TypeInfoDeclaration *create(Type *tinfo);
     TypeInfoDeclaration *syntaxCopy(Dsymbol *) override final;
-    const char *toChars() const override final;
 
     TypeInfoDeclaration *isTypeInfoDeclaration() override final { return this; }
     void accept(Visitor *v) override { v->visit(this); }
@@ -787,7 +786,6 @@ public:
     d_bool isMoveCtor;
     CtorDeclaration *syntaxCopy(Dsymbol *) override;
     const char *kind() const override;
-    const char *toChars() const override;
     bool isVirtual() const override;
     bool addPreInvariant() override;
     bool addPostInvariant() override;
@@ -814,7 +812,6 @@ class DtorDeclaration final : public FuncDeclaration
 public:
     DtorDeclaration *syntaxCopy(Dsymbol *) override;
     const char *kind() const override;
-    const char *toChars() const override;
     bool isVirtual() const override;
     bool addPreInvariant() override;
     bool addPostInvariant() override;
index f219e3f20279d7d97dd892d0ad56223a24f0d5d6..648c5b4177b27e2f4e18dd859f4b0da5f7fa8293 100644 (file)
@@ -1885,7 +1885,7 @@ public:
         // Check for taking an address of a shared variable.
         // If the shared variable is an array, the offset might not be zero.
         Type fromType = null;
-        if (e.var.type.ty == Tarray || e.var.type.ty == Tsarray)
+        if (e.var.type.isStaticOrDynamicArray())
         {
             fromType = (cast(TypeArray)e.var.type).next;
         }
@@ -1900,7 +1900,7 @@ public:
         Expression val = getVarExp(e.loc, istate, e.var, goal);
         if (exceptionOrCant(val))
             return;
-        if (val.type.ty == Tarray || val.type.ty == Tsarray)
+        if (val.type.isStaticOrDynamicArray())
         {
             // Check for unsupported type painting operations
             Type elemtype = (cast(TypeArray)val.type).next;
@@ -3354,7 +3354,7 @@ public:
             // a[] = e can have const e. So we compare the naked types.
             Type tdst = e1.type.toBasetype();
             Type tsrc = e.e2.type.toBasetype();
-            while (tdst.ty == Tsarray || tdst.ty == Tarray)
+            while (tdst.isStaticOrDynamicArray())
             {
                 tdst = (cast(TypeArray)tdst).next.toBasetype();
                 if (tsrc.equivalent(tdst))
@@ -4302,7 +4302,7 @@ public:
                 Expression assignTo(ArrayLiteralExp ae, size_t lwr, size_t upr)
                 {
                     Expressions* w = ae.elements;
-                    assert(ae.type.ty == Tsarray || ae.type.ty == Tarray || ae.type.ty == Tpointer);
+                    assert(ae.type.isStaticOrDynamicArray() || ae.type.ty == Tpointer);
                     bool directblk = (cast(TypeNext)ae.type).next.equivalent(newval.type);
                     for (size_t k = lwr; k < upr; k++)
                     {
@@ -5804,8 +5804,7 @@ public:
             auto expTb = exp.type.toBasetype();
 
             if (exp.type.implicitConvTo(tbNext) >= MATCH.convert &&
-                (tb.ty == Tarray || tb.ty == Tsarray) &&
-                (expTb.ty == Tarray || expTb.ty == Tsarray))
+                tb.isStaticOrDynamicArray() && expTb.isStaticOrDynamicArray())
                 return new ArrayLiteralExp(exp.loc, e.type, exp);
             return exp;
         }
@@ -5921,7 +5920,7 @@ public:
 
             bool castToSarrayPointer = false;
             bool castBackFromVoid = false;
-            if (e1.type.ty == Tarray || e1.type.ty == Tsarray || e1.type.ty == Tpointer)
+            if (e1.type.isStaticOrDynamicArray() || e1.type.ty == Tpointer)
             {
                 // Check for unsupported type painting operations
                 // For slices, we need the type being sliced,
@@ -6101,7 +6100,7 @@ public:
 
         // Disallow array type painting, except for conversions between built-in
         // types of identical size.
-        if ((e.to.ty == Tsarray || e.to.ty == Tarray) && (e1.type.ty == Tsarray || e1.type.ty == Tarray) && !isSafePointerCast(e1.type.nextOf(), e.to.nextOf()))
+        if (e.to.isStaticOrDynamicArray() && e1.type.isStaticOrDynamicArray() && !isSafePointerCast(e1.type.nextOf(), e.to.nextOf()))
         {
             auto se = e1.isStringExp();
             // Allow casting a hex string literal to short[], int[] or long[]
index f26c5812ddf9477c269ee5fbbb72b87dcdd7c9e4..d599d9c5d147e4dc3a5f4431b8252d4baefb96c4 100644 (file)
@@ -430,11 +430,9 @@ extern (C++) final class Module : Package
 
     Modules aimports;           // all imported modules
 
-    uint debuglevel;            // debug level
     Identifiers* debugids;      // debug identifiers
     Identifiers* debugidsNot;   // forward referenced debug identifiers
 
-    uint versionlevel;          // version level
     Identifiers* versionids;    // version identifiers
     Identifiers* versionidsNot; // forward referenced version identifiers
 
index eba8dddaf9881d04ce9d92d9b6be05f6341c487e..0e77cdfc982a59100b487e50146432a00bb6ca02 100644 (file)
@@ -433,10 +433,7 @@ void gendocfile(Module m, const char[] ddoctext, const char* datetime, ErrorSink
     OutBuffer buf;
     if (m.filetype == FileType.ddoc)
     {
-        const ploc = m.md ? &m.md.loc : &m.loc;
-        Loc loc = *ploc;
-        if (!loc.filename)
-            loc.filename = srcfilename.ptr;
+        Loc loc = m.md ? m.md.loc : m.loc;
 
         size_t commentlen = m.comment ? strlen(cast(char*)m.comment) : 0;
         Dsymbols a;
@@ -694,9 +691,7 @@ bool emitAnchorName(ref OutBuffer buf, Dsymbol s, Scope* sc, bool includeParent)
     }
     else
     {
-        /* We just want the identifier, not overloads like TemplateDeclaration::toChars.
-         * We don't want the template parameter list and constraints. */
-        buf.writestring(s.Dsymbol.toChars());
+        buf.writestring(s.ident ? s.ident.toString : "__anonymous");
     }
     return true;
 }
@@ -799,7 +794,11 @@ void emitAnchor(ref OutBuffer buf, Dsymbol s, Scope* sc, bool forHeader = false)
     }
     else
     {
-        auto symbolName = ident.toString();
+        // buf.writestring("<<<");
+        // buf.writestring(typeof(ident).stringof);
+        // buf.writestring(">>>");
+        // auto symbolName = ident.toString();
+        auto symbolName = ident.toChars().toDString();
         buf.printf("$(%.*s %.*s", cast(int) macroName.length, macroName.ptr,
             cast(int) symbolName.length, symbolName.ptr);
 
@@ -2624,7 +2623,7 @@ Parameter isFunctionParameter(Dsymbols* a, const(char)[] p) @safe
 
 /****************************************************
  */
-Parameter isEponymousFunctionParameter(Dsymbols *a, const(char)[] p) @safe
+Parameter isEponymousFunctionParameter(Dsymbolsa, const(char)[] p) @safe
 {
     foreach (Dsymbol dsym; *a)
     {
@@ -3603,7 +3602,7 @@ struct MarkdownLinkReferences
         auto id = Identifier.lookup(ids[0].ptr, ids[0].length);
         if (id)
         {
-            auto loc = Loc();
+            auto loc = Loc.initial;
             Dsymbol pscopesym;
             auto symbol = _scope.search(loc, id, pscopesym, SearchOpt.ignoreErrors);
             for (size_t i = 1; symbol && i < ids.length; ++i)
@@ -4096,9 +4095,8 @@ size_t endRowAndTable(ref OutBuffer buf, size_t iStart, size_t iEnd, ref Markdow
  */
 void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, size_t offset)
 {
-    const incrementLoc = loc.linnum == 0 ? 1 : 0;
-    loc.linnum = loc.linnum + incrementLoc;
-    loc.charnum = 0;
+    loc.nextLine();
+
     //printf("highlightText()\n");
     bool leadingBlank = true;
     size_t iParagraphStart = offset;
@@ -4202,7 +4200,7 @@ void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, size_t of
             lineQuoted = false;
             tableRowDetected = false;
             iLineStart = i + 1;
-            loc.linnum = loc.linnum + incrementLoc;
+            loc.nextLine();
 
             // update the paragraph start if we just entered a macro
             if (previousMacroLevel < macroLevel && iParagraphStart < iLineStart)
index e3feefed76eec2c066dea13a0ed9dbedca003803..2f2c017ed81f566637bdec746501aaa04a8db9dd 100644 (file)
@@ -55,7 +55,7 @@ import dmd.visitor;
 import dmd.common.outbuffer;
 
 /***************************************
- * Calls dg(Dsymbol *sym) for each Dsymbol.
+ * Calls dg(Dsymbolsym) for each Dsymbol.
  * If dg returns !=0, stops and returns that value else returns 0.
  * Params:
  *    symbols = Dsymbols
@@ -84,7 +84,7 @@ int foreachDsymbol(Dsymbols* symbols, scope int delegate(Dsymbol) dg)
 }
 
 /***************************************
- * Calls dg(Dsymbol *sym) for each Dsymbol.
+ * Calls dg(Dsymbolsym) for each Dsymbol.
  * Params:
  *    symbols = Dsymbols
  *    dg = delegate to call for each Dsymbol
@@ -297,9 +297,10 @@ extern (C++) class Dsymbol : ASTNode
         return new Dsymbol(ident);
     }
 
-    override const(char)* toChars() const
+    final override const(char)* toChars() const
     {
-        return ident ? ident.toChars() : "__anonymous";
+        import dmd.hdrgen : toChars;
+        return toChars(this);
     }
 
     // Getters / setters for fields stored in `DsymbolAttributes`
index 3936c3e4cfbb0f1189429ba3546f79fd355434cc..c83b8d1b6af1ac755f9c36e4e88d2da9b2db2b91 100644 (file)
@@ -187,7 +187,7 @@ public:
     PASS semanticRun;
     unsigned short localNum;        // perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab
     static Dsymbol *create(Identifier *);
-    const char *toChars() const override;
+    const char *toChars() const final override;
     DeprecatedDeclaration* depdecl();
     CPPNamespaceDeclaration* cppnamespace();
     UserAttributeDeclaration* userAttribDecl();
index c7fb26a9da1aa4da8655a5d3b2adc72ed6e685f3..378ef9a3d3a3f45e977b4b825057380a5b43617b 100644 (file)
@@ -424,7 +424,7 @@ private bool checkDeprecatedAliasThis(AliasThis at, const ref Loc loc, Scope* sc
 }
 
 // Save the scope and defer semantic analysis on the Dsymbol.
-void deferDsymbolSemantic(Scope* sc, Dsymbol s, Scope *scx)
+void deferDsymbolSemantic(Scope* sc, Dsymbol s, Scopescx)
 {
     s._scope = scx ? scx : sc.copy();
     s._scope.setNoFree();
@@ -4352,34 +4352,21 @@ private extern(C++) class AddMemberVisitor : Visitor
         Module m = sds.isModule();
         // Do not add the member to the symbol table,
         // just make sure subsequent debug declarations work.
-        if (ds.ident)
+        if (!m)
         {
-            if (!m)
-            {
-                .error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars);
-                ds.errors = true;
-            }
-            else
-            {
-                if (m.debugidsNot && findCondition(*m.debugidsNot, ds.ident))
-                {
-                    .error(ds.loc, "%s `%s` defined after use", ds.kind, ds.toPrettyChars);
-                    ds.errors = true;
-                }
-                if (!m.debugids)
-                    m.debugids = new Identifiers();
-                m.debugids.push(ds.ident);
-            }
+            .error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars);
+            ds.errors = true;
         }
         else
         {
-            if (!m)
+            if (m.debugidsNot && findCondition(*m.debugidsNot, ds.ident))
             {
-                .error(ds.loc, "%s `%s` level declaration must be at module level", ds.kind, ds.toPrettyChars);
+                .error(ds.loc, "%s `%s` defined after use", ds.kind, ds.toPrettyChars);
                 ds.errors = true;
             }
-            else
-                m.debuglevel = ds.level;
+            if (!m.debugids)
+                m.debugids = new Identifiers();
+            m.debugids.push(ds.ident);
         }
     }
 
@@ -4389,36 +4376,24 @@ private extern(C++) class AddMemberVisitor : Visitor
         Module m = sds.isModule();
         // Do not add the member to the symbol table,
         // just make sure subsequent debug declarations work.
-        if (vs.ident)
+        VersionCondition.checkReserved(vs.loc, vs.ident.toString());
+        if (!m)
         {
-            VersionCondition.checkReserved(vs.loc, vs.ident.toString());
-            if (!m)
-            {
-                .error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars);
-                vs.errors = true;
-            }
-            else
-            {
-                if (m.versionidsNot && findCondition(*m.versionidsNot, vs.ident))
-                {
-                    .error(vs.loc, "%s `%s` defined after use", vs.kind, vs.toPrettyChars);
-                    vs.errors = true;
-                }
-                if (!m.versionids)
-                    m.versionids = new Identifiers();
-                m.versionids.push(vs.ident);
-            }
+            .error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars);
+            vs.errors = true;
         }
         else
         {
-            if (!m)
+            if (m.versionidsNot && findCondition(*m.versionidsNot, vs.ident))
             {
-                .error(vs.loc, "%s `%s` level declaration must be at module level", vs.kind, vs.toPrettyChars);
+                .error(vs.loc, "%s `%s` defined after use", vs.kind, vs.toPrettyChars);
                 vs.errors = true;
             }
-            else
-                m.versionlevel = vs.level;
+            if (!m.versionids)
+                m.versionids = new Identifiers();
+            m.versionids.push(vs.ident);
         }
+
     }
 
     override void visit(Nspace ns)
index dd9f3dac6b04a41a7bd8becaff0875c095a9e600..296c10c7593b8125bd9040a8699143ee9661b13e 100644 (file)
@@ -57,7 +57,7 @@ import dmd.dsymbolsem : dsymbolSemantic, checkDeprecated, aliasSemantic, search,
 import dmd.errors;
 import dmd.errorsink;
 import dmd.expression;
-import dmd.expressionsem : resolveLoc, expressionSemantic, resolveProperties;
+import dmd.expressionsem : resolveLoc, expressionSemantic, resolveProperties, checkValue;
 import dmd.func;
 import dmd.funcsem : functionSemantic, leastAsSpecialized, overloadApply;
 import dmd.globals;
@@ -746,14 +746,6 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
         return (onemember && onemember.isAggregateDeclaration()) ? onemember.kind() : "template";
     }
 
-    override const(char)* toChars() const
-    {
-        HdrGenState hgs;
-        OutBuffer buf;
-        toCharsMaybeConstraints(this, buf, hgs);
-        return buf.extractChars();
-    }
-
     /****************************
      * Similar to `toChars`, but does not print the template constraints
      */
@@ -3830,13 +3822,6 @@ extern (C++) class TemplateInstance : ScopeDsymbol
         return true;
     }
 
-    override const(char)* toChars() const
-    {
-        OutBuffer buf;
-        toCBufferInstance(this, buf);
-        return buf.extractChars();
-    }
-
     override final const(char)* toPrettyCharsHelper()
     {
         OutBuffer buf;
@@ -5524,13 +5509,6 @@ extern (C++) final class TemplateMixin : TemplateInstance
         return members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
     }
 
-    override const(char)* toChars() const
-    {
-        OutBuffer buf;
-        toCBufferInstance(this, buf);
-        return buf.extractChars();
-    }
-
     extern (D) bool findTempDecl(Scope* sc)
     {
         // Follow qualifications to find the TemplateDeclaration
index 42d7d8f451888f4356173bb202134ce621f23cec..d8c8b24b3c65ca75d626cb59aa3c6e80e582578d 100644 (file)
@@ -29,21 +29,17 @@ import dmd.visitor;
 /***********************************************************
  * DebugSymbol's happen for statements like:
  *      debug = identifier;
- *      debug = integer;
  */
 extern (C++) final class DebugSymbol : Dsymbol
 {
-    uint level;
-
     extern (D) this(const ref Loc loc, Identifier ident) @safe
     {
         super(loc, ident);
     }
 
-    extern (D) this(const ref Loc loc, uint level) @safe
+    extern (D) this(const ref Loc loc) @safe
     {
         super(loc, null);
-        this.level = level;
     }
 
     override DebugSymbol syntaxCopy(Dsymbol s)
@@ -51,19 +47,9 @@ extern (C++) final class DebugSymbol : Dsymbol
         assert(!s);
         auto ds = new DebugSymbol(loc, ident);
         ds.comment = comment;
-        ds.level = level;
         return ds;
     }
 
-    override const(char)* toChars() const nothrow
-    {
-        if (ident)
-            return ident.toChars();
-        OutBuffer buf;
-        buf.print(level);
-        return buf.extractChars();
-    }
-
     override const(char)* kind() const nothrow
     {
         return "debug";
@@ -83,41 +69,28 @@ extern (C++) final class DebugSymbol : Dsymbol
 /***********************************************************
  * VersionSymbol's happen for statements like:
  *      version = identifier;
- *      version = integer;
  */
 extern (C++) final class VersionSymbol : Dsymbol
 {
-    uint level;
 
     extern (D) this(const ref Loc loc, Identifier ident) @safe
     {
         super(loc, ident);
     }
 
-    extern (D) this(const ref Loc loc, uint level) @safe
+    extern (D) this(const ref Loc loc) @safe
     {
         super(loc, null);
-        this.level = level;
     }
 
     override VersionSymbol syntaxCopy(Dsymbol s)
     {
         assert(!s);
-        auto ds = ident ? new VersionSymbol(loc, ident)
-                        : new VersionSymbol(loc, level);
+        auto ds = new VersionSymbol(loc, ident);
         ds.comment = comment;
         return ds;
     }
 
-    override const(char)* toChars() const nothrow
-    {
-        if (ident)
-            return ident.toChars();
-        OutBuffer buf;
-        buf.print(level);
-        return buf.extractChars();
-    }
-
     override const(char)* kind() const nothrow
     {
         return "version";
index 7faa536dea6f025766ed95f660f2995306ca0e7f..ddab8a8f7510cca58de14f4a531bc35e98650b33 100644 (file)
@@ -11,7 +11,8 @@
 
 module dmd.errors;
 
-import core.stdc.stdarg;
+public import core.stdc.stdarg;
+public import dmd.root.string: fTuple;
 import dmd.errorsink;
 import dmd.globals;
 import dmd.location;
@@ -384,7 +385,7 @@ else
  * see verrorReport for arguments
  * Returns: true if error handling is done, false to continue printing to stderr
  */
-alias DiagnosticHandler = bool delegate(const ref Loc location, Color headerColor, const(char)* header, const(char)* messageFormat, va_list args, const(char)* prefix1, const(char)* prefix2);
+alias DiagnosticHandler = bool delegate(const ref SourceLoc location, Color headerColor, const(char)* header, const(char)* messageFormat, va_list args, const(char)* prefix1, const(char)* prefix2);
 
 /**
  * The diagnostic handler.
index ecf4f919f28f9ef22ade098d62194e1fc97b3195..b9e89e8fcc7b8fcf5e7843b042c447233a8c8305 100644 (file)
@@ -1607,7 +1607,7 @@ void escapeExp(Expression e, ref scope EscapeByResults er, int deref)
     void visitArrayLiteral(ArrayLiteralExp e)
     {
         Type tb = e.type.toBasetype();
-        if (tb.isTypeSArray() || tb.isTypeDArray())
+        if (tb.isStaticOrDynamicArray())
         {
             if (e.basis)
                 escapeExp(e.basis, er, deref);
@@ -2245,7 +2245,7 @@ private bool isTypesafeVariadicArray(VarDeclaration v)
     if (v.storage_class & STC.variadic)
     {
         Type tb = v.type.toBasetype();
-        if (tb.ty == Tarray || tb.ty == Tsarray)
+        if (tb.isStaticOrDynamicArray())
             return true;
     }
     return false;
index 5b8e0107db9fc157bad8a56e30ef2e36113a3b96..c8e7309e6f3eedf7b36d11c2a85f5f3e4d493217 100644 (file)
@@ -301,8 +301,14 @@ extern (C++) abstract class Expression : ASTNode
 
     Loc loc;        // file location
     const EXP op;   // to minimize use of dynamic_cast
-    bool parens;    // if this is a parenthesized expression
-    bool rvalue;    // true if this is considered to be an rvalue, even if it is an lvalue
+
+    static struct BitFields
+    {
+        bool parens;    // if this is a parenthesized expression
+        bool rvalue;    // true if this is considered to be an rvalue, even if it is an lvalue
+    }
+    import dmd.common.bitfields;
+    mixin(generateBitFields!(BitFields, ubyte));
 
     extern (D) this(const ref Loc loc, EXP op) scope @safe
     {
@@ -375,8 +381,13 @@ extern (C++) abstract class Expression : ASTNode
         return DYNCAST.expression;
     }
 
-    override const(char)* toChars() const
+    final override const(char)* toChars() const
     {
+        // FIXME: Test suite relies on lambda's being printed as __lambdaXXX in errors and .stringof
+        // Printing a (truncated) lambda body is more user friendly
+        if (auto fe = isFuncExp())
+            return fe.fd.toChars();
+
         return .toChars(this);
     }
 
@@ -516,25 +527,6 @@ extern (C++) abstract class Expression : ASTNode
         return false;
     }
 
-    /****************************************
-     * Check that the expression has a valid value.
-     * If not, generates an error "... has no value".
-     * Returns:
-     *      true if the expression is not valid or has void type.
-     */
-    bool checkValue()
-    {
-        if (type && type.toBasetype().ty == Tvoid)
-        {
-            error(loc, "expression `%s` is `void` and has no value", toChars());
-            //print(); assert(0);
-            if (!global.gag)
-                type = Type.terror;
-            return true;
-        }
-        return false;
-    }
-
     /******************************
      * Take address of expression.
      */
@@ -2126,6 +2118,16 @@ extern (C++) final class AssocArrayLiteralExp : Expression
  */
 extern (C++) final class StructLiteralExp : Expression
 {
+    struct BitFields
+    {
+        bool useStaticInit;     /// if this is true, use the StructDeclaration's init symbol
+        bool isOriginal = false; /// used when moving instances to indicate `this is this.origin`
+        OwnedBy ownedByCtfe = OwnedBy.code;
+    }
+    import dmd.common.bitfields;
+    mixin(generateBitFields!(BitFields, ubyte));
+    StageFlags stageflags;
+
     StructDeclaration sd;   /// which aggregate this is for
     Expressions* elements;  /// parallels sd.fields[] with null entries for fields to skip
     Type stype;             /// final type of result (can be different from sd's type)
@@ -2163,11 +2165,6 @@ extern (C++) final class StructLiteralExp : Expression
         inlineScan        = 0x10, /// inlineScan is running
         toCBuffer         = 0x20 /// toCBuffer is running
     }
-    StageFlags stageflags;
-
-    bool useStaticInit;     /// if this is true, use the StructDeclaration's init symbol
-    bool isOriginal = false; /// used when moving instances to indicate `this is this.origin`
-    OwnedBy ownedByCtfe = OwnedBy.code;
 
     extern (D) this(const ref Loc loc, StructDeclaration sd, Expressions* elements, Type stype = null) @safe
     {
@@ -2349,12 +2346,6 @@ extern (C++) final class TypeExp : Expression
         return true;
     }
 
-    override bool checkValue()
-    {
-        error(loc, "type `%s` has no value", toChars());
-        return true;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -2408,12 +2399,6 @@ extern (C++) final class ScopeExp : Expression
         return false;
     }
 
-    override bool checkValue()
-    {
-        error(loc, "%s `%s` has no value", sds.kind(), sds.toChars());
-        return true;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -2447,12 +2432,6 @@ extern (C++) final class TemplateExp : Expression
         return true;
     }
 
-    override bool checkValue()
-    {
-        error(loc, "%s `%s` has no value", td.kind(), toChars());
-        return true;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -2720,11 +2699,6 @@ extern (C++) final class FuncExp : Expression
         return new FuncExp(loc, fd);
     }
 
-    override const(char)* toChars() const
-    {
-        return fd.toChars();
-    }
-
     override bool checkType()
     {
         if (td)
@@ -2735,16 +2709,6 @@ extern (C++) final class FuncExp : Expression
         return false;
     }
 
-    override bool checkValue()
-    {
-        if (td)
-        {
-            error(loc, "template lambda has no value");
-            return true;
-        }
-        return false;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -3168,12 +3132,6 @@ extern (C++) final class DotTemplateExp : UnaExp
         return true;
     }
 
-    override bool checkValue()
-    {
-        error(loc, "%s `%s` has no value", td.kind(), toChars());
-        return true;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -3252,18 +3210,6 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
         return false;
     }
 
-    override bool checkValue()
-    {
-        if (ti.tempdecl &&
-            ti.semantictiargsdone &&
-            ti.semanticRun == PASS.initial)
-
-            error(loc, "partial %s `%s` has no value", ti.kind(), toChars());
-        else
-            error(loc, "%s `%s` has no value", ti.kind(), ti.toChars());
-        return true;
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -4180,10 +4126,6 @@ extern (C++) final class LoweredAssignExp : AssignExp
         this.lowering = lowering;
     }
 
-    override const(char)* toChars() const
-    {
-        return lowering.toChars();
-    }
     override void accept(Visitor v)
     {
         v.visit(this);
@@ -5089,27 +5031,6 @@ extern (C++) final class CTFEExp : Expression
         type = Type.tvoid;
     }
 
-    override const(char)* toChars() const
-    {
-        switch (op)
-        {
-        case EXP.cantExpression:
-            return "<cant>";
-        case EXP.voidExpression:
-            return "cast(void)0";
-        case EXP.showCtfeContext:
-            return "<error>";
-        case EXP.break_:
-            return "<break>";
-        case EXP.continue_:
-            return "<continue>";
-        case EXP.goto_:
-            return "<goto>";
-        default:
-            assert(0);
-        }
-    }
-
     extern (D) __gshared CTFEExp cantexp;
     extern (D) __gshared CTFEExp voidexp;
     extern (D) __gshared CTFEExp breakexp;
@@ -5146,11 +5067,6 @@ extern (C++) final class ThrownExceptionExp : Expression
         this.type = victim.type;
     }
 
-    override const(char)* toChars() const
-    {
-        return "CTFE ThrownException";
-    }
-
     override void accept(Visitor v)
     {
         v.visit(this);
index 07b163f1d48178f43128dc5c6b88136b4a11bbaf..09ed60fad913c91bba29f0519d83800635d72b6b 100644 (file)
@@ -77,8 +77,12 @@ public:
     Type *type;                 // !=NULL means that semantic() has been run
     Loc loc;                    // file location
     EXP op;                     // to minimize use of dynamic_cast
-    d_bool parens;              // if this is a parenthesized expression
-    d_bool rvalue;              // consider this an rvalue, even if it is an lvalue
+    uint8_t bitFields;
+
+    bool parens() const;
+    bool parens(bool v);
+    bool rvalue() const;
+    bool rvalue(bool v);
 
     size_t size() const;
     static void _init();
@@ -87,7 +91,7 @@ public:
     // kludge for template.isExpression()
     DYNCAST dyncast() const override final { return DYNCAST_EXPRESSION; }
 
-    const char *toChars() const override;
+    const char* toChars() const final override;
 
     virtual dinteger_t toInteger();
     virtual uinteger_t toUInteger();
@@ -97,7 +101,6 @@ public:
     virtual StringExp *toStringExp();
     virtual bool isLvalue();
     virtual bool checkType();
-    virtual bool checkValue();
     Expression *addressOf();
     Expression *deref();
 
@@ -431,6 +434,24 @@ public:
 class StructLiteralExp final : public Expression
 {
 public:
+    uint8_t bitFields;
+
+    // if this is true, use the StructDeclaration's init symbol
+    bool useStaticInit() const;
+    bool useStaticInit(bool v);
+    // used when moving instances to indicate `this is this.origin`
+    bool isOriginal() const;
+    bool isOriginal(bool v);
+    OwnedBy ownedByCtfe() const;
+    OwnedBy ownedByCtfe(OwnedBy v);
+
+    /** anytime when recursive function is calling, 'stageflags' marks with bit flag of
+     * current stage and unmarks before return from this function.
+     * 'inlinecopy' uses similar 'stageflags' and from multiple evaluation 'doInline'
+     * (with infinite recursion) of this expression.
+     */
+    uint8_t stageflags;
+
     StructDeclaration *sd;      // which aggregate this is for
     Expressions *elements;      // parallels sd->fields[] with NULL entries for fields to skip
     Type *stype;                // final type of result (can be different from sd's type)
@@ -451,17 +472,6 @@ public:
     StructLiteralExp *origin;
 
 
-    /** anytime when recursive function is calling, 'stageflags' marks with bit flag of
-     * current stage and unmarks before return from this function.
-     * 'inlinecopy' uses similar 'stageflags' and from multiple evaluation 'doInline'
-     * (with infinite recursion) of this expression.
-     */
-    uint8_t stageflags;
-
-    d_bool useStaticInit;         // if this is true, use the StructDeclaration's init symbol
-    d_bool isOriginal;            // used when moving instances to indicate `this is this.origin`
-    OwnedBy ownedByCtfe;
-
     static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = nullptr);
     bool equals(const RootObject * const o) const override;
     StructLiteralExp *syntaxCopy() override;
@@ -474,7 +484,6 @@ class TypeExp final : public Expression
 public:
     TypeExp *syntaxCopy() override;
     bool checkType() override;
-    bool checkValue() override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -485,7 +494,6 @@ public:
 
     ScopeExp *syntaxCopy() override;
     bool checkType() override;
-    bool checkValue() override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -497,7 +505,6 @@ public:
 
     bool isLvalue() override;
     bool checkType() override;
-    bool checkValue() override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -595,9 +602,7 @@ public:
 
     bool equals(const RootObject * const o) const override;
     FuncExp *syntaxCopy() override;
-    const char *toChars() const override;
     bool checkType() override;
-    bool checkValue() override;
 
     void accept(Visitor *v) override { v->visit(this); }
 };
@@ -741,7 +746,6 @@ public:
     TemplateDeclaration *td;
 
     bool checkType() override;
-    bool checkValue() override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -762,7 +766,6 @@ public:
 
     DotTemplateInstanceExp *syntaxCopy() override;
     bool checkType() override;
-    bool checkValue() override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
@@ -1045,7 +1048,6 @@ class LoweredAssignExp final : public AssignExp
 public:
     Expression *lowering;
 
-    const char *toChars() const override;
     void accept(Visitor *v) override { v->visit(this); }
 };
 
index fcb47a5398447597edb4d080f6ed54e5d8cabce3..b498998cd67306d6620ab34e5c487561340bebe0 100644 (file)
@@ -308,7 +308,7 @@ extern (D) bool findTempDecl(DotTemplateInstanceExp exp, Scope* sc)
  * Returns:
  *  String literal, or `null` if error happens.
  */
-StringExp semanticString(Scope *sc, Expression exp, const char* s)
+StringExp semanticString(Scopesc, Expression exp, const char* s)
 {
     sc = sc.startCTFE();
     exp = exp.expressionSemantic(sc);
@@ -377,7 +377,7 @@ private Expression incompatibleTypes(UnaExp e)
  * Returns:
  *  ErrorExp
  */
-extern (D) Expression incompatibleTypes(BinExp e)
+extern (D) Expression incompatibleTypes(BinExp e, Scope* sc = null)
 {
     if (e.e1.type.toBasetype() == Type.terror)
         return e.e1;
@@ -386,6 +386,10 @@ extern (D) Expression incompatibleTypes(BinExp e)
 
     // CondExp uses 'a ? b : c' but we're comparing 'b : c'
     const(char)* thisOp = (e.op == EXP.question) ? ":" : EXPtoString(e.op).ptr;
+
+    if (sc && suggestBinaryOverloads(e, sc))
+        return ErrorExp.get();
+
     if (e.e1.op == EXP.type || e.e2.op == EXP.type)
     {
         error(e.loc, "incompatible types for `(%s) %s (%s)`: cannot use `%s` with types",
@@ -658,10 +662,9 @@ TupleDeclaration isAliasThisTuple(Expression e)
  * Runs semantic on ae.arguments. Declares temporary variables
  * if '$' was used.
  */
-Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
+Expression resolveOpDollar(Scope* sc, ArrayExp ae, out Expression pe0)
 {
     assert(!ae.lengthVar);
-    *pe0 = null;
     AggregateDeclaration ad = isAggregate(ae.e1.type);
     Dsymbol slice = search_function(ad, Id.opSlice);
     //printf("slice = %s %s\n", slice.kind(), slice.toChars());
@@ -675,7 +678,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
     foreach (i, e; *ae.arguments)
     {
         if (i == 0)
-            *pe0 = extractOpDollarSideEffect(sc, ae);
+            pe0 = extractOpDollarSideEffect(sc, ae);
 
         if (e.op == EXP.interval && !(slice && slice.isTemplateDeclaration()))
         {
@@ -698,7 +701,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
             // If $ was used, declare it now
             Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
             de = de.expressionSemantic(sc);
-            *pe0 = Expression.combine(*pe0, de);
+            pe0 = Expression.combine(pe0, de);
         }
         sc = sc.pop();
 
@@ -721,7 +724,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
             if (!fslice)
                 return fallback();
 
-            e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs);
+            e = new DotTemplateInstanceExp(ae.loc, ae.e1, Id.opSlice, tiargs);
             e = new CallExp(ae.loc, e, fargs);
             e = e.expressionSemantic(sc);
         }
@@ -745,7 +748,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
  * Returns:
  *      ae, or ErrorExp if errors occurred
  */
-Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0)
+Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, ref Expression pe0)
 {
     //assert(!ae.lengthVar);
     if (!ie)
@@ -782,7 +785,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* p
         // If $ was used, declare it now
         Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
         de = de.expressionSemantic(sc);
-        *pe0 = Expression.combine(*pe0, de);
+        pe0 = Expression.combine(pe0, de);
     }
 
     sc = sc.pop();
@@ -821,7 +824,7 @@ extern(D) bool arrayExpressionSemantic(
  * Returns:
  *  The expression that copy constructs or moves the value.
  */
-extern (D) Expression doCopyOrMove(Scope *sc, Expression e, Type t, bool nrvo, bool move = false)
+extern (D) Expression doCopyOrMove(Scopesc, Expression e, Type t, bool nrvo, bool move = false)
 {
     //printf("doCopyOrMove() %s\n", toChars(e));
     StructDeclaration sd;
@@ -1203,7 +1206,7 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
         eleft = die.e1;
 
         Type t = eleft.type.toBasetype();
-        if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
+        if (t.isStaticOrDynamicArray() || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
         {
             /* Built-in types and arrays have no callable properties, so do shortcut.
              * It is necessary in: e.init()
@@ -1561,7 +1564,7 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
  * Returns:
  *      `s` turned into an expression, `ErrorExp` if an error occurred
  */
-Expression symbolToExp(Dsymbol s, const ref Loc loc, Scope *sc, bool hasOverloads)
+Expression symbolToExp(Dsymbol s, const ref Loc loc, Scopesc, bool hasOverloads)
 {
     static if (LOGSEMANTIC)
     {
@@ -2346,7 +2349,7 @@ private bool checkNogc(FuncDeclaration f, ref Loc loc, Scope* sc)
     if (isRootTraitsCompilesScope(sc) ? !sc.func.isNogcBypassingInference() : !sc.func.setGCCall(f))
         return false;
 
-    if (loc.linnum == 0) // e.g. implicitly generated dtor
+    if (loc == Loc.initial) // e.g. implicitly generated dtor
         loc = sc.func.loc;
 
     // Lowered non-@nogc'd hooks will print their own error message inside of nogc.d (NOGCVisitor.visit(CallExp e)),
@@ -2368,8 +2371,14 @@ private bool checkNogc(FuncDeclaration f, ref Loc loc, Scope* sc)
 }
 
 /********************************************
- * Check that the postblit is callable if t is an array of structs.
- * Returns true if error happens.
+ * Check that the postblit of `t` isn't @disabled and has the right
+ * function attributes for this scope.
+ *
+ * Params:
+ *   t = struct type, or static array of struct type to check
+ *   loc = error message location
+ *   sc = scope in which attributes are checked
+ * Returns: true if there's an error
  */
 private bool checkPostblit(Type t, ref Loc loc, Scope* sc)
 {
@@ -2392,12 +2401,12 @@ private bool checkPostblit(Type t, ref Loc loc, Scope* sc)
         return true;
 
     //checkDeprecated(sc, sd.postblit);        // necessary?
-    sd.postblit.checkPurity(loc, sc);
-    sd.postblit.checkSafety(loc, sc);
-    sd.postblit.checkNogc(loc, sc);
     //checkAccess(sd, loc, sc, sd.postblit);   // necessary?
-    return false;
-
+    bool result = false;
+    result |= sd.postblit.checkPurity(loc, sc);
+    result |= sd.postblit.checkSafety(loc, sc);
+    result |= sd.postblit.checkNogc(loc, sc);
+    return result;
 }
 
 /***************************************
@@ -3815,6 +3824,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
     // See tryAliasThisSemantic
     Type[2] aliasThisStop;
 
+    // (Optional) the expression this was lowered from, for better error messages
+    Expression parent;
+
     this(Scope* sc) scope @safe
     {
         this.sc = sc;
@@ -7550,7 +7562,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             result = e;
             return;
         }
-        if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
+        if (exp.e1.op == EXP.slice || exp.e1.type.isStaticOrDynamicArray())
         {
             if (checkNonAssignmentArrayOp(exp.e1))
                 return setError();
@@ -7579,15 +7591,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
         exp.type = exp.e1.type;
 
-        if (auto ad = isAggregate(exp.e1.type))
-        {
-            if (const s = search_function(ad, Id.opOpAssign))
-            {
-                error(exp.loc, "none of the `opOpAssign` overloads of `%s` are callable for `%s` of type `%s`", ad.toChars(), exp.e1.toChars(), exp.e1.type.toChars());
-                return setError();
-            }
-        }
-        if (exp.e1.checkScalar() ||
+        if (exp.suggestOpOpAssign(sc, parent) ||
+            exp.e1.checkScalar() ||
             exp.e1.checkReadModifyWrite(exp.op, exp.e2) ||
             exp.e1.checkSharedAccess(sc))
             return setError();
@@ -7644,7 +7649,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         result = (cast(BinExp)e).reorderSettingAAElem(sc);
     }
 
-    private Expression compileIt(MixinExp exp, Scope *sc)
+    private Expression compileIt(MixinExp exp, Scopesc)
     {
         OutBuffer buf;
         if (expressionsToString(buf, sc, exp.exps, exp.loc, null, true))
@@ -8842,7 +8847,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         fix16997(sc, exp);
         exp.type = exp.e1.type;
         Type tb = exp.type.toBasetype();
-        if (tb.ty == Tarray || tb.ty == Tsarray)
+        if (tb.isStaticOrDynamicArray())
         {
             if (!isArrayOpValid(exp.e1))
             {
@@ -8857,9 +8862,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             result = exp.incompatibleTypes();
             return;
         }
-        if (exp.e1.checkNoBool())
-            return setError();
-        if (exp.e1.checkArithmetic(exp.op) ||
+        if (exp.e1.checkNoBool() ||
+            exp.e1.checkArithmetic(exp.op) ||
             exp.e1.checkSharedAccess(sc))
             return setError();
 
@@ -8885,11 +8889,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             result = exp.incompatibleTypes();
             return;
         }
-        if (exp.e1.checkNoBool())
-            return setError();
-        if (exp.e1.checkArithmetic(exp.op))
-            return setError();
-        if (exp.e1.checkSharedAccess(sc))
+
+        if (exp.e1.checkNoBool() ||
+            exp.e1.checkArithmetic(exp.op) ||
+            exp.e1.checkSharedAccess(sc))
             return setError();
 
         result = exp.e1;
@@ -8907,7 +8910,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         fix16997(sc, exp);
         exp.type = exp.e1.type;
         Type tb = exp.type.toBasetype();
-        if (tb.ty == Tarray || tb.ty == Tsarray)
+        if (tb.isStaticOrDynamicArray())
         {
             if (!isArrayOpValid(exp.e1))
             {
@@ -8922,9 +8925,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             result = exp.incompatibleTypes();
             return;
         }
-        if (exp.e1.checkNoBool())
-            return setError();
-        if (exp.e1.checkIntegral() ||
+        if (exp.e1.checkNoBool() ||
+            exp.e1.checkIntegral() ||
             exp.e1.checkSharedAccess(sc))
             return setError();
 
@@ -9189,7 +9191,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
         }
 
-        if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray))
+        if (!t1b.equals(tob) && t1b.isStaticOrDynamicArray())
         {
             if (checkNonAssignmentArrayOp(exp.e1))
                 return setError();
@@ -9509,7 +9511,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         /* Run semantic on lwr and upr.
          */
         Scope* scx = sc;
-        if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
+        if (t1b.isStaticOrDynamicArray() || t1b.ty == Ttuple)
         {
             // Create scope for 'length' variable
             ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
@@ -9616,7 +9618,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             IntRange lwrRange = getIntRange(exp.lwr);
             IntRange uprRange = getIntRange(exp.upr);
 
-            if (t1b.ty == Tsarray || t1b.ty == Tarray)
+            if (t1b.isStaticOrDynamicArray())
             {
                 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
                 el = el.expressionSemantic(sc);
@@ -9702,8 +9704,39 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         if (auto ad = isAggregate(exp.e1.type))
         {
-            error(exp.loc, "no `[]` operator overload for type `%s`", exp.e1.type.toChars());
-            errorSupplemental(ad.loc, "`%s` declared here", ad.toPrettyChars());
+            if (exp.arguments.length == 0)
+            {
+                error(exp.loc, "no `[]` operator overload for type `%s`", exp.e1.type.toChars());
+                errorSupplemental(ad.loc, "perhaps define `auto opIndex() {}` for `%s`", ad.toPrettyChars());
+            }
+            else
+            {
+                const(char)* typeString(Expression exp)
+                {
+                    if (auto e = exp.trySemantic(sc))
+                        return e.type.toChars();
+                    else
+                        return "__error__";
+                }
+
+                if (auto ie = (*exp.arguments)[0].isIntervalExp())
+                {
+                    error(exp.loc, "no `[%s]` operator overload for type `%s`", ie.toChars(), exp.e1.type.toChars());
+                    errorSupplemental(ad.loc, "perhaps define `auto opSlice(%s lower, %s upper) {}` for `%s`",
+                        typeString(ie.lwr), typeString(ie.upr), ad.toPrettyChars());
+                }
+                else
+                {
+                    OutBuffer buf;
+                    buf.printf("%s", typeString((*exp.arguments)[0]));
+                    foreach (e; (*exp.arguments)[1 .. $])
+                        buf.printf(", %s", typeString(e));
+
+                    error(exp.loc, "no `[]` operator overload for type `%s`", exp.e1.type.toChars());
+                    errorSupplemental(ad.loc, "perhaps define `auto opIndex(%s) {}` for `%s`",
+                        buf.extractChars, ad.toPrettyChars());
+                }
+            }
         }
         else if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
             error(exp.loc, "static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
@@ -9906,7 +9939,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             t1b = t1b.castMod(tv1.mod);
             exp.e1 = exp.e1.castTo(sc, t1b);
         }
-        if (t1b.ty == Tsarray || t1b.ty == Tarray)
+        if (t1b.isStaticOrDynamicArray())
         {
             if (!checkAddressable(exp, sc))
                 return setError();
@@ -9915,7 +9948,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         /* Run semantic on e2
          */
         Scope* scx = sc;
-        if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
+        if (t1b.isStaticOrDynamicArray() || t1b.ty == Ttuple)
         {
             // Create scope for 'length' variable
             ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
@@ -10051,7 +10084,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         // We might know $ now
         setLengthVarIfKnown(exp.lengthVar, t1b);
 
-        if (t1b.ty == Tsarray || t1b.ty == Tarray)
+        if (t1b.isStaticOrDynamicArray())
         {
             Expression el = new ArrayLengthExp(exp.loc, exp.e1);
             el = el.expressionSemantic(sc);
@@ -10198,7 +10231,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             e = new AddAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
         else
             e = new MinAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
-        result = e.expressionSemantic(sc);
+        result = e.expressionSemanticWithParent(sc, exp);
     }
 
     /*
@@ -10307,7 +10340,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 if (search_function(ad, Id.opIndexAssign))
                 {
                     // Deal with $
-                    res = resolveOpDollar(sc, ae, &e0);
+                    res = resolveOpDollar(sc, ae, e0);
                     if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j)
                         goto Lfallback;
                     if (res.op == EXP.error)
@@ -10337,7 +10370,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 if (maybeSlice && search_function(ad, Id.opSliceAssign))
                 {
                     // Deal with $
-                    res = resolveOpDollar(sc, ae, ie, &e0);
+                    res = resolveOpDollar(sc, ae, ie, e0);
                     if (res.op == EXP.error)
                         return setResult(res);
 
@@ -11317,7 +11350,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 return setError();
         }
         else if (exp.e1.op == EXP.slice &&
-                 (t2.ty == Tarray || t2.ty == Tsarray) &&
+                 t2.isStaticOrDynamicArray() &&
                  t2.nextOf().implicitConvTo(t1.nextOf()))
         {
             // Check element-wise assignment.
@@ -11426,7 +11459,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
 
         if (exp.e1.op == EXP.slice &&
-            (t1.ty == Tarray || t1.ty == Tsarray) &&
+            t1.isStaticOrDynamicArray() &&
             t1.nextOf().toBasetype().ty == Tvoid)
         {
             if (t2.nextOf().implicitConvTo(t1.nextOf()))
@@ -11461,7 +11494,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         /* Look for array operations
          */
-        if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2))
+        if (t2.isStaticOrDynamicArray() && isArrayOpValid(exp.e2))
         {
             // Look for valid array operations
             if (exp.memset != MemorySet.blockAssign &&
@@ -11638,7 +11671,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return ae;
 
         const isArrayAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
-            (ae.e2.type.ty == Tsarray || ae.e2.type.ty == Tarray) &&
+            (ae.e2.type.isStaticOrDynamicArray()) &&
             (ae.e1.type.nextOf() && ae.e2.type.nextOf() && ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf()));
 
         const isArraySetAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
@@ -11710,11 +11743,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
-        if (exp.e1.checkReadModifyWrite(exp.op, exp.e2))
+        if (exp.suggestOpOpAssign(sc, parent) ||
+            exp.e1.checkReadModifyWrite(exp.op, exp.e2))
             return setError();
 
         assert(exp.e1.type && exp.e2.type);
-        if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
+        if (exp.e1.op == EXP.slice || exp.e1.type.isStaticOrDynamicArray())
         {
             if (checkNonAssignmentArrayOp(exp.e1))
                 return setError();
@@ -11734,7 +11768,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             // Check element types are arithmetic
             Type tb1 = exp.e1.type.nextOf().toBasetype();
             Type tb2 = exp.e2.type.toBasetype();
-            if (tb2.ty == Tarray || tb2.ty == Tsarray)
+            if (tb2.isStaticOrDynamicArray())
                 tb2 = tb2.nextOf().toBasetype();
             if ((tb1.isIntegral() || tb1.isFloating()) && (tb2.isIntegral() || tb2.isFloating()))
             {
@@ -11789,6 +11823,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
+        if (exp.suggestOpOpAssign(sc, parent))
+            return setError();
+
         if (SliceExp se = exp.e1.isSliceExp())
         {
             if (se.e1.type.toBasetype().ty == Tsarray)
@@ -11823,7 +11860,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
          * EXP.concatenateDcharAssign: appending dchar to T[]
          */
         if ((tb1.ty == Tarray) &&
-            (tb2.ty == Tarray || tb2.ty == Tsarray) &&
+            tb2.isStaticOrDynamicArray() &&
             (exp.e2.implicitConvTo(exp.e1.type) ||
              (tb2.nextOf().implicitConvTo(tb1next) &&
              // Do not strip const(void)[]
@@ -12081,7 +12118,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
 
         Type tb = exp.type.toBasetype();
-        if (tb.ty == Tarray || tb.ty == Tsarray)
+        if (tb.isStaticOrDynamicArray())
         {
             if (!isArrayOpValid(exp))
             {
@@ -12092,7 +12129,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
-        if (exp.checkArithmeticBin())
+        if (exp.suggestBinaryOverloads(sc) || exp.checkArithmeticBin())
             return setError();
 
         tb1 = exp.e1.type.toBasetype();
@@ -12234,7 +12271,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
 
         Type tb = exp.type.toBasetype();
-        if (tb.ty == Tarray || tb.ty == Tsarray)
+        if (tb.isStaticOrDynamicArray())
         {
             if (!isArrayOpValid(exp))
             {
@@ -12245,7 +12282,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
-        if (exp.checkArithmeticBin())
+        if (exp.suggestBinaryOverloads(sc) || exp.checkArithmeticBin())
             return setError();
 
         t1 = exp.e1.type.toBasetype();
@@ -12308,7 +12345,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return result;
         }
 
-        void handleCatArgument(Expressions *arguments, Expression e, Type catType, bool isRightArg)
+        void handleCatArgument(Expressionsarguments, Expression e, Type catType, bool isRightArg)
         {
             auto tb = e.type.toBasetype();
 
@@ -12416,7 +12453,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
 
         // Check for: array ~ element
-        if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid)
+        if (tb1.isStaticOrDynamicArray() && tb2.ty != Tvoid)
         {
             if (exp.e1.op == EXP.arrayLiteral)
             {
@@ -12455,7 +12492,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             }
         }
         // Check for: element ~ array
-        if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid)
+        if (tb2.isStaticOrDynamicArray() && tb1.ty != Tvoid)
         {
             if (exp.e2.op == EXP.arrayLiteral)
             {
@@ -12490,7 +12527,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
 
     Lpeer:
-        if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
+        if (tb1.isStaticOrDynamicArray() && tb2.isStaticOrDynamicArray() &&
+            (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
         {
             Type t1 = tb1next.mutableOf().constOf().arrayOf();
             Type t2 = tb2next.mutableOf().constOf().arrayOf();
@@ -12529,8 +12567,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))
+        if (t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray())
         {
             // Normalize to ArrayLiteralExp or StringExp as far as possible
             e = exp.optimize(WANTvalue);
@@ -12546,7 +12583,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         trySetCatExpLowering(result);
     }
 
-    bool commonBinOpSemantic(BinExp exp)
+    bool commonArithBinOpSemantic(BinExp exp)
     {
         if (Expression e = exp.opOverloadBinary(sc, aliasThisStop))
         {
@@ -12559,15 +12596,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             result = ex;
             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)
+        if (tb.isStaticOrDynamicArray())
         {
             if (!isArrayOpValid(exp))
             {
@@ -12578,7 +12609,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return true;
         }
 
-        if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
+        if (exp.suggestBinaryOverloads(sc) || exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
         {
             setError();
             return true;
@@ -12792,7 +12823,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
-        if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
+        if (exp.suggestBinaryOverloads(sc) || exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
             return setError();
 
         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
@@ -12847,7 +12878,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         }
 
         Type tb = exp.type.toBasetype();
-        if (tb.ty == Tarray || tb.ty == Tsarray)
+        if (tb.isStaticOrDynamicArray())
         {
             if (!isArrayOpValid(exp))
             {
@@ -12862,7 +12893,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             result = exp.incompatibleTypes();
             return;
         }
-        if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
+
+        if (exp.suggestBinaryOverloads(sc) || exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
             return setError();
 
         result = exp;
@@ -13008,7 +13040,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         Expression arrayLowering = null;
         t1 = exp.e1.type.toBasetype();
         t2 = exp.e2.type.toBasetype();
-        if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
+        if ((t1.isStaticOrDynamicArray() || t1.ty == Tpointer) && (t2.isStaticOrDynamicArray() || t2.ty == Tpointer))
         {
             Type t1next = t1.nextOf();
             Type t2next = t2.nextOf();
@@ -13018,8 +13050,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 return setError();
             }
 
-            if ((t1.ty == Tarray || t1.ty == Tsarray) &&
-                (t2.ty == Tarray || t2.ty == Tsarray))
+            if (t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray())
             {
                 if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays"))
                     return setError();
@@ -13040,12 +13071,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 arrayLowering = al;
             }
         }
-        else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass))
+        else if (t1.isTypeClass() && t2.isTypeClass())
         {
-            if (t2.ty == Tstruct)
-                error(exp.loc, "need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars());
-            else
-                error(exp.loc, "need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
+            error(exp.loc, "need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
             return setError();
         }
         else if (t1.isComplex() || t2.isComplex())
@@ -13119,7 +13147,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return setError();
 
         case Tarray, Tsarray:
-            result = exp.incompatibleTypes();
+            result = exp.incompatibleTypes(sc);
             errorSupplemental(exp.loc, "`in` is only allowed on associative arrays");
             const(char)* slice = (t2b.ty == Tsarray) ? "[]" : "";
             errorSupplemental(exp.loc, "perhaps use `std.algorithm.find(%s, %s%s)` instead",
@@ -13127,7 +13155,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
 
         default:
-            result = exp.incompatibleTypes();
+            result = exp.incompatibleTypes(sc);
             return;
         }
         result = exp;
@@ -13258,8 +13286,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
 
-        const isArrayComparison = (t1.ty == Tarray || t1.ty == Tsarray) &&
-                                  (t2.ty == Tarray || t2.ty == Tsarray);
+        const isArrayComparison = t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray();
         const needsArrayLowering = isArrayComparison && needsDirectEq(t1, t2, sc);
 
         if (!needsArrayLowering)
@@ -13849,6 +13876,20 @@ private Expression expressionSemantic(Expression e, Scope* sc, Type[2] aliasThis
     return v.result;
 }
 
+// ditto, but with `parent` parameter that represents the expression before rewriting.
+// This way, when lowering an expression (e.g. i++ to i+=1), error messages can still
+// refer to the original expression.
+private Expression expressionSemanticWithParent(Expression e, Scope* sc, Expression parent)
+{
+    if (e.expressionSemanticDone)
+        return e;
+
+    scope v = new ExpressionSemanticVisitor(sc);
+    v.parent = parent;
+    e.accept(v);
+    return v.result;
+}
+
 private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc)
 {
     //printf("dotIdSemanticPropX() %s\n", toChars(exp));
@@ -14371,7 +14412,7 @@ Expression dotTemplateSemanticProp(DotTemplateInstanceExp exp, Scope* sc, bool g
     {
         exp.e1 = die.e1; // take back
         Type t1b = exp.e1.type.toBasetype();
-        if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
+        if (t1b.isStaticOrDynamicArray() || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
         {
             /* No built-in type has templatized properties, so do shortcut.
              * It is necessary in: 1024.max!"a < b"
@@ -14741,11 +14782,16 @@ private bool checkArithmetic(Expression e, EXP op)
         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)
+    if ((op == EXP.add || op == EXP.min) && e.isTypeExp())
+    {
+        // @@@DEPRECATED_2.121@@@
+        // Deprecated in 2.111
+        // In 2.121, remove this branch to let `checkValue` raise the error
+        deprecation(e.loc, "type `%s` has no value", e.toChars);
+        if (!e.type.isOpaqueType)
+            deprecationSupplemental(e.loc, "perhaps use `%s.init`", e.toChars);
         return false;
+    }
 
     return e.checkValue();
 }
@@ -14801,6 +14847,77 @@ private bool checkArithmeticBin(BinExp e)
     return (e.e1.checkArithmetic(e.op) || e.e2.checkArithmetic(e.op));
 }
 
+/****************************************
+ * Check that the expression has a valid value.
+ * If not, generates an error "... has no value".`
+ *
+ * Params:
+ *     e = expression to check
+ *
+ * Returns:
+ *     `true` if the expression is not valid or has `void` type.
+ */
+bool checkValue(Expression e)
+{
+    if (auto te = e.isTypeExp())
+    {
+        error(e.loc, "type `%s` has no value", e.toChars());
+        if (!e.type.isOpaqueType)
+            errorSupplemental(e.loc, "perhaps use `%s.init`", e.toChars());
+        return true;
+    }
+
+    if (auto dtie = e.isDotTemplateInstanceExp())
+    {
+        if (dtie.ti.tempdecl &&
+            dtie.ti.semantictiargsdone &&
+            dtie.ti.semanticRun == PASS.initial)
+
+            error(e.loc, "partial %s `%s` has no value", dtie.ti.kind(), e.toChars());
+        else
+            error(e.loc, "%s `%s` has no value", dtie.ti.kind(), dtie.ti.toChars());
+        return true;
+    }
+
+    if (auto se = e.isScopeExp())
+    {
+        error(e.loc, "%s `%s` has no value", se.sds.kind(), se.sds.toChars());
+        return true;
+    }
+
+    if (auto te = e.isTemplateExp())
+    {
+        error(e.loc, "%s `%s` has no value", te.td.kind(), te.toChars());
+        return true;
+    }
+
+    if (auto fe = e.isFuncExp())
+    {
+        if (fe.td)
+        {
+            error(e.loc, "template lambda has no value");
+            return true;
+        }
+        return false;
+    }
+
+    if (auto dte = e.isDotTemplateExp())
+    {
+        error(e.loc, "%s `%s` has no value", dte.td.kind(), e.toChars());
+        return true;
+    }
+
+    if (e.type && e.type.toBasetype().ty == Tvoid)
+    {
+        error(e.loc, "expression `%s` is `void` and has no value", e.toChars());
+        //print(); assert(0);
+        if (!global.gag)
+            e.type = Type.terror;
+        return true;
+    }
+    return false;
+}
+
 /***************************************
  * If expression is shared, check that we can access it.
  * Give error message if not.
@@ -16251,7 +16368,7 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions
             Type typeb = se.type.toBasetype();
             TY tynto = tb.nextOf().ty;
             if (!se.committed &&
-                (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
+                typeb.isStaticOrDynamicArray() && tynto.isSomeChar &&
                 se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
             {
                 e = se.castTo(sc, t);
@@ -16623,7 +16740,7 @@ private Modifiable checkModify(Declaration d, Loc loc, Scope* sc, Expression e1,
             if (scx.func == vthis.parent && scx.contract != Contract.none)
             {
                 if (!(flag & ModifyFlags.noError))
-                    error(loc, "%s `%s` cannot modify parameter `this` in contract", d.kind, d.toPrettyChars);
+                    error(loc, "cannot modify member variable `%s` in contract", d.toPrettyChars());
                 return Modifiable.initialization; // do not report type related errors
             }
         }
index 70f4c8303a76525b277d60061d373c0c2ba30ce4..613dc1c01aaea7916355a9f08e0a5e8eaa3f8ab7 100644 (file)
@@ -277,7 +277,7 @@ extern (C++) class FuncDeclaration : Declaration
     /// Sibling nested functions which called this one
     FuncDeclarations siblingCallers;
 
-    FuncDeclarations *inlinedNestedCallees;
+    FuncDeclarationsinlinedNestedCallees;
 
     /// In case of failed `@safe` inference, store the error that made the function `@system` for
     /// better diagnostics
@@ -1390,11 +1390,6 @@ extern (C++) final class CtorDeclaration : FuncDeclaration
         return isCpCtor ? "copy constructor" : "constructor";
     }
 
-    override const(char)* toChars() const
-    {
-        return "this";
-    }
-
     override bool isVirtual() const
     {
         return false;
@@ -1496,11 +1491,6 @@ extern (C++) final class DtorDeclaration : FuncDeclaration
         return "destructor";
     }
 
-    override const(char)* toChars() const
-    {
-        return "~this";
-    }
-
     override bool isVirtual() const
     {
         // D dtor's don't get put into the vtbl[]
index 4d3c1b9d19706dba2058a6b683ac8391ae01961a..be65557870d461b56b56a478d206cec225f623bb 100644 (file)
@@ -242,8 +242,7 @@ extern (C++) struct Param
     Output mixinOut;                    // write expanded mixins for debugging
     Output moduleDeps;                  // Generate `.deps` module dependencies
 
-    uint debuglevel;                    // debug level
-    uint versionlevel;                  // version level
+    bool debugEnabled;                  // Global -debug flag (no -debug=XXX) is active
 
     bool run; // run resulting executable
     Strings runargs; // arguments for executable
index 6dd4be4b0a0131444570139e8e5bd6dedc2e04b9..e94b804d242238cae054432e376a745f80f8c3c2 100644 (file)
@@ -250,8 +250,7 @@ struct Param
     Output mixinOut;          // write expanded mixins for debugging
     Output moduleDeps;        // Generate `.deps` module dependencies
 
-    unsigned debuglevel;   // debug level
-    unsigned versionlevel; // version level
+    d_bool debugEnabled;   // -debug flag is passed
 
     d_bool run;           // run resulting executable
     Strings runargs;    // arguments for executable
index 961a0d2c11de4bce2b4206ac1f9c5bdd5f8cabbb..c0fcf64be3188d879cc3ad1ef03e9d2041e05c8a 100644 (file)
@@ -140,6 +140,42 @@ public const(char)* toChars(const Type t)
     return buf.extractChars();
 }
 
+public const(char)* toChars(const Dsymbol d)
+{
+    if (auto td = d.isTemplateDeclaration())
+    {
+        HdrGenState hgs;
+        OutBuffer buf;
+        toCharsMaybeConstraints(td, buf, hgs);
+        return buf.extractChars();
+    }
+
+    if (auto ti = d.isTemplateInstance())
+    {
+        OutBuffer buf;
+        toCBufferInstance(ti, buf);
+        return buf.extractChars();
+    }
+
+    if (auto tm = d.isTemplateMixin())
+    {
+        OutBuffer buf;
+        toCBufferInstance(tm, buf);
+        return buf.extractChars();
+    }
+
+    if (auto tid = d.isTypeInfoDeclaration())
+    {
+        OutBuffer buf;
+        buf.writestring("typeid(");
+        buf.writestring(tid.tinfo.toChars());
+        buf.writeByte(')');
+        return buf.extractChars();
+    }
+
+    return d.ident ? d.ident.toHChars2() : "__anonymous";
+}
+
 public const(char)[] toString(const Initializer i)
 {
     OutBuffer buf;
@@ -880,10 +916,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
     void visitDebugSymbol(DebugSymbol s)
     {
         buf.writestring("debug = ");
-        if (s.ident)
-            buf.writestring(s.ident.toString());
-        else
-            buf.print(s.level);
+        buf.writestring(s.ident.toString());
         buf.writeByte(';');
         buf.writenl();
     }
@@ -891,10 +924,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
     void visitVersionSymbol(VersionSymbol s)
     {
         buf.writestring("version = ");
-        if (s.ident)
-            buf.writestring(s.ident.toString());
-        else
-            buf.print(s.level);
+        buf.writestring(s.ident.toString());
         buf.writeByte(';');
         buf.writenl();
     }
@@ -2237,9 +2267,20 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
             buf.writestring(e.ident.toString());
     }
 
-    void visitDsymbol(DsymbolExp e)
+    void visitDsymbol(Dsymbol s)
+    {
+        // For -vcg-ast, print internal names such as __invariant, __ctor etc.
+        // This condition is a bit kludge, and can be cleaned up if the
+        // mutual dependency `AST.toChars <> hdrgen.d` gets refactored
+        if (hgs.vcg_ast && s.ident && !s.isTemplateInstance() && !s.isTemplateDeclaration())
+            buf.writestring(s.ident.toChars());
+        else
+            buf.writestring(s.toChars());
+    }
+
+    void visitDsymbolExp(DsymbolExp e)
     {
-        buf.writestring(e.s.toChars());
+        visitDsymbol(e.s);
     }
 
     void visitThis(ThisExp e)
@@ -2444,7 +2485,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
 
     void visitVar(VarExp e)
     {
-        buf.writestring(e.var.toChars());
+        visitDsymbol(e.var);
     }
 
     void visitOver(OverExp e)
@@ -2678,7 +2719,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
     {
         expToBuffer(e.e1, PREC.primary, buf, hgs);
         buf.writeByte('.');
-        buf.writestring(e.var.toChars());
+        visitDsymbol(e.var);
     }
 
     void visitDotTemplateInstance(DotTemplateInstanceExp e)
@@ -2893,7 +2934,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
         case EXP.float64:       return visitReal(e.isRealExp());
         case EXP.complex80:     return visitComplex(e.isComplexExp());
         case EXP.identifier:    return visitIdentifier(e.isIdentifierExp());
-        case EXP.dSymbol:       return visitDsymbol(e.isDsymbolExp());
+        case EXP.dSymbol:       return visitDsymbolExp(e.isDsymbolExp());
         case EXP.this_:         return visitThis(e.isThisExp());
         case EXP.super_:        return visitSuper(e.isSuperExp());
         case EXP.null_:         return visitNull(e.isNullExp());
@@ -3112,20 +3153,14 @@ public:
     override void visit(DebugCondition c)
     {
         buf.writestring("debug (");
-        if (c.ident)
-            buf.writestring(c.ident.toString());
-        else
-            buf.print(c.level);
+        buf.writestring(c.ident.toString());
         buf.writeByte(')');
     }
 
     override void visit(VersionCondition c)
     {
         buf.writestring("version (");
-        if (c.ident)
-            buf.writestring(c.ident.toString());
-        else
-            buf.print(c.level);
+        buf.writestring(c.ident.toString());
         buf.writeByte(')');
     }
 
@@ -4505,7 +4540,15 @@ string EXPtoString(EXP op)
         EXP.declaration : "declaration",
 
         EXP.interval : "interval",
-        EXP.loweredAssignExp : "="
+        EXP.loweredAssignExp : "=",
+
+        EXP.thrownException : "CTFE ThrownException",
+        EXP.cantExpression :  "<cant>",
+        EXP.voidExpression : "cast(void)0",
+        EXP.showCtfeContext : "<error>",
+        EXP.break_ : "<break>",
+        EXP.continue_ : "<continue>",
+        EXP.goto_ : "<goto>",
     ];
     const p = strings[op];
     if (!p)
index 7eb51d995ce1ee9cd5707f718bc34f95261dbb15..d04bef3e2a82dc16432655c3239cc13d33b086b0 100644 (file)
@@ -39,7 +39,7 @@ else
 
 /************************ AsmStatement ***************************************/
 
-Statement asmSemantic(AsmStatement s, Scope *sc)
+Statement asmSemantic(AsmStatement s, Scopesc)
 {
     //printf("AsmStatement.semantic()\n");
 
@@ -89,7 +89,7 @@ Statement asmSemantic(AsmStatement s, Scope *sc)
 
 /************************ CAsmDeclaration ************************************/
 
-void asmSemantic(CAsmDeclaration ad, Scope *sc)
+void asmSemantic(CAsmDeclaration ad, Scopesc)
 {
     version (NoBackend)
     {
index 1410e0a2299173d055ce63260f0e4f318f7b9752..0961354bf386cfe805dad3f03898322a5012f5d1 100644 (file)
@@ -37,17 +37,17 @@ import dmd.statementsem;
  * Returns:
  *      the completed gcc asm statement, or null if errors occurred
  */
-public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
+public Statement gccAsmSemantic(GccAsmStatement s, Scopesc)
 {
     //printf("GccAsmStatement.semantic()\n");
     const bool doUnittests = global.params.parsingUnittestsRequired();
     scope p = new Parser!ASTCodegen(sc._module, ";", false, global.errorSink, &global.compileEnv, doUnittests);
 
     // Make a safe copy of the token list before parsing.
-    Token *toklist = null;
+    Tokentoklist = null;
     Token **ptoklist = &toklist;
 
-    for (Token *token = s.tokens; token; token = token.next)
+    for (Tokentoken = s.tokens; token; token = token.next)
     {
         *ptoklist = p.allocateToken();
         memcpy(*ptoklist, token, Token.sizeof);
@@ -126,7 +126,7 @@ public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
  *      ad  = asm declaration
  *      sc = the scope where the asm declaration is located
  */
-public void gccAsmSemantic(CAsmDeclaration ad, Scope *sc)
+public void gccAsmSemantic(CAsmDeclaration ad, Scopesc)
 {
     import dmd.typesem : pointerTo;
     ad.code = semanticString(sc, ad.code, "asm definition");
@@ -254,9 +254,9 @@ Lerror:
  * Returns:
  *      array of parsed clobber expressions
  */
-Expressions *parseExtAsmClobbers(Parser)(Parser p)
+ExpressionsparseExtAsmClobbers(Parser)(Parser p)
 {
-    Expressions *clobbers;
+    Expressionsclobbers;
 
     while (1)
     {
@@ -305,9 +305,9 @@ Lerror:
  * Returns:
  *      array of parsed goto labels
  */
-Identifiers *parseExtAsmGotoLabels(Parser)(Parser p)
+IdentifiersparseExtAsmGotoLabels(Parser)(Parser p)
 {
-    Identifiers *labels;
+    Identifierslabels;
 
     while (1)
     {
index 74be1beb29f91cc33b4cc44a9982d5025a11ecb9..c3ea0f76b5d439ae109fc3d2980b074da87aa70c 100644 (file)
@@ -108,7 +108,8 @@ nothrow:
         const(char)* p = null;
         if (this == Id.ctor)
             p = "this";
-        else if (this == Id.dtor)
+        else if (this == Id.dtor || this == Id.__xdtor || this == Id.__fieldDtor ||
+            this == Id.__aggrDtor || this == Id.cppdtor || this == Id.ticppdtor)
             p = "~this";
         else if (this == Id.unitTest)
             p = "unittest";
@@ -120,6 +121,8 @@ nothrow:
             p = "result";
         else if (this == Id.returnLabel)
             p = "return";
+        else if (this == Id.postblit)
+            p = "this(this)";
         else
         {
             p = toChars();
index 0413df03b5a9ddd44c6f52eee9db14d7bdeecdfd..84fed8fe63369678232c41edc051180000193f2c 100644 (file)
@@ -166,7 +166,7 @@ Expression carraySemantic(ArrayExp ae, Scope* sc)
      * So, rewrite as an IndexExp if we can.
      */
     auto t1 = e1.type.toBasetype();
-    if (t1.isTypeDArray() || t1.isTypeSArray())
+    if (t1.isStaticOrDynamicArray())
     {
         e2 = e2.expressionSemantic(sc).arrayFuncConv(sc);
         // C doesn't do array bounds checking, so `true` turns it off
@@ -176,7 +176,7 @@ Expression carraySemantic(ArrayExp ae, Scope* sc)
     e1 = e1.arrayFuncConv(sc);   // e1 might still be a function call
     e2 = e2.expressionSemantic(sc);
     auto t2 = e2.type.toBasetype();
-    if (t2.isTypeDArray() || t2.isTypeSArray())
+    if (t2.isStaticOrDynamicArray())
     {
         return new IndexExp(ae.loc, e2, e1, true).expressionSemantic(sc); // swap operands
     }
index c181d53e40720960e784d48bd9e7de4f1b260b6e..467b7966074f6b1954670432b56f53f487ad21ab 100644 (file)
@@ -439,7 +439,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
             Type typeb = se.type.toBasetype();
             TY tynto = tb.nextOf().ty;
             if (!se.committed &&
-                (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
+                typeb.isStaticOrDynamicArray() && tynto.isSomeChar &&
                 se.numberOfCodeUnits(tynto) < tb.isTypeSArray().dim.toInteger())
             {
                 i.exp = se.castTo(sc, t);
index 242cac0b7e96793304febeacb169550ebba9694c..8395a84bb179c5f678b4a78ca1b5bc4018cee20f 100644 (file)
@@ -141,7 +141,7 @@ struct SignExtendedNumber
 
     SignExtendedNumber opBinary(string op : "*")(SignExtendedNumber rhs)
     {
-        // perform *saturated* multiplication, otherwise we may get bogus ranges
+        // performsaturated* multiplication, otherwise we may get bogus ranges
         //  like 0x10 * 0x10 == 0x100 == 0.
 
         /* Special handling for zeros:
index 37f8cfdbeac9b09caed040cbd1b377a6dbea06d8..25b081249e5116fe5046e9ff7cbf8d8e5b143327 100644 (file)
@@ -351,19 +351,18 @@ public:
     {
         if (loc.isValid())
         {
-            if (auto filename = loc.filename.toDString)
+            SourceLoc sl = SourceLoc(loc);
+            if (sl.filename.length > 0 && sl.filename != this.filename)
             {
-                if (filename != this.filename)
-                {
-                    this.filename = filename;
-                    property("file", filename);
-                }
+                this.filename = sl.filename;
+                property("file", sl.filename);
             }
-            if (loc.linnum)
+
+            if (sl.linnum)
             {
-                property(linename, loc.linnum);
-                if (loc.charnum)
-                    property(charname, loc.charnum);
+                property(linename, sl.linnum);
+                if (sl.charnum)
+                    property(charname, sl.charnum);
             }
         }
     }
index 07870685910164cb105d33283f35fbe681616b0b..75cd068a1de76fe85b7a2dc0b755cb9f1315c18c 100644 (file)
@@ -96,6 +96,16 @@ nothrow:
         return _linnum = num;
     }
 
+    /// Advance this location to the first column of the next line
+    void nextLine()
+    {
+        if (this._linnum)
+        {
+            this._linnum++;
+            this.charnum = 0;
+        }
+    }
+
     /***
      * Returns: filename for this location, null if none
      */
@@ -126,9 +136,7 @@ nothrow:
         bool showColumns = Loc.showColumns,
         MessageStyle messageStyle = Loc.messageStyle) const nothrow
     {
-        OutBuffer buf;
-        writeSourceLoc(buf, SourceLoc(this), showColumns, messageStyle);
-        return buf.extractChars();
+        return SourceLoc(this).toChars(showColumns, messageStyle);
     }
 
     /**
@@ -140,9 +148,11 @@ nothrow:
      */
     extern (C++) bool equals(ref const(Loc) loc) const
     {
-        return (!showColumns || charnum == loc.charnum) &&
-               linnum == loc.linnum &&
-               FileName.equals(filename, loc.filename);
+        SourceLoc lhs = SourceLoc(this);
+        SourceLoc rhs = SourceLoc(loc);
+        return (!showColumns || lhs.column == rhs.column) &&
+               lhs.line == rhs.line &&
+               FileName.equals(lhs.filename, rhs.filename);
     }
 
     /**
@@ -198,6 +208,8 @@ void writeSourceLoc(ref OutBuffer buf,
     bool showColumns,
     MessageStyle messageStyle) nothrow
 {
+    if (loc.filename.length == 0)
+        return;
     buf.writestring(loc.filename);
     if (loc.line == 0)
         return;
@@ -258,4 +270,18 @@ struct SourceLoc
         this.line = loc.linnum;
         this.column = loc.charnum;
     }
+
+    extern (C++) const(char)* toChars(
+        bool showColumns = Loc.showColumns,
+        MessageStyle messageStyle = Loc.messageStyle) const nothrow
+    {
+        OutBuffer buf;
+        writeSourceLoc(buf, this, showColumns, messageStyle);
+        return buf.extractChars();
+    }
+
+    bool opEquals(SourceLoc other) const nothrow
+    {
+        return this.filename == other.filename && this.line == other.line && this.column == other.column;
+    }
 }
index 7f02bec2f3a0333f5de673ca12a209d67fc3932f..fd01e73fa007ec8d38dcd7ff0bdb7fc51edaf874 100644 (file)
@@ -109,11 +109,9 @@ public:
 
     Modules aimports;             // all imported modules
 
-    unsigned debuglevel;        // debug level
     Identifiers *debugids;      // debug identifiers
     Identifiers *debugidsNot;   // forward referenced debug identifiers
 
-    unsigned versionlevel;      // version level
     Identifiers *versionids;    // version identifiers
     Identifiers *versionidsNot; // forward referenced version identifiers
 
index b270943403213f594e7d6eea69f6098c56647d98..81f8a98bc273bb4b59fab5e801eb80fa050032fc 100644 (file)
@@ -1521,6 +1521,8 @@ extern (C++) abstract class Type : ASTNode
         inout(TypeTraits)     isTypeTraits()     { return ty == Ttraits    ? cast(typeof(return))this : null; }
         inout(TypeNoreturn)   isTypeNoreturn()   { return ty == Tnoreturn  ? cast(typeof(return))this : null; }
         inout(TypeTag)        isTypeTag()        { return ty == Ttag       ? cast(typeof(return))this : null; }
+
+        extern (D) bool isStaticOrDynamicArray() const { return ty == Tarray || ty == Tsarray; }
     }
 
     override void accept(Visitor v)
@@ -3947,7 +3949,7 @@ extern (C++) final class Parameter : ASTNode
     Type isLazyArray()
     {
         Type tb = type.toBasetype();
-        if (tb.ty == Tsarray || tb.ty == Tarray)
+        if (tb.isStaticOrDynamicArray())
         {
             Type tel = (cast(TypeArray)tb).next.toBasetype();
             if (auto td = tel.isTypeDelegate())
@@ -4057,7 +4059,7 @@ extern (C++) final class Parameter : ASTNode
 
     /***************************************
      * Expands tuples in args in depth first order. Calls
-     * dg(void *ctx, size_t argidx, Parameter *arg) for each Parameter.
+     * dg(void* ctx, size_t argidx, Parameter* arg) for each Parameter.
      * If dg returns !=0, stops and returns that value else returns 0.
      * Use this function to avoid the O(N + N^2/2) complexity of
      * calculating dim and calling N times getNth.
@@ -4316,10 +4318,10 @@ void attributesApply(const TypeFunction tf, void delegate(string) dg, TRUSTforma
 AggregateDeclaration isAggregate(Type t)
 {
     t = t.toBasetype();
-    if (t.ty == Tclass)
-        return (cast(TypeClass)t).sym;
-    if (t.ty == Tstruct)
-        return (cast(TypeStruct)t).sym;
+    if (auto tc = t.isTypeClass())
+        return tc.sym;
+    if (auto ts = t.isTypeStruct())
+        return ts.sym;
     return null;
 }
 
@@ -4334,7 +4336,7 @@ AggregateDeclaration isAggregate(Type t)
 bool isIndexableNonAggregate(Type t)
 {
     t = t.toBasetype();
-    return (t.ty == Tpointer || t.ty == Tsarray || t.ty == Tarray || t.ty == Taarray ||
+    return (t.ty == Tpointer || t.isStaticOrDynamicArray() || t.ty == Taarray ||
             t.ty == Ttuple || t.ty == Tvector);
 }
 
index ab480190a5d5a2ff1adf3ebd607072f12641de77..5e773f055e1aeef9e744b5061db8991ec2922497 100644 (file)
@@ -1683,7 +1683,7 @@ void genKill(ref ObState obstate, ObNode* ob)
             override void visit(ArrayLiteralExp e)
             {
                 Type tb = e.type.toBasetype();
-                if (tb.ty == Tsarray || tb.ty == Tarray)
+                if (tb.isStaticOrDynamicArray())
                 {
                     if (e.basis)
                         e.basis.accept(this);
@@ -2424,7 +2424,7 @@ void checkObErrors(ref ObState obstate)
             override void visit(ArrayLiteralExp e)
             {
                 Type tb = e.type.toBasetype();
-                if (tb.ty == Tsarray || tb.ty == Tarray)
+                if (tb.isStaticOrDynamicArray())
                 {
                     if (e.basis)
                         e.basis.accept(this);
index 92f3bb2ebd322c2ab6922409e0cb7fdb1edcff10..ac9e07246fd00dc5019b1e8ab704431bc89cbb49 100644 (file)
@@ -71,58 +71,63 @@ bool isCommutative(EXP op) @safe
     return false;
 }
 
+/// Returns: whether `op` can be overloaded with `opBinary`
+private bool hasOpBinary(EXP op) pure @safe
+{
+    switch (op)
+    {
+        case EXP.add: return true;
+        case EXP.min: return true;
+        case EXP.mul: return true;
+        case EXP.div: return true;
+        case EXP.mod: return true;
+        case EXP.and: return true;
+        case EXP.or: return true;
+        case EXP.xor: return true;
+        case EXP.leftShift: return true;
+        case EXP.rightShift: return true;
+        case EXP.unsignedRightShift: return true;
+        case EXP.concatenate: return true;
+        case EXP.pow: return true;
+        case EXP.in_: return true;
+        default: return false;
+    }
+}
+
+/**
+ * Remove the = from op=, e.g. += becomes +
+ *
+ * Params:
+ *     op = tag for a binary assign operator
+ * Returns: the corresponding binary operator, or `op` if it wasn't an assign operator
+*/
+private EXP stripAssignOp(EXP op)
+{
+    switch (op)
+    {
+    case EXP.addAssign: return EXP.add;
+    case EXP.minAssign: return EXP.min;
+    case EXP.mulAssign: return EXP.mul;
+    case EXP.divAssign: return EXP.div;
+    case EXP.modAssign: return EXP.mod;
+    case EXP.andAssign: return EXP.and;
+    case EXP.orAssign: return EXP.or;
+    case EXP.xorAssign: return EXP.xor;
+    case EXP.leftShiftAssign: return EXP.leftShift;
+    case EXP.rightShiftAssign: return EXP.rightShift;
+    case EXP.unsignedRightShiftAssign: return EXP.unsignedRightShift;
+    case EXP.concatenateAssign: return EXP.concatenate;
+    case EXP.powAssign: return EXP.pow;
+    default: return op;
+    }
+}
+
 /*******************************************
  * Helper function to turn operator into template argument list
  */
 Objects* opToArg(Scope* sc, EXP op)
 {
-    /* Remove the = from op=
-     */
-    switch (op)
-    {
-    case EXP.addAssign:
-        op = EXP.add;
-        break;
-    case EXP.minAssign:
-        op = EXP.min;
-        break;
-    case EXP.mulAssign:
-        op = EXP.mul;
-        break;
-    case EXP.divAssign:
-        op = EXP.div;
-        break;
-    case EXP.modAssign:
-        op = EXP.mod;
-        break;
-    case EXP.andAssign:
-        op = EXP.and;
-        break;
-    case EXP.orAssign:
-        op = EXP.or;
-        break;
-    case EXP.xorAssign:
-        op = EXP.xor;
-        break;
-    case EXP.leftShiftAssign:
-        op = EXP.leftShift;
-        break;
-    case EXP.rightShiftAssign:
-        op = EXP.rightShift;
-        break;
-    case EXP.unsignedRightShiftAssign:
-        op = EXP.unsignedRightShift;
-        break;
-    case EXP.concatenateAssign:
-        op = EXP.concatenate;
-        break;
-    case EXP.powAssign:
-        op = EXP.pow;
-        break;
-    default:
-        break;
-    }
-    Expression e = new StringExp(Loc.initial, EXPtoString(op));
+    Expression e = new StringExp(Loc.initial, EXPtoString(stripAssignOp(op)));
     e = e.expressionSemantic(sc);
     auto tiargs = new Objects();
     tiargs.push(e);
@@ -144,7 +149,7 @@ Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinExp e, Ty
     BinExp be = cast(BinExp)e.copy();
     // Resolve 'alias this' but in case of assigment don't resolve properties yet
     // because 'e1 = e2' could mean 'e1(e2)' or 'e1() = e2'
-    bool findOnly = (e.op == EXP.assign);
+    bool findOnly = e.isAssignExp() !is null;
     be.e1 = resolveAliasThis(sc, e.e1, true, findOnly);
     if (!be.e1)
         return null;
@@ -173,13 +178,12 @@ Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinExp e, Ty
 
 Expression opOverloadUnary(UnaExp e, Scope* sc)
 {
-    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);
+        const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].isIntervalExp());
         IntervalExp ie = null;
         if (maybeSlice && ae.arguments.length)
         {
@@ -188,70 +192,61 @@ Expression opOverloadUnary(UnaExp e, Scope* sc)
         Type att = null; // first cyclic `alias this` type
         while (true)
         {
-            if (ae.e1.op == EXP.error)
+            if (ae.e1.isErrorExp())
             {
                 return ae.e1;
             }
-            Expression e0 = null;
             Expression ae1save = ae.e1;
             ae.lengthVar = null;
-            Type t1b = ae.e1.type.toBasetype();
-            AggregateDeclaration ad = isAggregate(t1b);
+
+            AggregateDeclaration ad = isAggregate(ae.e1.type);
             if (!ad)
                 break;
+
             if (search_function(ad, Id.opIndexUnary))
             {
+                Expression e0;
                 // Deal with $
-                result = resolveOpDollar(sc, ae, &e0);
-                if (!result) // op(a[i..j]) might be: a.opSliceUnary!(op)(i, j)
+                Expression ae2 = resolveOpDollar(sc, ae, e0);
+                if (!ae2) // op(a[i..j]) might be: a.opSliceUnary!(op)(i, j)
                     goto Lfallback;
-                if (result.op == EXP.error)
-                    return result;
+                if (ae2.isErrorExp())
+                    return ae2;
                 /* 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);
+                 *      a.opIndexUnary!(op)(arguments)
+                 */
+                Expression result = dotTemplateCall(ae.e1, Id.opIndexUnary, opToArg(sc, e.op), (*ae.arguments)[]);
                 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;
+                Expression e0;
+                auto ae2 = resolveOpDollar(sc, ae, ie, e0);
+                if (ae2.isErrorExp())
+                    return ae2;
                 /* 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;
+                 *      a.opSliceUnary!(op)(i, j)
+                 */
+                Expression result = ie ?
+                    dotTemplateCall(ae.e1, Id.opSliceUnary, opToArg(sc, e.op), ie.lwr, ie.upr) :
+                    dotTemplateCall(ae.e1, Id.opSliceUnary, opToArg(sc, e.op));
+
+                return Expression.combine(e0, result.expressionSemantic(sc));
             }
             // Didn't find it. Forward to aliasthis
             if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
             {
                 /* Rewrite op(a[arguments]) as:
-                    *      op(a.aliasthis[arguments])
-                    */
+                 *      op(a.aliasthis[arguments])
+                 */
                 ae.e1 = resolveAliasThis(sc, ae1save, true);
                 if (ae.e1)
                     continue;
@@ -266,7 +261,7 @@ Expression opOverloadUnary(UnaExp e, Scope* sc)
     Type att = null; // first cyclic `alias this` type
     while (1)
     {
-        if (e.e1.op == EXP.error)
+        if (e.e1.isErrorExp())
         {
             return e.e1;
         }
@@ -275,19 +270,11 @@ Expression opOverloadUnary(UnaExp e, Scope* sc)
         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;
-        }
+        if (Dsymbol fd = search_function(ad, Id.opUnary))
+            return dotTemplateCall(e.e1, Id.opUnary, opToArg(sc, e.op)).expressionSemantic(sc);
 
         // Didn't find it. Forward to aliasthis
         if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type))
@@ -303,9 +290,19 @@ Expression opOverloadUnary(UnaExp e, Scope* sc)
             }
             break;
         }
+
+        // For ++ and --, rewrites to += and -= are also tried, so don't error yet
+        if (!e.isPreExp())
+        {
+            error(e.loc, "operator `%s` is not defined for `%s`", EXPtoString(e.op).ptr, ad.toChars());
+            errorSupplemental(ad.loc, "perhaps overload the operator with `auto opUnary(string op : \"%s\")() {}`",
+                EXPtoString(e.op).ptr);
+            return ErrorExp.get();
+        }
+
         break;
     }
-    return result;
+    return null;
 }
 
 Expression opOverloadArray(ArrayExp ae, Scope* sc)
@@ -313,17 +310,16 @@ 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);
+    const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].isIntervalExp());
     IntervalExp ie = null;
     if (maybeSlice && ae.arguments.length)
     {
         ie = (*ae.arguments)[0].isIntervalExp();
     }
-    Expression result;
     Type att = null; // first cyclic `alias this` type
     while (true)
     {
-        if (ae.e1.op == EXP.error)
+        if (ae.e1.isErrorExp())
         {
             return ae.e1;
         }
@@ -336,67 +332,58 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
         {
             // 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)
+            if (isIndexableNonAggregate(t1b) || ae.e1.isTypeExp())
             {
                 // Convert to SliceExp
                 if (maybeSlice)
-                {
-                    result = new SliceExp(ae.loc, ae.e1, ie);
-                    result = result.expressionSemantic(sc);
-                    return result;
-                }
+                    return new SliceExp(ae.loc, ae.e1, ie).expressionSemantic(sc);
+
                 // Convert to IndexExp
                 if (ae.arguments.length == 1)
-                {
-                    result = new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]);
-                    result = result.expressionSemantic(sc);
-                    return result;
-                }
+                    return new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]).expressionSemantic(sc);
             }
             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)
+            auto ae2 = resolveOpDollar(sc, ae, e0);
+            if (!ae2) // a[i..j] might be: a.opSlice(i, j)
                 goto Lfallback;
-            if (result.op == EXP.error)
-                return result;
+            if (ae2.isErrorExp())
+                return ae2;
             /* Rewrite e1[arguments] as:
              *      e1.opIndex(arguments)
              */
             Expressions* a = ae.arguments.copy();
-            result = new DotIdExp(ae.loc, ae.e1, Id.opIndex);
+            Expression 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)
-            {
                 return Expression.combine(e0, result);
-            }
         }
     Lfallback:
-        if (maybeSlice && ae.e1.op == EXP.type)
+        if (maybeSlice && ae.e1.isTypeExp())
         {
-            result = new SliceExp(ae.loc, ae.e1, ie);
+            Expression result = new SliceExp(ae.loc, ae.e1, ie);
             result = result.expressionSemantic(sc);
-            result = Expression.combine(e0, result);
-            return result;
+            return Expression.combine(e0, result);
         }
         if (maybeSlice && search_function(ad, Id.opSlice))
         {
             // Deal with $
-            result = resolveOpDollar(sc, ae, ie, &e0);
+            auto ae2 = resolveOpDollar(sc, ae, ie, e0);
 
-            if (result.op == EXP.error)
+            if (ae2.isErrorExp())
             {
-                if (!e0 && !search_function(ad, Id.dollar)) {
-                    ae.loc.errorSupplemental("Aggregate declaration '%s' does not define 'opDollar'", ae.e1.toChars());
-                }
-                return result;
+                if (!e0 && !search_function(ad, Id.dollar))
+                    ad.loc.errorSupplemental("perhaps define `opDollar` for `%s`", ad.toChars());
+
+                return ae2;
             }
             /* Rewrite a[i..j] as:
              *      a.opSlice(i, j)
@@ -407,11 +394,10 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
                 a.push(ie.lwr);
                 a.push(ie.upr);
             }
-            result = new DotIdExp(ae.loc, ae.e1, Id.opSlice);
+            Expression 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;
+            return Expression.combine(e0, result);
         }
         // Didn't find it. Forward to aliasthis
         if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
@@ -428,7 +414,7 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
     }
     ae.e1 = ae1old; // recovery
     ae.lengthVar = null;
-    return result;
+    return null;
 }
 
 /***********************************************
@@ -437,48 +423,38 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
  */
 Expression opOverloadCast(CastExp e, Scope* sc, Type att = null)
 {
-    Expression result;
-    if (AggregateDeclaration ad = isAggregate(e.e1.type))
+    AggregateDeclaration ad = isAggregate(e.e1.type);
+    if (!ad)
+        return null;
+
+    // Rewrite as: e1.opCast!(T)()
+    if (Dsymbol fd = search_function(ad, Id.opCast))
     {
-        Dsymbol fd = null;
-        /* Rewrite as:
-            *      e1.opCast!(T)()
-            */
-        fd = search_function(ad, Id.opCast);
-        if (fd)
+        version (all)
         {
-            version (all)
+            // Backwards compatibility with D1 if opCast is a function, not a template
+            if (fd.isFuncDeclaration())
             {
-                // 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);
-                }
+                // 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))
+        auto tiargs = new Objects();
+        tiargs.push(e.to);
+        return dotTemplateCall(e.e1, Id.opCast, tiargs).expressionSemantic(sc);
+    }
+    // Didn't find it. Forward to aliasthis
+    if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type))
+    {
+        // Rewrite `e1.opCast()` as `e1.aliasthis.opCast()`
+        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 = opOverloadCast(result.isCastExp(), sc, att);
-                return result;
-            }
+            CastExp result = e.copy().isCastExp();
+            result.e1 = e1;
+            return result.opOverloadCast(sc, att);
         }
     }
-    return result;
+    return null;
 }
 
 // When no operator overload functions are found for `e`, recursively try with `alias this`
@@ -488,7 +464,7 @@ 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 (!(e.isAssignExp && ad2 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
     {
         if (Expression result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop))
         {
@@ -503,14 +479,14 @@ Expression binAliasThis(BinExp e, Scope* sc, Type[2] aliasThisStop)
              * one of the members, hence the `ad1.fields.length == 2 && ad1.vthis`
              * condition.
              */
-            if (result.op != EXP.assign)
+            auto ae = result.isAssignExp();
+            if (!ae)
                 return result;     // i.e: Rewrote `e1 = e2` -> `e1(e2)`
 
-            auto ae = result.isAssignExp();
-            if (ae.e1.op != EXP.dotVariable)
+            auto dve = ae.e1.isDotVarExp();
+            if (!dve)
                 return result;     // i.e: Rewrote `e1 = e2` -> `e1() = e2`
 
-            auto dve = ae.e1.isDotVarExp();
             if (auto ad = dve.var.isMember2())
             {
                 // i.e: Rewrote `e1 = e2` -> `e1.some.var = e2`
@@ -524,7 +500,7 @@ Expression binAliasThis(BinExp e, Scope* sc, Type[2] aliasThisStop)
             rewrittenLhs = ae.e1;
         }
     }
-    if (!(e.op == EXP.assign && ad1 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
+    if (!(e.isAssignExp && ad1 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
     {
         if (Expression result = checkAliasThisForRhs(ad2, sc, e, aliasThisStop))
             return result;
@@ -591,12 +567,104 @@ Expression opOverloadBinary(BinExp e, Scope* sc, Type[2] aliasThisStop)
         s_r = null;
 
     bool choseReverse;
-    if (auto res = pickBestBinaryOverload(sc, opToArg(sc, e.op), s, s_r, e, choseReverse))
-        return res;
+    if (auto result = pickBestBinaryOverload(sc, opToArg(sc, e.op), s, s_r, e, choseReverse))
+        return result;
 
     return binAliasThis(e, sc, aliasThisStop);
 }
 
+/**
+ * If applicable, print an error relating to implementing / fixing `opBinary` functions.
+ * Params:
+ *   e = binary operation
+ *   sc = scope to try `opBinary!""` semantic in for error messages
+ * Returns: `true` when an error related to `opBinary` was printed
+ */
+bool suggestBinaryOverloads(BinExp e, Scope* sc)
+{
+    if (!e.op.hasOpBinary)
+        return false;
+
+    AggregateDeclaration ad1 = isAggregate(e.e1.type);
+    AggregateDeclaration ad2 = isAggregate(e.e2.type);
+
+    if (ad1)
+    {
+        if (Dsymbol s = search_function(ad1, Id.opBinary))
+        {
+            // This expressionSemantic will fail, otherwise operator overloading would have succeeded before
+            dotTemplateCall(e.e1, Id.opBinary, opToArg(sc, e.op), e.e2).expressionSemantic(sc);
+            errorSupplemental(s.loc, "`opBinary` defined here");
+            return true;
+        }
+        error(e.loc, "operator `%s` is not defined for type `%s`", EXPtoString(e.op).ptr, e.e1.type.toChars);
+        errorSupplemental(ad1.loc, "perhaps overload the operator with `auto opBinary(string op : \"%s\")(%s rhs) {}`", EXPtoString(e.op).ptr, e.e2.type.toChars);
+        return true;
+    }
+    else if (ad2)
+    {
+        if (Dsymbol s_r = search_function(ad1, Id.opBinaryRight))
+        {
+            dotTemplateCall(e.e2, Id.opBinaryRight, opToArg(sc, e.op), e.e1).expressionSemantic(sc);
+            errorSupplemental(s_r.loc, "`opBinaryRight` defined here");
+            return true;
+        }
+        error(e.loc, "operator `%s` is not defined for type `%s`", EXPtoString(e.op).ptr, e.e2.type.toChars);
+        errorSupplemental(ad2.loc, "perhaps overload the operator with `auto opBinaryRight(string op : \"%s\")(%s rhs) {}`", EXPtoString(e.op).ptr, e.e1.type.toChars);
+        return true;
+    }
+    return false;
+}
+
+/**
+ * If applicable, print an error relating to implementing / fixing `opOpAssign` or `opUnary` functions.
+ * Params:
+ *   exp = binary operation
+ *   sc = scope to try `opOpAssign!""` semantic in for error messages
+ *   parent = if `exp` was lowered from this `PreExp` or `PostExp`, mention `opUnary` as well
+ * Returns: `true` when an error related to `opOpAssign` was printed
+ */
+bool suggestOpOpAssign(BinAssignExp exp, Scope* sc, Expression parent)
+{
+    auto ad = isAggregate(exp.e1.type);
+    if (!ad)
+        return false;
+
+    if (parent && (parent.isPreExp() || parent.isPostExp()))
+    {
+        error(exp.loc, "operator `%s` not supported for `%s` of type `%s`", EXPtoString(parent.op).ptr, exp.e1.toChars(), ad.toChars());
+        errorSupplemental(ad.loc,
+            "perhaps implement `auto opUnary(string op : \"%s\")() {}`"~
+            " or `auto opOpAssign(string op : \"%s\")(int) {}`",
+            EXPtoString(stripAssignOp(parent.op)).ptr,
+            EXPtoString(stripAssignOp(exp.op)).ptr
+            );
+        return true;
+    }
+
+    if (const s = search_function(ad, Id.opOpAssign))
+    {
+        // This expressionSemantic will fail, otherwise operator overloading would have succeeded before
+        dotTemplateCall(exp.e1, Id.opOpAssign, opToArg(sc, exp.op), exp.e2).expressionSemantic(sc);
+    }
+    else
+    {
+        error(exp.loc, "operator `%s` not supported for `%s` of type `%s`", EXPtoString(exp.op).ptr, exp.e1.toChars(), ad.toChars());
+        errorSupplemental(ad.loc, "perhaps implement `auto opOpAssign(string op : \"%s\")(%s) {}`",
+            EXPtoString(stripAssignOp(exp.op)).ptr, exp.e2.type.toChars());
+    }
+    return true;
+}
+
+// Helper to construct e.id!tiargs(args), e.g. `lhs.opBinary!"+"(rhs)`
+private Expression dotTemplateCall(Expression e, Identifier id, Objects* tiargs, Expression[] args...)
+{
+    auto ti = new DotTemplateInstanceExp(e.loc, e, id, tiargs);
+    auto expressions = new Expressions();
+    expressions.pushSlice(args);
+    return new CallExp(e.loc, ti, expressions);
+}
+
 Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
 {
     Type t1 = e.e1.type.toBasetype();
@@ -606,24 +674,23 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
      * 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))
+    if (t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray())
     {
         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_)
+    if (t1.isTypeClass() && e.e2.isNullExp() ||
+        t2.isTypeClass() && e.e1.isNullExp())
     {
         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)
+    if (t1.isTypeClass() && t2.isTypeNull() ||
+        t1.isTypeNull() && t2.isTypeClass())
     {
         // Comparing a class with typeof(null) should not call opEquals
         return null;
@@ -631,7 +698,7 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
 
     /* Check for class equality.
      */
-    if (t1.ty == Tclass && t2.ty == Tclass)
+    if (t1.isTypeClass() && t2.isTypeClass())
     {
         ClassDeclaration cd1 = t1.isClassHandle();
         ClassDeclaration cd2 = t2.isClassHandle();
@@ -672,7 +739,7 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
     EXP cmpOp;
     if (Expression result = compare_overload(e, sc, Id.opEquals, cmpOp, aliasThisStop))
     {
-        if (lastComma(result).op == EXP.call && e.op == EXP.notEqual)
+        if (lastComma(result).isCallExp() && e.op == EXP.notEqual)
         {
             result = new NotExp(result.loc, result);
             result = result.expressionSemantic(sc);
@@ -682,7 +749,7 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
 
     /* Check for pointer equality.
      */
-    if (t1.ty == Tpointer || t2.ty == Tpointer)
+    if (t1.isTypePointer() || t2.isTypePointer())
     {
         /* Rewrite:
          *      ptr1 == ptr2
@@ -699,7 +766,7 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
 
     /* Check for struct equality without opEquals.
      */
-    if (t1.ty == Tstruct && t2.ty == Tstruct)
+    if (t1.isTypeStruct() && t2.isTypeStruct())
     {
         auto sd = t1.isTypeStruct().sym;
         if (sd != t2.isTypeStruct().sym)
@@ -738,10 +805,10 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
 
     /* 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();
+    if (tup1 && tup2)
     {
-        auto tup1 = e.e1.isTupleExp();
-        auto tup2 = e.e2.isTupleExp();
         size_t dim = tup1.exps.length;
         if (dim != tup2.exps.length)
         {
@@ -794,12 +861,12 @@ Expression opOverloadCmp(CmpExp exp, Scope* sc, Type[2] aliasThisStop)
         error(e.loc, "recursive `opCmp` expansion");
         return ErrorExp.get();
     }
-    if (e.op != EXP.call)
+    if (!e.isCallExp())
         return e;
 
     Type t1 = exp.e1.type.toBasetype();
     Type t2 = exp.e2.type.toBasetype();
-    if (t1.ty != Tclass || t2.ty != Tclass)
+    if (!t1.isTypeClass() || !t2.isTypeClass())
     {
         return new CmpExp(cmpOp, exp.loc, e, IntegerExp.literal!0).expressionSemantic(sc);
     }
@@ -842,7 +909,7 @@ Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisSt
         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);
+        const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].isIntervalExp());
         IntervalExp ie = null;
         if (maybeSlice && ae.arguments.length)
         {
@@ -851,73 +918,61 @@ Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisSt
         Type att = null; // first cyclic `alias this` type
         while (true)
         {
-            if (ae.e1.op == EXP.error)
-            {
+            if (ae.e1.isErrorExp())
                 return ae.e1;
-            }
+
             Expression e0 = null;
             Expression ae1save = ae.e1;
             ae.lengthVar = null;
-            Type t1b = ae.e1.type.toBasetype();
-            AggregateDeclaration ad = isAggregate(t1b);
+            AggregateDeclaration ad = isAggregate(ae.e1.type);
             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)
+                Expression ae2 = resolveOpDollar(sc, ae, e0);
+                if (!ae2) // (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;
+                if (ae2.isErrorExp())
+                    return ae2;
+                e.e2 = e.e2.expressionSemantic(sc);
+                if (e.e2.isErrorExp())
+                    return e.e2;
+
                 /* 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);
+                Expression result = dotTemplateCall(ae.e1, Id.opIndexOpAssign, opToArg(sc, e.op), (*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;
+                Expression ae2 = resolveOpDollar(sc, ae, ie, e0);
+                if (ae2.isErrorExp())
+                    return ae2;
+
+                e.e2 = e.e2.expressionSemantic(sc);
+                if (e.e2.isErrorExp())
+                    return e.e2;
+
                 /* 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;
+                auto result = ie ?
+                    dotTemplateCall(ae.e1, Id.opSliceOpAssign, opToArg(sc, e.op), e.e2, ie.lwr, ie.upr) :
+                    dotTemplateCall(ae.e1, Id.opSliceOpAssign, opToArg(sc, e.op), e.e2);
+
+                return Expression.combine(e0, result.expressionSemantic(sc));
             }
             // Didn't find it. Forward to aliasthis
             if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
@@ -934,14 +989,14 @@ Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisSt
         ae.e1 = ae1old; // recovery
         ae.lengthVar = null;
     }
-    Expression result = e.binSemanticProp(sc);
-    if (result)
+
+    if (Expression result = e.binSemanticProp(sc))
         return result;
+
     // Don't attempt 'alias this' if an error occurred
-    if (e.e1.type.ty == Terror || e.e2.type.ty == Terror)
-    {
+    if (e.e1.type.isTypeError() || e.e2.type.isTypeError())
         return ErrorExp.get();
-    }
+
     AggregateDeclaration ad1 = isAggregate(e.e1.type);
     Dsymbol s = search_function(ad1, Id.opOpAssign);
     if (s && !s.isTemplateDeclaration())
@@ -954,7 +1009,7 @@ Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisSt
     if (auto res = pickBestBinaryOverload(sc, opToArg(sc, e.op), s, null, e, choseReverse))
         return res;
 
-    result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop);
+    Expression 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;
 
@@ -990,7 +1045,7 @@ private Expression pickBestBinaryOverload(Scope* sc, Objects* tiargs, Dsymbol s,
 
     if (s)
     {
-        functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2));
+        functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2), null);
         if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
             return ErrorExp.get();
     }
@@ -998,7 +1053,7 @@ private Expression pickBestBinaryOverload(Scope* sc, Objects* tiargs, Dsymbol s,
     int count = m.count;
     if (s_r)
     {
-        functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1));
+        functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1), null);
         if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
             return ErrorExp.get();
     }
@@ -1069,10 +1124,34 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, ref EXP
      * at this point, no matching opEquals was found for structs,
      * so we should not follow the alias this comparison code.
      */
-    if ((e.op == EXP.equal || e.op == EXP.notEqual) && ad1 == ad2)
+    if (e.isEqualExp() && ad1 == ad2)
         return null;
     Expression result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop);
-    return result ? result : checkAliasThisForRhs(isAggregate(e.e2.type), sc, e, aliasThisStop);
+    if (result)
+        return result;
+
+    result = checkAliasThisForRhs(isAggregate(e.e2.type), sc, e, aliasThisStop);
+    if (result)
+        return result;
+
+    if (s || s_r)
+        return null;
+
+    Expression suggestOverloading(Expression other, AggregateDeclaration ad)
+    {
+        error(e.loc, "no operator `%s` for type `%s`", EXPtoString(e.op).ptr, ad.toChars);
+        string op = e.isEqualExp() ? "bool" : "int";
+        errorSupplemental(ad.loc, "perhaps overload it with `%.*s %s(%s other) const {}`", op.fTuple.expand, id.toChars, other.type.toChars);
+        return ErrorExp.get();
+    }
+
+    // Classes have opCmp and opEquals defined in `Object` to fall back on already
+    if (ad1 && ad1.isStructDeclaration)
+        return suggestOverloading(e.e2, ad1);
+    if (ad2 && ad2.isStructDeclaration)
+        return suggestOverloading(e.e1, ad2);
+
+    return null;
 }
 
 /***********************************
@@ -1104,7 +1183,7 @@ Dsymbol search_function(ScopeDsymbol ad, Identifier funcid)
         Dsymbol s2 = s.toAlias();
         //printf("search_function: s2 = '%s'\n", s2.kind());
         FuncDeclaration fd = s2.isFuncDeclaration();
-        if (fd && fd.type.ty == Tfunction)
+        if (fd && fd.type.isTypeFunction())
             return fd;
         if (TemplateDeclaration td = s2.isTemplateDeclaration())
             return td;
@@ -1135,7 +1214,7 @@ bool inferForeachAggregate(Scope* sc, bool isForeach, ref Expression feaggr, out
         aggr = aggr.expressionSemantic(sc);
         aggr = resolveProperties(sc, aggr);
         aggr = aggr.optimize(WANTvalue);
-        if (!aggr.type || aggr.op == EXP.error)
+        if (!aggr.type || aggr.isErrorExp())
             return false;
         Type tab = aggr.type.toBasetype();
         switch (tab.ty)
@@ -1149,8 +1228,7 @@ bool inferForeachAggregate(Scope* sc, bool isForeach, ref Expression feaggr, out
         case Tclass:
         case Tstruct:
         {
-            AggregateDeclaration ad = (tab.ty == Tclass) ? tab.isTypeClass().sym
-                                                         : tab.isTypeStruct().sym;
+            AggregateDeclaration ad = isAggregate(tab);
             if (!sliced)
             {
                 sapply = search_function(ad, isForeach ? Id.apply : Id.applyReverse);
@@ -1240,11 +1318,11 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
         // Determine ethis for sapply
         Expression ethis;
         Type tab = fes.aggr.type.toBasetype();
-        if (tab.ty == Tclass || tab.ty == Tstruct)
+        if (tab.isTypeClass() || tab.isTypeStruct())
             ethis = fes.aggr;
         else
         {
-            assert(tab.ty == Tdelegate && fes.aggr.op == EXP.delegate_);
+            assert(tab.isTypeDelegate() && fes.aggr.isDelegateExp());
             ethis = fes.aggr.isDelegateExp().e1;
         }
 
@@ -1284,7 +1362,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
             }
             p = (*fes.parameters)[1];
         }
-        if (!p.type && tab.ty != Ttuple)
+        if (!p.type && !tab.isTypeTuple())
         {
             p.type = tab.nextOf(); // value type
             p.type = p.type.addStorageClass(p.storageClass);
@@ -1316,8 +1394,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
     case Tclass:
     case Tstruct:
     {
-        AggregateDeclaration ad = (tab.ty == Tclass) ? tab.isTypeClass().sym
-                                                     : tab.isTypeStruct().sym;
+        AggregateDeclaration ad = isAggregate(tab);
         if (fes.parameters.length == 1)
         {
             if (!p.type)
index 2e29762d010c4b4cc48c9d5be36ec77bf1561200..33472c8ac358dd416a8adc7661a59212ceb9fa85 100644 (file)
@@ -2274,7 +2274,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
      */
     private AST.Condition parseDebugCondition()
     {
-        uint level = 1;
         Identifier id = null;
         Loc loc = token.loc;
 
@@ -2290,7 +2289,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             nextToken();
             check(TOK.rightParenthesis);
         }
-        return new AST.DebugCondition(loc, mod, level, id);
+        return new AST.DebugCondition(loc, mod, id);
     }
 
     /**************************************
@@ -2319,7 +2318,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
      */
     private AST.Condition parseVersionCondition()
     {
-        uint level = 1;
         Identifier id = null;
         Loc loc;
 
@@ -2345,7 +2343,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         }
         else
             error("(condition) expected following `version`");
-        return new AST.VersionCondition(loc, mod, level, id);
+        return new AST.VersionCondition(loc, mod, id);
     }
 
     /***********************************************
@@ -5379,7 +5377,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
      */
     private void checkDanglingElse(Loc elseloc)
     {
-        if (token.value != TOK.else_ && token.value != TOK.catch_ && token.value != TOK.finally_ && lookingForElse.linnum != 0)
+        if (token.value != TOK.else_ && token.value != TOK.catch_ && token.value != TOK.finally_ && lookingForElse.isValid)
         {
             eSink.warning(elseloc, "else is dangling, add { } after condition at %s", lookingForElse.toChars());
         }
@@ -6255,12 +6253,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             if (token.value == TOK.assign)
             {
                 if (auto ds = parseDebugSpecification())
-                {
-                    if (ds.ident)
-                        eSink.error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars);
-                    else
-                        eSink.error(ds.loc, "%s `%s` level declaration must be at module level", ds.kind, ds.toPrettyChars);
-                }
+                    eSink.error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars);
+
                 break;
             }
             cond = parseDebugCondition();
@@ -6271,12 +6265,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
             if (token.value == TOK.assign)
             {
                 if (auto vs = parseVersionSpecification())
-                {
-                    if (vs.ident)
-                        eSink.error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars);
-                    else
-                        eSink.error(vs.loc, "%s `%s` level declaration must be at module level", vs.kind, vs.toPrettyChars);
-                }
+                    eSink.error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars);
+
                 break;
             }
             cond = parseVersionCondition();
index 6bbc1a9b28eb2ed98be2ae8ce28339f3b330346c..00dc606b4fa6149786a64b7e3be48076046ebb49 100644 (file)
@@ -2089,7 +2089,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
 
         // Make a copy of all the cases so that qsort doesn't scramble the actual
         // data we pass to codegen (the order of the cases in the switch).
-        CaseStatements *csCopy = (*ss.cases).copy();
+        CaseStatementscsCopy = (*ss.cases).copy();
 
         if (numcases)
         {
index e751eadb5aeb7066c77b9045b732e19e0eaa171d..cdb1c852f4b6531e2103bc889f8db1a4d6c72d5f 100644 (file)
@@ -79,7 +79,6 @@ public:
     bool overloadInsert(Dsymbol *s) override;
     bool hasStaticCtorOrDtor() override;
     const char *kind() const override;
-    const char *toChars() const override;
 
     Visibility visible() override;
 
@@ -272,7 +271,6 @@ public:
     Dsymbol *toAlias() override final;   // resolve real symbol
     const char *kind() const override;
     bool oneMember(Dsymbol *&ps, Identifier *ident) override;
-    const char *toChars() const override;
     const char* toPrettyCharsHelper() override final;
     Identifier *getIdent() override final;
 
@@ -292,7 +290,6 @@ public:
     const char *kind() const override;
     bool oneMember(Dsymbol *&ps, Identifier *ident) override;
     bool hasPointers() override;
-    const char *toChars() const override;
 
     TemplateMixin *isTemplateMixin() override { return this; }
     void accept(Visitor *v) override { v->visit(this); }
index a69edef2c28af153ff602db6bb50c0d971d5a0fa..48c4297b6b42df2dcbc2269df8452bb64e9f0852 100644 (file)
@@ -1425,7 +1425,7 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat
                             Expression e;
                             Type t;
                             Dsymbol s;
-                            Scope *sco;
+                            Scopesco;
 
                             const errors = global.startGagging();
                             /* ref: https://issues.dlang.org/show_bug.cgi?id=11118
index 65d267f155a3179ccacc4221992acbcb56fc4bb5..6d21d67befc5b238bf099ebe1126ec766710836e 100644 (file)
@@ -3128,7 +3128,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                 else
                 {
                     /* struct S { int a; };
-                     * struct S *s;
+                     * struct Ss;
                      */
                 }
                 mtype.resolved = sd.type;
@@ -3159,14 +3159,14 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                      mtype.tok == TOK.struct_ && s.isStructDeclaration())
             {
                 /* struct S;
-                 * { struct S *s; }
+                 * { struct Ss; }
                  */
                 mtype.resolved = s.isStructDeclaration().type;
             }
             else
             {
                 /* union S;
-                 * { struct S *s; }
+                 * { struct Ss; }
                  */
                 .error(mtype.loc, "redeclaring `%s %s` as `%s %s`",
                     s.kind(), s.toChars(), Token.toChars(mtype.tok), mtype.id.toChars());
@@ -7609,6 +7609,18 @@ bool checkRetType(TypeFunction tf, const ref Loc loc)
     return false;
 }
 
+/// Returns: whether `t` is a struct/class/enum without a body
+bool isOpaqueType(Type t)
+{
+    if (auto te = t.isTypeEnum())
+        return te.sym.members is null;
+    if (auto ts = t.isTypeStruct())
+        return ts.sym.members is null;
+    if (auto tc = t.isTypeClass())
+        return tc.sym.members is null;
+    return false;
+}
+
 
 /******************************* Private *****************************************/
 
index dd83fd67dff0338a1de6f594bc05e825adba151a..7913c96c3f895219f9c358ff8206d89e9eccb910 100644 (file)
 class DebugSymbol final : public Dsymbol
 {
 public:
-    unsigned level;
-
     DebugSymbol *syntaxCopy(Dsymbol *) override;
 
-    const char *toChars() const override;
     const char *kind() const override;
     DebugSymbol *isDebugSymbol() override;
     void accept(Visitor *v) override { v->visit(this); }
@@ -28,11 +25,8 @@ public:
 class VersionSymbol final : public Dsymbol
 {
 public:
-    unsigned level;
-
     VersionSymbol *syntaxCopy(Dsymbol *) override;
 
-    const char *toChars() const override;
     const char *kind() const override;
     VersionSymbol *isVersionSymbol() override;
     void accept(Visitor *v) override { v->visit(this); }
index f04ec33320a480d39c334724228fa418505c69d2..da794ea5f2be0e1552be313422992ac38aa56aad 100644 (file)
@@ -1622,7 +1622,7 @@ public:
        if (dve->e1->op == EXP::structLiteral)
          {
            StructLiteralExp *sle = dve->e1->isStructLiteralExp ();
-           sle->useStaticInit = false;
+           sle->useStaticInit (false);
          }
 
        FuncDeclaration *fd = dve->var->isFuncDeclaration ();
@@ -2773,7 +2773,7 @@ public:
 
     /* Building sinit trees are delayed until after frontend semantic
        processing has complete.  Build the static initializer now.  */
-    if (e->useStaticInit && !this->constp_ && !e->sd->isCsymbol ())
+    if (e->useStaticInit () && !this->constp_ && !e->sd->isCsymbol ())
       {
        tree init = aggregate_initializer_decl (e->sd);
 
@@ -2841,7 +2841,7 @@ public:
        tree field = get_symbol_decl (e->sd->vthis);
        tree value = build_vthis (e->sd);
        CONSTRUCTOR_APPEND_ELT (ve, field, value);
-       gcc_assert (e->useStaticInit == false);
+       gcc_assert (e->useStaticInit () == false);
       }
 
     /* Build a constructor in the correct shape of the aggregate type.  */
index 7b79cf0666fc4fee99c1b1d4e75f2b1ac07d0ed0..9bf5d96cb247f13b6855487d0962c4842936d232 100644 (file)
@@ -1,9 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/b17285.d(14): Error: type `ONE` has no value
-fail_compilation/b17285.d(14): Error: type `TWO` has no value
-fail_compilation/b17285.d(14): Error: cannot implicitly convert expression `ONE` of type `b17285.ONE` to `int`
+fail_compilation/b17285.d(15): Error: type `ONE` has no value
+fail_compilation/b17285.d(15):        perhaps use `ONE.init`
+fail_compilation/b17285.d(15): Error: type `TWO` has no value
+fail_compilation/b17285.d(15): Error: cannot implicitly convert expression `ONE` of type `b17285.ONE` to `int`
 ---
 */
 
index 60828bef17a7b6234fc30bd59ad5d10d74203579..574b29aae38c76d7fd31271890d3a6c475098b28 100644 (file)
@@ -19,11 +19,11 @@ void main()
 {
     T2!().F x = T1!().F();
 }
-
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/bug9631.d(41): Error: incompatible types for `(x) == (y)`: `bug9631.S` and `bug9631.tem!().S`
+fail_compilation/bug9631.d(41): Error: no operator `==` for type `S`
+fail_compilation/bug9631.d(30):        perhaps overload it with `bool opEquals(S other) const {}`
 ---
 */
 
index f8ebc37f80193724aeaa6e9fc069e43e57ee7dc4..83e700632a8c89366d0c1bc73e937b0b3c541405 100644 (file)
 REQUIRED_ARGS:
 TEST_OUTPUT:
 ---
-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`
+fail_compilation/dep_d1_ops.d(281): Error: operator `+` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : "+")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(282): Error: operator `+` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinaryRight(string op : "+")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(283): Error: operator `-` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : "-")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(284): Error: operator `-` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinaryRight(string op : "-")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(285): Error: operator `*` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : "*")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(286): Error: operator `*` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinaryRight(string op : "*")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(287): Error: operator `/` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : "/")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(288): Error: operator `/` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinaryRight(string op : "/")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(289): Error: operator `%` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : "%")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(290): Error: operator `%` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinaryRight(string op : "%")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(292): Error: operator `&` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : "&")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(293): Error: operator `|` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : "|")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(294): Error: operator `^` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : "^")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(296): Error: operator `<<` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : "<<")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(297): Error: operator `<<` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinaryRight(string op : "<<")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(298): Error: operator `>>` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : ">>")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(299): Error: operator `>>` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinaryRight(string op : ">>")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(300): Error: operator `>>>` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : ">>>")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(301): Error: operator `>>>` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinaryRight(string op : ">>>")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(303): Error: operator `~` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : "~")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(304): Error: operator `~` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinaryRight(string op : "~")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(306): Error: operator `+` is not defined for `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opUnary(string op : "+")() {}`
+fail_compilation/dep_d1_ops.d(307): Error: operator `-` is not defined for `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opUnary(string op : "-")() {}`
+fail_compilation/dep_d1_ops.d(308): Error: operator `~` is not defined for `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opUnary(string op : "~")() {}`
+fail_compilation/dep_d1_ops.d(309): Error: operator `++` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opUnary(string op : "++")() {}` or `auto opOpAssign(string op : "+")(int) {}`
+fail_compilation/dep_d1_ops.d(310): Error: operator `--` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opUnary(string op : "--")() {}` or `auto opOpAssign(string op : "-")(int) {}`
+fail_compilation/dep_d1_ops.d(311): Error: operator `*` is not defined for `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opUnary(string op : "*")() {}`
+fail_compilation/dep_d1_ops.d(313): Error: operator `in` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinary(string op : "in")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(314): Error: operator `in` is not defined for type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps overload the operator with `auto opBinaryRight(string op : "in")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(316): Error: operator `+=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : "+")(int) {}`
+fail_compilation/dep_d1_ops.d(317): Error: operator `-=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : "-")(int) {}`
+fail_compilation/dep_d1_ops.d(318): Error: operator `*=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : "*")(int) {}`
+fail_compilation/dep_d1_ops.d(319): Error: operator `/=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : "/")(int) {}`
+fail_compilation/dep_d1_ops.d(320): Error: operator `%=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : "%")(int) {}`
+fail_compilation/dep_d1_ops.d(321): Error: operator `&=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : "&")(int) {}`
+fail_compilation/dep_d1_ops.d(322): Error: operator `|=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : "|")(int) {}`
+fail_compilation/dep_d1_ops.d(323): Error: operator `^=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : "^")(int) {}`
+fail_compilation/dep_d1_ops.d(324): Error: operator `<<=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : "<<")(int) {}`
+fail_compilation/dep_d1_ops.d(325): Error: operator `>>=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : ">>")(int) {}`
+fail_compilation/dep_d1_ops.d(326): Error: operator `>>>=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : ">>>")(int) {}`
+fail_compilation/dep_d1_ops.d(327): Error: operator `~=` not supported for `s` of type `S`
+fail_compilation/dep_d1_ops.d(174):        perhaps implement `auto opOpAssign(string op : "~")(int) {}`
+fail_compilation/dep_d1_ops.d(331): Error: operator `+` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : "+")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(332): Error: operator `+` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinaryRight(string op : "+")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(333): Error: operator `-` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : "-")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(334): Error: operator `-` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinaryRight(string op : "-")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(335): Error: operator `*` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : "*")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(336): Error: operator `*` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinaryRight(string op : "*")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(337): Error: operator `/` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : "/")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(338): Error: operator `/` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinaryRight(string op : "/")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(339): Error: operator `%` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : "%")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(340): Error: operator `%` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinaryRight(string op : "%")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(342): Error: operator `&` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : "&")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(343): Error: operator `|` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : "|")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(344): Error: operator `^` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : "^")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(346): Error: operator `<<` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : "<<")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(347): Error: operator `<<` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinaryRight(string op : "<<")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(348): Error: operator `>>` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : ">>")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(349): Error: operator `>>` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinaryRight(string op : ">>")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(350): Error: operator `>>>` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : ">>>")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(351): Error: operator `>>>` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinaryRight(string op : ">>>")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(353): Error: operator `~` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : "~")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(354): Error: operator `~` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinaryRight(string op : "~")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(356): Error: operator `+` is not defined for `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opUnary(string op : "+")() {}`
+fail_compilation/dep_d1_ops.d(357): Error: operator `-` is not defined for `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opUnary(string op : "-")() {}`
+fail_compilation/dep_d1_ops.d(358): Error: operator `~` is not defined for `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opUnary(string op : "~")() {}`
+fail_compilation/dep_d1_ops.d(359): Error: operator `++` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opUnary(string op : "++")() {}` or `auto opOpAssign(string op : "+")(int) {}`
+fail_compilation/dep_d1_ops.d(360): Error: operator `--` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opUnary(string op : "--")() {}` or `auto opOpAssign(string op : "-")(int) {}`
+fail_compilation/dep_d1_ops.d(361): Error: operator `*` is not defined for `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opUnary(string op : "*")() {}`
+fail_compilation/dep_d1_ops.d(363): Error: operator `in` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinary(string op : "in")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(364): Error: operator `in` is not defined for type `dep_d1_ops.C`
+fail_compilation/dep_d1_ops.d(225):        perhaps overload the operator with `auto opBinaryRight(string op : "in")(int rhs) {}`
+fail_compilation/dep_d1_ops.d(366): Error: operator `+=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : "+")(int) {}`
+fail_compilation/dep_d1_ops.d(367): Error: operator `-=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : "-")(int) {}`
+fail_compilation/dep_d1_ops.d(368): Error: operator `*=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : "*")(int) {}`
+fail_compilation/dep_d1_ops.d(369): Error: operator `/=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : "/")(int) {}`
+fail_compilation/dep_d1_ops.d(370): Error: operator `%=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : "%")(int) {}`
+fail_compilation/dep_d1_ops.d(371): Error: operator `&=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : "&")(int) {}`
+fail_compilation/dep_d1_ops.d(372): Error: operator `|=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : "|")(int) {}`
+fail_compilation/dep_d1_ops.d(373): Error: operator `^=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : "^")(int) {}`
+fail_compilation/dep_d1_ops.d(374): Error: operator `<<=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : "<<")(int) {}`
+fail_compilation/dep_d1_ops.d(375): Error: operator `>>=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : ">>")(int) {}`
+fail_compilation/dep_d1_ops.d(376): Error: operator `>>>=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : ">>>")(int) {}`
+fail_compilation/dep_d1_ops.d(377): Error: operator `~=` not supported for `c` of type `C`
+fail_compilation/dep_d1_ops.d(225):        perhaps implement `auto opOpAssign(string op : "~")(int) {}`
+fail_compilation/dep_d1_ops.d(386): Error: operator `~` is not defined for `NoDeprecation`
+fail_compilation/dep_d1_ops.d(390):        perhaps overload the operator with `auto opUnary(string op : "~")() {}`
 ---
 */
 
index 3e9535ab421096ff331155bf546b76bc88e3e59c..a87d5bf833a26bca23f64eaab3352610592b7736 100644 (file)
@@ -1,13 +1,15 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag12063.d(19): Error: cannot check `diag12063.Bar.b` value for overflow
-fail_compilation/diag12063.d(16): Error: no property `max` for type `Foo`, perhaps `import std.algorithm;` is needed?
-fail_compilation/diag12063.d(19): Error: cannot generate value for `diag12063.Bar.b`
-fail_compilation/diag12063.d(19): Error: incompatible types for `(Foo()) + (1)`: `Bar` and `int`
-fail_compilation/diag12063.d(29): Error: cannot check `diag12063.b` value for overflow
-fail_compilation/diag12063.d(29): Error: incompatible types for `(S()) == (1)`: `S` and `int`
-fail_compilation/diag12063.d(38): Error: enum member `diag12063.d` initialization with `__anonymous.c+1` causes overflow for type `Q`
+fail_compilation/diag12063.d(21): Error: cannot check `diag12063.Bar.b` value for overflow
+fail_compilation/diag12063.d(18): Error: no property `max` for type `Foo`, perhaps `import std.algorithm;` is needed?
+fail_compilation/diag12063.d(21): Error: cannot generate value for `diag12063.Bar.b`
+fail_compilation/diag12063.d(21): Error: operator `+` is not defined for type `Bar`
+fail_compilation/diag12063.d(16):        perhaps overload the operator with `auto opBinary(string op : "+")(int rhs) {}`
+fail_compilation/diag12063.d(31): Error: cannot check `diag12063.b` value for overflow
+fail_compilation/diag12063.d(31): Error: no operator `==` for type `S`
+fail_compilation/diag12063.d(24):        perhaps overload it with `bool opEquals(int other) const {}`
+fail_compilation/diag12063.d(40): Error: enum member `diag12063.d` initialization with `__anonymous.c+1` causes overflow for type `Q`
 ---
 */
 
index 2808606bdcae852485f7710dc73893f304e885a4..40b99ab39d09baeef3115a1e4e1e075109bb673d 100644 (file)
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag13320.d(13): Error: `f` is not a scalar, it is a `Foo`
+fail_compilation/diag13320.d(14): Error: operator `++` not supported for `f` of type `Foo`
+fail_compilation/diag13320.d(9):        perhaps implement `auto opUnary(string op : "++")() {}` or `auto opOpAssign(string op : "+")(int) {}`
 ---
 */
 
index 63b4b3c5279509b57f3ae68e1b48f39c6544bca2..f3757954d4a39134f7825c6be0c2c030c594376e 100644 (file)
@@ -1,8 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/diag16499.d(22): Error: incompatible types for `(2) in (foo)`: `int` and `A`
-fail_compilation/diag16499.d(24): Error: incompatible types for `(1.0) in (bar)`: `double` and `B`
+fail_compilation/diag16499.d(24): Error: operator `in` is not defined for type `A`
+fail_compilation/diag16499.d(11):        perhaps overload the operator with `auto opBinaryRight(string op : "in")(int rhs) {}`
+fail_compilation/diag16499.d(26): Error: operator `in` is not defined for type `B`
+fail_compilation/diag16499.d(12):        perhaps overload the operator with `auto opBinaryRight(string op : "in")(double rhs) {}`
 ---
 */
 
index 9f38cb04069b84d308f6b22176672695ab05b029..e496f87043e4c04d5324b68d253f9c8fc7aadfb3 100644 (file)
@@ -1,12 +1,12 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail10964.d(28): Error: function `fail10964.S.__postblit` is not `nothrow`
-fail_compilation/fail10964.d(29): Error: function `fail10964.S.__postblit` is not `nothrow`
-fail_compilation/fail10964.d(30): Error: function `fail10964.S.__postblit` is not `nothrow`
-fail_compilation/fail10964.d(33): Error: function `fail10964.S.__postblit` is not `nothrow`
-fail_compilation/fail10964.d(34): Error: function `fail10964.S.__postblit` is not `nothrow`
-fail_compilation/fail10964.d(35): Error: function `fail10964.S.__postblit` is not `nothrow`
+fail_compilation/fail10964.d(28): Error: function `fail10964.S.this(this)` is not `nothrow`
+fail_compilation/fail10964.d(29): Error: function `fail10964.S.this(this)` is not `nothrow`
+fail_compilation/fail10964.d(30): Error: function `fail10964.S.this(this)` is not `nothrow`
+fail_compilation/fail10964.d(33): Error: function `fail10964.S.this(this)` is not `nothrow`
+fail_compilation/fail10964.d(34): Error: function `fail10964.S.this(this)` is not `nothrow`
+fail_compilation/fail10964.d(35): Error: function `fail10964.S.this(this)` is not `nothrow`
 fail_compilation/fail10964.d(22): Error: function `fail10964.foo` may throw but is marked as `nothrow`
 ---
 */
index a436197d0477e3d44c83ec424662546f0213453b..dd793e108a547b7bb0f3265e05c78ecb6d9742d3 100644 (file)
@@ -1,36 +1,24 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail10968.d(43): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(43): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(31):        `fail10968.SA.__postblit` is declared here
-fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(44): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(31):        `fail10968.SA.__postblit` is declared here
-fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.arrayassign._d_arraysetassign!(SA[], SA)._d_arraysetassign`
-$p:druntime/import/core/internal/array/arrayassign.d$($n$):        which calls `core.lifetime.copyEmplace!(SA, SA).copyEmplace`
-$p:druntime/import/core/lifetime.d$($n$):        which calls `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(45): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(45): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(31):        `fail10968.SA.__postblit` is declared here
-fail_compilation/fail10968.d(45): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.arrayassign._d_arrayassign_l!(SA[], SA)._d_arrayassign_l`
-$p:druntime/import/core/internal/array/arrayassign.d$-mixin-$n$($n$):        which calls `core.lifetime.copyEmplace!(SA, SA).copyEmplace`
-$p:druntime/import/core/lifetime.d$($n$):        which calls `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(48): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(48): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(31):        `fail10968.SA.__postblit` is declared here
-fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(49): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(31):        `fail10968.SA.__postblit` is declared here
-fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arraysetctor!(SA[], SA)._d_arraysetctor`
-$p:druntime/import/core/internal/array/construction.d$($n$):        which calls `core.lifetime.copyEmplace!(SA, SA).copyEmplace`
-$p:druntime/import/core/lifetime.d$($n$):        which calls `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(50): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(50): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
-fail_compilation/fail10968.d(31):        `fail10968.SA.__postblit` is declared here
-fail_compilation/fail10968.d(50): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arrayctor!(SA[], SA)._d_arrayctor`
-$p:druntime/import/core/internal/array/construction.d$($n$):        which calls `core.lifetime.copyEmplace!(SA, SA).copyEmplace`
-$p:druntime/import/core/lifetime.d$($n$):        which calls `fail10968.SA.__postblit`
+fail_compilation/fail10968.d(43): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(43): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(31):        `fail10968.SA.this(this)` is declared here
+fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(44): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(31):        `fail10968.SA.this(this)` is declared here
+fail_compilation/fail10968.d(45): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(45): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(31):        `fail10968.SA.this(this)` is declared here
+fail_compilation/fail10968.d(48): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(48): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(31):        `fail10968.SA.this(this)` is declared here
+fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(49): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(31):        `fail10968.SA.this(this)` is declared here
+fail_compilation/fail10968.d(50): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(50): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
+fail_compilation/fail10968.d(31):        `fail10968.SA.this(this)` is declared here
 ---
 */
 
index 28df93a1997588d5e53c70eabaff112f2b72ce99..52c4ae5e6ccfa4409d7b66315a69fb58b1923487 100644 (file)
@@ -1,14 +1,14 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail18143.d(20): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
-fail_compilation/fail18143.d(21): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
-fail_compilation/fail18143.d(25): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
-fail_compilation/fail18143.d(26): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
-fail_compilation/fail18143.d(35): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
-fail_compilation/fail18143.d(36): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
-fail_compilation/fail18143.d(40): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
-fail_compilation/fail18143.d(41): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
+fail_compilation/fail18143.d(20): Error: cannot modify member variable `fail18143.S.a` in contract
+fail_compilation/fail18143.d(21): Error: cannot modify member variable `fail18143.S.a` in contract
+fail_compilation/fail18143.d(25): Error: cannot modify member variable `fail18143.S.a` in contract
+fail_compilation/fail18143.d(26): Error: cannot modify member variable `fail18143.S.a` in contract
+fail_compilation/fail18143.d(35): Error: cannot modify member variable `fail18143.C.a` in contract
+fail_compilation/fail18143.d(36): Error: cannot modify member variable `fail18143.C.a` in contract
+fail_compilation/fail18143.d(40): Error: cannot modify member variable `fail18143.C.a` in contract
+fail_compilation/fail18143.d(41): Error: cannot modify member variable `fail18143.C.a` in contract
 ---
 */
 
index 830a6792ad2dda522e0d54c05c5ffd6bb7a02b30..f2899bdb3377ff71294f77f073dfe1ab1dc18d9f 100644 (file)
@@ -1,15 +1,19 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail18985.d(16): Error: `foo` is not a scalar, it is a `object.Object`
-fail_compilation/fail18985.d(17): Error: `bar` is not a scalar, it is a `shared(Object)`
+fail_compilation/fail18985.d(20): Error: operator `+=` not supported for `foo` of type `C`
+fail_compilation/fail18985.d(13):        perhaps implement `auto opOpAssign(string op : "+")(int) {}`
+fail_compilation/fail18985.d(21): Error: operator `+=` not supported for `bar` of type `C`
+fail_compilation/fail18985.d(13):        perhaps implement `auto opOpAssign(string op : "+")(int) {}`
 ---
 */
 
 // https://issues.dlang.org/show_bug.cgi?id=18985
 
-Object foo;
-shared Object bar;
+class C {}
+
+C foo;
+shared C bar;
 
 void main()
 {
index 4528d365da87050ffb83203c3896466e05913269..dbd4333fc633712ad36357c548e6d1834078db1b 100644 (file)
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail20.d(16): Error: need member function `opCmp()` for struct `FOO` to compare
+fail_compilation/fail20.d(17): Error: no operator `<` for type `FOO`
+fail_compilation/fail20.d(11):        perhaps overload it with `int opCmp(FOO other) const {}`
 ---
 */
 
index 0f76e315ac741593c80c03fa18944c34374bdfce..3acf84fb8f71849ede007297bb34eabcc6ae8c22 100644 (file)
@@ -2,9 +2,9 @@
 TEST_OUTPUT:
 ---
 fail_compilation/fail20616.d(16): Error: undefined identifier `$`
-fail_compilation/fail20616.d(16):        Aggregate declaration 'X()' does not define 'opDollar'
+fail_compilation/fail20616.d(13):        perhaps define `opDollar` for `X`
 fail_compilation/fail20616.d(18): Error: undefined identifier `$`
-fail_compilation/fail20616.d(18):        Aggregate declaration 'b' does not define 'opDollar'
+fail_compilation/fail20616.d(13):        perhaps define `opDollar` for `X`
 ---
 */
 module fail20616;
index 3bb25dd0fae483eeaf2e75994a46c0b2bc1ecaf8..f74b814c187fd570fc939475b75dfb2569454f13 100644 (file)
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail297.d(30): Error: operator `+` is not defined for `Bar()` of type `Bar`
+fail_compilation/fail297.d(31): Error: operator `+` is not defined for type `Bar`
+fail_compilation/fail297.d(25):        perhaps overload the operator with `auto opBinary(string op : "+")(const(Bar) rhs) {}`
 ---
 */
 
index 1c40c4f93c7696015fb0dfbc05b602ce4ae4be34..bcc9614db65612a84de5ec5956156c9358d2d75d 100644 (file)
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail3.d(41): Error: operator `+` is not defined for `a` of type `vec2`
+fail_compilation/fail3.d(42): Error: operator `+` is not defined for type `vec2`
+fail_compilation/fail3.d(13):        perhaps overload the operator with `auto opBinary(string op : "+")(vec2 rhs) {}`
 ---
 */
 
index 2f9bdf742b7e350451e84fa51275144d0a58d436..0062798f312a81a73ab39722a8591358972cc2d3 100644 (file)
@@ -1,9 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail3672.d(28): Error: read-modify-write operations are not allowed for `shared` variables
-fail_compilation/fail3672.d(28):        Use `core.atomic.atomicOp!"+="(*p, 1)` instead
-fail_compilation/fail3672.d(32): Error: none of the `opOpAssign` overloads of `SF` are callable for `*sfp` of type `shared(SF)`
+fail_compilation/fail3672.d(29): Error: read-modify-write operations are not allowed for `shared` variables
+fail_compilation/fail3672.d(29):        Use `core.atomic.atomicOp!"+="(*p, 1)` instead
+fail_compilation/fail3672.d(33): Error: template `opOpAssign` is not callable using argument types `!("+")(int) shared`
+fail_compilation/fail3672.d(13):        Candidate is: `opOpAssign(string op, T)(T rhs)`
 ---
 */
 
index 3aedfc31f3ea111068aa20da610e5ea543070a58..e7af18127edcd404cd0b166ac3ef928b1d128548 100644 (file)
@@ -1,9 +1,9 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail4421.d(16): Error: function `fail4421.U1.__postblit` destructors, postblits and invariants are not allowed in union `U1`
+fail_compilation/fail4421.d(16): Error: function `fail4421.U1.this(this)` destructors, postblits and invariants are not allowed in union `U1`
 fail_compilation/fail4421.d(17): Error: destructor `fail4421.U1.~this` destructors, postblits and invariants are not allowed in union `U1`
-fail_compilation/fail4421.d(18): Error: function `fail4421.U1.__invariant1` destructors, postblits and invariants are not allowed in union `U1`
+fail_compilation/fail4421.d(18): Error: function `fail4421.U1.invariant` destructors, postblits and invariants are not allowed in union `U1`
 ---
 
 
index a21fbb78f2f0a0ff3503b6e1c760be341c7cc91d..b707a568b339f381f7a8e08254fb34a1053df955 100644 (file)
@@ -1,8 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail6107.d(10): Error: variable `fail6107.Foo.__ctor` is not a constructor; identifiers starting with `__` are reserved for the implementation
-fail_compilation/fail6107.d(14): Error: variable `fail6107.Bar.__ctor` is not a constructor; identifiers starting with `__` are reserved for the implementation
+fail_compilation/fail6107.d(12): Error: variable name `__ctor` is not allowed
+fail_compilation/fail6107.d(12):        identifiers starting with `__` are reserved for internal use
+fail_compilation/fail6107.d(16): Error: variable name `__ctor` is not allowed
+fail_compilation/fail6107.d(16):        identifiers starting with `__` are reserved for internal use
 ---
 */
 struct Foo
index 001c7d75443c4f6160ae3d4b51d76558cfc4d34e..8237fd1cb5134d3d6183e490dfb2d2467fccf6ea 100644 (file)
@@ -9,12 +9,12 @@ fail_compilation/fail7848.d(21):        `fail7848.func` is declared here
 fail_compilation/fail7848.d(27): Error: `@nogc` function `fail7848.C.__unittest_L25_C30` cannot call non-@nogc function `fail7848.func`
 fail_compilation/fail7848.d(27): Error: function `fail7848.func` is not `nothrow`
 fail_compilation/fail7848.d(25): Error: function `fail7848.C.__unittest_L25_C30` may throw but is marked as `nothrow`
-fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.__invariant0` cannot call impure function `fail7848.func`
-fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.__invariant0` cannot call `@system` function `fail7848.func`
+fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.invariant` cannot call impure function `fail7848.func`
+fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.invariant` cannot call `@system` function `fail7848.func`
 fail_compilation/fail7848.d(21):        `fail7848.func` is declared here
-fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.__invariant0` cannot call non-@nogc function `fail7848.func`
+fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.invariant` cannot call non-@nogc function `fail7848.func`
 fail_compilation/fail7848.d(32): Error: function `fail7848.func` is not `nothrow`
-fail_compilation/fail7848.d(30): Error: function `fail7848.C.__invariant0` may throw but is marked as `nothrow`
+fail_compilation/fail7848.d(30): Error: function `fail7848.C.invariant` may throw but is marked as `nothrow`
 ---
 */
 
index c20541392e6ac7700b16ba092831f4f6e476d50c..6f9868a48b69b1949bebba553c3662978d442c7d 100644 (file)
@@ -6,7 +6,7 @@ fail_compilation/fail_arrayexp.d(25): Error: cannot use `[]` operator on express
 fail_compilation/fail_arrayexp.d(26): Error: static array of `const(int)[]` with multiple lengths not allowed
 fail_compilation/fail_arrayexp.d(27): Error: only one index allowed to index `string`
 fail_compilation/fail_arrayexp.d(28): Error: no `[]` operator overload for type `U`
-fail_compilation/fail_arrayexp.d(16):        `fail_arrayexp.U` declared here
+fail_compilation/fail_arrayexp.d(16):        perhaps define `auto opIndex() {}` for `fail_arrayexp.U`
 fail_compilation/fail_arrayexp.d(29): Error: only one index allowed to index `(int, string)`
 ---
 */
@@ -29,3 +29,24 @@ void test19534() // https://issues.dlang.org/show_bug.cgi?id=19534
     auto t = agg[];
     auto u = getTuple!(int, string)[1, 2];
 }
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail_arrayexp.d(49): Error: no `[3.."4"]` operator overload for type `S`
+fail_compilation/fail_arrayexp.d(42):        perhaps define `auto opSlice(int lower, string upper) {}` for `fail_arrayexp.S`
+fail_compilation/fail_arrayexp.d(50): Error: no `[]` operator overload for type `S`
+fail_compilation/fail_arrayexp.d(42):        perhaps define `auto opIndex(int, string, char) {}` for `fail_arrayexp.S`
+---
+*/
+
+struct S
+{
+}
+
+void testSlice()
+{
+    S s;
+    const b = s[3 .. "4"];
+    const c = s[3, "4", 'c'];
+}
index 368755ae78cb8233e31157934af213e0e23c4413..1a0c9e1ac158f752adf9325aa3649a18b00c86a8 100644 (file)
@@ -4,33 +4,33 @@
 TEST_OUTPUT:
 ---
 fail_compilation/fail_opover.d(39): Error: no `[]` operator overload for type `object.Object`
-$p:object.d$(110):        `object.Object` declared here
+$p:object.d$(110):        perhaps define `auto opIndex() {}` for `object.Object`
 fail_compilation/fail_opover.d(43): Error: no `[]` operator overload for type `TestS`
-fail_compilation/fail_opover.d(41):        `fail_opover.test1.TestS` declared here
+fail_compilation/fail_opover.d(41):        perhaps define `auto opIndex() {}` for `fail_opover.test1.TestS`
 fail_compilation/fail_opover.d(55): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
+fail_compilation/fail_opover.d(48):        perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
 fail_compilation/fail_opover.d(56): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
-fail_compilation/fail_opover.d(57): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
+fail_compilation/fail_opover.d(48):        perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
+fail_compilation/fail_opover.d(57): Error: no `[1..2]` operator overload for type `S`
+fail_compilation/fail_opover.d(48):        perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
 fail_compilation/fail_opover.d(58): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
+fail_compilation/fail_opover.d(48):        perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
 fail_compilation/fail_opover.d(59): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
-fail_compilation/fail_opover.d(60): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
+fail_compilation/fail_opover.d(48):        perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
+fail_compilation/fail_opover.d(60): Error: no `[1..2]` operator overload for type `S`
+fail_compilation/fail_opover.d(48):        perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
 fail_compilation/fail_opover.d(61): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
+fail_compilation/fail_opover.d(48):        perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
 fail_compilation/fail_opover.d(62): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
-fail_compilation/fail_opover.d(63): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
+fail_compilation/fail_opover.d(48):        perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
+fail_compilation/fail_opover.d(63): Error: no `[1..2]` operator overload for type `S`
+fail_compilation/fail_opover.d(48):        perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
 fail_compilation/fail_opover.d(64): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
+fail_compilation/fail_opover.d(48):        perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
 fail_compilation/fail_opover.d(65): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
-fail_compilation/fail_opover.d(66): Error: no `[]` operator overload for type `S`
-fail_compilation/fail_opover.d(48):        `fail_opover.test2.S` declared here
+fail_compilation/fail_opover.d(48):        perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
+fail_compilation/fail_opover.d(66): Error: no `[1..2]` operator overload for type `S`
+fail_compilation/fail_opover.d(48):        perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
 ---
 */
 void test1()
index 3bc3c7d50285de8bd5e23187e05ce0e048e93c3b..8fa2e6b1a8b858af452f520a3d14723ba43a8cbf 100644 (file)
@@ -1,9 +1,10 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice10624.d(38): Error: need member function `opCmp()` for struct `Tuple!(Msg)` to compare
-fail_compilation/ice10624.d(48): Error: template instance `ice10624.Variant.handler!(Tuple!(Msg))` error instantiating
-fail_compilation/ice10624.d(21):        instantiated from here: `opAssign!(Tuple!(Msg))`
+fail_compilation/ice10624.d(39): Error: no operator `<` for type `Tuple`
+fail_compilation/ice10624.d(13):        perhaps overload it with `int opCmp(Tuple!(Msg) other) const {}`
+fail_compilation/ice10624.d(49): Error: template instance `ice10624.Variant.handler!(Tuple!(Msg))` error instantiating
+fail_compilation/ice10624.d(22):        instantiated from here: `opAssign!(Tuple!(Msg))`
 ---
 */
 
index 03763f7c18a535857b0619ea8f88744bbfa9c70e..5f27ce45c1dea939ce3a2523af123a787fcb0f2b 100644 (file)
@@ -1,7 +1,7 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice12902.d(20): Error: variable `ice12902.main.__dollar` - type `void` is inferred from initializer `s.opDollar()`, and variables cannot be of type `void`
+fail_compilation/ice12902.d(20): Error: variable `ice12902.main.$` - type `void` is inferred from initializer `s.opDollar()`, and variables cannot be of type `void`
 fail_compilation/ice12902.d(20): Error: expression `s.opDollar()` is `void` and has no value
 ---
 */
index 7360bc534f2a8f9ce5aa57562c49301874a31814..b10e63987cf1d2eab0522765115fbe4bfe9d27f0 100644 (file)
@@ -2,7 +2,8 @@
 /*
 TEST_OUTPUT:
 ----
-fail_compilation/ice9545.d(13): Error: type `int` has no value
+fail_compilation/ice9545.d(14): Error: type `int` has no value
+fail_compilation/ice9545.d(14):        perhaps use `int.init`
 ----
 */
 
index 3065bdb8e79a5387301ac6223eb7c8184ad89492..1c9803d21eee3a797e64249af14c1e66ea4ef82c 100644 (file)
@@ -1,7 +1,8 @@
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/operator_undefined.d(19): Error: operator `-` is not defined for `toJson(2)` of type `Json`
+fail_compilation/operator_undefined.d(20): Error: operator `-` is not defined for `Json`
+fail_compilation/operator_undefined.d(11):        perhaps overload the operator with `auto opUnary(string op : "-")() {}`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20763.d b/gcc/testsuite/gdc.test/fail_compilation/test20763.d
new file mode 100644 (file)
index 0000000..786f8d8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+REQUIRED_ARGS: -de
+
+TEST_OUTPUT:
+---
+fail_compilation/test20763.d(25): Deprecation: type `ulong` has no value
+fail_compilation/test20763.d(25):        perhaps use `ulong.init`
+fail_compilation/test20763.d(26): Deprecation: type `ulong` has no value
+fail_compilation/test20763.d(26):        perhaps use `ulong.init`
+fail_compilation/test20763.d(27): Error: type `ulong` has no value
+fail_compilation/test20763.d(27):        perhaps use `ulong.init`
+fail_compilation/test20763.d(28): Error: type `ulong` has no value
+fail_compilation/test20763.d(28):        perhaps use `ulong.init`
+fail_compilation/test20763.d(29): Error: type `ulong` has no value
+fail_compilation/test20763.d(29):        perhaps use `ulong.init`
+fail_compilation/test20763.d(30): Error: type `ulong` has no value
+fail_compilation/test20763.d(30):        perhaps use `ulong.init`
+---
+*/
+
+// https://github.com/dlang/dmd/issues/20763
+void test()
+{
+    alias I = ulong;
+    alias U0 = typeof(I + 1u);
+    alias U1 = typeof(1 - I);
+    alias U2 = typeof(+I);
+    alias U3 = typeof(I * 1);
+    alias U4 = typeof(I << 1);
+    alias U5 = typeof(I | 1);
+}
index 25c83f5142d6a8029b54647e5bd395d0706b18c7..a6e152ce1d11c218146369a8f046c0052e445170 100644 (file)
@@ -4,9 +4,10 @@
 TEST_OUTPUT:
 ---
 fail_compilation/imports/imp22329.d(3): Error: no property `values` for type `test22329.Foo`
-fail_compilation/test22329.d(13):        struct `Foo` defined here
-fail_compilation/imports/imp22329.d(3): Error: incompatible types for `(arg) + (1)`: `Foo` and `int`
-fail_compilation/test22329.d(21): Error: template instance `imp22329.func!(Foo)` error instantiating
+fail_compilation/test22329.d(14):        struct `Foo` defined here
+fail_compilation/imports/imp22329.d(3): Error: operator `+` is not defined for type `Foo`
+fail_compilation/test22329.d(14):        perhaps overload the operator with `auto opBinary(string op : "+")(int rhs) {}`
+fail_compilation/test22329.d(22): Error: template instance `imp22329.func!(Foo)` error instantiating
 ---
 */
 
index a91f40b6bfce85980b123172edffe39f134f9732..c81fccbb902eff24cfb95d7f71dab77f1d5d9877 100644 (file)
@@ -1,4 +1,4 @@
-b7e3b3b61711bf6c6cad27c7b5b73df0e570c215
+d29e3eca45edaeef63b31f78c9846fc6e2870c49
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index 59445f091475efd103496f5e9977ecc7a60e61d9..cc05247d6cad8c5fde77ebe9275ac389aae72ff1 100644 (file)
@@ -704,6 +704,11 @@ private int softPopcnt(N)(N x) pure
     return cast(int) x;
 }
 
+version (DigitalMars) version (AArch64)
+{
+    int _popcnt(ulong x) pure;
+}
+
 version (DigitalMars) version (AnyX86)
 {
     /**
index a0213dc56f07743df96f1263a4b48887b2558af2..160443312b4b4d8151269a347f693b840e3bb604 100644 (file)
@@ -33,7 +33,12 @@ void InitializeObjectAttributes(OBJECT_ATTRIBUTES* p, UNICODE_STRING* n,
     }
 }
 
-bool NT_SUCCESS(int x) { return x >= 0; }
+pragma(inline, true) @safe pure nothrow @nogc {
+    bool NT_SUCCESS(NTSTATUS Status)     { return Status >= 0; }
+    bool NT_INFORMATION(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 1; }
+    bool NT_WARNING(NTSTATUS Status)     { return ((cast(ULONG) Status) >> 30) == 2; }
+    bool NT_ERROR(NTSTATUS Status)       { return ((cast(ULONG) Status) >> 30) == 3; }
+}
 
 /*  In MinGW, NTSTATUS, UNICODE_STRING, STRING and their associated pointer
  *  type aliases are defined in ntdef.h, ntsecapi.h and subauth.h, each of