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.
This commit is contained in:
Iain Buclaw 2025-03-12 18:16:46 +01:00
parent e8c9f4ab8f
commit df1f6b9857
82 changed files with 1204 additions and 1037 deletions

View file

@ -637,7 +637,7 @@ static bool
can_elide_copy_p (Expression *exp)
{
/* Explicit `__rvalue(exp)'. */
if (exp->rvalue)
if (exp->rvalue ())
return true;
/* Look for variable expression. */

View file

@ -450,7 +450,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
break;
case OPT_fdebug:
global.params.debuglevel = value ? 1 : 0;
global.params.debugEnabled = value ? true : false;
break;
case OPT_fdebug_:

View file

@ -1,4 +1,4 @@
b7e3b3b61711bf6c6cad27c7b5b73df0e570c215
d29e3eca45edaeef63b31f78c9846fc6e2870c49
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View file

@ -142,7 +142,7 @@ private bool hasPackageAccess(Module mod, Dsymbol s)
/****************************************
* Determine if scope sc has protected level access to cd.
*/
private bool hasProtectedAccess(Scope *sc, Dsymbol s)
private bool hasProtectedAccess(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)
{

View file

@ -447,7 +447,8 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
s.isTemplateDeclaration() ||
s.isOverloadSet()))
{
.error(s.loc, "%s `%s` is not a constructor; identifiers starting with `__` are reserved for the implementation", s.kind(), s.toPrettyChars());
error(s.loc, "%s name `__ctor` is not allowed", s.kind);
errorSupplemental(s.loc, "identifiers starting with `__` are reserved for internal use");
errors = true;
s = null;
}

View file

@ -44,12 +44,12 @@ bool isArrayOpValid(Expression e)
if (e.op == EXP.arrayLiteral)
{
Type t = e.type.toBasetype();
while (t.ty == Tarray || t.ty == Tsarray)
while (t.isStaticOrDynamicArray())
t = t.nextOf().toBasetype();
return (t.ty != Tvoid);
}
Type tb = e.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
if (isUnaArrayOp(e.op))
{
@ -80,7 +80,7 @@ bool isNonAssignmentArrayOp(Expression e)
return isNonAssignmentArrayOp(e.isSliceExp().e1);
Type tb = e.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
return (isUnaArrayOp(e.op) || isBinArrayOp(e.op));
}
@ -119,7 +119,7 @@ Expression arrayOp(BinExp e, Scope* sc)
{
//printf("BinExp.arrayOp() %s\n", e.toChars());
Type tb = e.type.toBasetype();
assert(tb.ty == Tarray || tb.ty == Tsarray);
assert(tb.isStaticOrDynamicArray());
Type tbn = tb.nextOf().toBasetype();
if (tbn.ty == Tvoid)
{
@ -346,7 +346,7 @@ bool isArrayOpOperand(Expression e)
if (e.op == EXP.arrayLiteral)
{
Type t = e.type.toBasetype();
while (t.ty == Tarray || t.ty == Tsarray)
while (t.isStaticOrDynamicArray())
t = t.nextOf().toBasetype();
return (t.ty != Tvoid);
}

View file

@ -271,17 +271,6 @@ extern (C++) final class LinkDeclaration : AttribDeclaration
return new LinkDeclaration(loc, linkage, Dsymbol.arraySyntaxCopy(decl));
}
override const(char)* toChars() const
{
return toString().ptr;
}
extern(D) override const(char)[] toString() const
{
return "extern ()";
}
override void accept(Visitor v)
{
v.visit(this);
@ -313,16 +302,6 @@ extern (C++) final class CPPMangleDeclaration : AttribDeclaration
return new CPPMangleDeclaration(loc, cppmangle, Dsymbol.arraySyntaxCopy(decl));
}
override const(char)* toChars() const
{
return toString().ptr;
}
extern(D) override const(char)[] toString() const
{
return "extern ()";
}
override void accept(Visitor v)
{
v.visit(this);
@ -383,16 +362,6 @@ extern (C++) final class CPPNamespaceDeclaration : AttribDeclaration
this.loc, this.ident, this.exp, Dsymbol.arraySyntaxCopy(this.decl), this.cppnamespace);
}
override const(char)* toChars() const
{
return toString().ptr;
}
extern(D) override const(char)[] toString() const
{
return "extern (C++, `namespace`)";
}
override void accept(Visitor v)
{
v.visit(this);

View file

@ -67,7 +67,6 @@ public:
static LinkDeclaration *create(const Loc &loc, LINK p, Dsymbols *decl);
LinkDeclaration *syntaxCopy(Dsymbol *s) override;
const char *toChars() const override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -77,7 +76,6 @@ public:
CPPMANGLE cppmangle;
CPPMangleDeclaration *syntaxCopy(Dsymbol *s) override;
const char *toChars() const override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -87,7 +85,6 @@ public:
Expression *exp;
CPPNamespaceDeclaration *syntaxCopy(Dsymbol *s) override;
const char *toChars() const override;
void accept(Visitor *v) override { v->visit(this); }
};

View file

@ -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');
}

View file

@ -58,7 +58,6 @@ public:
class DVCondition : public Condition
{
public:
unsigned level;
Identifier *ident;
Module *mod;

View file

@ -2990,7 +2990,7 @@ final class CParser(AST) : Parser!AST
if (isStatic || mod)
error("static or type qualifier used outside of function prototype");
}
if (ts.isTypeSArray() || ts.isTypeDArray())
if (ts.isStaticOrDynamicArray())
{
/* C11 6.7.6.2-1: type qualifiers and 'static' shall only appear
* in the outermost array type derivation.

View file

@ -48,7 +48,6 @@ class ThrownExceptionExp final : public Expression
{
public:
ClassReferenceExp *thrown; // the thing being tossed
const char *toChars() const override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -58,6 +57,4 @@ public:
class CTFEExp final : public Expression
{
public:
const char *toChars() const override;
};

View file

@ -688,7 +688,7 @@ Expression getAggregateFromPointer(Expression e, dinteger_t* ofs)
if (auto ie = e.isIndexExp())
{
// Note that each AA element is part of its own memory block
if ((ie.e1.type.ty == Tarray || ie.e1.type.ty == Tsarray || ie.e1.op == EXP.string_ || ie.e1.op == EXP.arrayLiteral) && ie.e2.op == EXP.int64)
if ((ie.e1.type.isStaticOrDynamicArray() || ie.e1.op == EXP.string_ || ie.e1.op == EXP.arrayLiteral) && ie.e2.op == EXP.int64)
{
*ofs = ie.e2.toInteger();
return ie.e1;
@ -697,7 +697,7 @@ Expression getAggregateFromPointer(Expression e, dinteger_t* ofs)
if (auto se = e.isSliceExp())
{
if (se && e.type.toBasetype().ty == Tsarray &&
(se.e1.type.ty == Tarray || se.e1.type.ty == Tsarray || se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral) && se.lwr.op == EXP.int64)
(se.e1.type.isStaticOrDynamicArray() || se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral) && se.lwr.op == EXP.int64)
{
*ofs = se.lwr.toInteger();
return se.e1;
@ -1841,7 +1841,7 @@ bool isCtfeValueValid(Expression newval)
const SliceExp se = newval.isSliceExp();
assert(se.lwr && se.lwr.op == EXP.int64);
assert(se.upr && se.upr.op == EXP.int64);
return (tb.ty == Tarray || tb.ty == Tsarray) && (se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral);
return tb.isStaticOrDynamicArray() && (se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral);
}
case EXP.void_:

View file

@ -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);

View file

@ -626,7 +626,7 @@ MATCH implicitConvTo(Expression e, Type t)
if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
return MATCH.nomatch;
if (!(e.type.ty == Tsarray || e.type.ty == Tarray || e.type.ty == Tpointer))
if (!(e.type.isStaticOrDynamicArray() || e.type.ty == Tpointer))
return visit(e);
TY tyn = e.type.nextOf().ty;
@ -758,8 +758,7 @@ MATCH implicitConvTo(Expression e, Type t)
Type typeb = e.type.toBasetype();
auto result = MATCH.nomatch;
if ((tb.ty == Tarray || tb.ty == Tsarray) &&
(typeb.ty == Tarray || typeb.ty == Tsarray))
if (tb.isStaticOrDynamicArray() && typeb.isStaticOrDynamicArray())
{
result = MATCH.exact;
Type typen = typeb.nextOf().toBasetype();
@ -802,7 +801,7 @@ MATCH implicitConvTo(Expression e, Type t)
return result;
}
else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray || typeb.ty == Tpointer))
else if (tb.ty == Tvector && (typeb.isStaticOrDynamicArray() || typeb.ty == Tpointer))
{ // Tpointer because ImportC eagerly converts Tsarray to Tpointer
result = MATCH.exact;
// Convert array literal to vector type
@ -2724,8 +2723,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
}
Type typeb = e.type.toBasetype();
if ((tb.ty == Tarray || tb.ty == Tsarray) &&
(typeb.ty == Tarray || typeb.ty == Tsarray))
if (tb.isStaticOrDynamicArray() && typeb.isStaticOrDynamicArray())
{
if (tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)
{
@ -2768,7 +2766,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
ae.type = tp;
}
}
else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray || typeb.ty == Tpointer))
else if (tb.ty == Tvector && (typeb.isStaticOrDynamicArray() || typeb.ty == Tpointer))
{
// Convert array literal to vector type
// The Tpointer case comes from C eagerly converting Tsarray to Tpointer
@ -3140,7 +3138,7 @@ Expression inferType(Expression e, Type t, int flag = 0)
Expression visitAle(ArrayLiteralExp ale)
{
Type tb = t.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
{
Type tn = tb.nextOf();
if (ale.basis)
@ -3284,7 +3282,7 @@ private bool isVoidArrayLiteral(Expression e, Type other)
{
auto ale = e.isArrayLiteralExp();
e = ale[0];
if (other.ty == Tsarray || other.ty == Tarray)
if (other.isStaticOrDynamicArray())
other = other.nextOf();
else
return false;
@ -3550,7 +3548,7 @@ Lagain:
return null;
}
if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == EXP.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == EXP.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && t2.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
if (t1.isStaticOrDynamicArray() && (e2.op == EXP.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == EXP.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && t2.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
{
/* (T[n] op void*) => T[]
* (T[] op void*) => T[]
@ -3562,7 +3560,9 @@ Lagain:
return coerce(t1.nextOf().arrayOf());
}
if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == EXP.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == EXP.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && t1.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
if (t2.isStaticOrDynamicArray() &&
(e1.op == EXP.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == EXP.arrayLiteral
&& t1.ty == Tsarray && t1.nextOf().ty == Tvoid && t1.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
{
/* (void* op T[n]) => T[]
* (void* op T[]) => T[]
@ -3574,7 +3574,7 @@ Lagain:
return coerce(t2.nextOf().arrayOf());
}
if ((t1.ty == Tsarray || t1.ty == Tarray) && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
if (t1.isStaticOrDynamicArray() && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
{
// https://issues.dlang.org/show_bug.cgi?id=7285
// Tsarray op [x, y, ...] should to be Tsarray
@ -3590,7 +3590,7 @@ Lagain:
return convert(e1, t2);
}
if ((t2.ty == Tsarray || t2.ty == Tarray) && t2.implicitConvTo(t1))
if (t2.isStaticOrDynamicArray() && t2.implicitConvTo(t1))
{
// https://issues.dlang.org/show_bug.cgi?id=7285
// https://issues.dlang.org/show_bug.cgi?id=14737
@ -3599,7 +3599,8 @@ Lagain:
return convert(e2, t1);
}
if ((t1.ty == Tsarray || t1.ty == Tarray || t1.ty == Tpointer) && (t2.ty == Tsarray || t2.ty == Tarray || t2.ty == Tpointer) && t1.nextOf().mod != t2.nextOf().mod)
if ((t1.isStaticOrDynamicArray() || t1.ty == Tpointer) && (t2.isStaticOrDynamicArray() || t2.ty == Tpointer)
&& t1.nextOf().mod != t2.nextOf().mod)
{
/* If one is mutable and the other immutable, then retry
* with both of them as const
@ -3919,7 +3920,7 @@ LmodCompare:
return convert(e1, t2);
/// Covers array operations for user-defined types
Type checkArrayOpType(Expression e1, Expression e2, EXP op, Scope *sc)
Type checkArrayOpType(Expression e1, Expression e2, EXP op, 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;

View file

@ -1379,16 +1379,6 @@ extern (C++) class TypeInfoDeclaration : VarDeclaration
assert(0); // should never be produced by syntax
}
override final const(char)* toChars() const
{
//printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
OutBuffer buf;
buf.writestring("typeid(");
buf.writestring(tinfo.toChars());
buf.writeByte(')');
return buf.extractChars();
}
override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
{
return this;

View file

@ -342,7 +342,6 @@ public:
static TypeInfoDeclaration *create(Type *tinfo);
TypeInfoDeclaration *syntaxCopy(Dsymbol *) override final;
const char *toChars() const override final;
TypeInfoDeclaration *isTypeInfoDeclaration() override final { return this; }
void accept(Visitor *v) override { v->visit(this); }
@ -787,7 +786,6 @@ public:
d_bool isMoveCtor;
CtorDeclaration *syntaxCopy(Dsymbol *) override;
const char *kind() const override;
const char *toChars() const override;
bool isVirtual() const override;
bool addPreInvariant() override;
bool addPostInvariant() override;
@ -814,7 +812,6 @@ class DtorDeclaration final : public FuncDeclaration
public:
DtorDeclaration *syntaxCopy(Dsymbol *) override;
const char *kind() const override;
const char *toChars() const override;
bool isVirtual() const override;
bool addPreInvariant() override;
bool addPostInvariant() override;

View file

@ -1885,7 +1885,7 @@ public:
// Check for taking an address of a shared variable.
// If the shared variable is an array, the offset might not be zero.
Type fromType = null;
if (e.var.type.ty == Tarray || e.var.type.ty == Tsarray)
if (e.var.type.isStaticOrDynamicArray())
{
fromType = (cast(TypeArray)e.var.type).next;
}
@ -1900,7 +1900,7 @@ public:
Expression val = getVarExp(e.loc, istate, e.var, goal);
if (exceptionOrCant(val))
return;
if (val.type.ty == Tarray || val.type.ty == Tsarray)
if (val.type.isStaticOrDynamicArray())
{
// Check for unsupported type painting operations
Type elemtype = (cast(TypeArray)val.type).next;
@ -3354,7 +3354,7 @@ public:
// a[] = e can have const e. So we compare the naked types.
Type tdst = e1.type.toBasetype();
Type tsrc = e.e2.type.toBasetype();
while (tdst.ty == Tsarray || tdst.ty == Tarray)
while (tdst.isStaticOrDynamicArray())
{
tdst = (cast(TypeArray)tdst).next.toBasetype();
if (tsrc.equivalent(tdst))
@ -4302,7 +4302,7 @@ public:
Expression assignTo(ArrayLiteralExp ae, size_t lwr, size_t upr)
{
Expressions* w = ae.elements;
assert(ae.type.ty == Tsarray || ae.type.ty == Tarray || ae.type.ty == Tpointer);
assert(ae.type.isStaticOrDynamicArray() || ae.type.ty == Tpointer);
bool directblk = (cast(TypeNext)ae.type).next.equivalent(newval.type);
for (size_t k = lwr; k < upr; k++)
{
@ -5804,8 +5804,7 @@ public:
auto expTb = exp.type.toBasetype();
if (exp.type.implicitConvTo(tbNext) >= MATCH.convert &&
(tb.ty == Tarray || tb.ty == Tsarray) &&
(expTb.ty == Tarray || expTb.ty == Tsarray))
tb.isStaticOrDynamicArray() && expTb.isStaticOrDynamicArray())
return new ArrayLiteralExp(exp.loc, e.type, exp);
return exp;
}
@ -5921,7 +5920,7 @@ public:
bool castToSarrayPointer = false;
bool castBackFromVoid = false;
if (e1.type.ty == Tarray || e1.type.ty == Tsarray || e1.type.ty == Tpointer)
if (e1.type.isStaticOrDynamicArray() || e1.type.ty == Tpointer)
{
// Check for unsupported type painting operations
// For slices, we need the type being sliced,
@ -6101,7 +6100,7 @@ public:
// Disallow array type painting, except for conversions between built-in
// types of identical size.
if ((e.to.ty == Tsarray || e.to.ty == Tarray) && (e1.type.ty == Tsarray || e1.type.ty == Tarray) && !isSafePointerCast(e1.type.nextOf(), e.to.nextOf()))
if (e.to.isStaticOrDynamicArray() && e1.type.isStaticOrDynamicArray() && !isSafePointerCast(e1.type.nextOf(), e.to.nextOf()))
{
auto se = e1.isStringExp();
// Allow casting a hex string literal to short[], int[] or long[]

View file

@ -430,11 +430,9 @@ extern (C++) final class Module : Package
Modules aimports; // all imported modules
uint debuglevel; // debug level
Identifiers* debugids; // debug identifiers
Identifiers* debugidsNot; // forward referenced debug identifiers
uint versionlevel; // version level
Identifiers* versionids; // version identifiers
Identifiers* versionidsNot; // forward referenced version identifiers

View file

@ -433,10 +433,7 @@ void gendocfile(Module m, const char[] ddoctext, const char* datetime, ErrorSink
OutBuffer buf;
if (m.filetype == FileType.ddoc)
{
const ploc = m.md ? &m.md.loc : &m.loc;
Loc loc = *ploc;
if (!loc.filename)
loc.filename = srcfilename.ptr;
Loc loc = m.md ? m.md.loc : m.loc;
size_t commentlen = m.comment ? strlen(cast(char*)m.comment) : 0;
Dsymbols a;
@ -694,9 +691,7 @@ bool emitAnchorName(ref OutBuffer buf, Dsymbol s, Scope* sc, bool includeParent)
}
else
{
/* We just want the identifier, not overloads like TemplateDeclaration::toChars.
* We don't want the template parameter list and constraints. */
buf.writestring(s.Dsymbol.toChars());
buf.writestring(s.ident ? s.ident.toString : "__anonymous");
}
return true;
}
@ -799,7 +794,11 @@ void emitAnchor(ref OutBuffer buf, Dsymbol s, Scope* sc, bool forHeader = false)
}
else
{
auto symbolName = ident.toString();
// buf.writestring("<<<");
// buf.writestring(typeof(ident).stringof);
// buf.writestring(">>>");
// auto symbolName = ident.toString();
auto symbolName = ident.toChars().toDString();
buf.printf("$(%.*s %.*s", cast(int) macroName.length, macroName.ptr,
cast(int) symbolName.length, symbolName.ptr);
@ -2624,7 +2623,7 @@ Parameter isFunctionParameter(Dsymbols* a, const(char)[] p) @safe
/****************************************************
*/
Parameter isEponymousFunctionParameter(Dsymbols *a, const(char)[] p) @safe
Parameter isEponymousFunctionParameter(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)

View file

@ -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`

View file

@ -187,7 +187,7 @@ public:
PASS semanticRun;
unsigned short localNum; // perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab
static Dsymbol *create(Identifier *);
const char *toChars() const override;
const char *toChars() const final override;
DeprecatedDeclaration* depdecl();
CPPNamespaceDeclaration* cppnamespace();
UserAttributeDeclaration* userAttribDecl();

View file

@ -424,7 +424,7 @@ private bool checkDeprecatedAliasThis(AliasThis at, const ref Loc loc, Scope* sc
}
// Save the scope and defer semantic analysis on the Dsymbol.
void deferDsymbolSemantic(Scope* sc, Dsymbol s, Scope *scx)
void deferDsymbolSemantic(Scope* sc, Dsymbol s, 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)

View file

@ -57,7 +57,7 @@ import dmd.dsymbolsem : dsymbolSemantic, checkDeprecated, aliasSemantic, search,
import dmd.errors;
import dmd.errorsink;
import dmd.expression;
import dmd.expressionsem : resolveLoc, expressionSemantic, resolveProperties;
import dmd.expressionsem : resolveLoc, expressionSemantic, resolveProperties, checkValue;
import dmd.func;
import dmd.funcsem : functionSemantic, leastAsSpecialized, overloadApply;
import dmd.globals;
@ -746,14 +746,6 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
return (onemember && onemember.isAggregateDeclaration()) ? onemember.kind() : "template";
}
override const(char)* toChars() const
{
HdrGenState hgs;
OutBuffer buf;
toCharsMaybeConstraints(this, buf, hgs);
return buf.extractChars();
}
/****************************
* Similar to `toChars`, but does not print the template constraints
*/
@ -3830,13 +3822,6 @@ extern (C++) class TemplateInstance : ScopeDsymbol
return true;
}
override const(char)* toChars() const
{
OutBuffer buf;
toCBufferInstance(this, buf);
return buf.extractChars();
}
override final const(char)* toPrettyCharsHelper()
{
OutBuffer buf;
@ -5524,13 +5509,6 @@ extern (C++) final class TemplateMixin : TemplateInstance
return members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
}
override const(char)* toChars() const
{
OutBuffer buf;
toCBufferInstance(this, buf);
return buf.extractChars();
}
extern (D) bool findTempDecl(Scope* sc)
{
// Follow qualifications to find the TemplateDeclaration

View file

@ -29,21 +29,17 @@ import dmd.visitor;
/***********************************************************
* DebugSymbol's happen for statements like:
* debug = identifier;
* debug = integer;
*/
extern (C++) final class DebugSymbol : Dsymbol
{
uint level;
extern (D) this(const ref Loc loc, Identifier ident) @safe
{
super(loc, ident);
}
extern (D) this(const ref Loc loc, uint level) @safe
extern (D) this(const ref Loc loc) @safe
{
super(loc, null);
this.level = level;
}
override DebugSymbol syntaxCopy(Dsymbol s)
@ -51,19 +47,9 @@ extern (C++) final class DebugSymbol : Dsymbol
assert(!s);
auto ds = new DebugSymbol(loc, ident);
ds.comment = comment;
ds.level = level;
return ds;
}
override const(char)* toChars() const nothrow
{
if (ident)
return ident.toChars();
OutBuffer buf;
buf.print(level);
return buf.extractChars();
}
override const(char)* kind() const nothrow
{
return "debug";
@ -83,41 +69,28 @@ extern (C++) final class DebugSymbol : Dsymbol
/***********************************************************
* VersionSymbol's happen for statements like:
* version = identifier;
* version = integer;
*/
extern (C++) final class VersionSymbol : Dsymbol
{
uint level;
extern (D) this(const ref Loc loc, Identifier ident) @safe
{
super(loc, ident);
}
extern (D) this(const ref Loc loc, uint level) @safe
extern (D) this(const ref Loc loc) @safe
{
super(loc, null);
this.level = level;
}
override VersionSymbol syntaxCopy(Dsymbol s)
{
assert(!s);
auto ds = ident ? new VersionSymbol(loc, ident)
: new VersionSymbol(loc, level);
auto ds = new VersionSymbol(loc, ident);
ds.comment = comment;
return ds;
}
override const(char)* toChars() const nothrow
{
if (ident)
return ident.toChars();
OutBuffer buf;
buf.print(level);
return buf.extractChars();
}
override const(char)* kind() const nothrow
{
return "version";

View file

@ -11,7 +11,8 @@
module dmd.errors;
import core.stdc.stdarg;
public import core.stdc.stdarg;
public import dmd.root.string: fTuple;
import dmd.errorsink;
import dmd.globals;
import dmd.location;
@ -384,7 +385,7 @@ else
* see verrorReport for arguments
* Returns: true if error handling is done, false to continue printing to stderr
*/
alias DiagnosticHandler = bool delegate(const ref Loc location, Color headerColor, const(char)* header, const(char)* messageFormat, va_list args, const(char)* prefix1, const(char)* prefix2);
alias DiagnosticHandler = bool delegate(const ref SourceLoc location, Color headerColor, const(char)* header, const(char)* messageFormat, va_list args, const(char)* prefix1, const(char)* prefix2);
/**
* The diagnostic handler.

View file

@ -1607,7 +1607,7 @@ void escapeExp(Expression e, ref scope EscapeByResults er, int deref)
void visitArrayLiteral(ArrayLiteralExp e)
{
Type tb = e.type.toBasetype();
if (tb.isTypeSArray() || tb.isTypeDArray())
if (tb.isStaticOrDynamicArray())
{
if (e.basis)
escapeExp(e.basis, er, deref);
@ -2245,7 +2245,7 @@ private bool isTypesafeVariadicArray(VarDeclaration v)
if (v.storage_class & STC.variadic)
{
Type tb = v.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
if (tb.isStaticOrDynamicArray())
return true;
}
return false;

View file

@ -301,8 +301,14 @@ extern (C++) abstract class Expression : ASTNode
Loc loc; // file location
const EXP op; // to minimize use of dynamic_cast
bool parens; // if this is a parenthesized expression
bool rvalue; // true if this is considered to be an rvalue, even if it is an lvalue
static struct BitFields
{
bool parens; // if this is a parenthesized expression
bool rvalue; // true if this is considered to be an rvalue, even if it is an lvalue
}
import dmd.common.bitfields;
mixin(generateBitFields!(BitFields, ubyte));
extern (D) this(const ref Loc loc, EXP op) scope @safe
{
@ -375,8 +381,13 @@ extern (C++) abstract class Expression : ASTNode
return DYNCAST.expression;
}
override const(char)* toChars() const
final override const(char)* toChars() const
{
// FIXME: Test suite relies on lambda's being printed as __lambdaXXX in errors and .stringof
// Printing a (truncated) lambda body is more user friendly
if (auto fe = isFuncExp())
return fe.fd.toChars();
return .toChars(this);
}
@ -516,25 +527,6 @@ extern (C++) abstract class Expression : ASTNode
return false;
}
/****************************************
* Check that the expression has a valid value.
* If not, generates an error "... has no value".
* Returns:
* true if the expression is not valid or has void type.
*/
bool checkValue()
{
if (type && type.toBasetype().ty == Tvoid)
{
error(loc, "expression `%s` is `void` and has no value", toChars());
//print(); assert(0);
if (!global.gag)
type = Type.terror;
return true;
}
return false;
}
/******************************
* Take address of expression.
*/
@ -2126,6 +2118,16 @@ extern (C++) final class AssocArrayLiteralExp : Expression
*/
extern (C++) final class StructLiteralExp : Expression
{
struct BitFields
{
bool useStaticInit; /// if this is true, use the StructDeclaration's init symbol
bool isOriginal = false; /// used when moving instances to indicate `this is this.origin`
OwnedBy ownedByCtfe = OwnedBy.code;
}
import dmd.common.bitfields;
mixin(generateBitFields!(BitFields, ubyte));
StageFlags stageflags;
StructDeclaration sd; /// which aggregate this is for
Expressions* elements; /// parallels sd.fields[] with null entries for fields to skip
Type stype; /// final type of result (can be different from sd's type)
@ -2163,11 +2165,6 @@ extern (C++) final class StructLiteralExp : Expression
inlineScan = 0x10, /// inlineScan is running
toCBuffer = 0x20 /// toCBuffer is running
}
StageFlags stageflags;
bool useStaticInit; /// if this is true, use the StructDeclaration's init symbol
bool isOriginal = false; /// used when moving instances to indicate `this is this.origin`
OwnedBy ownedByCtfe = OwnedBy.code;
extern (D) this(const ref Loc loc, StructDeclaration sd, Expressions* elements, Type stype = null) @safe
{
@ -2349,12 +2346,6 @@ extern (C++) final class TypeExp : Expression
return true;
}
override bool checkValue()
{
error(loc, "type `%s` has no value", toChars());
return true;
}
override void accept(Visitor v)
{
v.visit(this);
@ -2408,12 +2399,6 @@ extern (C++) final class ScopeExp : Expression
return false;
}
override bool checkValue()
{
error(loc, "%s `%s` has no value", sds.kind(), sds.toChars());
return true;
}
override void accept(Visitor v)
{
v.visit(this);
@ -2447,12 +2432,6 @@ extern (C++) final class TemplateExp : Expression
return true;
}
override bool checkValue()
{
error(loc, "%s `%s` has no value", td.kind(), toChars());
return true;
}
override void accept(Visitor v)
{
v.visit(this);
@ -2720,11 +2699,6 @@ extern (C++) final class FuncExp : Expression
return new FuncExp(loc, fd);
}
override const(char)* toChars() const
{
return fd.toChars();
}
override bool checkType()
{
if (td)
@ -2735,16 +2709,6 @@ extern (C++) final class FuncExp : Expression
return false;
}
override bool checkValue()
{
if (td)
{
error(loc, "template lambda has no value");
return true;
}
return false;
}
override void accept(Visitor v)
{
v.visit(this);
@ -3168,12 +3132,6 @@ extern (C++) final class DotTemplateExp : UnaExp
return true;
}
override bool checkValue()
{
error(loc, "%s `%s` has no value", td.kind(), toChars());
return true;
}
override void accept(Visitor v)
{
v.visit(this);
@ -3252,18 +3210,6 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
return false;
}
override bool checkValue()
{
if (ti.tempdecl &&
ti.semantictiargsdone &&
ti.semanticRun == PASS.initial)
error(loc, "partial %s `%s` has no value", ti.kind(), toChars());
else
error(loc, "%s `%s` has no value", ti.kind(), ti.toChars());
return true;
}
override void accept(Visitor v)
{
v.visit(this);
@ -4180,10 +4126,6 @@ extern (C++) final class LoweredAssignExp : AssignExp
this.lowering = lowering;
}
override const(char)* toChars() const
{
return lowering.toChars();
}
override void accept(Visitor v)
{
v.visit(this);
@ -5089,27 +5031,6 @@ extern (C++) final class CTFEExp : Expression
type = Type.tvoid;
}
override const(char)* toChars() const
{
switch (op)
{
case EXP.cantExpression:
return "<cant>";
case EXP.voidExpression:
return "cast(void)0";
case EXP.showCtfeContext:
return "<error>";
case EXP.break_:
return "<break>";
case EXP.continue_:
return "<continue>";
case EXP.goto_:
return "<goto>";
default:
assert(0);
}
}
extern (D) __gshared CTFEExp cantexp;
extern (D) __gshared CTFEExp voidexp;
extern (D) __gshared CTFEExp breakexp;
@ -5146,11 +5067,6 @@ extern (C++) final class ThrownExceptionExp : Expression
this.type = victim.type;
}
override const(char)* toChars() const
{
return "CTFE ThrownException";
}
override void accept(Visitor v)
{
v.visit(this);

View file

@ -77,8 +77,12 @@ public:
Type *type; // !=NULL means that semantic() has been run
Loc loc; // file location
EXP op; // to minimize use of dynamic_cast
d_bool parens; // if this is a parenthesized expression
d_bool rvalue; // consider this an rvalue, even if it is an lvalue
uint8_t bitFields;
bool parens() const;
bool parens(bool v);
bool rvalue() const;
bool rvalue(bool v);
size_t size() const;
static void _init();
@ -87,7 +91,7 @@ public:
// kludge for template.isExpression()
DYNCAST dyncast() const override final { return DYNCAST_EXPRESSION; }
const char *toChars() const override;
const char* toChars() const final override;
virtual dinteger_t toInteger();
virtual uinteger_t toUInteger();
@ -97,7 +101,6 @@ public:
virtual StringExp *toStringExp();
virtual bool isLvalue();
virtual bool checkType();
virtual bool checkValue();
Expression *addressOf();
Expression *deref();
@ -431,6 +434,24 @@ public:
class StructLiteralExp final : public Expression
{
public:
uint8_t bitFields;
// if this is true, use the StructDeclaration's init symbol
bool useStaticInit() const;
bool useStaticInit(bool v);
// used when moving instances to indicate `this is this.origin`
bool isOriginal() const;
bool isOriginal(bool v);
OwnedBy ownedByCtfe() const;
OwnedBy ownedByCtfe(OwnedBy v);
/** anytime when recursive function is calling, 'stageflags' marks with bit flag of
* current stage and unmarks before return from this function.
* 'inlinecopy' uses similar 'stageflags' and from multiple evaluation 'doInline'
* (with infinite recursion) of this expression.
*/
uint8_t stageflags;
StructDeclaration *sd; // which aggregate this is for
Expressions *elements; // parallels sd->fields[] with NULL entries for fields to skip
Type *stype; // final type of result (can be different from sd's type)
@ -451,17 +472,6 @@ public:
StructLiteralExp *origin;
/** anytime when recursive function is calling, 'stageflags' marks with bit flag of
* current stage and unmarks before return from this function.
* 'inlinecopy' uses similar 'stageflags' and from multiple evaluation 'doInline'
* (with infinite recursion) of this expression.
*/
uint8_t stageflags;
d_bool useStaticInit; // if this is true, use the StructDeclaration's init symbol
d_bool isOriginal; // used when moving instances to indicate `this is this.origin`
OwnedBy ownedByCtfe;
static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = nullptr);
bool equals(const RootObject * const o) const override;
StructLiteralExp *syntaxCopy() override;
@ -474,7 +484,6 @@ class TypeExp final : public Expression
public:
TypeExp *syntaxCopy() override;
bool checkType() override;
bool checkValue() override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -485,7 +494,6 @@ public:
ScopeExp *syntaxCopy() override;
bool checkType() override;
bool checkValue() override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -497,7 +505,6 @@ public:
bool isLvalue() override;
bool checkType() override;
bool checkValue() override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -595,9 +602,7 @@ public:
bool equals(const RootObject * const o) const override;
FuncExp *syntaxCopy() override;
const char *toChars() const override;
bool checkType() override;
bool checkValue() override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -741,7 +746,6 @@ public:
TemplateDeclaration *td;
bool checkType() override;
bool checkValue() override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -762,7 +766,6 @@ public:
DotTemplateInstanceExp *syntaxCopy() override;
bool checkType() override;
bool checkValue() override;
void accept(Visitor *v) override { v->visit(this); }
};
@ -1045,7 +1048,6 @@ class LoweredAssignExp final : public AssignExp
public:
Expression *lowering;
const char *toChars() const override;
void accept(Visitor *v) override { v->visit(this); }
};

View file

@ -308,7 +308,7 @@ extern (D) bool findTempDecl(DotTemplateInstanceExp exp, Scope* sc)
* Returns:
* String literal, or `null` if error happens.
*/
StringExp semanticString(Scope *sc, Expression exp, const char* s)
StringExp semanticString(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
}
}

View file

@ -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[]

View file

@ -242,8 +242,7 @@ extern (C++) struct Param
Output mixinOut; // write expanded mixins for debugging
Output moduleDeps; // Generate `.deps` module dependencies
uint debuglevel; // debug level
uint versionlevel; // version level
bool debugEnabled; // Global -debug flag (no -debug=XXX) is active
bool run; // run resulting executable
Strings runargs; // arguments for executable

View file

@ -250,8 +250,7 @@ struct Param
Output mixinOut; // write expanded mixins for debugging
Output moduleDeps; // Generate `.deps` module dependencies
unsigned debuglevel; // debug level
unsigned versionlevel; // version level
d_bool debugEnabled; // -debug flag is passed
d_bool run; // run resulting executable
Strings runargs; // arguments for executable

View file

@ -140,6 +140,42 @@ public const(char)* toChars(const Type t)
return buf.extractChars();
}
public const(char)* toChars(const Dsymbol d)
{
if (auto td = d.isTemplateDeclaration())
{
HdrGenState hgs;
OutBuffer buf;
toCharsMaybeConstraints(td, buf, hgs);
return buf.extractChars();
}
if (auto ti = d.isTemplateInstance())
{
OutBuffer buf;
toCBufferInstance(ti, buf);
return buf.extractChars();
}
if (auto tm = d.isTemplateMixin())
{
OutBuffer buf;
toCBufferInstance(tm, buf);
return buf.extractChars();
}
if (auto tid = d.isTypeInfoDeclaration())
{
OutBuffer buf;
buf.writestring("typeid(");
buf.writestring(tid.tinfo.toChars());
buf.writeByte(')');
return buf.extractChars();
}
return d.ident ? d.ident.toHChars2() : "__anonymous";
}
public const(char)[] toString(const Initializer i)
{
OutBuffer buf;
@ -880,10 +916,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
void visitDebugSymbol(DebugSymbol s)
{
buf.writestring("debug = ");
if (s.ident)
buf.writestring(s.ident.toString());
else
buf.print(s.level);
buf.writestring(s.ident.toString());
buf.writeByte(';');
buf.writenl();
}
@ -891,10 +924,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
void visitVersionSymbol(VersionSymbol s)
{
buf.writestring("version = ");
if (s.ident)
buf.writestring(s.ident.toString());
else
buf.print(s.level);
buf.writestring(s.ident.toString());
buf.writeByte(';');
buf.writenl();
}
@ -2237,9 +2267,20 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
buf.writestring(e.ident.toString());
}
void visitDsymbol(DsymbolExp e)
void visitDsymbol(Dsymbol s)
{
buf.writestring(e.s.toChars());
// 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)
{
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)

View file

@ -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)
{

View file

@ -37,17 +37,17 @@ import dmd.statementsem;
* Returns:
* the completed gcc asm statement, or null if errors occurred
*/
public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
public Statement gccAsmSemantic(GccAsmStatement s, 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)
{

View file

@ -108,7 +108,8 @@ nothrow:
const(char)* p = null;
if (this == Id.ctor)
p = "this";
else if (this == Id.dtor)
else if (this == Id.dtor || this == Id.__xdtor || this == Id.__fieldDtor ||
this == Id.__aggrDtor || this == Id.cppdtor || this == Id.ticppdtor)
p = "~this";
else if (this == Id.unitTest)
p = "unittest";
@ -120,6 +121,8 @@ nothrow:
p = "result";
else if (this == Id.returnLabel)
p = "return";
else if (this == Id.postblit)
p = "this(this)";
else
{
p = toChars();

View file

@ -166,7 +166,7 @@ Expression carraySemantic(ArrayExp ae, Scope* sc)
* So, rewrite as an IndexExp if we can.
*/
auto t1 = e1.type.toBasetype();
if (t1.isTypeDArray() || t1.isTypeSArray())
if (t1.isStaticOrDynamicArray())
{
e2 = e2.expressionSemantic(sc).arrayFuncConv(sc);
// C doesn't do array bounds checking, so `true` turns it off
@ -176,7 +176,7 @@ Expression carraySemantic(ArrayExp ae, Scope* sc)
e1 = e1.arrayFuncConv(sc); // e1 might still be a function call
e2 = e2.expressionSemantic(sc);
auto t2 = e2.type.toBasetype();
if (t2.isTypeDArray() || t2.isTypeSArray())
if (t2.isStaticOrDynamicArray())
{
return new IndexExp(ae.loc, e2, e1, true).expressionSemantic(sc); // swap operands
}

View file

@ -439,7 +439,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
Type typeb = se.type.toBasetype();
TY tynto = tb.nextOf().ty;
if (!se.committed &&
(typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
typeb.isStaticOrDynamicArray() && tynto.isSomeChar &&
se.numberOfCodeUnits(tynto) < tb.isTypeSArray().dim.toInteger())
{
i.exp = se.castTo(sc, t);

View file

@ -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:

View file

@ -351,19 +351,18 @@ public:
{
if (loc.isValid())
{
if (auto filename = loc.filename.toDString)
SourceLoc sl = SourceLoc(loc);
if (sl.filename.length > 0 && sl.filename != this.filename)
{
if (filename != this.filename)
{
this.filename = filename;
property("file", filename);
}
this.filename = sl.filename;
property("file", sl.filename);
}
if (loc.linnum)
if (sl.linnum)
{
property(linename, loc.linnum);
if (loc.charnum)
property(charname, loc.charnum);
property(linename, sl.linnum);
if (sl.charnum)
property(charname, sl.charnum);
}
}
}

View file

@ -96,6 +96,16 @@ nothrow:
return _linnum = num;
}
/// Advance this location to the first column of the next line
void nextLine()
{
if (this._linnum)
{
this._linnum++;
this.charnum = 0;
}
}
/***
* Returns: filename for this location, null if none
*/
@ -126,9 +136,7 @@ nothrow:
bool showColumns = Loc.showColumns,
MessageStyle messageStyle = Loc.messageStyle) const nothrow
{
OutBuffer buf;
writeSourceLoc(buf, SourceLoc(this), showColumns, messageStyle);
return buf.extractChars();
return SourceLoc(this).toChars(showColumns, messageStyle);
}
/**
@ -140,9 +148,11 @@ nothrow:
*/
extern (C++) bool equals(ref const(Loc) loc) const
{
return (!showColumns || charnum == loc.charnum) &&
linnum == loc.linnum &&
FileName.equals(filename, loc.filename);
SourceLoc lhs = SourceLoc(this);
SourceLoc rhs = SourceLoc(loc);
return (!showColumns || lhs.column == rhs.column) &&
lhs.line == rhs.line &&
FileName.equals(lhs.filename, rhs.filename);
}
/**
@ -198,6 +208,8 @@ void writeSourceLoc(ref OutBuffer buf,
bool showColumns,
MessageStyle messageStyle) nothrow
{
if (loc.filename.length == 0)
return;
buf.writestring(loc.filename);
if (loc.line == 0)
return;
@ -258,4 +270,18 @@ struct SourceLoc
this.line = loc.linnum;
this.column = loc.charnum;
}
extern (C++) const(char)* toChars(
bool showColumns = Loc.showColumns,
MessageStyle messageStyle = Loc.messageStyle) const nothrow
{
OutBuffer buf;
writeSourceLoc(buf, this, showColumns, messageStyle);
return buf.extractChars();
}
bool opEquals(SourceLoc other) const nothrow
{
return this.filename == other.filename && this.line == other.line && this.column == other.column;
}
}

View file

@ -109,11 +109,9 @@ public:
Modules aimports; // all imported modules
unsigned debuglevel; // debug level
Identifiers *debugids; // debug identifiers
Identifiers *debugidsNot; // forward referenced debug identifiers
unsigned versionlevel; // version level
Identifiers *versionids; // version identifiers
Identifiers *versionidsNot; // forward referenced version identifiers

View file

@ -1521,6 +1521,8 @@ extern (C++) abstract class Type : ASTNode
inout(TypeTraits) isTypeTraits() { return ty == Ttraits ? cast(typeof(return))this : null; }
inout(TypeNoreturn) isTypeNoreturn() { return ty == Tnoreturn ? cast(typeof(return))this : null; }
inout(TypeTag) isTypeTag() { return ty == Ttag ? cast(typeof(return))this : null; }
extern (D) bool isStaticOrDynamicArray() const { return ty == Tarray || ty == Tsarray; }
}
override void accept(Visitor v)
@ -3947,7 +3949,7 @@ extern (C++) final class Parameter : ASTNode
Type isLazyArray()
{
Type tb = type.toBasetype();
if (tb.ty == Tsarray || tb.ty == Tarray)
if (tb.isStaticOrDynamicArray())
{
Type tel = (cast(TypeArray)tb).next.toBasetype();
if (auto td = tel.isTypeDelegate())
@ -4057,7 +4059,7 @@ extern (C++) final class Parameter : ASTNode
/***************************************
* Expands tuples in args in depth first order. Calls
* dg(void *ctx, size_t argidx, Parameter *arg) for each Parameter.
* dg(void* ctx, size_t argidx, Parameter* arg) for each Parameter.
* If dg returns !=0, stops and returns that value else returns 0.
* Use this function to avoid the O(N + N^2/2) complexity of
* calculating dim and calling N times getNth.
@ -4316,10 +4318,10 @@ void attributesApply(const TypeFunction tf, void delegate(string) dg, TRUSTforma
AggregateDeclaration isAggregate(Type t)
{
t = t.toBasetype();
if (t.ty == Tclass)
return (cast(TypeClass)t).sym;
if (t.ty == Tstruct)
return (cast(TypeStruct)t).sym;
if (auto tc = t.isTypeClass())
return tc.sym;
if (auto ts = t.isTypeStruct())
return ts.sym;
return null;
}
@ -4334,7 +4336,7 @@ AggregateDeclaration isAggregate(Type t)
bool isIndexableNonAggregate(Type t)
{
t = t.toBasetype();
return (t.ty == Tpointer || t.ty == Tsarray || t.ty == Tarray || t.ty == Taarray ||
return (t.ty == Tpointer || t.isStaticOrDynamicArray() || t.ty == Taarray ||
t.ty == Ttuple || t.ty == Tvector);
}

View file

@ -1683,7 +1683,7 @@ void genKill(ref ObState obstate, ObNode* ob)
override void visit(ArrayLiteralExp e)
{
Type tb = e.type.toBasetype();
if (tb.ty == Tsarray || tb.ty == Tarray)
if (tb.isStaticOrDynamicArray())
{
if (e.basis)
e.basis.accept(this);
@ -2424,7 +2424,7 @@ void checkObErrors(ref ObState obstate)
override void visit(ArrayLiteralExp e)
{
Type tb = e.type.toBasetype();
if (tb.ty == Tsarray || tb.ty == Tarray)
if (tb.isStaticOrDynamicArray())
{
if (e.basis)
e.basis.accept(this);

View file

@ -71,58 +71,63 @@ bool isCommutative(EXP op) @safe
return false;
}
/// Returns: whether `op` can be overloaded with `opBinary`
private bool hasOpBinary(EXP op) pure @safe
{
switch (op)
{
case EXP.add: return true;
case EXP.min: return true;
case EXP.mul: return true;
case EXP.div: return true;
case EXP.mod: return true;
case EXP.and: return true;
case EXP.or: return true;
case EXP.xor: return true;
case EXP.leftShift: return true;
case EXP.rightShift: return true;
case EXP.unsignedRightShift: return true;
case EXP.concatenate: return true;
case EXP.pow: return true;
case EXP.in_: return true;
default: return false;
}
}
/**
* Remove the = from op=, e.g. += becomes +
*
* Params:
* op = tag for a binary assign operator
* Returns: the corresponding binary operator, or `op` if it wasn't an assign operator
*/
private EXP stripAssignOp(EXP op)
{
switch (op)
{
case EXP.addAssign: return EXP.add;
case EXP.minAssign: return EXP.min;
case EXP.mulAssign: return EXP.mul;
case EXP.divAssign: return EXP.div;
case EXP.modAssign: return EXP.mod;
case EXP.andAssign: return EXP.and;
case EXP.orAssign: return EXP.or;
case EXP.xorAssign: return EXP.xor;
case EXP.leftShiftAssign: return EXP.leftShift;
case EXP.rightShiftAssign: return EXP.rightShift;
case EXP.unsignedRightShiftAssign: return EXP.unsignedRightShift;
case EXP.concatenateAssign: return EXP.concatenate;
case EXP.powAssign: return EXP.pow;
default: return op;
}
}
/*******************************************
* Helper function to turn operator into template argument list
*/
Objects* opToArg(Scope* sc, EXP op)
{
/* Remove the = from op=
*/
switch (op)
{
case EXP.addAssign:
op = EXP.add;
break;
case EXP.minAssign:
op = EXP.min;
break;
case EXP.mulAssign:
op = EXP.mul;
break;
case EXP.divAssign:
op = EXP.div;
break;
case EXP.modAssign:
op = EXP.mod;
break;
case EXP.andAssign:
op = EXP.and;
break;
case EXP.orAssign:
op = EXP.or;
break;
case EXP.xorAssign:
op = EXP.xor;
break;
case EXP.leftShiftAssign:
op = EXP.leftShift;
break;
case EXP.rightShiftAssign:
op = EXP.rightShift;
break;
case EXP.unsignedRightShiftAssign:
op = EXP.unsignedRightShift;
break;
case EXP.concatenateAssign:
op = EXP.concatenate;
break;
case EXP.powAssign:
op = EXP.pow;
break;
default:
break;
}
Expression e = new StringExp(Loc.initial, EXPtoString(op));
Expression e = new StringExp(Loc.initial, EXPtoString(stripAssignOp(op)));
e = e.expressionSemantic(sc);
auto tiargs = new Objects();
tiargs.push(e);
@ -144,7 +149,7 @@ Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinExp e, Ty
BinExp be = cast(BinExp)e.copy();
// Resolve 'alias this' but in case of assigment don't resolve properties yet
// because 'e1 = e2' could mean 'e1(e2)' or 'e1() = e2'
bool findOnly = (e.op == EXP.assign);
bool findOnly = e.isAssignExp() !is null;
be.e1 = resolveAliasThis(sc, e.e1, true, findOnly);
if (!be.e1)
return null;
@ -173,13 +178,12 @@ Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinExp e, Ty
Expression opOverloadUnary(UnaExp e, Scope* sc)
{
Expression result;
if (auto ae = e.e1.isArrayExp())
{
ae.e1 = ae.e1.expressionSemantic(sc);
ae.e1 = resolveProperties(sc, ae.e1);
Expression ae1old = ae.e1;
const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].isIntervalExp());
IntervalExp ie = null;
if (maybeSlice && ae.arguments.length)
{
@ -188,70 +192,61 @@ Expression opOverloadUnary(UnaExp e, Scope* sc)
Type att = null; // first cyclic `alias this` type
while (true)
{
if (ae.e1.op == EXP.error)
if (ae.e1.isErrorExp())
{
return ae.e1;
}
Expression e0 = null;
Expression ae1save = ae.e1;
ae.lengthVar = null;
Type t1b = ae.e1.type.toBasetype();
AggregateDeclaration ad = isAggregate(t1b);
AggregateDeclaration ad = isAggregate(ae.e1.type);
if (!ad)
break;
if (search_function(ad, Id.opIndexUnary))
{
Expression e0;
// Deal with $
result = resolveOpDollar(sc, ae, &e0);
if (!result) // op(a[i..j]) might be: a.opSliceUnary!(op)(i, j)
Expression ae2 = resolveOpDollar(sc, ae, e0);
if (!ae2) // op(a[i..j]) might be: a.opSliceUnary!(op)(i, j)
goto Lfallback;
if (result.op == EXP.error)
return result;
if (ae2.isErrorExp())
return ae2;
/* Rewrite op(a[arguments]) as:
* a.opIndexUnary!(op)(arguments)
*/
Expressions* a = ae.arguments.copy();
Objects* tiargs = opToArg(sc, e.op);
result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opIndexUnary, tiargs);
result = new CallExp(e.loc, result, a);
* a.opIndexUnary!(op)(arguments)
*/
Expression result = dotTemplateCall(ae.e1, Id.opIndexUnary, opToArg(sc, e.op), (*ae.arguments)[]);
if (maybeSlice) // op(a[]) might be: a.opSliceUnary!(op)()
result = result.trySemantic(sc);
else
result = result.expressionSemantic(sc);
if (result)
{
return Expression.combine(e0, result);
}
}
Lfallback:
if (maybeSlice && search_function(ad, Id.opSliceUnary))
{
// Deal with $
result = resolveOpDollar(sc, ae, ie, &e0);
if (result.op == EXP.error)
return result;
Expression e0;
auto ae2 = resolveOpDollar(sc, ae, ie, e0);
if (ae2.isErrorExp())
return ae2;
/* Rewrite op(a[i..j]) as:
* a.opSliceUnary!(op)(i, j)
*/
auto a = new Expressions();
if (ie)
{
a.push(ie.lwr);
a.push(ie.upr);
}
Objects* tiargs = opToArg(sc, e.op);
result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opSliceUnary, tiargs);
result = new CallExp(e.loc, result, a);
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
return result;
* a.opSliceUnary!(op)(i, j)
*/
Expression result = ie ?
dotTemplateCall(ae.e1, Id.opSliceUnary, opToArg(sc, e.op), ie.lwr, ie.upr) :
dotTemplateCall(ae.e1, Id.opSliceUnary, opToArg(sc, e.op));
return Expression.combine(e0, result.expressionSemantic(sc));
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
{
/* Rewrite op(a[arguments]) as:
* op(a.aliasthis[arguments])
*/
* op(a.aliasthis[arguments])
*/
ae.e1 = resolveAliasThis(sc, ae1save, true);
if (ae.e1)
continue;
@ -266,7 +261,7 @@ Expression opOverloadUnary(UnaExp e, Scope* sc)
Type att = null; // first cyclic `alias this` type
while (1)
{
if (e.e1.op == EXP.error)
if (e.e1.isErrorExp())
{
return e.e1;
}
@ -275,19 +270,11 @@ Expression opOverloadUnary(UnaExp e, Scope* sc)
if (!ad)
break;
Dsymbol fd = null;
/* Rewrite as:
* e1.opUnary!(op)()
*/
fd = search_function(ad, Id.opUnary);
if (fd)
{
Objects* tiargs = opToArg(sc, e.op);
result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs);
result = new CallExp(e.loc, result);
result = result.expressionSemantic(sc);
return result;
}
if (Dsymbol fd = search_function(ad, Id.opUnary))
return dotTemplateCall(e.e1, Id.opUnary, opToArg(sc, e.op)).expressionSemantic(sc);
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type))
@ -303,9 +290,19 @@ Expression opOverloadUnary(UnaExp e, Scope* sc)
}
break;
}
// For ++ and --, rewrites to += and -= are also tried, so don't error yet
if (!e.isPreExp())
{
error(e.loc, "operator `%s` is not defined for `%s`", EXPtoString(e.op).ptr, ad.toChars());
errorSupplemental(ad.loc, "perhaps overload the operator with `auto opUnary(string op : \"%s\")() {}`",
EXPtoString(e.op).ptr);
return ErrorExp.get();
}
break;
}
return result;
return null;
}
Expression opOverloadArray(ArrayExp ae, Scope* sc)
@ -313,17 +310,16 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
ae.e1 = ae.e1.expressionSemantic(sc);
ae.e1 = resolveProperties(sc, ae.e1);
Expression ae1old = ae.e1;
const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].isIntervalExp());
IntervalExp ie = null;
if (maybeSlice && ae.arguments.length)
{
ie = (*ae.arguments)[0].isIntervalExp();
}
Expression result;
Type att = null; // first cyclic `alias this` type
while (true)
{
if (ae.e1.op == EXP.error)
if (ae.e1.isErrorExp())
{
return ae.e1;
}
@ -336,67 +332,58 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
{
// If the non-aggregate expression ae.e1 is indexable or sliceable,
// convert it to the corresponding concrete expression.
if (isIndexableNonAggregate(t1b) || ae.e1.op == EXP.type)
if (isIndexableNonAggregate(t1b) || ae.e1.isTypeExp())
{
// Convert to SliceExp
if (maybeSlice)
{
result = new SliceExp(ae.loc, ae.e1, ie);
result = result.expressionSemantic(sc);
return result;
}
return new SliceExp(ae.loc, ae.e1, ie).expressionSemantic(sc);
// Convert to IndexExp
if (ae.arguments.length == 1)
{
result = new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]);
result = result.expressionSemantic(sc);
return result;
}
return new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]).expressionSemantic(sc);
}
break;
}
if (search_function(ad, Id.opIndex))
{
// Deal with $
result = resolveOpDollar(sc, ae, &e0);
if (!result) // a[i..j] might be: a.opSlice(i, j)
auto ae2 = resolveOpDollar(sc, ae, e0);
if (!ae2) // a[i..j] might be: a.opSlice(i, j)
goto Lfallback;
if (result.op == EXP.error)
return result;
if (ae2.isErrorExp())
return ae2;
/* Rewrite e1[arguments] as:
* e1.opIndex(arguments)
*/
Expressions* a = ae.arguments.copy();
result = new DotIdExp(ae.loc, ae.e1, Id.opIndex);
Expression result = new DotIdExp(ae.loc, ae.e1, Id.opIndex);
result = new CallExp(ae.loc, result, a);
if (maybeSlice) // a[] might be: a.opSlice()
result = result.trySemantic(sc);
else
result = result.expressionSemantic(sc);
if (result)
{
return Expression.combine(e0, result);
}
}
Lfallback:
if (maybeSlice && ae.e1.op == EXP.type)
if (maybeSlice && ae.e1.isTypeExp())
{
result = new SliceExp(ae.loc, ae.e1, ie);
Expression result = new SliceExp(ae.loc, ae.e1, ie);
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
return result;
return Expression.combine(e0, result);
}
if (maybeSlice && search_function(ad, Id.opSlice))
{
// Deal with $
result = resolveOpDollar(sc, ae, ie, &e0);
auto ae2 = resolveOpDollar(sc, ae, ie, e0);
if (result.op == EXP.error)
if (ae2.isErrorExp())
{
if (!e0 && !search_function(ad, Id.dollar)) {
ae.loc.errorSupplemental("Aggregate declaration '%s' does not define 'opDollar'", ae.e1.toChars());
}
return result;
if (!e0 && !search_function(ad, Id.dollar))
ad.loc.errorSupplemental("perhaps define `opDollar` for `%s`", ad.toChars());
return ae2;
}
/* Rewrite a[i..j] as:
* a.opSlice(i, j)
@ -407,11 +394,10 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
a.push(ie.lwr);
a.push(ie.upr);
}
result = new DotIdExp(ae.loc, ae.e1, Id.opSlice);
Expression result = new DotIdExp(ae.loc, ae.e1, Id.opSlice);
result = new CallExp(ae.loc, result, a);
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
return result;
return Expression.combine(e0, result);
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
@ -428,7 +414,7 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
}
ae.e1 = ae1old; // recovery
ae.lengthVar = null;
return result;
return null;
}
/***********************************************
@ -437,48 +423,38 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
*/
Expression opOverloadCast(CastExp e, Scope* sc, Type att = null)
{
Expression result;
if (AggregateDeclaration ad = isAggregate(e.e1.type))
AggregateDeclaration ad = isAggregate(e.e1.type);
if (!ad)
return null;
// Rewrite as: e1.opCast!(T)()
if (Dsymbol fd = search_function(ad, Id.opCast))
{
Dsymbol fd = null;
/* Rewrite as:
* e1.opCast!(T)()
*/
fd = search_function(ad, Id.opCast);
if (fd)
version (all)
{
version (all)
// Backwards compatibility with D1 if opCast is a function, not a template
if (fd.isFuncDeclaration())
{
// Backwards compatibility with D1 if opCast is a function, not a template
if (fd.isFuncDeclaration())
{
// Rewrite as: e1.opCast()
return build_overload(e.loc, sc, e.e1, null, fd);
}
// Rewrite as: e1.opCast()
return build_overload(e.loc, sc, e.e1, null, fd);
}
auto tiargs = new Objects();
tiargs.push(e.to);
result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs);
result = new CallExp(e.loc, result);
result = result.expressionSemantic(sc);
return result;
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type))
auto tiargs = new Objects();
tiargs.push(e.to);
return dotTemplateCall(e.e1, Id.opCast, tiargs).expressionSemantic(sc);
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type))
{
// Rewrite `e1.opCast()` as `e1.aliasthis.opCast()`
if (auto e1 = resolveAliasThis(sc, e.e1, true))
{
/* Rewrite op(e1) as:
* op(e1.aliasthis)
*/
if (auto e1 = resolveAliasThis(sc, e.e1, true))
{
result = e.copy();
(cast(UnaExp)result).e1 = e1;
result = opOverloadCast(result.isCastExp(), sc, att);
return result;
}
CastExp result = e.copy().isCastExp();
result.e1 = e1;
return result.opOverloadCast(sc, att);
}
}
return result;
return null;
}
// When no operator overload functions are found for `e`, recursively try with `alias this`
@ -488,7 +464,7 @@ Expression binAliasThis(BinExp e, Scope* sc, Type[2] aliasThisStop)
AggregateDeclaration ad1 = isAggregate(e.e1.type);
AggregateDeclaration ad2 = isAggregate(e.e2.type);
Expression rewrittenLhs;
if (!(e.op == EXP.assign && ad2 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
if (!(e.isAssignExp && ad2 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
{
if (Expression result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop))
{
@ -503,14 +479,14 @@ Expression binAliasThis(BinExp e, Scope* sc, Type[2] aliasThisStop)
* one of the members, hence the `ad1.fields.length == 2 && ad1.vthis`
* condition.
*/
if (result.op != EXP.assign)
auto ae = result.isAssignExp();
if (!ae)
return result; // i.e: Rewrote `e1 = e2` -> `e1(e2)`
auto ae = result.isAssignExp();
if (ae.e1.op != EXP.dotVariable)
auto dve = ae.e1.isDotVarExp();
if (!dve)
return result; // i.e: Rewrote `e1 = e2` -> `e1() = e2`
auto dve = ae.e1.isDotVarExp();
if (auto ad = dve.var.isMember2())
{
// i.e: Rewrote `e1 = e2` -> `e1.some.var = e2`
@ -524,7 +500,7 @@ Expression binAliasThis(BinExp e, Scope* sc, Type[2] aliasThisStop)
rewrittenLhs = ae.e1;
}
}
if (!(e.op == EXP.assign && ad1 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
if (!(e.isAssignExp && ad1 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
{
if (Expression result = checkAliasThisForRhs(ad2, sc, e, aliasThisStop))
return result;
@ -591,12 +567,104 @@ Expression opOverloadBinary(BinExp e, Scope* sc, Type[2] aliasThisStop)
s_r = null;
bool choseReverse;
if (auto res = pickBestBinaryOverload(sc, opToArg(sc, e.op), s, s_r, e, choseReverse))
return res;
if (auto result = pickBestBinaryOverload(sc, opToArg(sc, e.op), s, s_r, e, choseReverse))
return result;
return binAliasThis(e, sc, aliasThisStop);
}
/**
* If applicable, print an error relating to implementing / fixing `opBinary` functions.
* Params:
* e = binary operation
* sc = scope to try `opBinary!""` semantic in for error messages
* Returns: `true` when an error related to `opBinary` was printed
*/
bool suggestBinaryOverloads(BinExp e, Scope* sc)
{
if (!e.op.hasOpBinary)
return false;
AggregateDeclaration ad1 = isAggregate(e.e1.type);
AggregateDeclaration ad2 = isAggregate(e.e2.type);
if (ad1)
{
if (Dsymbol s = search_function(ad1, Id.opBinary))
{
// This expressionSemantic will fail, otherwise operator overloading would have succeeded before
dotTemplateCall(e.e1, Id.opBinary, opToArg(sc, e.op), e.e2).expressionSemantic(sc);
errorSupplemental(s.loc, "`opBinary` defined here");
return true;
}
error(e.loc, "operator `%s` is not defined for type `%s`", EXPtoString(e.op).ptr, e.e1.type.toChars);
errorSupplemental(ad1.loc, "perhaps overload the operator with `auto opBinary(string op : \"%s\")(%s rhs) {}`", EXPtoString(e.op).ptr, e.e2.type.toChars);
return true;
}
else if (ad2)
{
if (Dsymbol s_r = search_function(ad1, Id.opBinaryRight))
{
dotTemplateCall(e.e2, Id.opBinaryRight, opToArg(sc, e.op), e.e1).expressionSemantic(sc);
errorSupplemental(s_r.loc, "`opBinaryRight` defined here");
return true;
}
error(e.loc, "operator `%s` is not defined for type `%s`", EXPtoString(e.op).ptr, e.e2.type.toChars);
errorSupplemental(ad2.loc, "perhaps overload the operator with `auto opBinaryRight(string op : \"%s\")(%s rhs) {}`", EXPtoString(e.op).ptr, e.e1.type.toChars);
return true;
}
return false;
}
/**
* If applicable, print an error relating to implementing / fixing `opOpAssign` or `opUnary` functions.
* Params:
* exp = binary operation
* sc = scope to try `opOpAssign!""` semantic in for error messages
* parent = if `exp` was lowered from this `PreExp` or `PostExp`, mention `opUnary` as well
* Returns: `true` when an error related to `opOpAssign` was printed
*/
bool suggestOpOpAssign(BinAssignExp exp, Scope* sc, Expression parent)
{
auto ad = isAggregate(exp.e1.type);
if (!ad)
return false;
if (parent && (parent.isPreExp() || parent.isPostExp()))
{
error(exp.loc, "operator `%s` not supported for `%s` of type `%s`", EXPtoString(parent.op).ptr, exp.e1.toChars(), ad.toChars());
errorSupplemental(ad.loc,
"perhaps implement `auto opUnary(string op : \"%s\")() {}`"~
" or `auto opOpAssign(string op : \"%s\")(int) {}`",
EXPtoString(stripAssignOp(parent.op)).ptr,
EXPtoString(stripAssignOp(exp.op)).ptr
);
return true;
}
if (const s = search_function(ad, Id.opOpAssign))
{
// This expressionSemantic will fail, otherwise operator overloading would have succeeded before
dotTemplateCall(exp.e1, Id.opOpAssign, opToArg(sc, exp.op), exp.e2).expressionSemantic(sc);
}
else
{
error(exp.loc, "operator `%s` not supported for `%s` of type `%s`", EXPtoString(exp.op).ptr, exp.e1.toChars(), ad.toChars());
errorSupplemental(ad.loc, "perhaps implement `auto opOpAssign(string op : \"%s\")(%s) {}`",
EXPtoString(stripAssignOp(exp.op)).ptr, exp.e2.type.toChars());
}
return true;
}
// Helper to construct e.id!tiargs(args), e.g. `lhs.opBinary!"+"(rhs)`
private Expression dotTemplateCall(Expression e, Identifier id, Objects* tiargs, Expression[] args...)
{
auto ti = new DotTemplateInstanceExp(e.loc, e, id, tiargs);
auto expressions = new Expressions();
expressions.pushSlice(args);
return new CallExp(e.loc, ti, expressions);
}
Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
{
Type t1 = e.e1.type.toBasetype();
@ -606,24 +674,23 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
* lowering to object.__equals(), which takes care of overloaded
* operators for the element types.
*/
if ((t1.ty == Tarray || t1.ty == Tsarray) &&
(t2.ty == Tarray || t2.ty == Tsarray))
if (t1.isStaticOrDynamicArray() && t2.isStaticOrDynamicArray())
{
return null;
}
/* Check for class equality with null literal or typeof(null).
*/
if (t1.ty == Tclass && e.e2.op == EXP.null_ ||
t2.ty == Tclass && e.e1.op == EXP.null_)
if (t1.isTypeClass() && e.e2.isNullExp() ||
t2.isTypeClass() && e.e1.isNullExp())
{
error(e.loc, "use `%s` instead of `%s` when comparing with `null`",
EXPtoString(e.op == EXP.equal ? EXP.identity : EXP.notIdentity).ptr,
EXPtoString(e.op).ptr);
return ErrorExp.get();
}
if (t1.ty == Tclass && t2.ty == Tnull ||
t1.ty == Tnull && t2.ty == Tclass)
if (t1.isTypeClass() && t2.isTypeNull() ||
t1.isTypeNull() && t2.isTypeClass())
{
// Comparing a class with typeof(null) should not call opEquals
return null;
@ -631,7 +698,7 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
/* Check for class equality.
*/
if (t1.ty == Tclass && t2.ty == Tclass)
if (t1.isTypeClass() && t2.isTypeClass())
{
ClassDeclaration cd1 = t1.isClassHandle();
ClassDeclaration cd2 = t2.isClassHandle();
@ -672,7 +739,7 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
EXP cmpOp;
if (Expression result = compare_overload(e, sc, Id.opEquals, cmpOp, aliasThisStop))
{
if (lastComma(result).op == EXP.call && e.op == EXP.notEqual)
if (lastComma(result).isCallExp() && e.op == EXP.notEqual)
{
result = new NotExp(result.loc, result);
result = result.expressionSemantic(sc);
@ -682,7 +749,7 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
/* Check for pointer equality.
*/
if (t1.ty == Tpointer || t2.ty == Tpointer)
if (t1.isTypePointer() || t2.isTypePointer())
{
/* Rewrite:
* ptr1 == ptr2
@ -699,7 +766,7 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
/* Check for struct equality without opEquals.
*/
if (t1.ty == Tstruct && t2.ty == Tstruct)
if (t1.isTypeStruct() && t2.isTypeStruct())
{
auto sd = t1.isTypeStruct().sym;
if (sd != t2.isTypeStruct().sym)
@ -738,10 +805,10 @@ Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop)
/* Check for tuple equality.
*/
if (e.e1.op == EXP.tuple && e.e2.op == EXP.tuple)
auto tup1 = e.e1.isTupleExp();
auto tup2 = e.e2.isTupleExp();
if (tup1 && tup2)
{
auto tup1 = e.e1.isTupleExp();
auto tup2 = e.e2.isTupleExp();
size_t dim = tup1.exps.length;
if (dim != tup2.exps.length)
{
@ -794,12 +861,12 @@ Expression opOverloadCmp(CmpExp exp, Scope* sc, Type[2] aliasThisStop)
error(e.loc, "recursive `opCmp` expansion");
return ErrorExp.get();
}
if (e.op != EXP.call)
if (!e.isCallExp())
return e;
Type t1 = exp.e1.type.toBasetype();
Type t2 = exp.e2.type.toBasetype();
if (t1.ty != Tclass || t2.ty != Tclass)
if (!t1.isTypeClass() || !t2.isTypeClass())
{
return new CmpExp(cmpOp, exp.loc, e, IntegerExp.literal!0).expressionSemantic(sc);
}
@ -842,7 +909,7 @@ Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisSt
ae.e1 = ae.e1.expressionSemantic(sc);
ae.e1 = resolveProperties(sc, ae.e1);
Expression ae1old = ae.e1;
const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].isIntervalExp());
IntervalExp ie = null;
if (maybeSlice && ae.arguments.length)
{
@ -851,73 +918,61 @@ Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisSt
Type att = null; // first cyclic `alias this` type
while (true)
{
if (ae.e1.op == EXP.error)
{
if (ae.e1.isErrorExp())
return ae.e1;
}
Expression e0 = null;
Expression ae1save = ae.e1;
ae.lengthVar = null;
Type t1b = ae.e1.type.toBasetype();
AggregateDeclaration ad = isAggregate(t1b);
AggregateDeclaration ad = isAggregate(ae.e1.type);
if (!ad)
break;
if (search_function(ad, Id.opIndexOpAssign))
{
// Deal with $
Expression result = resolveOpDollar(sc, ae, &e0);
if (!result) // (a[i..j] op= e2) might be: a.opSliceOpAssign!(op)(e2, i, j)
Expression ae2 = resolveOpDollar(sc, ae, e0);
if (!ae2) // (a[i..j] op= e2) might be: a.opSliceOpAssign!(op)(e2, i, j)
goto Lfallback;
if (result.op == EXP.error)
return result;
result = e.e2.expressionSemantic(sc);
if (result.op == EXP.error)
return result;
e.e2 = result;
if (ae2.isErrorExp())
return ae2;
e.e2 = e.e2.expressionSemantic(sc);
if (e.e2.isErrorExp())
return e.e2;
/* Rewrite a[arguments] op= e2 as:
* a.opIndexOpAssign!(op)(e2, arguments)
*/
Expressions* a = ae.arguments.copy();
a.insert(0, e.e2);
Objects* tiargs = opToArg(sc, e.op);
result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opIndexOpAssign, tiargs);
result = new CallExp(e.loc, result, a);
Expression result = dotTemplateCall(ae.e1, Id.opIndexOpAssign, opToArg(sc, e.op), (*a)[]);
if (maybeSlice) // (a[] op= e2) might be: a.opSliceOpAssign!(op)(e2)
result = result.trySemantic(sc);
else
result = result.expressionSemantic(sc);
if (result)
{
return Expression.combine(e0, result);
}
}
Lfallback:
if (maybeSlice && search_function(ad, Id.opSliceOpAssign))
{
// Deal with $
Expression result = resolveOpDollar(sc, ae, ie, &e0);
if (result.op == EXP.error)
return result;
result = e.e2.expressionSemantic(sc);
if (result.op == EXP.error)
return result;
e.e2 = result;
Expression ae2 = resolveOpDollar(sc, ae, ie, e0);
if (ae2.isErrorExp())
return ae2;
e.e2 = e.e2.expressionSemantic(sc);
if (e.e2.isErrorExp())
return e.e2;
/* Rewrite (a[i..j] op= e2) as:
* a.opSliceOpAssign!(op)(e2, i, j)
*/
auto a = new Expressions();
a.push(e.e2);
if (ie)
{
a.push(ie.lwr);
a.push(ie.upr);
}
Objects* tiargs = opToArg(sc, e.op);
result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opSliceOpAssign, tiargs);
result = new CallExp(e.loc, result, a);
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
return result;
auto result = ie ?
dotTemplateCall(ae.e1, Id.opSliceOpAssign, opToArg(sc, e.op), e.e2, ie.lwr, ie.upr) :
dotTemplateCall(ae.e1, Id.opSliceOpAssign, opToArg(sc, e.op), e.e2);
return Expression.combine(e0, result.expressionSemantic(sc));
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
@ -934,14 +989,14 @@ Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisSt
ae.e1 = ae1old; // recovery
ae.lengthVar = null;
}
Expression result = e.binSemanticProp(sc);
if (result)
if (Expression result = e.binSemanticProp(sc))
return result;
// Don't attempt 'alias this' if an error occurred
if (e.e1.type.ty == Terror || e.e2.type.ty == Terror)
{
if (e.e1.type.isTypeError() || e.e2.type.isTypeError())
return ErrorExp.get();
}
AggregateDeclaration ad1 = isAggregate(e.e1.type);
Dsymbol s = search_function(ad1, Id.opOpAssign);
if (s && !s.isTemplateDeclaration())
@ -954,7 +1009,7 @@ Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisSt
if (auto res = pickBestBinaryOverload(sc, opToArg(sc, e.op), s, null, e, choseReverse))
return res;
result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop);
Expression result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop);
if (result || !s) // no point in trying Rhs alias-this if there's no overload of any kind in lhs
return result;
@ -990,7 +1045,7 @@ private Expression pickBestBinaryOverload(Scope* sc, Objects* tiargs, Dsymbol s,
if (s)
{
functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2));
functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2), null);
if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
return ErrorExp.get();
}
@ -998,7 +1053,7 @@ private Expression pickBestBinaryOverload(Scope* sc, Objects* tiargs, Dsymbol s,
int count = m.count;
if (s_r)
{
functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1));
functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1), null);
if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
return ErrorExp.get();
}
@ -1069,10 +1124,34 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, ref EXP
* at this point, no matching opEquals was found for structs,
* so we should not follow the alias this comparison code.
*/
if ((e.op == EXP.equal || e.op == EXP.notEqual) && ad1 == ad2)
if (e.isEqualExp() && ad1 == ad2)
return null;
Expression result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop);
return result ? result : checkAliasThisForRhs(isAggregate(e.e2.type), sc, e, aliasThisStop);
if (result)
return result;
result = checkAliasThisForRhs(isAggregate(e.e2.type), sc, e, aliasThisStop);
if (result)
return result;
if (s || s_r)
return null;
Expression suggestOverloading(Expression other, AggregateDeclaration ad)
{
error(e.loc, "no operator `%s` for type `%s`", EXPtoString(e.op).ptr, ad.toChars);
string op = e.isEqualExp() ? "bool" : "int";
errorSupplemental(ad.loc, "perhaps overload it with `%.*s %s(%s other) const {}`", op.fTuple.expand, id.toChars, other.type.toChars);
return ErrorExp.get();
}
// Classes have opCmp and opEquals defined in `Object` to fall back on already
if (ad1 && ad1.isStructDeclaration)
return suggestOverloading(e.e2, ad1);
if (ad2 && ad2.isStructDeclaration)
return suggestOverloading(e.e1, ad2);
return null;
}
/***********************************
@ -1104,7 +1183,7 @@ Dsymbol search_function(ScopeDsymbol ad, Identifier funcid)
Dsymbol s2 = s.toAlias();
//printf("search_function: s2 = '%s'\n", s2.kind());
FuncDeclaration fd = s2.isFuncDeclaration();
if (fd && fd.type.ty == Tfunction)
if (fd && fd.type.isTypeFunction())
return fd;
if (TemplateDeclaration td = s2.isTemplateDeclaration())
return td;
@ -1135,7 +1214,7 @@ bool inferForeachAggregate(Scope* sc, bool isForeach, ref Expression feaggr, out
aggr = aggr.expressionSemantic(sc);
aggr = resolveProperties(sc, aggr);
aggr = aggr.optimize(WANTvalue);
if (!aggr.type || aggr.op == EXP.error)
if (!aggr.type || aggr.isErrorExp())
return false;
Type tab = aggr.type.toBasetype();
switch (tab.ty)
@ -1149,8 +1228,7 @@ bool inferForeachAggregate(Scope* sc, bool isForeach, ref Expression feaggr, out
case Tclass:
case Tstruct:
{
AggregateDeclaration ad = (tab.ty == Tclass) ? tab.isTypeClass().sym
: tab.isTypeStruct().sym;
AggregateDeclaration ad = isAggregate(tab);
if (!sliced)
{
sapply = search_function(ad, isForeach ? Id.apply : Id.applyReverse);
@ -1240,11 +1318,11 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
// Determine ethis for sapply
Expression ethis;
Type tab = fes.aggr.type.toBasetype();
if (tab.ty == Tclass || tab.ty == Tstruct)
if (tab.isTypeClass() || tab.isTypeStruct())
ethis = fes.aggr;
else
{
assert(tab.ty == Tdelegate && fes.aggr.op == EXP.delegate_);
assert(tab.isTypeDelegate() && fes.aggr.isDelegateExp());
ethis = fes.aggr.isDelegateExp().e1;
}
@ -1284,7 +1362,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
}
p = (*fes.parameters)[1];
}
if (!p.type && tab.ty != Ttuple)
if (!p.type && !tab.isTypeTuple())
{
p.type = tab.nextOf(); // value type
p.type = p.type.addStorageClass(p.storageClass);
@ -1316,8 +1394,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
case Tclass:
case Tstruct:
{
AggregateDeclaration ad = (tab.ty == Tclass) ? tab.isTypeClass().sym
: tab.isTypeStruct().sym;
AggregateDeclaration ad = isAggregate(tab);
if (fes.parameters.length == 1)
{
if (!p.type)

View file

@ -2274,7 +2274,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
*/
private AST.Condition parseDebugCondition()
{
uint level = 1;
Identifier id = null;
Loc loc = token.loc;
@ -2290,7 +2289,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
nextToken();
check(TOK.rightParenthesis);
}
return new AST.DebugCondition(loc, mod, level, id);
return new AST.DebugCondition(loc, mod, id);
}
/**************************************
@ -2319,7 +2318,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
*/
private AST.Condition parseVersionCondition()
{
uint level = 1;
Identifier id = null;
Loc loc;
@ -2345,7 +2343,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
else
error("(condition) expected following `version`");
return new AST.VersionCondition(loc, mod, level, id);
return new AST.VersionCondition(loc, mod, id);
}
/***********************************************
@ -5379,7 +5377,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
*/
private void checkDanglingElse(Loc elseloc)
{
if (token.value != TOK.else_ && token.value != TOK.catch_ && token.value != TOK.finally_ && lookingForElse.linnum != 0)
if (token.value != TOK.else_ && token.value != TOK.catch_ && token.value != TOK.finally_ && lookingForElse.isValid)
{
eSink.warning(elseloc, "else is dangling, add { } after condition at %s", lookingForElse.toChars());
}
@ -6255,12 +6253,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (token.value == TOK.assign)
{
if (auto ds = parseDebugSpecification())
{
if (ds.ident)
eSink.error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars);
else
eSink.error(ds.loc, "%s `%s` level declaration must be at module level", ds.kind, ds.toPrettyChars);
}
eSink.error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars);
break;
}
cond = parseDebugCondition();
@ -6271,12 +6265,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (token.value == TOK.assign)
{
if (auto vs = parseVersionSpecification())
{
if (vs.ident)
eSink.error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars);
else
eSink.error(vs.loc, "%s `%s` level declaration must be at module level", vs.kind, vs.toPrettyChars);
}
eSink.error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars);
break;
}
cond = parseVersionCondition();

View file

@ -2089,7 +2089,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
// Make a copy of all the cases so that qsort doesn't scramble the actual
// data we pass to codegen (the order of the cases in the switch).
CaseStatements *csCopy = (*ss.cases).copy();
CaseStatements* csCopy = (*ss.cases).copy();
if (numcases)
{

View file

@ -79,7 +79,6 @@ public:
bool overloadInsert(Dsymbol *s) override;
bool hasStaticCtorOrDtor() override;
const char *kind() const override;
const char *toChars() const override;
Visibility visible() override;
@ -272,7 +271,6 @@ public:
Dsymbol *toAlias() override final; // resolve real symbol
const char *kind() const override;
bool oneMember(Dsymbol *&ps, Identifier *ident) override;
const char *toChars() const override;
const char* toPrettyCharsHelper() override final;
Identifier *getIdent() override final;
@ -292,7 +290,6 @@ public:
const char *kind() const override;
bool oneMember(Dsymbol *&ps, Identifier *ident) override;
bool hasPointers() override;
const char *toChars() const override;
TemplateMixin *isTemplateMixin() override { return this; }
void accept(Visitor *v) override { v->visit(this); }

View file

@ -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

View file

@ -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 *****************************************/

View file

@ -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); }

View file

@ -1622,7 +1622,7 @@ public:
if (dve->e1->op == EXP::structLiteral)
{
StructLiteralExp *sle = dve->e1->isStructLiteralExp ();
sle->useStaticInit = false;
sle->useStaticInit (false);
}
FuncDeclaration *fd = dve->var->isFuncDeclaration ();
@ -2773,7 +2773,7 @@ public:
/* Building sinit trees are delayed until after frontend semantic
processing has complete. Build the static initializer now. */
if (e->useStaticInit && !this->constp_ && !e->sd->isCsymbol ())
if (e->useStaticInit () && !this->constp_ && !e->sd->isCsymbol ())
{
tree init = aggregate_initializer_decl (e->sd);
@ -2841,7 +2841,7 @@ public:
tree field = get_symbol_decl (e->sd->vthis);
tree value = build_vthis (e->sd);
CONSTRUCTOR_APPEND_ELT (ve, field, value);
gcc_assert (e->useStaticInit == false);
gcc_assert (e->useStaticInit () == false);
}
/* Build a constructor in the correct shape of the aggregate type. */

View file

@ -1,9 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/b17285.d(14): Error: type `ONE` has no value
fail_compilation/b17285.d(14): Error: type `TWO` has no value
fail_compilation/b17285.d(14): Error: cannot implicitly convert expression `ONE` of type `b17285.ONE` to `int`
fail_compilation/b17285.d(15): Error: type `ONE` has no value
fail_compilation/b17285.d(15): perhaps use `ONE.init`
fail_compilation/b17285.d(15): Error: type `TWO` has no value
fail_compilation/b17285.d(15): Error: cannot implicitly convert expression `ONE` of type `b17285.ONE` to `int`
---
*/

View file

@ -19,11 +19,11 @@ void main()
{
T2!().F x = T1!().F();
}
/*
TEST_OUTPUT:
---
fail_compilation/bug9631.d(41): Error: incompatible types for `(x) == (y)`: `bug9631.S` and `bug9631.tem!().S`
fail_compilation/bug9631.d(41): Error: no operator `==` for type `S`
fail_compilation/bug9631.d(30): perhaps overload it with `bool opEquals(S other) const {}`
---
*/

View file

@ -2,89 +2,172 @@
REQUIRED_ARGS:
TEST_OUTPUT:
---
fail_compilation/dep_d1_ops.d(198): Error: incompatible types for `(s) + (1)`: `S` and `int`
fail_compilation/dep_d1_ops.d(199): Error: incompatible types for `(1) + (s)`: `int` and `S`
fail_compilation/dep_d1_ops.d(200): Error: incompatible types for `(s) - (1)`: `S` and `int`
fail_compilation/dep_d1_ops.d(201): Error: incompatible types for `(1) - (s)`: `int` and `S`
fail_compilation/dep_d1_ops.d(202): Error: incompatible types for `(s) * (1)`: `S` and `int`
fail_compilation/dep_d1_ops.d(203): Error: incompatible types for `(1) * (s)`: `int` and `S`
fail_compilation/dep_d1_ops.d(204): Error: incompatible types for `(s) / (1)`: `S` and `int`
fail_compilation/dep_d1_ops.d(205): Error: incompatible types for `(1) / (s)`: `int` and `S`
fail_compilation/dep_d1_ops.d(206): Error: incompatible types for `(s) % (1)`: `S` and `int`
fail_compilation/dep_d1_ops.d(207): Error: incompatible types for `(1) % (s)`: `int` and `S`
fail_compilation/dep_d1_ops.d(209): Error: incompatible types for `(s) & (1)`: `S` and `int`
fail_compilation/dep_d1_ops.d(210): Error: incompatible types for `(s) | (1)`: `S` and `int`
fail_compilation/dep_d1_ops.d(211): Error: incompatible types for `(s) ^ (1)`: `S` and `int`
fail_compilation/dep_d1_ops.d(213): Error: `s` is not of integral type, it is a `S`
fail_compilation/dep_d1_ops.d(214): Error: `s` is not of integral type, it is a `S`
fail_compilation/dep_d1_ops.d(215): Error: `s` is not of integral type, it is a `S`
fail_compilation/dep_d1_ops.d(216): Error: `s` is not of integral type, it is a `S`
fail_compilation/dep_d1_ops.d(217): Error: `s` is not of integral type, it is a `S`
fail_compilation/dep_d1_ops.d(218): Error: `s` is not of integral type, it is a `S`
fail_compilation/dep_d1_ops.d(220): Error: incompatible types for `(s) ~ (1)`: `S` and `int`
fail_compilation/dep_d1_ops.d(221): Error: incompatible types for `(1) ~ (s)`: `int` and `S`
fail_compilation/dep_d1_ops.d(223): Error: operator `+` is not defined for `s` of type `S`
fail_compilation/dep_d1_ops.d(224): Error: operator `-` is not defined for `s` of type `S`
fail_compilation/dep_d1_ops.d(225): Error: `s` is not of integral type, it is a `S`
fail_compilation/dep_d1_ops.d(226): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(227): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(228): Error: can only `*` a pointer, not a `S`
fail_compilation/dep_d1_ops.d(230): Error: incompatible types for `(s) in (1)`: `S` and `int`
fail_compilation/dep_d1_ops.d(231): Error: incompatible types for `(1) in (s)`: `int` and `S`
fail_compilation/dep_d1_ops.d(233): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(234): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(235): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(236): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(237): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(238): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(239): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(240): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(241): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(242): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(243): Error: `s` is not a scalar, it is a `S`
fail_compilation/dep_d1_ops.d(244): Error: cannot append type `int` to type `S`
fail_compilation/dep_d1_ops.d(248): Error: incompatible types for `(c) + (1)`: `dep_d1_ops.C` and `int`
fail_compilation/dep_d1_ops.d(249): Error: incompatible types for `(1) + (c)`: `int` and `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(250): Error: incompatible types for `(c) - (1)`: `dep_d1_ops.C` and `int`
fail_compilation/dep_d1_ops.d(251): Error: incompatible types for `(1) - (c)`: `int` and `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(252): Error: incompatible types for `(c) * (1)`: `dep_d1_ops.C` and `int`
fail_compilation/dep_d1_ops.d(253): Error: incompatible types for `(1) * (c)`: `int` and `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(254): Error: incompatible types for `(c) / (1)`: `dep_d1_ops.C` and `int`
fail_compilation/dep_d1_ops.d(255): Error: incompatible types for `(1) / (c)`: `int` and `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(256): Error: incompatible types for `(c) % (1)`: `dep_d1_ops.C` and `int`
fail_compilation/dep_d1_ops.d(257): Error: incompatible types for `(1) % (c)`: `int` and `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(259): Error: incompatible types for `(c) & (1)`: `dep_d1_ops.C` and `int`
fail_compilation/dep_d1_ops.d(260): Error: incompatible types for `(c) | (1)`: `dep_d1_ops.C` and `int`
fail_compilation/dep_d1_ops.d(261): Error: incompatible types for `(c) ^ (1)`: `dep_d1_ops.C` and `int`
fail_compilation/dep_d1_ops.d(263): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(264): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(265): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(266): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(267): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(268): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(270): Error: incompatible types for `(c) ~ (1)`: `dep_d1_ops.C` and `int`
fail_compilation/dep_d1_ops.d(271): Error: incompatible types for `(1) ~ (c)`: `int` and `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(273): Error: operator `+` is not defined for `c` of type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(274): Error: operator `-` is not defined for `c` of type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(275): Error: `c` is not of integral type, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(276): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(277): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(278): Error: can only `*` a pointer, not a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(280): Error: incompatible types for `(c) in (1)`: `dep_d1_ops.C` and `int`
fail_compilation/dep_d1_ops.d(281): Error: incompatible types for `(1) in (c)`: `int` and `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(283): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(284): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(285): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(286): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(287): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(288): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(289): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(290): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(291): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(292): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(293): Error: `c` is not a scalar, it is a `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(294): Error: cannot append type `int` to type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(303): Error: `nd` is not of integral type, it is a `dep_d1_ops.NoDeprecation`
fail_compilation/dep_d1_ops.d(281): Error: operator `+` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : "+")(int rhs) {}`
fail_compilation/dep_d1_ops.d(282): Error: operator `+` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinaryRight(string op : "+")(int rhs) {}`
fail_compilation/dep_d1_ops.d(283): Error: operator `-` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : "-")(int rhs) {}`
fail_compilation/dep_d1_ops.d(284): Error: operator `-` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinaryRight(string op : "-")(int rhs) {}`
fail_compilation/dep_d1_ops.d(285): Error: operator `*` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : "*")(int rhs) {}`
fail_compilation/dep_d1_ops.d(286): Error: operator `*` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinaryRight(string op : "*")(int rhs) {}`
fail_compilation/dep_d1_ops.d(287): Error: operator `/` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : "/")(int rhs) {}`
fail_compilation/dep_d1_ops.d(288): Error: operator `/` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinaryRight(string op : "/")(int rhs) {}`
fail_compilation/dep_d1_ops.d(289): Error: operator `%` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : "%")(int rhs) {}`
fail_compilation/dep_d1_ops.d(290): Error: operator `%` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinaryRight(string op : "%")(int rhs) {}`
fail_compilation/dep_d1_ops.d(292): Error: operator `&` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : "&")(int rhs) {}`
fail_compilation/dep_d1_ops.d(293): Error: operator `|` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : "|")(int rhs) {}`
fail_compilation/dep_d1_ops.d(294): Error: operator `^` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : "^")(int rhs) {}`
fail_compilation/dep_d1_ops.d(296): Error: operator `<<` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : "<<")(int rhs) {}`
fail_compilation/dep_d1_ops.d(297): Error: operator `<<` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinaryRight(string op : "<<")(int rhs) {}`
fail_compilation/dep_d1_ops.d(298): Error: operator `>>` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : ">>")(int rhs) {}`
fail_compilation/dep_d1_ops.d(299): Error: operator `>>` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinaryRight(string op : ">>")(int rhs) {}`
fail_compilation/dep_d1_ops.d(300): Error: operator `>>>` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : ">>>")(int rhs) {}`
fail_compilation/dep_d1_ops.d(301): Error: operator `>>>` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinaryRight(string op : ">>>")(int rhs) {}`
fail_compilation/dep_d1_ops.d(303): Error: operator `~` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : "~")(int rhs) {}`
fail_compilation/dep_d1_ops.d(304): Error: operator `~` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinaryRight(string op : "~")(int rhs) {}`
fail_compilation/dep_d1_ops.d(306): Error: operator `+` is not defined for `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opUnary(string op : "+")() {}`
fail_compilation/dep_d1_ops.d(307): Error: operator `-` is not defined for `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opUnary(string op : "-")() {}`
fail_compilation/dep_d1_ops.d(308): Error: operator `~` is not defined for `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opUnary(string op : "~")() {}`
fail_compilation/dep_d1_ops.d(309): Error: operator `++` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opUnary(string op : "++")() {}` or `auto opOpAssign(string op : "+")(int) {}`
fail_compilation/dep_d1_ops.d(310): Error: operator `--` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opUnary(string op : "--")() {}` or `auto opOpAssign(string op : "-")(int) {}`
fail_compilation/dep_d1_ops.d(311): Error: operator `*` is not defined for `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opUnary(string op : "*")() {}`
fail_compilation/dep_d1_ops.d(313): Error: operator `in` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinary(string op : "in")(int rhs) {}`
fail_compilation/dep_d1_ops.d(314): Error: operator `in` is not defined for type `S`
fail_compilation/dep_d1_ops.d(174): perhaps overload the operator with `auto opBinaryRight(string op : "in")(int rhs) {}`
fail_compilation/dep_d1_ops.d(316): Error: operator `+=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : "+")(int) {}`
fail_compilation/dep_d1_ops.d(317): Error: operator `-=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : "-")(int) {}`
fail_compilation/dep_d1_ops.d(318): Error: operator `*=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : "*")(int) {}`
fail_compilation/dep_d1_ops.d(319): Error: operator `/=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : "/")(int) {}`
fail_compilation/dep_d1_ops.d(320): Error: operator `%=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : "%")(int) {}`
fail_compilation/dep_d1_ops.d(321): Error: operator `&=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : "&")(int) {}`
fail_compilation/dep_d1_ops.d(322): Error: operator `|=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : "|")(int) {}`
fail_compilation/dep_d1_ops.d(323): Error: operator `^=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : "^")(int) {}`
fail_compilation/dep_d1_ops.d(324): Error: operator `<<=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : "<<")(int) {}`
fail_compilation/dep_d1_ops.d(325): Error: operator `>>=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : ">>")(int) {}`
fail_compilation/dep_d1_ops.d(326): Error: operator `>>>=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : ">>>")(int) {}`
fail_compilation/dep_d1_ops.d(327): Error: operator `~=` not supported for `s` of type `S`
fail_compilation/dep_d1_ops.d(174): perhaps implement `auto opOpAssign(string op : "~")(int) {}`
fail_compilation/dep_d1_ops.d(331): Error: operator `+` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : "+")(int rhs) {}`
fail_compilation/dep_d1_ops.d(332): Error: operator `+` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinaryRight(string op : "+")(int rhs) {}`
fail_compilation/dep_d1_ops.d(333): Error: operator `-` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : "-")(int rhs) {}`
fail_compilation/dep_d1_ops.d(334): Error: operator `-` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinaryRight(string op : "-")(int rhs) {}`
fail_compilation/dep_d1_ops.d(335): Error: operator `*` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : "*")(int rhs) {}`
fail_compilation/dep_d1_ops.d(336): Error: operator `*` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinaryRight(string op : "*")(int rhs) {}`
fail_compilation/dep_d1_ops.d(337): Error: operator `/` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : "/")(int rhs) {}`
fail_compilation/dep_d1_ops.d(338): Error: operator `/` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinaryRight(string op : "/")(int rhs) {}`
fail_compilation/dep_d1_ops.d(339): Error: operator `%` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : "%")(int rhs) {}`
fail_compilation/dep_d1_ops.d(340): Error: operator `%` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinaryRight(string op : "%")(int rhs) {}`
fail_compilation/dep_d1_ops.d(342): Error: operator `&` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : "&")(int rhs) {}`
fail_compilation/dep_d1_ops.d(343): Error: operator `|` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : "|")(int rhs) {}`
fail_compilation/dep_d1_ops.d(344): Error: operator `^` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : "^")(int rhs) {}`
fail_compilation/dep_d1_ops.d(346): Error: operator `<<` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : "<<")(int rhs) {}`
fail_compilation/dep_d1_ops.d(347): Error: operator `<<` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinaryRight(string op : "<<")(int rhs) {}`
fail_compilation/dep_d1_ops.d(348): Error: operator `>>` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : ">>")(int rhs) {}`
fail_compilation/dep_d1_ops.d(349): Error: operator `>>` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinaryRight(string op : ">>")(int rhs) {}`
fail_compilation/dep_d1_ops.d(350): Error: operator `>>>` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : ">>>")(int rhs) {}`
fail_compilation/dep_d1_ops.d(351): Error: operator `>>>` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinaryRight(string op : ">>>")(int rhs) {}`
fail_compilation/dep_d1_ops.d(353): Error: operator `~` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : "~")(int rhs) {}`
fail_compilation/dep_d1_ops.d(354): Error: operator `~` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinaryRight(string op : "~")(int rhs) {}`
fail_compilation/dep_d1_ops.d(356): Error: operator `+` is not defined for `C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opUnary(string op : "+")() {}`
fail_compilation/dep_d1_ops.d(357): Error: operator `-` is not defined for `C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opUnary(string op : "-")() {}`
fail_compilation/dep_d1_ops.d(358): Error: operator `~` is not defined for `C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opUnary(string op : "~")() {}`
fail_compilation/dep_d1_ops.d(359): Error: operator `++` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opUnary(string op : "++")() {}` or `auto opOpAssign(string op : "+")(int) {}`
fail_compilation/dep_d1_ops.d(360): Error: operator `--` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opUnary(string op : "--")() {}` or `auto opOpAssign(string op : "-")(int) {}`
fail_compilation/dep_d1_ops.d(361): Error: operator `*` is not defined for `C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opUnary(string op : "*")() {}`
fail_compilation/dep_d1_ops.d(363): Error: operator `in` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinary(string op : "in")(int rhs) {}`
fail_compilation/dep_d1_ops.d(364): Error: operator `in` is not defined for type `dep_d1_ops.C`
fail_compilation/dep_d1_ops.d(225): perhaps overload the operator with `auto opBinaryRight(string op : "in")(int rhs) {}`
fail_compilation/dep_d1_ops.d(366): Error: operator `+=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : "+")(int) {}`
fail_compilation/dep_d1_ops.d(367): Error: operator `-=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : "-")(int) {}`
fail_compilation/dep_d1_ops.d(368): Error: operator `*=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : "*")(int) {}`
fail_compilation/dep_d1_ops.d(369): Error: operator `/=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : "/")(int) {}`
fail_compilation/dep_d1_ops.d(370): Error: operator `%=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : "%")(int) {}`
fail_compilation/dep_d1_ops.d(371): Error: operator `&=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : "&")(int) {}`
fail_compilation/dep_d1_ops.d(372): Error: operator `|=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : "|")(int) {}`
fail_compilation/dep_d1_ops.d(373): Error: operator `^=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : "^")(int) {}`
fail_compilation/dep_d1_ops.d(374): Error: operator `<<=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : "<<")(int) {}`
fail_compilation/dep_d1_ops.d(375): Error: operator `>>=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : ">>")(int) {}`
fail_compilation/dep_d1_ops.d(376): Error: operator `>>>=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : ">>>")(int) {}`
fail_compilation/dep_d1_ops.d(377): Error: operator `~=` not supported for `c` of type `C`
fail_compilation/dep_d1_ops.d(225): perhaps implement `auto opOpAssign(string op : "~")(int) {}`
fail_compilation/dep_d1_ops.d(386): Error: operator `~` is not defined for `NoDeprecation`
fail_compilation/dep_d1_ops.d(390): perhaps overload the operator with `auto opUnary(string op : "~")() {}`
---
*/

View file

@ -1,13 +1,15 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag12063.d(19): Error: cannot check `diag12063.Bar.b` value for overflow
fail_compilation/diag12063.d(16): Error: no property `max` for type `Foo`, perhaps `import std.algorithm;` is needed?
fail_compilation/diag12063.d(19): Error: cannot generate value for `diag12063.Bar.b`
fail_compilation/diag12063.d(19): Error: incompatible types for `(Foo()) + (1)`: `Bar` and `int`
fail_compilation/diag12063.d(29): Error: cannot check `diag12063.b` value for overflow
fail_compilation/diag12063.d(29): Error: incompatible types for `(S()) == (1)`: `S` and `int`
fail_compilation/diag12063.d(38): Error: enum member `diag12063.d` initialization with `__anonymous.c+1` causes overflow for type `Q`
fail_compilation/diag12063.d(21): Error: cannot check `diag12063.Bar.b` value for overflow
fail_compilation/diag12063.d(18): Error: no property `max` for type `Foo`, perhaps `import std.algorithm;` is needed?
fail_compilation/diag12063.d(21): Error: cannot generate value for `diag12063.Bar.b`
fail_compilation/diag12063.d(21): Error: operator `+` is not defined for type `Bar`
fail_compilation/diag12063.d(16): perhaps overload the operator with `auto opBinary(string op : "+")(int rhs) {}`
fail_compilation/diag12063.d(31): Error: cannot check `diag12063.b` value for overflow
fail_compilation/diag12063.d(31): Error: no operator `==` for type `S`
fail_compilation/diag12063.d(24): perhaps overload it with `bool opEquals(int other) const {}`
fail_compilation/diag12063.d(40): Error: enum member `diag12063.d` initialization with `__anonymous.c+1` causes overflow for type `Q`
---
*/

View file

@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag13320.d(13): Error: `f` is not a scalar, it is a `Foo`
fail_compilation/diag13320.d(14): Error: operator `++` not supported for `f` of type `Foo`
fail_compilation/diag13320.d(9): perhaps implement `auto opUnary(string op : "++")() {}` or `auto opOpAssign(string op : "+")(int) {}`
---
*/

View file

@ -1,8 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/diag16499.d(22): Error: incompatible types for `(2) in (foo)`: `int` and `A`
fail_compilation/diag16499.d(24): Error: incompatible types for `(1.0) in (bar)`: `double` and `B`
fail_compilation/diag16499.d(24): Error: operator `in` is not defined for type `A`
fail_compilation/diag16499.d(11): perhaps overload the operator with `auto opBinaryRight(string op : "in")(int rhs) {}`
fail_compilation/diag16499.d(26): Error: operator `in` is not defined for type `B`
fail_compilation/diag16499.d(12): perhaps overload the operator with `auto opBinaryRight(string op : "in")(double rhs) {}`
---
*/

View file

@ -1,12 +1,12 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail10964.d(28): Error: function `fail10964.S.__postblit` is not `nothrow`
fail_compilation/fail10964.d(29): Error: function `fail10964.S.__postblit` is not `nothrow`
fail_compilation/fail10964.d(30): Error: function `fail10964.S.__postblit` is not `nothrow`
fail_compilation/fail10964.d(33): Error: function `fail10964.S.__postblit` is not `nothrow`
fail_compilation/fail10964.d(34): Error: function `fail10964.S.__postblit` is not `nothrow`
fail_compilation/fail10964.d(35): Error: function `fail10964.S.__postblit` is not `nothrow`
fail_compilation/fail10964.d(28): Error: function `fail10964.S.this(this)` is not `nothrow`
fail_compilation/fail10964.d(29): Error: function `fail10964.S.this(this)` is not `nothrow`
fail_compilation/fail10964.d(30): Error: function `fail10964.S.this(this)` is not `nothrow`
fail_compilation/fail10964.d(33): Error: function `fail10964.S.this(this)` is not `nothrow`
fail_compilation/fail10964.d(34): Error: function `fail10964.S.this(this)` is not `nothrow`
fail_compilation/fail10964.d(35): Error: function `fail10964.S.this(this)` is not `nothrow`
fail_compilation/fail10964.d(22): Error: function `fail10964.foo` may throw but is marked as `nothrow`
---
*/

View file

@ -1,36 +1,24 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail10968.d(43): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(43): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(44): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.arrayassign._d_arraysetassign!(SA[], SA)._d_arraysetassign`
$p:druntime/import/core/internal/array/arrayassign.d$($n$): which calls `core.lifetime.copyEmplace!(SA, SA).copyEmplace`
$p:druntime/import/core/lifetime.d$($n$): which calls `fail10968.SA.__postblit`
fail_compilation/fail10968.d(45): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(45): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(45): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.arrayassign._d_arrayassign_l!(SA[], SA)._d_arrayassign_l`
$p:druntime/import/core/internal/array/arrayassign.d$-mixin-$n$($n$): which calls `core.lifetime.copyEmplace!(SA, SA).copyEmplace`
$p:druntime/import/core/lifetime.d$($n$): which calls `fail10968.SA.__postblit`
fail_compilation/fail10968.d(48): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(48): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(49): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arraysetctor!(SA[], SA)._d_arraysetctor`
$p:druntime/import/core/internal/array/construction.d$($n$): which calls `core.lifetime.copyEmplace!(SA, SA).copyEmplace`
$p:druntime/import/core/lifetime.d$($n$): which calls `fail10968.SA.__postblit`
fail_compilation/fail10968.d(50): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(50): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit`
fail_compilation/fail10968.d(31): `fail10968.SA.__postblit` is declared here
fail_compilation/fail10968.d(50): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arrayctor!(SA[], SA)._d_arrayctor`
$p:druntime/import/core/internal/array/construction.d$($n$): which calls `core.lifetime.copyEmplace!(SA, SA).copyEmplace`
$p:druntime/import/core/lifetime.d$($n$): which calls `fail10968.SA.__postblit`
fail_compilation/fail10968.d(43): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(43): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(31): `fail10968.SA.this(this)` is declared here
fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(44): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(31): `fail10968.SA.this(this)` is declared here
fail_compilation/fail10968.d(45): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(45): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(31): `fail10968.SA.this(this)` is declared here
fail_compilation/fail10968.d(48): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(48): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(31): `fail10968.SA.this(this)` is declared here
fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(49): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(31): `fail10968.SA.this(this)` is declared here
fail_compilation/fail10968.d(50): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(50): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.this(this)`
fail_compilation/fail10968.d(31): `fail10968.SA.this(this)` is declared here
---
*/

View file

