aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2021-12-20 19:25:32 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2021-12-20 19:29:43 +0100
commitb3f58f87d78b958e35e4a44f5fdb4b7721cb2837 (patch)
treecb6530272537c7d845faab6a1ce0042f3096f618 /gcc
parent7d5d5032c7200714388db63c7a5676b6ab3e040e (diff)
downloadgcc-b3f58f87d78b958e35e4a44f5fdb4b7721cb2837.zip
gcc-b3f58f87d78b958e35e4a44f5fdb4b7721cb2837.tar.gz
gcc-b3f58f87d78b958e35e4a44f5fdb4b7721cb2837.tar.bz2
d: Merge upstream dmd ad8412530, druntime fd9a4544, phobos 495e835c2.
D front-end changes: - Import dmd v2.098.1 - Remove calling of _d_delstruct from code generator. Druntime changes: - Import druntime v2.098.1 Phobos changes: - Import phobos v2.098.1 gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd ad8412530. * expr.cc (ExprVisitor::visit (DeleteExp *)): Remove code generation of _d_delstruct. * runtime.def (DELSTRUCT): Remove. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime fd9a4544. * src/MERGE: Merge upstream phobos 495e835c2.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/canthrow.d16
-rw-r--r--gcc/d/dmd/dcast.d73
-rw-r--r--gcc/d/dmd/dinterpret.d41
-rw-r--r--gcc/d/dmd/dsymbol.d16
-rw-r--r--gcc/d/dmd/dsymbolsem.d24
-rw-r--r--gcc/d/dmd/expressionsem.d26
-rw-r--r--gcc/d/dmd/id.d3
-rw-r--r--gcc/d/dmd/initsem.d106
-rw-r--r--gcc/d/dmd/nogc.d14
-rw-r--r--gcc/d/dmd/semantic3.d3
-rw-r--r--gcc/d/dmd/tokens.d26
-rw-r--r--gcc/d/dmd/tokens.h11
-rw-r--r--gcc/d/dmd/typesem.d178
-rw-r--r--gcc/d/expr.cc12
-rw-r--r--gcc/d/runtime.def2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22593.d13
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice17074.d12
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test22593.d23
19 files changed, 356 insertions, 245 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index d7eff4f..b42576c 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-93108bb9ea6216d67fa97bb4842fb59f26f6bfc7
+ad8412530e607ffebec36f2dbdff1a6f2798faf7
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index b67a9d1..b187715 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -82,6 +82,22 @@ extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow
if (global.errors && !ce.e1.type)
return; // error recovery
+
+ import dmd.id : Id;
+
+ if (ce.f && ce.f.ident == Id._d_delstruct)
+ {
+ // Only check if the dtor throws.
+ Type tb = (*ce.arguments)[0].type.toBasetype();
+ auto ts = tb.nextOf().baseElemOf().isTypeStruct();
+ if (ts)
+ {
+ auto sd = ts.sym;
+ if (sd.dtor)
+ checkFuncThrows(ce, sd.dtor);
+ }
+ }
+
/* If calling a function or delegate that is typed as nothrow,
* then this expression cannot throw.
* Note that pure functions can throw.
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 2e5a79d..a572a1f 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -1565,9 +1565,9 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
result = e;
return;
}
- if (e.op == EXP.variable)
+ if (auto ve = e.isVarExp())
{
- VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration();
+ VarDeclaration v = ve.var.isVarDeclaration();
if (v && v.storage_class & STC.manifest)
{
result = e.ctfeInterpret();
@@ -1852,8 +1852,8 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
override void visit(StructLiteralExp e)
{
visit(cast(Expression)e);
- if (result.op == EXP.structLiteral)
- (cast(StructLiteralExp)result).stype = t; // commit type
+ if (auto sle = result.isStructLiteralExp())
+ sle.stype = t; // commit type
}
override void visit(StringExp e)
@@ -1866,7 +1866,8 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
//printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t.toChars(), e.toChars(), e.committed);
- if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
+ if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid &&
+ (!sc || !(sc.flags & SCOPE.Cfile)))
{
e.error("cannot convert string literal to `void*`");
result = ErrorExp.get();
@@ -1883,7 +1884,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
if (!e.committed)
{
- se = cast(StringExp)e.copy();
+ se = e.copy().isStringExp();
se.committed = 1;
copied = 1;
}
@@ -1908,7 +1909,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{
if (!copied)
{
- se = cast(StringExp)e.copy();
+ se = e.copy().isStringExp();
copied = 1;
}
se.type = t;
@@ -1924,7 +1925,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
*/
if (e.committed && tb.ty == Tsarray && typeb.ty == Tarray)
{
- se = cast(StringExp)e.copy();
+ se = e.copy().isStringExp();
d_uns64 szx = tb.nextOf().size();
assert(szx <= 255);
se.sz = cast(ubyte)szx;
@@ -1952,7 +1953,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{
if (!copied)
{
- se = cast(StringExp)e.copy();
+ se = e.copy().isStringExp();
copied = 1;
}
return lcast();
@@ -1961,7 +1962,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{
if (!copied)
{
- se = cast(StringExp)e.copy();
+ se = e.copy().isStringExp();
copied = 1;
}
return lcast();
@@ -1977,7 +1978,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{
if (!copied)
{
- se = cast(StringExp)e.copy();
+ se = e.copy().isStringExp();
copied = 1;
}
if (tb.ty == Tsarray)
@@ -2088,7 +2089,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
L1:
if (!copied)
{
- se = cast(StringExp)e.copy();
+ se = e.copy().isStringExp();
copied = 1;
}
@@ -2154,10 +2155,10 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
}
// Look for pointers to functions where the functions are overloaded.
- if (e.e1.op == EXP.overloadSet &&
+ if (e.e1.isOverExp() &&
(tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
{
- OverExp eo = cast(OverExp)e.e1;
+ OverExp eo = e.e1.isOverExp();
FuncDeclaration f = null;
for (size_t i = 0; i < eo.vars.a.dim; i++)
{
@@ -2188,11 +2189,11 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
}
}
- if (e.e1.op == EXP.variable &&
+ if (e.e1.isVarExp() &&
typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
{
- auto ve = cast(VarExp)e.e1;
+ auto ve = e.e1.isVarExp();
auto f = ve.var.isFuncDeclaration();
if (f)
{
@@ -2303,7 +2304,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
goto L1;
}
- ae = cast(ArrayLiteralExp)e.copy();
+ ae = e.copy().isArrayLiteralExp();
if (e.basis)
ae.basis = e.basis.castTo(sc, tb.nextOf());
ae.elements = e.elements.copy();
@@ -2325,7 +2326,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
Type tp = typeb.nextOf().pointerTo();
if (!tp.equals(ae.type))
{
- ae = cast(ArrayLiteralExp)e.copy();
+ ae = e.copy().isArrayLiteralExp();
ae.type = tp;
}
}
@@ -2382,7 +2383,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
if (tb.ty == Taarray && typeb.ty == Taarray &&
tb.nextOf().toBasetype().ty != Tvoid)
{
- AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)e.copy();
+ AssocArrayLiteralExp ae = e.copy().isAssocArrayLiteralExp();
ae.keys = e.keys.copy();
ae.values = e.values.copy();
assert(e.keys.dim == e.values.dim);
@@ -2422,7 +2423,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{
result = e.copy();
result.type = t;
- (cast(SymOffExp)result).hasOverloads = false;
+ result.isSymOffExp().hasOverloads = false;
return;
}
@@ -2641,7 +2642,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{
Expression e1x = e.e1.implicitCastTo(sc, t1b);
assert(e1x.op != EXP.error);
- e = cast(SliceExp)e.copy();
+ e = e.copy().isSliceExp();
e.e1 = e1x;
e.type = t;
result = e;
@@ -2751,10 +2752,10 @@ Expression inferType(Expression e, Type t, int flag = 0)
if (t) switch (e.op)
{
- case EXP.arrayLiteral: return visitAle(cast(ArrayLiteralExp) e);
- case EXP.assocArrayLiteral: return visitAar(cast(AssocArrayLiteralExp) e);
- case EXP.function_: return visitFun(cast(FuncExp) e);
- case EXP.question: return visitTer(cast(CondExp) e);
+ case EXP.arrayLiteral: return visitAle(e.isArrayLiteralExp());
+ case EXP.assocArrayLiteral: return visitAar(e.isAssocArrayLiteralExp());
+ case EXP.function_: return visitFun(e.isFuncExp());
+ case EXP.question: return visitTer(e.isCondExp());
default:
}
return e;
@@ -2830,9 +2831,9 @@ Expression scaleFactor(BinExp be, Scope* sc)
*/
private bool isVoidArrayLiteral(Expression e, Type other)
{
- while (e.op == EXP.arrayLiteral && e.type.ty == Tarray && ((cast(ArrayLiteralExp)e).elements.dim == 1))
+ while (e.op == EXP.arrayLiteral && e.type.ty == Tarray && (e.isArrayLiteralExp().elements.dim == 1))
{
- auto ale = cast(ArrayLiteralExp)e;
+ auto ale = e.isArrayLiteralExp();
e = ale[0];
if (other.ty == Tsarray || other.ty == Tarray)
other = other.nextOf();
@@ -2842,7 +2843,7 @@ private bool isVoidArrayLiteral(Expression e, Type other)
if (other.ty != Tsarray && other.ty != Tarray)
return false;
Type t = e.type;
- return (e.op == EXP.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && (cast(ArrayLiteralExp)e).elements.dim == 0);
+ return (e.op == EXP.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && e.isArrayLiteralExp().elements.dim == 0);
}
/**
@@ -3463,20 +3464,20 @@ LmodCompare:
Expression rhs = e2;
// T[x .. y] op ?
- if (e1.isSliceExp())
- lhs = new IndexExp(Loc.initial, (cast(UnaExp)e1).e1, IntegerExp.literal!0);
+ if (auto se1 = e1.isSliceExp())
+ lhs = new IndexExp(Loc.initial, se1.e1, IntegerExp.literal!0);
// [t1, t2, .. t3] op ?
- if (e1.isArrayLiteralExp())
- lhs = (cast(ArrayLiteralExp)e1).opIndex(0);
+ if (auto ale1 = e1.isArrayLiteralExp())
+ lhs = ale1.opIndex(0);
// ? op U[z .. t]
- if (e2.isSliceExp())
- rhs = new IndexExp(Loc.initial, (cast(UnaExp)e2).e1, IntegerExp.literal!0);
+ if (auto se2 = e2.isSliceExp())
+ rhs = new IndexExp(Loc.initial, se2.e1, IntegerExp.literal!0);
// ? op [u1, u2, .. u3]
- if (e2.isArrayLiteralExp())
- rhs = (cast(ArrayLiteralExp)e2).opIndex(0);
+ if (auto ale2 = e2.isArrayLiteralExp())
+ rhs = ale2.opIndex(0);
// create a new binary expression with the new lhs and rhs (at this stage, at least
// one of lhs/rhs has been replaced with the 0'th element of the array it was before)
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 8f20c38..fc5b9a8 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -4837,6 +4837,47 @@ public:
result = interpret(ce, istate);
return;
}
+ else if (fd.ident == Id._d_delstruct)
+ {
+ // Only interpret the dtor and the argument.
+ assert(e.arguments.dim == 1);
+
+ Type tb = (*e.arguments)[0].type.toBasetype();
+ auto ts = tb.nextOf().baseElemOf().isTypeStruct();
+ if (ts)
+ {
+ result = interpretRegion((*e.arguments)[0], istate);
+ if (exceptionOrCant(result))
+ return;
+
+ if (result.op == EXP.null_)
+ {
+ result = CTFEExp.voidexp;
+ return;
+ }
+
+ if (result.op != EXP.address ||
+ (cast(AddrExp)result).e1.op != EXP.structLiteral)
+ {
+ e.error("`delete` on invalid struct pointer `%s`", result.toChars());
+ result = CTFEExp.cantexp;
+ return;
+ }
+
+ auto sd = ts.sym;
+ if (sd.dtor)
+ {
+ auto sle = cast(StructLiteralExp)(cast(AddrExp)result).e1;
+ result = interpretFunction(pue, sd.dtor, istate, null, sle);
+ if (exceptionOrCant(result))
+ return;
+
+ result = CTFEExp.voidexp;
+ }
+ }
+
+ return;
+ }
}
else if (auto soe = ecall.isSymOffExp())
{
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 0f75157..e34a94a 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -2453,10 +2453,10 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
if (i1 && i2)
return collision(); // can't both have initializers
- if (i1)
+ if (i1) // vd is the definition
{
- vd2._init = vd._init;
- vd._init = null;
+ sds.symtab.update(vd); // replace vd2 with the definition
+ return vd;
}
/* BUG: the types should match, which needs semantic() to be run on it
@@ -2497,14 +2497,10 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
if (fd.fbody && fd2.fbody)
return collision(); // can't both have bodies
- if (fd.fbody)
+ if (fd.fbody) // fd is the definition
{
- fd2.fbody = fd.fbody; // transfer body to existing declaration
- fd.fbody = null;
-
- auto tf = fd.type.toTypeFunction();
- auto tf2 = fd2.type.toTypeFunction();
- tf2.parameterList = tf.parameterList; // transfer parameter list.
+ sds.symtab.update(fd); // replace fd2 in symbol table with fd
+ return fd;
}
/* BUG: just like with VarDeclaration, the types should match, which needs semantic() to be run on it.
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 3a9abd2d..118b861 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -3981,15 +3981,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
return;
TypeFunction tf = ctd.type.toTypeFunction();
+ immutable dim = tf.parameterList.length;
+ auto sd = ad.isStructDeclaration();
/* See if it's the default constructor
* But, template constructor should not become a default constructor.
*/
if (ad && (!ctd.parent.isTemplateInstance() || ctd.parent.isTemplateMixin()))
{
- immutable dim = tf.parameterList.length;
-
- if (auto sd = ad.isStructDeclaration())
+ if (sd)
{
if (dim == 0 && tf.parameterList.varargs == VarArg.none) // empty default ctor w/o any varargs
{
@@ -4034,6 +4034,24 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
ad.defaultCtor = ctd;
}
}
+ // https://issues.dlang.org/show_bug.cgi?id=22593
+ else if (auto ti = ctd.parent.isTemplateInstance())
+ {
+ if (sd && sd.hasCopyCtor && (dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
+ {
+ auto param = tf.parameterList[0];
+
+ // if the template instance introduces an rvalue constructor
+ // between the members of a struct declaration, we should check if a
+ // copy constructor exists and issue an error in that case.
+ if (!(param.storageClass & STC.ref_) && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
+ {
+ .error(ctd.loc, "Cannot define both an rvalue constructor and a copy constructor for `struct %s`", sd.toChars);
+ .errorSupplemental(ti.loc, "Template instance `%s` creates a rvalue constructor for `struct %s`",
+ ti.toChars(), sd.toChars());
+ }
+ }
+ }
}
override void visit(PostBlitDeclaration pbd)
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 48e47ce..2f1cd47 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -7316,6 +7316,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
deprecation(exp.loc, "The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.");
}
+ Expression e = exp;
+
if (Expression ex = unaSemantic(exp, sc))
{
result = ex;
@@ -7352,7 +7354,27 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (tb.ty == Tstruct)
{
ad = (cast(TypeStruct)tb).sym;
- semanticTypeInfo(sc, tb);
+
+ Identifier hook = global.params.tracegc ? Id._d_delstructTrace : Id._d_delstruct;
+ if (!verifyHookExist(exp.loc, *sc, Id._d_delstructImpl, "deleting struct with dtor", Id.object))
+ return setError();
+
+ // Lower to .object._d_delstruct{,Trace}(exp.e1)
+ Expression id = new IdentifierExp(exp.loc, Id.empty);
+ id = new DotIdExp(exp.loc, id, Id.object);
+
+ auto tiargs = new Objects();
+ tiargs.push(exp.e1.type);
+ id = new DotTemplateInstanceExp(exp.loc, id, Id._d_delstructImpl, tiargs);
+ id = new DotIdExp(exp.loc, id, hook);
+
+ e = new CallExp(exp.loc, id, exp.e1);
+ /* Gag errors generated by calls to `_d_delstruct`, because they display
+ * internal compiler information, which is unnecessary to the user.
+ */
+ uint errors = global.startGagging();
+ e = e.expressionSemantic(sc);
+ global.endGagging(errors);
}
break;
@@ -7397,7 +7419,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (err)
return setError();
- result = exp;
+ result = e;
}
override void visit(CastExp exp)
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 83c89c0..d33b676 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -311,6 +311,9 @@ immutable Msgtable[] msgtable =
{ "__ArrayPostblit" },
{ "__ArrayDtor" },
{ "_d_delThrowable" },
+ { "_d_delstructImpl" },
+ { "_d_delstruct" },
+ { "_d_delstructTrace" },
{ "_d_assert_fail" },
{ "dup" },
{ "_aaApply" },
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index 51ee27d..826b0ad 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -284,7 +284,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
case Tarray:
break;
case Tvector:
- t = (cast(TypeVector)t).basetype;
+ t = t.isTypeVector().basetype;
break;
case Taarray:
case Tstruct: // consider implicit constructor call
@@ -346,7 +346,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
// found a tuple, expand it
if (ei && ei.exp.op == EXP.tuple)
{
- TupleExp te = cast(TupleExp)ei.exp;
+ TupleExp te = ei.exp.isTupleExp();
i.index.remove(j);
i.value.remove(j);
for (size_t k = 0; k < te.exps.dim; ++k)
@@ -462,7 +462,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
{
return i; // Failed, suppress duplicate error messages
}
- if (i.exp.type.ty == Ttuple && (cast(TypeTuple)i.exp.type).arguments.dim == 0)
+ if (i.exp.type.isTypeTuple() && i.exp.type.isTypeTuple().arguments.dim == 0)
{
Type et = i.exp.type;
i.exp = new TupleExp(i.exp.loc, new Expressions());
@@ -492,12 +492,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
*/
if (i.exp.op == EXP.string_ && tb.ty == Tsarray)
{
- StringExp se = cast(StringExp)i.exp;
+ StringExp se = i.exp.isStringExp();
Type typeb = se.type.toBasetype();
TY tynto = tb.nextOf().ty;
if (!se.committed &&
(typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
- se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
+ se.numberOfCodeUnits(tynto) < tb.isTypeSArray().dim.toInteger())
{
i.exp = se.castTo(sc, t);
goto L1;
@@ -520,7 +520,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
// Look for implicit constructor call
if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !i.exp.implicitConvTo(t))
{
- StructDeclaration sd = (cast(TypeStruct)tb).sym;
+ StructDeclaration sd = tb.isTypeStruct().sym;
if (sd.ctor)
{
// Rewrite as S().ctor(exp)
@@ -573,18 +573,16 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
// better diagnostic message, as same as AssignExp::semantic.
if (tb.ty == Tsarray && i.exp.implicitConvTo(tb.nextOf().arrayOf()) > MATCH.nomatch)
{
- uinteger_t dim1 = (cast(TypeSArray)tb).dim.toInteger();
+ uinteger_t dim1 = tb.isTypeSArray().dim.toInteger();
uinteger_t dim2 = dim1;
- if (i.exp.op == EXP.arrayLiteral)
+ if (auto ale = i.exp.isArrayLiteralExp())
{
- ArrayLiteralExp ale = cast(ArrayLiteralExp)i.exp;
dim2 = ale.elements ? ale.elements.dim : 0;
}
- else if (i.exp.op == EXP.slice)
+ else if (auto se = i.exp.isSliceExp())
{
- Type tx = toStaticArrayType(cast(SliceExp)i.exp);
- if (tx)
- dim2 = (cast(TypeSArray)tx).dim.toInteger();
+ if (Type tx = toStaticArrayType(se))
+ dim2 = tx.isTypeSArray().dim.toInteger();
}
if (dim1 != dim2)
{
@@ -746,10 +744,11 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
* Params:
* t = element type
* dim = max number of elements
+ * simple = true if array of simple elements
* Returns:
* # of elements in array
*/
- size_t array(Type t, size_t dim)
+ size_t array(Type t, size_t dim, ref bool simple)
{
//printf(" type %s i %d dim %d dil.length = %d\n", t.toChars(), cast(int)i, cast(int)dim, cast(int)dil.length);
auto tn = t.nextOf().toBasetype();
@@ -791,14 +790,30 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
if (tnsa && di.initializer.isExpInitializer())
{
// no braces enclosing array initializer, so recurse
- array(tnsa, nelems);
+ array(tnsa, nelems, simple);
}
else if (auto tns = tn.isTypeStruct())
{
- if (di.initializer.isExpInitializer())
+ if (auto ei = di.initializer.isExpInitializer())
{
// no braces enclosing struct initializer
- dil[n].initializer = structs(tns);
+
+ /* Disambiguate between an exp representing the entire
+ * struct, and an exp representing the first field of the struct
+ */
+ if (needInterpret)
+ sc = sc.startCTFE();
+ ei.exp = ei.exp.expressionSemantic(sc);
+ ei.exp = resolveProperties(sc, ei.exp);
+ if (needInterpret)
+ sc = sc.endCTFE();
+ if (ei.exp.implicitConvTo(tn))
+ di.initializer = elem(di.initializer); // the whole struct
+ else
+ {
+ simple = false;
+ dil[n].initializer = structs(tns); // the first field
+ }
}
else
dil[n].initializer = elem(di.initializer);
@@ -816,7 +831,8 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
}
size_t dim = tsa.isIncomplete() ? dil.length : cast(size_t)tsa.dim.toInteger();
- auto newdim = array(t, dim);
+ bool simple = true;
+ auto newdim = array(t, dim, simple);
if (errors)
return err();
@@ -849,7 +865,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
/* If an array of simple elements, replace with an ArrayInitializer
*/
auto tnb = tn.toBasetype();
- if (!(tnb.isTypeSArray() || tnb.isTypeStruct()))
+ if (!tnb.isTypeSArray() && (!tnb.isTypeStruct() || simple))
{
auto ai = new ArrayInitializer(ci.loc);
ai.dim = cast(uint) dil.length;
@@ -884,12 +900,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
final switch (init.kind)
{
- case InitKind.void_: return visitVoid (cast( VoidInitializer)init);
- case InitKind.error: return visitError (cast( ErrorInitializer)init);
- case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
- case InitKind.array: return visitArray (cast( ArrayInitializer)init);
- case InitKind.exp: return visitExp (cast( ExpInitializer)init);
- case InitKind.C_: return visitC (cast( CInitializer)init);
+ case InitKind.void_: return visitVoid (init.isVoidInitializer());
+ case InitKind.error: return visitError (init.isErrorInitializer());
+ case InitKind.struct_: return visitStruct(init.isStructInitializer());
+ case InitKind.array: return visitArray (init.isArrayInitializer());
+ case InitKind.exp: return visitExp (init.isExpInitializer());
+ case InitKind.C_: return visitC (init.isCInitializer());
}
}
@@ -943,8 +959,7 @@ Initializer inferType(Initializer init, Scope* sc)
{
return iz;
}
- assert(iz.isExpInitializer());
- (*values)[i] = (cast(ExpInitializer)iz).exp;
+ (*values)[i] = iz.isExpInitializer().exp;
assert(!(*values)[i].isErrorExp());
}
Expression e = new AssocArrayLiteralExp(init.loc, keys, values);
@@ -966,8 +981,7 @@ Initializer inferType(Initializer init, Scope* sc)
{
return iz;
}
- assert(iz.isExpInitializer());
- (*elements)[i] = (cast(ExpInitializer)iz).exp;
+ (*elements)[i] = iz.isExpInitializer().exp;
assert(!(*elements)[i].isErrorExp());
}
Expression e = new ArrayLiteralExp(init.loc, null, elements);
@@ -996,9 +1010,8 @@ Initializer inferType(Initializer init, Scope* sc)
init.exp = resolveAliasThis(sc, init.exp);
init.exp = resolveProperties(sc, init.exp);
- if (init.exp.op == EXP.scope_)
+ if (auto se = init.exp.isScopeExp())
{
- ScopeExp se = cast(ScopeExp)init.exp;
TemplateInstance ti = se.sds.isTemplateInstance();
if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl)
se.error("cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars());
@@ -1021,16 +1034,15 @@ Initializer inferType(Initializer init, Scope* sc)
return new ErrorInitializer();
}
}
- if (init.exp.op == EXP.address)
+ if (auto ae = init.exp.isAddrExp())
{
- AddrExp ae = cast(AddrExp)init.exp;
if (ae.e1.op == EXP.overloadSet)
{
init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
return new ErrorInitializer();
}
}
- if (init.exp.op == EXP.error)
+ if (init.exp.isErrorExp())
{
return new ErrorInitializer();
}
@@ -1050,12 +1062,12 @@ Initializer inferType(Initializer init, Scope* sc)
final switch (init.kind)
{
- case InitKind.void_: return visitVoid (cast( VoidInitializer)init);
- case InitKind.error: return visitError (cast( ErrorInitializer)init);
- case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
- case InitKind.array: return visitArray (cast( ArrayInitializer)init);
- case InitKind.exp: return visitExp (cast( ExpInitializer)init);
- case InitKind.C_: return visitC (cast( CInitializer)init);
+ case InitKind.void_: return visitVoid (init.isVoidInitializer());
+ case InitKind.error: return visitError (init.isErrorInitializer());
+ case InitKind.struct_: return visitStruct(init.isStructInitializer());
+ case InitKind.array: return visitArray (init.isArrayInitializer());
+ case InitKind.exp: return visitExp (init.isExpInitializer());
+ case InitKind.C_: return visitC (init.isCInitializer());
}
}
@@ -1260,12 +1272,12 @@ extern (C++) Expression initializerToExpression(Initializer init, Type itype = n
final switch (init.kind)
{
- case InitKind.void_: return visitVoid (cast( VoidInitializer)init);
- case InitKind.error: return visitError (cast( ErrorInitializer)init);
- case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
- case InitKind.array: return visitArray (cast( ArrayInitializer)init);
- case InitKind.exp: return visitExp (cast( ExpInitializer)init);
- case InitKind.C_: return visitC (cast( CInitializer)init);
+ case InitKind.void_: return visitVoid (init.isVoidInitializer());
+ case InitKind.error: return visitError (init.isErrorInitializer());
+ case InitKind.struct_: return visitStruct(init.isStructInitializer());
+ case InitKind.array: return visitArray (init.isArrayInitializer());
+ case InitKind.exp: return visitExp (init.isExpInitializer());
+ case InitKind.C_: return visitC (init.isCInitializer());
}
}
@@ -1308,7 +1320,7 @@ private bool hasNonConstPointers(Expression e)
{
if (ae.type.nextOf().hasPointers() && checkArray(ae.values))
return true;
- if ((cast(TypeAArray)ae.type).index.hasPointers())
+ if (ae.type.isTypeAArray().index.hasPointers())
return checkArray(ae.keys);
return false;
}
diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index 31a25a7..8bdddb8 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -83,6 +83,20 @@ public:
}
f.printGCUsage(e.loc, "setting `length` may cause a GC allocation");
}
+ else if (fd.ident == Id._d_delstruct)
+ {
+ // In expressionsem.d, `delete s` was lowererd to `_d_delstruct(s)`.
+ // The following code handles the call like the original expression,
+ // so the error is menaningful to the user.
+ if (f.setGC())
+ {
+ e.error("cannot use `delete` in `@nogc` %s `%s`", f.kind(),
+ f.toPrettyChars());
+ err = true;
+ return;
+ }
+ f.printGCUsage(e.loc, "`delete` requires the GC");
+ }
}
override void visit(ArrayLiteralExp e)
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index da328fd..49b87d6 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -419,8 +419,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
sc2.insert(_arguments);
_arguments.parent = funcdecl;
}
- if ((f.linkage == LINK.d || f.parameterList.length) &&
- !(sc.flags & SCOPE.Cfile)) // don't want to require importing stdarg for C files
+ if (f.linkage == LINK.d || f.parameterList.length)
{
// Declare _argptr
Type t = target.va_listType(funcdecl.loc, sc);
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index 2d98d5e..e5b05d3 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -23,7 +23,7 @@ import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.utf;
-enum TOK : ushort
+enum TOK : ubyte
{
reserved,
@@ -84,10 +84,7 @@ enum TOK : ushort
rightShiftAssign,
unsignedRightShift,
unsignedRightShiftAssign,
- concatenate,
concatenateAssign, // ~=
- concatenateElemAssign,
- concatenateDcharAssign,
add,
min,
addAssign,
@@ -109,15 +106,11 @@ enum TOK : ushort
tilde,
plusPlus,
minusMinus,
- construct,
- blit,
dot,
comma,
question,
andAnd,
orOr,
- prePlusPlus,
- preMinusMinus,
// Numeric literals
int32Literal,
@@ -144,7 +137,6 @@ enum TOK : ushort
hexadecimalString,
this_,
super_,
- tuple,
error,
// Basic types
@@ -244,7 +236,6 @@ enum TOK : ushort
parameters,
traits,
- overloadSet,
pure_,
nothrow_,
gshared,
@@ -564,7 +555,6 @@ private immutable TOK[] keywords =
TOK.gshared,
TOK.traits,
TOK.vector,
- TOK.overloadSet,
TOK.file,
TOK.fileFullPath,
TOK.line,
@@ -769,7 +759,6 @@ extern (C++) struct Token
TOK.gshared: "__gshared",
TOK.traits: "__traits",
TOK.vector: "__vector",
- TOK.overloadSet: "__overloadset",
TOK.file: "__FILE__",
TOK.fileFullPath: "__FILE_FULL_PATH__",
TOK.line: "__LINE__",
@@ -793,8 +782,6 @@ extern (C++) struct Token
TOK.xor: "^",
TOK.xorAssign: "^=",
TOK.assign: "=",
- TOK.construct: "=",
- TOK.blit: "=",
TOK.lessThan: "<",
TOK.greaterThan: ">",
TOK.lessOrEqual: "<=",
@@ -824,8 +811,6 @@ extern (C++) struct Token
TOK.dollar: "$",
TOK.plusPlus: "++",
TOK.minusMinus: "--",
- TOK.prePlusPlus: "++",
- TOK.preMinusMinus: "--",
TOK.type: "type",
TOK.question: "?",
TOK.negate: "-",
@@ -842,9 +827,6 @@ extern (C++) struct Token
TOK.andAssign: "&=",
TOK.orAssign: "|=",
TOK.concatenateAssign: "~=",
- TOK.concatenateElemAssign: "~=",
- TOK.concatenateDcharAssign: "~=",
- TOK.concatenate: "~",
TOK.call: "call",
TOK.identity: "is",
TOK.notIdentity: "!is",
@@ -860,7 +842,6 @@ extern (C++) struct Token
// For debugging
TOK.error: "error",
TOK.string_: "string",
- TOK.tuple: "tuple",
TOK.declaration: "declaration",
TOK.onScopeExit: "scope(exit)",
TOK.onScopeSuccess: "scope(success)",
@@ -1113,11 +1094,6 @@ nothrow:
return toString(value).ptr;
}
- static const(char)* toChars(ushort value)
- {
- return toString(cast(TOK)value).ptr;
- }
-
extern (D) static string toString(TOK value) pure nothrow @nogc @safe
{
return tochars[value];
diff --git a/gcc/d/dmd/tokens.h b/gcc/d/dmd/tokens.h
index 2e1d1f4..e095aa6 100644
--- a/gcc/d/dmd/tokens.h
+++ b/gcc/d/dmd/tokens.h
@@ -32,7 +32,7 @@ class Identifier;
? && ||
*/
-enum class TOK : unsigned short
+enum class TOK : unsigned char
{
reserved,
@@ -93,10 +93,7 @@ enum class TOK : unsigned short
rightShiftAssign,
unsignedRightShift,
unsignedRightShiftAssign,
- concatenate,
concatenateAssign, // ~=
- concatenateElemAssign,
- concatenateDcharAssign,
add,
min,
addAssign,
@@ -118,15 +115,11 @@ enum class TOK : unsigned short
tilde,
plusPlus,
minusMinus,
- construct,
- blit,
dot,
comma,
question,
andAnd,
orOr,
- prePlusPlus,
- preMinusMinus,
// Numeric literals
int32Literal, // 104,
@@ -153,7 +146,6 @@ enum class TOK : unsigned short
hexadecimalString,
this_,
super_,
- tuple,
error,
// Basic types
@@ -253,7 +245,6 @@ enum class TOK : unsigned short
parameters, // 210
traits,
- overloadSet,
pure_,
nothrow_,
gshared,
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 2a86416..b8c4317 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -271,7 +271,7 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb
sm = null;
}
// Same check as in Expression.semanticY(DotIdExp)
- else if (sm.isPackage() && checkAccess(sc, cast(Package)sm))
+ else if (sm.isPackage() && checkAccess(sc, sm.isPackage()))
{
// @@@DEPRECATED_2.096@@@
// Should be an error in 2.106. Just remove the deprecation call
@@ -509,7 +509,7 @@ private Type stripDefaultArgs(Type t)
Parameters* params = stripParams(tf.parameterList.parameters);
if (tret == tf.next && params == tf.parameterList.parameters)
return t;
- TypeFunction tr = cast(TypeFunction)tf.copy();
+ TypeFunction tr = tf.copy().isTypeFunction();
tr.parameterList.parameters = params;
tr.next = tret;
//printf("strip %s\n <- %s\n", tr.toChars(), t.toChars());
@@ -520,7 +520,7 @@ private Type stripDefaultArgs(Type t)
Parameters* args = stripParams(tt.arguments);
if (args == tt.arguments)
return t;
- TypeTuple tr = cast(TypeTuple)t.copy();
+ TypeTuple tr = t.copy().isTypeTuple();
tr.arguments = args;
return tr;
}
@@ -588,11 +588,11 @@ Expression typeToExpression(Type t)
return null;
switch (t.ty)
{
- case Tsarray: return visitSArray(cast(TypeSArray) t);
- case Taarray: return visitAArray(cast(TypeAArray) t);
- case Tident: return visitIdentifier(cast(TypeIdentifier) t);
- case Tinstance: return visitInstance(cast(TypeInstance) t);
- case Tmixin: return visitMixin(cast(TypeMixin) t);
+ case Tsarray: return visitSArray(t.isTypeSArray());
+ case Taarray: return visitAArray(t.isTypeAArray());
+ case Tident: return visitIdentifier(t.isTypeIdentifier());
+ case Tinstance: return visitInstance(t.isTypeInstance());
+ case Tmixin: return visitMixin(t.isTypeMixin());
default: return null;
}
}
@@ -684,7 +684,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
.error(loc, "T in __vector(T) must be a static array, not `%s`", mtype.basetype.toChars());
return error();
}
- TypeSArray t = cast(TypeSArray)mtype.basetype;
+ TypeSArray t = mtype.basetype.isTypeSArray();
const sz = cast(int)t.size(loc);
final switch (target.isVectorTypeSupported(sz, t.nextOf()))
{
@@ -790,8 +790,8 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
return overflowError();
Type tbx = tbn.baseElemOf();
- if (tbx.ty == Tstruct && !(cast(TypeStruct)tbx).sym.members ||
- tbx.ty == Tenum && !(cast(TypeEnum)tbx).sym.members)
+ if (tbx.ty == Tstruct && !tbx.isTypeStruct().sym.members ||
+ tbx.ty == Tenum && !tbx.isTypeEnum().sym.members)
{
/* To avoid meaningless error message, skip the total size limit check
* when the bottom of element type is opaque.
@@ -802,7 +802,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
tbn.ty == Tarray ||
tbn.ty == Tsarray ||
tbn.ty == Taarray ||
- (tbn.ty == Tstruct && ((cast(TypeStruct)tbn).sym.sizeok == Sizeok.done)) ||
+ (tbn.ty == Tstruct && tbn.isTypeStruct().sym.sizeok == Sizeok.done) ||
tbn.ty == Tclass)
{
/* Only do this for types that don't need to have semantic()
@@ -819,7 +819,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
{
// Index the tuple to get the type
assert(mtype.dim);
- TypeTuple tt = cast(TypeTuple)tbn;
+ TypeTuple tt = tbn.isTypeTuple();
uinteger_t d = mtype.dim.toUInteger();
if (d >= tt.arguments.dim)
{
@@ -1026,9 +1026,9 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
*/
}
}
- else if (tbase.ty == Tclass && !(cast(TypeClass)tbase).sym.isInterfaceDeclaration())
+ else if (tbase.ty == Tclass && !tbase.isTypeClass().sym.isInterfaceDeclaration())
{
- ClassDeclaration cd = (cast(TypeClass)tbase).sym;
+ ClassDeclaration cd = tbase.isTypeClass().sym;
if (cd.semanticRun < PASS.semanticdone)
cd.dsymbolSemantic(null);
@@ -1275,7 +1275,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
}
if (e.op == EXP.function_) // https://issues.dlang.org/show_bug.cgi?id=4820
{
- FuncExp fe = cast(FuncExp)e;
+ FuncExp fe = e.isFuncExp();
// Replace function literal with a function symbol,
// since default arg expression must be copied when used
// and copying the literal itself is wrong.
@@ -1402,8 +1402,8 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
(t.ty == Tstruct || t.ty == Tsarray || t.ty == Tenum))
{
Type tb2 = t.baseElemOf();
- if (tb2.ty == Tstruct && !(cast(TypeStruct)tb2).sym.members ||
- tb2.ty == Tenum && !(cast(TypeEnum)tb2).sym.memtype)
+ if (tb2.ty == Tstruct && !tb2.isTypeStruct().sym.members ||
+ tb2.ty == Tenum && !tb2.isTypeEnum().sym.memtype)
{
if (global.params.previewIn && (fparam.storageClass & STC.in_))
{
@@ -1467,7 +1467,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
else
{
Type tv = t.baseElemOf();
- if (tv.ty == Tstruct && (cast(TypeStruct)tv).sym.noDefaultCtor)
+ if (tv.ty == Tstruct && tv.isTypeStruct().sym.noDefaultCtor)
{
.error(loc, "cannot have `out` parameter of type `%s` because the default construction is disabled", fparam.type.toChars());
errors = true;
@@ -1824,26 +1824,26 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
switch (e.op)
{
case EXP.dotVariable:
- mtype.sym = (cast(DotVarExp)e).var;
+ mtype.sym = e.isDotVarExp().var;
break;
case EXP.variable:
- mtype.sym = (cast(VarExp)e).var;
+ mtype.sym = e.isVarExp().var;
break;
case EXP.function_:
- auto fe = cast(FuncExp)e;
+ auto fe = e.isFuncExp();
mtype.sym = fe.td ? fe.td : fe.fd;
break;
case EXP.dotTemplateDeclaration:
- mtype.sym = (cast(DotTemplateExp)e).td;
+ mtype.sym = e.isDotTemplateExp().td;
break;
case EXP.dSymbol:
- mtype.sym = (cast(DsymbolExp)e).s;
+ mtype.sym = e.isDsymbolExp().s;
break;
case EXP.template_:
- mtype.sym = (cast(TemplateExp)e).td;
+ mtype.sym = e.isTemplateExp().td;
break;
case EXP.scope_:
- mtype.sym = (cast(ScopeExp)e).sds;
+ mtype.sym = e.isScopeExp().sds;
break;
case EXP.tuple:
TupleExp te = e.toTupleExp();
@@ -1854,13 +1854,13 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
switch (src.op)
{
case EXP.type:
- (*elems)[i] = (cast(TypeExp)src).type;
+ (*elems)[i] = src.isTypeExp().type;
break;
case EXP.dotType:
- (*elems)[i] = (cast(DotTypeExp)src).sym.isType();
+ (*elems)[i] = src.isDotTypeExp().sym.isType();
break;
case EXP.overloadSet:
- (*elems)[i] = (cast(OverExp)src).type;
+ (*elems)[i] = src.isOverExp().type;
break;
default:
if (auto sym = isDsymbol(src))
@@ -1873,13 +1873,13 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
mtype.sym = td;
break;
case EXP.dotType:
- result = (cast(DotTypeExp)e).sym.isType();
+ result = e.isDotTypeExp().sym.isType();
break;
case EXP.type:
- result = (cast(TypeExp)e).type;
+ result = e.isTypeExp().type;
break;
case EXP.overloadSet:
- result = (cast(OverExp)e).type;
+ result = e.isOverExp().type;
break;
default:
break;
@@ -2211,26 +2211,26 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
switch (type.ty)
{
default: return visitType(type);
- case Tvector: return visitVector(cast(TypeVector)type);
- case Tsarray: return visitSArray(cast(TypeSArray)type);
- case Tarray: return visitDArray(cast(TypeDArray)type);
- case Taarray: return visitAArray(cast(TypeAArray)type);
- case Tpointer: return visitPointer(cast(TypePointer)type);
- case Treference: return visitReference(cast(TypeReference)type);
- case Tfunction: return visitFunction(cast(TypeFunction)type);
- case Tdelegate: return visitDelegate(cast(TypeDelegate)type);
- case Tident: return visitIdentifier(cast(TypeIdentifier)type);
- case Tinstance: return visitInstance(cast(TypeInstance)type);
- case Ttypeof: return visitTypeof(cast(TypeTypeof)type);
- case Ttraits: return visitTraits(cast(TypeTraits)type);
- case Treturn: return visitReturn(cast(TypeReturn)type);
- case Tstruct: return visitStruct(cast(TypeStruct)type);
- case Tenum: return visitEnum(cast(TypeEnum)type);
- case Tclass: return visitClass(cast(TypeClass)type);
- case Ttuple: return visitTuple (cast(TypeTuple)type);
- case Tslice: return visitSlice(cast(TypeSlice)type);
- case Tmixin: return visitMixin(cast(TypeMixin)type);
- case Ttag: return visitTag(cast(TypeTag)type);
+ case Tvector: return visitVector(type.isTypeVector());
+ case Tsarray: return visitSArray(type.isTypeSArray());
+ case Tarray: return visitDArray(type.isTypeDArray());
+ case Taarray: return visitAArray(type.isTypeAArray());
+ case Tpointer: return visitPointer(type.isTypePointer());
+ case Treference: return visitReference(type.isTypeReference());
+ case Tfunction: return visitFunction(type.isTypeFunction());
+ case Tdelegate: return visitDelegate(type.isTypeDelegate());
+ case Tident: return visitIdentifier(type.isTypeIdentifier());
+ case Tinstance: return visitInstance(type.isTypeInstance());
+ case Ttypeof: return visitTypeof(type.isTypeTypeof());
+ case Ttraits: return visitTraits(type.isTypeTraits());
+ case Treturn: return visitReturn(type.isTypeReturn());
+ case Tstruct: return visitStruct(type.isTypeStruct());
+ case Tenum: return visitEnum(type.isTypeEnum());
+ case Tclass: return visitClass(type.isTypeClass());
+ case Ttuple: return visitTuple(type.isTypeTuple());
+ case Tslice: return visitSlice(type.isTypeSlice());
+ case Tmixin: return visitMixin(type.isTypeMixin());
+ case Ttag: return visitTag(type.isTypeTag());
}
}
@@ -2300,7 +2300,7 @@ extern (C++) Type merge(Type type)
case Tsarray:
// prevents generating the mangle if the array dim is not yet known
- if (!(cast(TypeSArray) type).dim.isIntegerExp())
+ if (!type.isTypeSArray().dim.isIntegerExp())
return type;
goto default;
@@ -2308,7 +2308,7 @@ extern (C++) Type merge(Type type)
break;
case Taarray:
- if (!(cast(TypeAArray)type).index.merge().deco)
+ if (!type.isTypeAArray().index.merge().deco)
return type;
goto default;
@@ -2761,10 +2761,10 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
visitBasic(cast(TypeBasic)t) :
visitType(t);
- case Terror: return visitError (cast(TypeError)t);
- case Tvector: return visitVector(cast(TypeVector)t);
- case Tenum: return visitEnum (cast(TypeEnum)t);
- case Ttuple: return visitTuple (cast(TypeTuple)t);
+ case Terror: return visitError (t.isTypeError());
+ case Tvector: return visitVector(t.isTypeVector());
+ case Tenum: return visitEnum (t.isTypeEnum());
+ case Ttuple: return visitTuple (t.isTypeTuple());
}
}
@@ -2889,7 +2889,7 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
{
Expression e = cast(Expression)o;
if (e.op == EXP.dSymbol)
- return returnSymbol((cast(DsymbolExp)e).s);
+ return returnSymbol(e.isDsymbolExp().s);
else
return returnExp(e);
}
@@ -3154,8 +3154,8 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
* template functions.
*/
}
- if (auto f = mt.exp.op == EXP.variable ? (cast( VarExp)mt.exp).var.isFuncDeclaration()
- : mt.exp.op == EXP.dotVariable ? (cast(DotVarExp)mt.exp).var.isFuncDeclaration() : null)
+ if (auto f = mt.exp.op == EXP.variable ? mt.exp.isVarExp().var.isFuncDeclaration()
+ : mt.exp.op == EXP.dotVariable ? mt.exp.isDotVarExp().var.isFuncDeclaration() : null)
{
// f might be a unittest declaration which is incomplete when compiled
// without -unittest. That causes a segfault in checkForwardRef, see
@@ -3350,17 +3350,17 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
switch (mt.ty)
{
- default: visitType (mt); break;
- case Tsarray: visitSArray (cast(TypeSArray)mt); break;
- case Tarray: visitDArray (cast(TypeDArray)mt); break;
- case Taarray: visitAArray (cast(TypeAArray)mt); break;
- case Tident: visitIdentifier(cast(TypeIdentifier)mt); break;
- case Tinstance: visitInstance (cast(TypeInstance)mt); break;
- case Ttypeof: visitTypeof (cast(TypeTypeof)mt); break;
- case Treturn: visitReturn (cast(TypeReturn)mt); break;
- case Tslice: visitSlice (cast(TypeSlice)mt); break;
- case Tmixin: visitMixin (cast(TypeMixin)mt); break;
- case Ttraits: visitTraits (cast(TypeTraits)mt); break;
+ default: visitType (mt); break;
+ case Tsarray: visitSArray (mt.isTypeSArray()); break;
+ case Tarray: visitDArray (mt.isTypeDArray()); break;
+ case Taarray: visitAArray (mt.isTypeAArray()); break;
+ case Tident: visitIdentifier(mt.isTypeIdentifier()); break;
+ case Tinstance: visitInstance (mt.isTypeInstance()); break;
+ case Ttypeof: visitTypeof (mt.isTypeTypeof()); break;
+ case Treturn: visitReturn (mt.isTypeReturn()); break;
+ case Tslice: visitSlice (mt.isTypeSlice()); break;
+ case Tmixin: visitMixin (mt.isTypeMixin()); break;
+ case Ttraits: visitTraits (mt.isTypeTraits()); break;
}
}
@@ -4616,16 +4616,16 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
switch (mt.ty)
{
- case Tvector: return visitVector (cast(TypeVector)mt);
- case Tsarray: return visitSArray (cast(TypeSArray)mt);
- case Tstruct: return visitStruct (cast(TypeStruct)mt);
- case Tenum: return visitEnum (cast(TypeEnum)mt);
- case Terror: return visitError (cast(TypeError)mt);
- case Tarray: return visitDArray (cast(TypeDArray)mt);
- case Taarray: return visitAArray (cast(TypeAArray)mt);
- case Treference: return visitReference(cast(TypeReference)mt);
- case Tdelegate: return visitDelegate (cast(TypeDelegate)mt);
- case Tclass: return visitClass (cast(TypeClass)mt);
+ case Tvector: return visitVector (mt.isTypeVector());
+ case Tsarray: return visitSArray (mt.isTypeSArray());
+ case Tstruct: return visitStruct (mt.isTypeStruct());
+ case Tenum: return visitEnum (mt.isTypeEnum());
+ case Terror: return visitError (mt.isTypeError());
+ case Tarray: return visitDArray (mt.isTypeDArray());
+ case Taarray: return visitAArray (mt.isTypeAArray());
+ case Treference: return visitReference(mt.isTypeReference());
+ case Tdelegate: return visitDelegate (mt.isTypeDelegate());
+ case Tclass: return visitClass (mt.isTypeClass());
default: return mt.isTypeBasic()
? visitBasic(cast(TypeBasic)mt)
@@ -4786,12 +4786,12 @@ extern (C++) Expression defaultInit(Type mt, const ref Loc loc, const bool isCfi
switch (mt.ty)
{
- case Tvector: return visitVector (cast(TypeVector)mt);
- case Tsarray: return visitSArray (cast(TypeSArray)mt);
- case Tfunction: return visitFunction(cast(TypeFunction)mt);
- case Tstruct: return visitStruct (cast(TypeStruct)mt);
- case Tenum: return visitEnum (cast(TypeEnum)mt);
- case Ttuple: return visitTuple (cast(TypeTuple)mt);
+ case Tvector: return visitVector (mt.isTypeVector());
+ case Tsarray: return visitSArray (mt.isTypeSArray());
+ case Tfunction: return visitFunction(mt.isTypeFunction());
+ case Tstruct: return visitStruct (mt.isTypeStruct());
+ case Tenum: return visitEnum (mt.isTypeEnum());
+ case Ttuple: return visitTuple (mt.isTypeTuple());
case Tnull: return new NullExp(Loc.initial, Type.tnull);
@@ -4803,7 +4803,7 @@ extern (C++) Expression defaultInit(Type mt, const ref Loc loc, const bool isCfi
case Treference:
case Tdelegate:
case Tclass: return new NullExp(loc, mt);
- case Tnoreturn: return visitNoreturn(cast(TypeNoreturn) mt);
+ case Tnoreturn: return visitNoreturn(mt.isTypeNoreturn());
default: return mt.isTypeBasic() ?
visitBasic(cast(TypeBasic)mt) :
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index f1c014d..665d122 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -1477,16 +1477,10 @@ public:
t1 = build_address (t1);
Type *tnext = tb1->isTypePointer ()->next->toBasetype ();
+ /* This case should have been rewritten to `_d_delstruct` in the
+ semantic phase. */
if (TypeStruct *ts = tnext->isTypeStruct ())
- {
- if (ts->sym->dtor)
- {
- tree ti = build_typeinfo (e->loc, tnext);
- this->result_ = build_libcall (LIBCALL_DELSTRUCT, Type::tvoid,
- 2, t1, ti);
- return;
- }
- }
+ gcc_assert (!ts->sym->dtor);
/* Otherwise, the garbage collector is called to immediately free the
memory allocated for the pointer. */
diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def
index 3961a1d..ef54a37 100644
--- a/gcc/d/runtime.def
+++ b/gcc/d/runtime.def
@@ -85,8 +85,6 @@ DEF_D_RUNTIME (NEWITEMIT, "_d_newitemiT", RT(VOIDPTR), P1(CONST_TYPEINFO), 0)
/* Used when calling delete on a pointer. */
DEF_D_RUNTIME (DELMEMORY, "_d_delmemory", RT(VOID), P1(POINTER_VOIDPTR), 0)
-DEF_D_RUNTIME (DELSTRUCT, "_d_delstruct", RT(VOID),
- P2(POINTER_VOIDPTR, TYPEINFO), 0)
/* Used when calling new on an array. The `i' variant is for when the
initializer is nonzero, and the `m' variant is when initializing a
diff --git a/gcc/testsuite/gdc.test/compilable/test22593.d b/gcc/testsuite/gdc.test/compilable/test22593.d
new file mode 100644
index 0000000..2091294
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22593.d
@@ -0,0 +1,13 @@
+// https://issues.dlang.org/show_bug.cgi?id=22593
+
+struct Foo(T){
+ this(Rhs, this This)(scope Rhs rhs){
+ }
+
+ this(ref scope typeof(this) rhs){
+ }
+}
+
+struct Bar{
+ Foo!int foo;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice17074.d b/gcc/testsuite/gdc.test/fail_compilation/ice17074.d
index 53e75e4..84c4d85 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice17074.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice17074.d
@@ -1,19 +1,13 @@
/*
-TEST_OUTPUT:
----
-fail_compilation/ice17074.d(9): Error: identifier expected for C++ namespace
-fail_compilation/ice17074.d(9): Error: found `__overloadset` when expecting `)`
-fail_compilation/ice17074.d(9): Error: declaration expected, not `)`
----
*/
extern(C++, std.__overloadset) void ice_std_keyword();
/*
TEST_OUTPUT:
---
-fail_compilation/ice17074.d(19): Error: identifier expected for C++ namespace
-fail_compilation/ice17074.d(19): Error: found `*` when expecting `)`
-fail_compilation/ice17074.d(19): Error: declaration expected, not `)`
+fail_compilation/ice17074.d(13): Error: identifier expected for C++ namespace
+fail_compilation/ice17074.d(13): Error: found `*` when expecting `)`
+fail_compilation/ice17074.d(13): Error: declaration expected, not `)`
---
*/
extern(C++, std.*) void ice_std_token();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22593.d b/gcc/testsuite/gdc.test/fail_compilation/test22593.d
new file mode 100644
index 0000000..f90287e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22593.d
@@ -0,0 +1,23 @@
+// https://issues.dlang.org/show_bug.cgi?id=22593
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test22593.d(14): Error: Cannot define both an rvalue constructor and a copy constructor for `struct Foo`
+fail_compilation/test22593.d(22): Template instance `__ctor!(immutable(Foo!int), immutable(Foo!int))` creates a rvalue constructor for `struct Foo`
+fail_compilation/test22593.d(22): Error: template instance `test22593.Foo!int.Foo.__ctor!(immutable(Foo!int), immutable(Foo!int))` error instantiating
+---
+*/
+
+struct Foo(T)
+{
+ this(Rhs, this This)(scope Rhs rhs){}
+
+ this(ref scope typeof(this) rhs){}
+}
+
+void main()
+{
+ immutable Foo!int a;
+ a.__ctor(a);
+}