aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2025-03-12 18:16:46 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2025-03-15 17:54:15 +0100
commitdf1f6b98578be7a6276580e35c9302aa5622f113 (patch)
treeadac24cf39366869dd233e2e5fd0a099daad1aea /gcc/d
parente8c9f4ab8f0c8ad8da5f7fb0f1a4956507fe64f5 (diff)
downloadgcc-df1f6b98578be7a6276580e35c9302aa5622f113.zip
gcc-df1f6b98578be7a6276580e35c9302aa5622f113.tar.gz
gcc-df1f6b98578be7a6276580e35c9302aa5622f113.tar.bz2
d: Merge upstream dmd, druntime d29e3eca45
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.
Diffstat (limited to 'gcc/d')
-rw-r--r--gcc/d/d-codegen.cc2
-rw-r--r--gcc/d/d-lang.cc2
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/access.d6
-rw-r--r--gcc/d/dmd/aggregate.d3
-rw-r--r--gcc/d/dmd/arrayop.d10
-rw-r--r--gcc/d/dmd/attrib.d31
-rw-r--r--gcc/d/dmd/attrib.h3
-rw-r--r--gcc/d/dmd/cond.d40
-rw-r--r--gcc/d/dmd/cond.h1
-rw-r--r--gcc/d/dmd/cparse.d2
-rw-r--r--gcc/d/dmd/ctfe.h3
-rw-r--r--gcc/d/dmd/ctfeexpr.d6
-rw-r--r--gcc/d/dmd/cxxfrontend.d8
-rw-r--r--gcc/d/dmd/dcast.d35
-rw-r--r--gcc/d/dmd/declaration.d10
-rw-r--r--gcc/d/dmd/declaration.h3
-rw-r--r--gcc/d/dmd/dinterpret.d15
-rw-r--r--gcc/d/dmd/dmodule.d2
-rw-r--r--gcc/d/dmd/doc.d26
-rw-r--r--gcc/d/dmd/dsymbol.d9
-rw-r--r--gcc/d/dmd/dsymbol.h2
-rw-r--r--gcc/d/dmd/dsymbolsem.d63
-rw-r--r--gcc/d/dmd/dtemplate.d24
-rw-r--r--gcc/d/dmd/dversion.d33
-rw-r--r--gcc/d/dmd/errors.d5
-rw-r--r--gcc/d/dmd/escape.d4
-rw-r--r--gcc/d/dmd/expression.d132
-rw-r--r--gcc/d/dmd/expression.h48
-rw-r--r--gcc/d/dmd/expressionsem.d325
-rw-r--r--gcc/d/dmd/func.d12
-rw-r--r--gcc/d/dmd/globals.d3
-rw-r--r--gcc/d/dmd/globals.h3
-rw-r--r--gcc/d/dmd/hdrgen.d87
-rw-r--r--gcc/d/dmd/iasm.d4
-rw-r--r--gcc/d/dmd/iasmgcc.d16
-rw-r--r--gcc/d/dmd/identifier.d5
-rw-r--r--gcc/d/dmd/importc.d4
-rw-r--r--gcc/d/dmd/initsem.d2
-rw-r--r--gcc/d/dmd/intrange.d2
-rw-r--r--gcc/d/dmd/json.d19
-rw-r--r--gcc/d/dmd/location.d38
-rw-r--r--gcc/d/dmd/module.h2
-rw-r--r--gcc/d/dmd/mtype.d16
-rw-r--r--gcc/d/dmd/ob.d4
-rw-r--r--gcc/d/dmd/opover.d571
-rw-r--r--gcc/d/dmd/parse.d24
-rw-r--r--gcc/d/dmd/statementsem.d2
-rw-r--r--gcc/d/dmd/template.h3
-rw-r--r--gcc/d/dmd/templatesem.d2
-rw-r--r--gcc/d/dmd/typesem.d18
-rw-r--r--gcc/d/dmd/version.h6
-rw-r--r--gcc/d/expr.cc6
53 files changed, 859 insertions, 845 deletions
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 50362e6f..4d8ed65 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -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. */
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index a4cde58..585737b 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -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_:
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index a91f40b..c81fccb 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -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.
diff --git a/gcc/d/dmd/access.d b/gcc/d/dmd/access.d
index e778ed9..b3e98f8 100644
--- a/gcc/d/dmd/access.d
+++ b/gcc/d/dmd/access.d
@@ -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(Scope* sc, 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(Scope* sc, 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(Scope* sc, Dsymbol s)
{
final switch (s.visible().kind)
{
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index 25f54b5..20bcafe 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -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;
}
diff --git a/gcc/d/dmd/arrayop.d b/gcc/d/dmd/arrayop.d
index 5fe5273..e1aefdb 100644
--- a/gcc/d/dmd/arrayop.d
+++ b/gcc/d/dmd/arrayop.d
@@ -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);
}
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index 5da4721..7a60ecb 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -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);
diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h
index ef01d0f..1c9bd96 100644
--- a/gcc/d/dmd/attrib.h
+++ b/gcc/d/dmd/attrib.h
@@ -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); }
};
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index f66f14a..186efb0 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -166,7 +166,7 @@ extern (C++) final class StaticForeach : RootObject
return;
}
- Expressions *es;
+ Expressions* es;
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');
}
diff --git a/gcc/d/dmd/cond.h b/gcc/d/dmd/cond.h
index fc3ebd4..ec68d19 100644
--- a/gcc/d/dmd/cond.h
+++ b/gcc/d/dmd/cond.h
@@ -58,7 +58,6 @@ public:
class DVCondition : public Condition
{
public:
- unsigned level;
Identifier *ident;
Module *mod;
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 354d83b..bef1ec9 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -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.
diff --git a/gcc/d/dmd/ctfe.h b/gcc/d/dmd/ctfe.h
index 72d895c..73f1939 100644
--- a/gcc/d/dmd/ctfe.h
+++ b/gcc/d/dmd/ctfe.h
@@ -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;
};
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index 6d2a954..9a92781 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -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_:
diff --git a/gcc/d/dmd/cxxfrontend.d b/gcc/d/dmd/cxxfrontend.d
index b74b11b..3807c1d 100644
--- a/gcc/d/dmd/cxxfrontend.d
+++ b/gcc/d/dmd/cxxfrontend.d
@@ -338,13 +338,13 @@ const(char)* parametersTypeToChars(ParameterList pl)
/***********************************************************
* iasm.d
*/
-Statement asmSemantic(AsmStatement s, Scope *sc)
+Statement asmSemantic(AsmStatement s, Scope* sc)
{
import dmd.iasm;
return dmd.iasm.asmSemantic(s, sc);
}
-void asmSemantic(CAsmDeclaration d, Scope *sc)
+void asmSemantic(CAsmDeclaration d, Scope* sc)
{
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, Scope* sc)
{
import dmd.iasmgcc;
return dmd.iasmgcc.gccAsmSemantic(s, sc);
}
-void gccAsmSemantic(CAsmDeclaration d, Scope *sc)
+void gccAsmSemantic(CAsmDeclaration d, Scope* sc)
{
import dmd.iasmgcc;
return dmd.iasmgcc.gccAsmSemantic(d, sc);
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 0d95ad4..bb85318 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -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, Scope* sc)
{
// 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;
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index e6fb1ed..c94443d 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -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;
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 7f37f89..e2ac13e 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -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;
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index f219e3f..648c5b4 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -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[]
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index f26c581..d599d9c 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -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
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index eba8ddd..0e77cdf 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -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(Dsymbols* a, 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)
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index e3feefe..2f2c017 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -55,7 +55,7 @@ import dmd.visitor;
import dmd.common.outbuffer;
/***************************************
- * Calls dg(Dsymbol *sym) for each Dsymbol.
+ * Calls dg(Dsymbol* sym) 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(Dsymbol* sym) 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`
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 3936c3e..c83b8d1 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -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();
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index c7fb26a..378ef9a 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -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, Scope* scx)
{
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)
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index dd9f3da..296c10c 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -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
diff --git a/gcc/d/dmd/dversion.d b/gcc/d/dmd/dversion.d
index 42d7d8f..d8c8b24 100644
--- a/gcc/d/dmd/dversion.d
+++ b/gcc/d/dmd/dversion.d
@@ -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";
diff --git a/gcc/d/dmd/errors.d b/gcc/d/dmd/errors.d
index 7faa536d..ddab8a8 100644
--- a/gcc/d/dmd/errors.d
+++ b/gcc/d/dmd/errors.d
@@ -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.
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index ecf4f91..b9e89e8 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -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;
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 5b8e010..c8e7309 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -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);
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 07b163f1..09ed60f 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -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); }
};
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index fcb47a5..b498998 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -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(Scope* sc, 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(Scope* sc, 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, Scope* sc, 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, Scope* sc)
{
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(Expressions* arguments, 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
}
}
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 70f4c83..613dc1c 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -277,7 +277,7 @@ extern (C++) class FuncDeclaration : Declaration
/// Sibling nested functions which called this one
FuncDeclarations siblingCallers;
- FuncDeclarations *inlinedNestedCallees;
+ FuncDeclarations* inlinedNestedCallees;
/// 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[]
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index 4d3c1b9..be65557 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -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
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 6dd4be4..e94b804 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -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
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 961a0d2..c0fcf64 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -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)
diff --git a/gcc/d/dmd/iasm.d b/gcc/d/dmd/iasm.d
index 7eb51d9..d04bef3 100644
--- a/gcc/d/dmd/iasm.d
+++ b/gcc/d/dmd/iasm.d
@@ -39,7 +39,7 @@ else
/************************ AsmStatement ***************************************/
-Statement asmSemantic(AsmStatement s, Scope *sc)
+Statement asmSemantic(AsmStatement s, Scope* sc)
{
//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, Scope* sc)
{
version (NoBackend)
{
diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d
index 1410e0a..0961354 100644
--- a/gcc/d/dmd/iasmgcc.d
+++ b/gcc/d/dmd/iasmgcc.d
@@ -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, Scope* sc)
{
//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;
+ Token* toklist = null;
Token **ptoklist = &toklist;
- for (Token *token = s.tokens; token; token = token.next)
+ for (Token* token = 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, Scope* sc)
{
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)
+Expressions* parseExtAsmClobbers(Parser)(Parser p)
{
- Expressions *clobbers;
+ Expressions* clobbers;
while (1)
{
@@ -305,9 +305,9 @@ Lerror:
* Returns:
* array of parsed goto labels
*/
-Identifiers *parseExtAsmGotoLabels(Parser)(Parser p)
+Identifiers* parseExtAsmGotoLabels(Parser)(Parser p)
{
- Identifiers *labels;
+ Identifiers* labels;
while (1)
{
diff --git a/gcc/d/dmd/identifier.d b/gcc/d/dmd/identifier.d
index 74be1be..c3ea0f7 100644
--- a/gcc/d/dmd/identifier.d
+++ b/gcc/d/dmd/identifier.d
@@ -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();
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index 0413df0..84fed8f 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/dmd/importc.d
@@ -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
}
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index c181d53..467b796 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -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);
diff --git a/gcc/d/dmd/intrange.d b/gcc/d/dmd/intrange.d
index 242cac0..8395a84 100644
--- a/gcc/d/dmd/intrange.d
+++ b/gcc/d/dmd/intrange.d
@@ -141,7 +141,7 @@ struct SignExtendedNumber
SignExtendedNumber opBinary(string op : "*")(SignExtendedNumber rhs)
{
- // perform *saturated* multiplication, otherwise we may get bogus ranges
+ // perform* saturated* multiplication, otherwise we may get bogus ranges
// like 0x10 * 0x10 == 0x100 == 0.
/* Special handling for zeros:
diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d
index 37f8cfd..25b0812 100644
--- a/gcc/d/dmd/json.d
+++ b/gcc/d/dmd/json.d
@@ -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);
}
}
}
diff --git a/gcc/d/dmd/location.d b/gcc/d/dmd/location.d
index 0787068..75cd068 100644
--- a/gcc/d/dmd/location.d
+++ b/gcc/d/dmd/location.d
@@ -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;
+ }
}
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index 7f02bec2..fd01e73 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -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
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index b270943..81f8a98 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -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);
}
diff --git a/gcc/d/dmd/ob.d b/gcc/d/dmd/ob.d
index ab48019..5e773f0 100644
--- a/gcc/d/dmd/ob.d
+++ b/gcc/d/dmd/ob.d
@@ -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);
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index 92f3bb2..ac9e072 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -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)
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 2e29762..33472c8 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -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();
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 6bbc1a9..00dc606 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -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();
+ CaseStatements* csCopy = (*ss.cases).copy();
if (numcases)
{
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index e751ead..cdb1c85 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -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); }
diff --git a/gcc/d/dmd/templatesem.d b/gcc/d/dmd/templatesem.d
index a69edef..48c4297 100644
--- a/gcc/d/dmd/templatesem.d
+++ b/gcc/d/dmd/templatesem.d
@@ -1425,7 +1425,7 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat
Expression e;
Type t;
Dsymbol s;
- Scope *sco;
+ Scope* sco;
const errors = global.startGagging();
/* ref: https://issues.dlang.org/show_bug.cgi?id=11118
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 65d267f..6d21d67 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -3128,7 +3128,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
else
{
/* struct S { int a; };
- * struct S *s;
+ * struct S* s;
*/
}
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 S* s; }
*/
mtype.resolved = s.isStructDeclaration().type;
}
else
{
/* union S;
- * { struct S *s; }
+ * { struct S* s; }
*/
.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 *****************************************/
diff --git a/gcc/d/dmd/version.h b/gcc/d/dmd/version.h
index dd83fd6..7913c96 100644
--- a/gcc/d/dmd/version.h
+++ b/gcc/d/dmd/version.h
@@ -15,11 +15,8 @@
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); }
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index f04ec33..da794ea 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -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. */