@ -1,14 +1,14 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail18143.d(20): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
fail_compilation/fail18143.d(21): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
fail_compilation/fail18143.d(25): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
fail_compilation/fail18143.d(26): Error: variable `fail18143.S.a` cannot modify parameter `this` in contract
fail_compilation/fail18143.d(35): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
fail_compilation/fail18143.d(36): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
fail_compilation/fail18143.d(40): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
fail_compilation/fail18143.d(41): Error: variable `fail18143.C.a` cannot modify parameter `this` in contract
fail_compilation/fail18143.d(20): Error: cannot modify member variable `fail18143.S.a` in contract
fail_compilation/fail18143.d(21): Error: cannot modify member variable `fail18143.S.a` in contract
fail_compilation/fail18143.d(25): Error: cannot modify member variable `fail18143.S.a` in contract
fail_compilation/fail18143.d(26): Error: cannot modify member variable `fail18143.S.a` in contract
fail_compilation/fail18143.d(35): Error: cannot modify member variable `fail18143.C.a` in contract
fail_compilation/fail18143.d(36): Error: cannot modify member variable `fail18143.C.a` in contract
fail_compilation/fail18143.d(40): Error: cannot modify member variable `fail18143.C.a` in contract
fail_compilation/fail18143.d(41): Error: cannot modify member variable `fail18143.C.a` in contract
---
*/

View file

@ -1,15 +1,19 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail18985.d(16): Error: `foo` is not a scalar, it is a `object.Object`
fail_compilation/fail18985.d(17): Error: `bar` is not a scalar, it is a `shared(Object)`
fail_compilation/fail18985.d(20): Error: operator `+=` not supported for `foo` of type `C`
fail_compilation/fail18985.d(13): perhaps implement `auto opOpAssign(string op : "+")(int) {}`
fail_compilation/fail18985.d(21): Error: operator `+=` not supported for `bar` of type `C`
fail_compilation/fail18985.d(13): perhaps implement `auto opOpAssign(string op : "+")(int) {}`
---
*/
// https://issues.dlang.org/show_bug.cgi?id=18985
Object foo;
shared Object bar;
class C {}
C foo;
shared C bar;
void main()
{

View file

@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail20.d(16): Error: need member function `opCmp()` for struct `FOO` to compare
fail_compilation/fail20.d(17): Error: no operator `<` for type `FOO`
fail_compilation/fail20.d(11): perhaps overload it with `int opCmp(FOO other) const {}`
---
*/

View file

@ -2,9 +2,9 @@
TEST_OUTPUT:
---
fail_compilation/fail20616.d(16): Error: undefined identifier `$`
fail_compilation/fail20616.d(16): Aggregate declaration 'X()' does not define 'opDollar'
fail_compilation/fail20616.d(13): perhaps define `opDollar` for `X`
fail_compilation/fail20616.d(18): Error: undefined identifier `$`
fail_compilation/fail20616.d(18): Aggregate declaration 'b' does not define 'opDollar'
fail_compilation/fail20616.d(13): perhaps define `opDollar` for `X`
---
*/
module fail20616;

View file

@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail297.d(30): Error: operator `+` is not defined for `Bar()` of type `Bar`
fail_compilation/fail297.d(31): Error: operator `+` is not defined for type `Bar`
fail_compilation/fail297.d(25): perhaps overload the operator with `auto opBinary(string op : "+")(const(Bar) rhs) {}`
---
*/

View file

@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail3.d(41): Error: operator `+` is not defined for `a` of type `vec2`
fail_compilation/fail3.d(42): Error: operator `+` is not defined for type `vec2`
fail_compilation/fail3.d(13): perhaps overload the operator with `auto opBinary(string op : "+")(vec2 rhs) {}`
---
*/

View file

@ -1,9 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail3672.d(28): Error: read-modify-write operations are not allowed for `shared` variables
fail_compilation/fail3672.d(28): Use `core.atomic.atomicOp!"+="(*p, 1)` instead
fail_compilation/fail3672.d(32): Error: none of the `opOpAssign` overloads of `SF` are callable for `*sfp` of type `shared(SF)`
fail_compilation/fail3672.d(29): Error: read-modify-write operations are not allowed for `shared` variables
fail_compilation/fail3672.d(29): Use `core.atomic.atomicOp!"+="(*p, 1)` instead
fail_compilation/fail3672.d(33): Error: template `opOpAssign` is not callable using argument types `!("+")(int) shared`
fail_compilation/fail3672.d(13): Candidate is: `opOpAssign(string op, T)(T rhs)`
---
*/

View file

@ -1,9 +1,9 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail4421.d(16): Error: function `fail4421.U1.__postblit` destructors, postblits and invariants are not allowed in union `U1`
fail_compilation/fail4421.d(16): Error: function `fail4421.U1.this(this)` destructors, postblits and invariants are not allowed in union `U1`
fail_compilation/fail4421.d(17): Error: destructor `fail4421.U1.~this` destructors, postblits and invariants are not allowed in union `U1`
fail_compilation/fail4421.d(18): Error: function `fail4421.U1.__invariant1` destructors, postblits and invariants are not allowed in union `U1`
fail_compilation/fail4421.d(18): Error: function `fail4421.U1.invariant` destructors, postblits and invariants are not allowed in union `U1`
---

View file

@ -1,8 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail6107.d(10): Error: variable `fail6107.Foo.__ctor` is not a constructor; identifiers starting with `__` are reserved for the implementation
fail_compilation/fail6107.d(14): Error: variable `fail6107.Bar.__ctor` is not a constructor; identifiers starting with `__` are reserved for the implementation
fail_compilation/fail6107.d(12): Error: variable name `__ctor` is not allowed
fail_compilation/fail6107.d(12): identifiers starting with `__` are reserved for internal use
fail_compilation/fail6107.d(16): Error: variable name `__ctor` is not allowed
fail_compilation/fail6107.d(16): identifiers starting with `__` are reserved for internal use
---
*/
struct Foo

View file

@ -9,12 +9,12 @@ fail_compilation/fail7848.d(21): `fail7848.func` is declared here
fail_compilation/fail7848.d(27): Error: `@nogc` function `fail7848.C.__unittest_L25_C30` cannot call non-@nogc function `fail7848.func`
fail_compilation/fail7848.d(27): Error: function `fail7848.func` is not `nothrow`
fail_compilation/fail7848.d(25): Error: function `fail7848.C.__unittest_L25_C30` may throw but is marked as `nothrow`
fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.__invariant0` cannot call impure function `fail7848.func`
fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.__invariant0` cannot call `@system` function `fail7848.func`
fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.invariant` cannot call impure function `fail7848.func`
fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.invariant` cannot call `@system` function `fail7848.func`
fail_compilation/fail7848.d(21): `fail7848.func` is declared here
fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.__invariant0` cannot call non-@nogc function `fail7848.func`
fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.invariant` cannot call non-@nogc function `fail7848.func`
fail_compilation/fail7848.d(32): Error: function `fail7848.func` is not `nothrow`
fail_compilation/fail7848.d(30): Error: function `fail7848.C.__invariant0` may throw but is marked as `nothrow`
fail_compilation/fail7848.d(30): Error: function `fail7848.C.invariant` may throw but is marked as `nothrow`
---
*/

View file

@ -6,7 +6,7 @@ fail_compilation/fail_arrayexp.d(25): Error: cannot use `[]` operator on express
fail_compilation/fail_arrayexp.d(26): Error: static array of `const(int)[]` with multiple lengths not allowed
fail_compilation/fail_arrayexp.d(27): Error: only one index allowed to index `string`
fail_compilation/fail_arrayexp.d(28): Error: no `[]` operator overload for type `U`
fail_compilation/fail_arrayexp.d(16): `fail_arrayexp.U` declared here
fail_compilation/fail_arrayexp.d(16): perhaps define `auto opIndex() {}` for `fail_arrayexp.U`
fail_compilation/fail_arrayexp.d(29): Error: only one index allowed to index `(int, string)`
---
*/
@ -29,3 +29,24 @@ void test19534() // https://issues.dlang.org/show_bug.cgi?id=19534
auto t = agg[];
auto u = getTuple!(int, string)[1, 2];
}
/*
TEST_OUTPUT:
---
fail_compilation/fail_arrayexp.d(49): Error: no `[3.."4"]` operator overload for type `S`
fail_compilation/fail_arrayexp.d(42): perhaps define `auto opSlice(int lower, string upper) {}` for `fail_arrayexp.S`
fail_compilation/fail_arrayexp.d(50): Error: no `[]` operator overload for type `S`
fail_compilation/fail_arrayexp.d(42): perhaps define `auto opIndex(int, string, char) {}` for `fail_arrayexp.S`
---
*/
struct S
{
}
void testSlice()
{
S s;
const b = s[3 .. "4"];
const c = s[3, "4", 'c'];
}

View file

@ -4,33 +4,33 @@
TEST_OUTPUT:
---
fail_compilation/fail_opover.d(39): Error: no `[]` operator overload for type `object.Object`
$p:object.d$(110): `object.Object` declared here
$p:object.d$(110): perhaps define `auto opIndex() {}` for `object.Object`
fail_compilation/fail_opover.d(43): Error: no `[]` operator overload for type `TestS`
fail_compilation/fail_opover.d(41): `fail_opover.test1.TestS` declared here
fail_compilation/fail_opover.d(41): perhaps define `auto opIndex() {}` for `fail_opover.test1.TestS`
fail_compilation/fail_opover.d(55): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
fail_compilation/fail_opover.d(56): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(57): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
fail_compilation/fail_opover.d(57): Error: no `[1..2]` operator overload for type `S`
fail_compilation/fail_opover.d(48): perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
fail_compilation/fail_opover.d(58): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
fail_compilation/fail_opover.d(59): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(60): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
fail_compilation/fail_opover.d(60): Error: no `[1..2]` operator overload for type `S`
fail_compilation/fail_opover.d(48): perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
fail_compilation/fail_opover.d(61): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
fail_compilation/fail_opover.d(62): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(63): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
fail_compilation/fail_opover.d(63): Error: no `[1..2]` operator overload for type `S`
fail_compilation/fail_opover.d(48): perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
fail_compilation/fail_opover.d(64): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex() {}` for `fail_opover.test2.S`
fail_compilation/fail_opover.d(65): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(66): Error: no `[]` operator overload for type `S`
fail_compilation/fail_opover.d(48): `fail_opover.test2.S` declared here
fail_compilation/fail_opover.d(48): perhaps define `auto opIndex(int) {}` for `fail_opover.test2.S`
fail_compilation/fail_opover.d(66): Error: no `[1..2]` operator overload for type `S`
fail_compilation/fail_opover.d(48): perhaps define `auto opSlice(int lower, int upper) {}` for `fail_opover.test2.S`
---
*/
void test1()

View file

@ -1,9 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice10624.d(38): Error: need member function `opCmp()` for struct `Tuple!(Msg)` to compare
fail_compilation/ice10624.d(48): Error: template instance `ice10624.Variant.handler!(Tuple!(Msg))` error instantiating
fail_compilation/ice10624.d(21): instantiated from here: `opAssign!(Tuple!(Msg))`
fail_compilation/ice10624.d(39): Error: no operator `<` for type `Tuple`
fail_compilation/ice10624.d(13): perhaps overload it with `int opCmp(Tuple!(Msg) other) const {}`
fail_compilation/ice10624.d(49): Error: template instance `ice10624.Variant.handler!(Tuple!(Msg))` error instantiating
fail_compilation/ice10624.d(22): instantiated from here: `opAssign!(Tuple!(Msg))`
---
*/

View file

@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice12902.d(20): Error: variable `ice12902.main.__dollar` - type `void` is inferred from initializer `s.opDollar()`, and variables cannot be of type `void`
fail_compilation/ice12902.d(20): Error: variable `ice12902.main.$` - type `void` is inferred from initializer `s.opDollar()`, and variables cannot be of type `void`
fail_compilation/ice12902.d(20): Error: expression `s.opDollar()` is `void` and has no value
---
*/

View file

@ -2,7 +2,8 @@
/*
TEST_OUTPUT:
----
fail_compilation/ice9545.d(13): Error: type `int` has no value
fail_compilation/ice9545.d(14): Error: type `int` has no value
fail_compilation/ice9545.d(14): perhaps use `int.init`
----
*/

View file

@ -1,7 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/operator_undefined.d(19): Error: operator `-` is not defined for `toJson(2)` of type `Json`
fail_compilation/operator_undefined.d(20): Error: operator `-` is not defined for `Json`
fail_compilation/operator_undefined.d(11): perhaps overload the operator with `auto opUnary(string op : "-")() {}`
---
*/

View file

@ -0,0 +1,31 @@
/*
REQUIRED_ARGS: -de
TEST_OUTPUT:
---
fail_compilation/test20763.d(25): Deprecation: type `ulong` has no value
fail_compilation/test20763.d(25): perhaps use `ulong.init`
fail_compilation/test20763.d(26): Deprecation: type `ulong` has no value
fail_compilation/test20763.d(26): perhaps use `ulong.init`
fail_compilation/test20763.d(27): Error: type `ulong` has no value
fail_compilation/test20763.d(27): perhaps use `ulong.init`
fail_compilation/test20763.d(28): Error: type `ulong` has no value
fail_compilation/test20763.d(28): perhaps use `ulong.init`
fail_compilation/test20763.d(29): Error: type `ulong` has no value
fail_compilation/test20763.d(29): perhaps use `ulong.init`
fail_compilation/test20763.d(30): Error: type `ulong` has no value
fail_compilation/test20763.d(30): perhaps use `ulong.init`
---
*/
// https://github.com/dlang/dmd/issues/20763
void test()
{
alias I = ulong;
alias U0 = typeof(I + 1u);
alias U1 = typeof(1 - I);
alias U2 = typeof(+I);
alias U3 = typeof(I * 1);
alias U4 = typeof(I << 1);
alias U5 = typeof(I | 1);
}

View file

@ -4,9 +4,10 @@
TEST_OUTPUT:
---
fail_compilation/imports/imp22329.d(3): Error: no property `values` for type `test22329.Foo`
fail_compilation/test22329.d(13): struct `Foo` defined here
fail_compilation/imports/imp22329.d(3): Error: incompatible types for `(arg) + (1)`: `Foo` and `int`
fail_compilation/test22329.d(21): Error: template instance `imp22329.func!(Foo)` error instantiating
fail_compilation/test22329.d(14): struct `Foo` defined here
fail_compilation/imports/imp22329.d(3): Error: operator `+` is not defined for type `Foo`
fail_compilation/test22329.d(14): perhaps overload the operator with `auto opBinary(string op : "+")(int rhs) {}`
fail_compilation/test22329.d(22): Error: template instance `imp22329.func!(Foo)` error instantiating
---
*/

View file

@ -1,4 +1,4 @@
b7e3b3b61711bf6c6cad27c7b5b73df0e570c215
d29e3eca45edaeef63b31f78c9846fc6e2870c49
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View file

@ -704,6 +704,11 @@ private int softPopcnt(N)(N x) pure
return cast(int) x;
}
version (DigitalMars) version (AArch64)
{
int _popcnt(ulong x) pure;
}
version (DigitalMars) version (AnyX86)
{
/**

View file

@ -33,7 +33,12 @@ void InitializeObjectAttributes(OBJECT_ATTRIBUTES* p, UNICODE_STRING* n,
}
}
bool NT_SUCCESS(int x) { return x >= 0; }
pragma(inline, true) @safe pure nothrow @nogc {
bool NT_SUCCESS(NTSTATUS Status) { return Status >= 0; }
bool NT_INFORMATION(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 1; }
bool NT_WARNING(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 2; }
bool NT_ERROR(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 3; }
}
/* In MinGW, NTSTATUS, UNICODE_STRING, STRING and their associated pointer
* type aliases are defined in ntdef.h, ntsecapi.h and subauth.h, each of