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.
This commit is contained in:
parent
7d5d5032c7
commit
b3f58f87d7
28 changed files with 468 additions and 272 deletions
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -311,6 +311,9 @@ immutable Msgtable[] msgtable =
|
|||
{ "__ArrayPostblit" },
|
||||
{ "__ArrayDtor" },
|
||||
{ "_d_delThrowable" },
|
||||
{ "_d_delstructImpl" },
|
||||
{ "_d_delstruct" },
|
||||
{ "_d_delstructTrace" },
|
||||
{ "_d_assert_fail" },
|
||||
{ "dup" },
|
||||
{ "_aaApply" },
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) :
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
13
gcc/testsuite/gdc.test/compilable/test22593.d
Normal file
13
gcc/testsuite/gdc.test/compilable/test22593.d
Normal file
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
|
|
23
gcc/testsuite/gdc.test/fail_compilation/test22593.d
Normal file
23
gcc/testsuite/gdc.test/fail_compilation/test22593.d
Normal file
|
@ -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);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
6364e010bc87f3621028c8ac648133535c126fb3
|
||||
fd9a45448244fb9dd4326520ad8526c540895eb0
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/druntime repository.
|
||||
|
|
|
@ -1,11 +1,45 @@
|
|||
/**********************************************
|
||||
* This module implements common builtins for the D frontend.
|
||||
*
|
||||
* Copyright: Copyright © 2019, The D Language Foundation
|
||||
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
|
||||
* Authors: Walter Bright
|
||||
* Source: $(DRUNTIMESRC core/builtins.d)
|
||||
*/
|
||||
To provide access to features that would be otherwise counterproductive or
|
||||
difficult to implement, compilers provide an interface consisting of a set
|
||||
of builtins (also called intrinsics) which can be called like normal functions.
|
||||
|
||||
This module exposes builtins both common to all D compilers
|
||||
(those provided by the frontend) and specific to the host compiler i.e. those
|
||||
specific to either LLVM or GCC (`ldc.intrinsics` and `gcc.builtins` are publicly imported, respectively).
|
||||
Host-specific intrinsics cannot be reliably listed here, however listings can be found
|
||||
at the documentation for the relevant backends, i.e.
|
||||
$(LINK2 https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html, GCC) and
|
||||
$(LINK2 https://llvm.org/docs/LangRef.html, LLVM). It should be noted that not all
|
||||
builtins listed are necessarily supported by the host compiler, please file a bug
|
||||
if this is the case for your workload.
|
||||
|
||||
Use of this module reduces the amount of conditional compilation needed
|
||||
to use a given builtin. For example, to write a target independent function
|
||||
that uses prefetching we can write the following:
|
||||
---
|
||||
float usePrefetch(float[] x)
|
||||
{
|
||||
// There is only one import statement required rather than two (versioned) imports
|
||||
import core.builtins;
|
||||
version (GNU)
|
||||
__builtin_prefetch(x.ptr);
|
||||
version (LDC)
|
||||
/+
|
||||
For the curious: 0, 3, 1 mean `x` will only be read-from (0), it will be used
|
||||
very often (3), and it should be fetched to the data-cache (1).
|
||||
+/
|
||||
llvm_prefetch(x.ptr, 0, 3, 1);
|
||||
const doMath = blahBlahBlah;
|
||||
return doMath;
|
||||
}
|
||||
---
|
||||
|
||||
|
||||
Copyright: Copyright © 2021, The D Language Foundation
|
||||
License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
|
||||
Authors: Walter Bright
|
||||
Source: $(DRUNTIMESRC core/builtins.d)
|
||||
*/
|
||||
|
||||
module core.builtins;
|
||||
|
||||
|
|
|
@ -1545,9 +1545,8 @@ template forward(args...)
|
|||
{
|
||||
import core.internal.traits : AliasSeq;
|
||||
|
||||
static if (args.length)
|
||||
template fwd(alias arg)
|
||||
{
|
||||
alias arg = args[0];
|
||||
// by ref || lazy || const/immutable
|
||||
static if (__traits(isRef, arg) ||
|
||||
__traits(isOut, arg) ||
|
||||
|
@ -1556,15 +1555,16 @@ template forward(args...)
|
|||
alias fwd = arg;
|
||||
// (r)value
|
||||
else
|
||||
@property auto fwd(){ return move(arg); }
|
||||
|
||||
static if (args.length == 1)
|
||||
alias forward = fwd;
|
||||
else
|
||||
alias forward = AliasSeq!(fwd, forward!(args[1..$]));
|
||||
@property auto fwd(){ pragma(inline, true); return move(arg); }
|
||||
}
|
||||
|
||||
alias Result = AliasSeq!();
|
||||
static foreach (arg; args)
|
||||
Result = AliasSeq!(Result, fwd!arg);
|
||||
static if (Result.length == 1)
|
||||
alias forward = Result[0];
|
||||
else
|
||||
alias forward = AliasSeq!();
|
||||
alias forward = Result;
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -2316,7 +2316,7 @@ template _d_delstructImpl(T)
|
|||
@system pure nothrow unittest
|
||||
{
|
||||
int dtors = 0;
|
||||
struct S { ~this() { ++dtors; } }
|
||||
struct S { ~this() nothrow { ++dtors; } }
|
||||
|
||||
S *s = new S();
|
||||
_d_delstructImpl!(typeof(s))._d_delstruct(s);
|
||||
|
|
|
@ -153,6 +153,9 @@ version (CRuntime_Glibc)
|
|||
int sched_getcpu();
|
||||
}
|
||||
|
||||
/* Reassociate the calling thread with namespace referred to by fd */
|
||||
int setns(int fd, int nstype);
|
||||
|
||||
enum CLONE_FILES = 0x400;
|
||||
enum CLONE_FS = 0x200;
|
||||
enum CLONE_NEWCGROUP = 0x2000000;
|
||||
|
|
|
@ -4667,17 +4667,33 @@ public import core.internal.switch_: __switch_error;
|
|||
public @trusted @nogc nothrow pure extern (C) void _d_delThrowable(scope Throwable);
|
||||
|
||||
// Compare class and interface objects for ordering.
|
||||
private int __cmp(Obj)(Obj lhs, Obj rhs)
|
||||
if (is(Obj : Object))
|
||||
int __cmp(C1, C2)(C1 lhs, C2 rhs)
|
||||
if ((is(C1 : const(Object)) || (is(C1 == interface) && (__traits(getLinkage, C1) == "D"))) &&
|
||||
(is(C2 : const(Object)) || (is(C2 == interface) && (__traits(getLinkage, C2) == "D"))))
|
||||
{
|
||||
if (lhs is rhs)
|
||||
static if (is(C1 == typeof(null)) && is(C2 == typeof(null)))
|
||||
{
|
||||
return 0;
|
||||
// Regard null references as always being "less than"
|
||||
if (!lhs)
|
||||
}
|
||||
else static if (is(C1 == typeof(null)))
|
||||
{
|
||||
// Regard null references as always being "less than"
|
||||
return -1;
|
||||
if (!rhs)
|
||||
}
|
||||
else static if (is(C2 == typeof(null)))
|
||||
{
|
||||
return 1;
|
||||
return lhs.opCmp(rhs);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lhs is rhs)
|
||||
return 0;
|
||||
if (lhs is null)
|
||||
return -1;
|
||||
if (rhs is null)
|
||||
return 1;
|
||||
return lhs.opCmp(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
// objects
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
575b67a9b4f78415f96ca77ad50b2de4c667cc74
|
||||
495e835c2da47606142ff24c85de707e3b955a9a
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/phobos repository.
|
||||
|
|
|
@ -1287,3 +1287,26 @@ void formatValue(Writer, T, Char)(auto ref Writer w, auto ref T val, scope const
|
|||
|
||||
assertThrown!FormatException(formattedWrite(w, "%(%0*d%)", new int[1]));
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=22609
|
||||
@safe pure unittest
|
||||
{
|
||||
static enum State: ubyte { INACTIVE }
|
||||
static struct S {
|
||||
State state = State.INACTIVE;
|
||||
int generation = 1;
|
||||
alias state this;
|
||||
// DMDBUG: https://issues.dlang.org/show_bug.cgi?id=16657
|
||||
auto opEquals(S other) const { return state == other.state && generation == other.generation; }
|
||||
auto opEquals(State other) const { return state == other; }
|
||||
}
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto writer = appender!string();
|
||||
const spec = singleSpec("%s");
|
||||
S a;
|
||||
writer.formatValue(a, spec);
|
||||
assert(writer.data == "0");
|
||||
}
|
||||
|
|
|
@ -201,6 +201,9 @@ interface RandomAccessFinite(E) : BidirectionalRange!(E) {
|
|||
|
||||
/**Interface for an infinite random access range of type `E`.*/
|
||||
interface RandomAccessInfinite(E) : ForwardRange!E {
|
||||
///
|
||||
enum bool empty = false;
|
||||
|
||||
/**Calls $(REF moveAt, std, range, primitives) on the wrapped range, if
|
||||
* possible. Otherwise, throws an $(LREF UnsupportedRangeMethod) exception.
|
||||
*/
|
||||
|
@ -213,6 +216,12 @@ interface RandomAccessInfinite(E) : ForwardRange!E {
|
|||
E opIndex(size_t);
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=22608
|
||||
@safe unittest
|
||||
{
|
||||
static assert(isRandomAccessRange!(RandomAccessInfinite!int));
|
||||
}
|
||||
|
||||
/**Adds assignable elements to InputRange.*/
|
||||
interface InputAssignable(E) : InputRange!E {
|
||||
///
|
||||
|
|
|
@ -6971,7 +6971,7 @@ mixin template Proxy(alias a)
|
|||
static if (is(typeof(a.opCmp(b))))
|
||||
return a.opCmp(b);
|
||||
else static if (is(typeof(b.opCmp(a))))
|
||||
return -b.opCmp(b);
|
||||
return -b.opCmp(a);
|
||||
else
|
||||
return a < b ? -1 : a > b ? +1 : 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue