d: Merge upstream dmd 821ed393d, druntime 454471d8, phobos 1206fc94f.
D front-end changes: - Import latest bug fixes to mainline. D runtime changes: - Fix duplicate Elf64_Dyn definitions on Solaris. - _d_newThrowable has been converted to a template. Phobos changes: - Import latest bug fixes to mainline. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 821ed393d. * expr.cc (ExprVisitor::visit (NewExp *)): Remove handled of allocating `@nogc' throwable object. * runtime.def (NEWTHROW): Remove. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 454471d8. * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add core/sync/package.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos 1206fc94f.
This commit is contained in:
parent
13ea4a6e83
commit
ec486b739b
62 changed files with 1029 additions and 712 deletions
|
@ -1,4 +1,4 @@
|
|||
4d07f22f29d098869ad937f0499d8895df089a71
|
||||
821ed393d428c7db5a48623e77d43f5647d5c6a2
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/dmd repository.
|
||||
|
|
|
@ -1274,14 +1274,14 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration
|
|||
* declarations.
|
||||
*/
|
||||
|
||||
extern(C++) final class ForwardingAttribDeclaration: AttribDeclaration
|
||||
extern(C++) final class ForwardingAttribDeclaration : AttribDeclaration
|
||||
{
|
||||
ForwardingScopeDsymbol sym = null;
|
||||
|
||||
this(Dsymbols* decl)
|
||||
{
|
||||
super(decl);
|
||||
sym = new ForwardingScopeDsymbol(null);
|
||||
sym = new ForwardingScopeDsymbol();
|
||||
sym.symtab = new DsymbolTable();
|
||||
}
|
||||
|
||||
|
@ -1298,7 +1298,7 @@ extern(C++) final class ForwardingAttribDeclaration: AttribDeclaration
|
|||
*/
|
||||
override void addMember(Scope* sc, ScopeDsymbol sds)
|
||||
{
|
||||
parent = sym.parent = sym.forward = sds;
|
||||
sym.parent = sds;
|
||||
return super.addMember(sc, sym);
|
||||
}
|
||||
|
||||
|
|
|
@ -5156,26 +5156,80 @@ final class CParser(AST) : Parser!AST
|
|||
{
|
||||
auto id = n.ident;
|
||||
scan(&n);
|
||||
if (n.value == TOK.endOfLine) // #define identifier
|
||||
|
||||
AST.Type t;
|
||||
|
||||
switch (n.value)
|
||||
{
|
||||
nextDefineLine();
|
||||
continue;
|
||||
}
|
||||
if (n.value == TOK.int32Literal)
|
||||
{
|
||||
const value = n.intvalue;
|
||||
scan(&n);
|
||||
if (n.value == TOK.endOfLine)
|
||||
{
|
||||
/* Declare manifest constant:
|
||||
* enum id = value;
|
||||
*/
|
||||
AST.Expression e = new AST.IntegerExp(scanloc, value, AST.Type.tint32);
|
||||
auto v = new AST.VarDeclaration(scanloc, AST.Type.tint32, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
|
||||
symbols.push(v);
|
||||
case TOK.endOfLine: // #define identifier
|
||||
nextDefineLine();
|
||||
continue;
|
||||
}
|
||||
|
||||
case TOK.int32Literal:
|
||||
case TOK.charLiteral: t = AST.Type.tint32; goto Linteger;
|
||||
case TOK.uns32Literal: t = AST.Type.tuns32; goto Linteger;
|
||||
case TOK.int64Literal: t = AST.Type.tint64; goto Linteger;
|
||||
case TOK.uns64Literal: t = AST.Type.tuns64; goto Linteger;
|
||||
|
||||
Linteger:
|
||||
const intvalue = n.intvalue;
|
||||
scan(&n);
|
||||
if (n.value == TOK.endOfLine)
|
||||
{
|
||||
/* Declare manifest constant:
|
||||
* enum id = intvalue;
|
||||
*/
|
||||
AST.Expression e = new AST.IntegerExp(scanloc, intvalue, t);
|
||||
auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
|
||||
symbols.push(v);
|
||||
nextDefineLine();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOK.float32Literal: t = AST.Type.tfloat32; goto Lfloat;
|
||||
case TOK.float64Literal: t = AST.Type.tfloat64; goto Lfloat;
|
||||
case TOK.float80Literal: t = AST.Type.tfloat80; goto Lfloat;
|
||||
case TOK.imaginary32Literal: t = AST.Type.timaginary32; goto Lfloat;
|
||||
case TOK.imaginary64Literal: t = AST.Type.timaginary64; goto Lfloat;
|
||||
case TOK.imaginary80Literal: t = AST.Type.timaginary80; goto Lfloat;
|
||||
|
||||
Lfloat:
|
||||
const floatvalue = n.floatvalue;
|
||||
scan(&n);
|
||||
if (n.value == TOK.endOfLine)
|
||||
{
|
||||
/* Declare manifest constant:
|
||||
* enum id = floatvalue;
|
||||
*/
|
||||
AST.Expression e = new AST.RealExp(scanloc, floatvalue, t);
|
||||
auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
|
||||
symbols.push(v);
|
||||
nextDefineLine();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOK.string_:
|
||||
const str = n.ustring;
|
||||
const len = n.len;
|
||||
const postfix = n.postfix;
|
||||
scan(&n);
|
||||
if (n.value == TOK.endOfLine)
|
||||
{
|
||||
/* Declare manifest constant:
|
||||
* enum id = "string";
|
||||
*/
|
||||
AST.Expression e = new AST.StringExp(scanloc, str[0 .. len], len, 1, postfix);
|
||||
auto v = new AST.VarDeclaration(scanloc, null, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
|
||||
symbols.push(v);
|
||||
nextDefineLine();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
skipToNextLine();
|
||||
|
|
|
@ -1318,7 +1318,7 @@ private final class CppMangleVisitor : Visitor
|
|||
Type t = fparam.type.merge2();
|
||||
if (fparam.isReference())
|
||||
t = t.referenceTo();
|
||||
else if (fparam.storageClass & STC.lazy_)
|
||||
else if (fparam.isLazy())
|
||||
{
|
||||
// Mangle as delegate
|
||||
auto tf = new TypeFunction(ParameterList(), t, LINK.d);
|
||||
|
|
|
@ -916,7 +916,7 @@ MATCH implicitConvTo(Expression e, Type t)
|
|||
if (i - j < nparams)
|
||||
{
|
||||
Parameter fparam = tf.parameterList[i - j];
|
||||
if (fparam.storageClass & STC.lazy_)
|
||||
if (fparam.isLazy())
|
||||
return result; // not sure what to do with this
|
||||
Type tparam = fparam.type;
|
||||
if (!tparam)
|
||||
|
@ -1224,7 +1224,7 @@ MATCH implicitConvTo(Expression e, Type t)
|
|||
if (i - j < nparams)
|
||||
{
|
||||
Parameter fparam = tf.parameterList[i - j];
|
||||
if (fparam.storageClass & STC.lazy_)
|
||||
if (fparam.isLazy())
|
||||
return MATCH.nomatch; // not sure what to do with this
|
||||
Type tparam = fparam.type;
|
||||
if (!tparam)
|
||||
|
|
|
@ -492,7 +492,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
|
|||
if (CTFEExp.isCantExp(earg))
|
||||
return earg;
|
||||
}
|
||||
else if (fparam.storageClass & STC.lazy_)
|
||||
else if (fparam.isLazy())
|
||||
{
|
||||
}
|
||||
else
|
||||
|
@ -5000,6 +5000,27 @@ public:
|
|||
printf("%s CommaExp::interpret() %s\n", e.loc.toChars(), e.toChars());
|
||||
}
|
||||
|
||||
bool isNewThrowableHook()
|
||||
{
|
||||
auto de = e.e1.isDeclarationExp();
|
||||
if (de is null)
|
||||
return false;
|
||||
|
||||
auto vd = de.declaration.isVarDeclaration();
|
||||
if (vd is null)
|
||||
return false;
|
||||
|
||||
auto ei = vd._init.isExpInitializer();
|
||||
if (ei is null)
|
||||
return false;
|
||||
|
||||
auto ce = ei.exp.isConstructExp();
|
||||
if (ce is null)
|
||||
return false;
|
||||
|
||||
return isRuntimeHook(ce.e2, Id._d_newThrowable) !is null;
|
||||
}
|
||||
|
||||
if (auto ce = isRuntimeHook(e.e1, Id._d_arrayappendcTX))
|
||||
{
|
||||
// In expressionsem.d `arr ~= elem` was lowered to
|
||||
|
@ -5018,6 +5039,21 @@ public:
|
|||
result = interpret(cae, istate);
|
||||
return;
|
||||
}
|
||||
else if (isNewThrowableHook())
|
||||
{
|
||||
// In expressionsem.d `throw new Exception(args)` was lowered to
|
||||
// `throw (tmp = _d_newThrowable!Exception(), tmp.ctor(args), tmp)`.
|
||||
// The following code will rewrite it back to `throw new Exception(args)`
|
||||
// and then interpret this expression instead.
|
||||
auto ce = e.e2.isCallExp();
|
||||
assert(ce);
|
||||
|
||||
auto ne = new NewExp(e.loc, null, e.type, ce.arguments);
|
||||
ne.type = e.e1.type;
|
||||
|
||||
result = interpret(ne, istate);
|
||||
return;
|
||||
}
|
||||
|
||||
// If it creates a variable, and there's no context for
|
||||
// the variable to be created in, we need to create one now.
|
||||
|
|
|
@ -754,7 +754,6 @@ struct Scope
|
|||
// assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************
|
||||
*/
|
||||
structalign_t alignment()
|
||||
|
@ -771,13 +770,13 @@ struct Scope
|
|||
return sa;
|
||||
}
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow const:
|
||||
/**********************************
|
||||
* Checks whether the current scope (or any of its parents) is deprecated.
|
||||
*
|
||||
* Returns: `true` if this or any parent scope is deprecated, `false` otherwise`
|
||||
*/
|
||||
extern(C++) bool isDeprecated() @safe @nogc pure nothrow const
|
||||
extern(C++) bool isDeprecated()
|
||||
{
|
||||
for (const(Dsymbol)* sp = &(this.parent); *sp; sp = &(sp.parent))
|
||||
{
|
||||
|
@ -799,4 +798,16 @@ struct Scope
|
|||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* dmd relies on mutation of state during semantic analysis, however
|
||||
* sometimes semantic is being performed in a speculative context that should
|
||||
* not have any visible effect on the rest of the compilation: for example when compiling
|
||||
* a typeof() or __traits(compiles).
|
||||
*
|
||||
* Returns: `true` if this `Scope` is known to be from one of these speculative contexts
|
||||
*/
|
||||
extern(C++) bool isFromSpeculativeSemanticContext() scope
|
||||
{
|
||||
return this.intypeof || this.flags & SCOPE.compile;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2184,20 +2184,13 @@ extern (C++) final class OverloadSet : Dsymbol
|
|||
*/
|
||||
extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
|
||||
{
|
||||
/*************************
|
||||
* Symbol to forward insertions to.
|
||||
* Can be `null` before being lazily initialized.
|
||||
*/
|
||||
ScopeDsymbol forward;
|
||||
extern (D) this(ScopeDsymbol forward) nothrow
|
||||
extern (D) this() nothrow
|
||||
{
|
||||
super(null);
|
||||
this.forward = forward;
|
||||
super();
|
||||
}
|
||||
|
||||
override Dsymbol symtabInsert(Dsymbol s) nothrow
|
||||
{
|
||||
assert(forward);
|
||||
if (auto d = s.isDeclaration())
|
||||
{
|
||||
if (d.storage_class & STC.local)
|
||||
|
@ -2212,6 +2205,8 @@ extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
|
|||
return super.symtabInsert(s); // insert locally
|
||||
}
|
||||
}
|
||||
auto forward = parent.isScopeDsymbol();
|
||||
assert(forward);
|
||||
if (!forward.symtab)
|
||||
{
|
||||
forward.symtab = new DsymbolTable();
|
||||
|
@ -2228,7 +2223,6 @@ extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
|
|||
*/
|
||||
override Dsymbol symtabLookup(Dsymbol s, Identifier id) nothrow
|
||||
{
|
||||
assert(forward);
|
||||
// correctly diagnose clashing foreach loop variables.
|
||||
if (auto d = s.isDeclaration())
|
||||
{
|
||||
|
@ -2243,6 +2237,8 @@ extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
|
|||
}
|
||||
// Declarations within `static foreach` do not clash with
|
||||
// `static foreach` loop variables.
|
||||
auto forward = parent.isScopeDsymbol();
|
||||
assert(forward);
|
||||
if (!forward.symtab)
|
||||
{
|
||||
forward.symtab = new DsymbolTable();
|
||||
|
@ -2252,6 +2248,8 @@ extern (C++) final class ForwardingScopeDsymbol : ScopeDsymbol
|
|||
|
||||
override void importScope(Dsymbol s, Visibility visibility)
|
||||
{
|
||||
auto forward = parent.isScopeDsymbol();
|
||||
assert(forward);
|
||||
forward.importScope(s, visibility);
|
||||
}
|
||||
|
||||
|
|
|
@ -391,8 +391,6 @@ public:
|
|||
class ForwardingScopeDsymbol final : public ScopeDsymbol
|
||||
{
|
||||
public:
|
||||
ScopeDsymbol *forward;
|
||||
|
||||
Dsymbol *symtabInsert(Dsymbol *s) override;
|
||||
Dsymbol *symtabLookup(Dsymbol *s, Identifier *id) override;
|
||||
void importScope(Dsymbol *s, Visibility visibility) override;
|
||||
|
|
|
@ -3276,13 +3276,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
if ((funcdecl.storage_class & STC.auto_) && !f.isref && !funcdecl.inferRetType)
|
||||
funcdecl.error("storage class `auto` has no effect if return type is not inferred");
|
||||
|
||||
/* Functions can only be 'scope' if they have a 'this'
|
||||
*/
|
||||
if (f.isScopeQual && !funcdecl.isNested() && !ad)
|
||||
{
|
||||
funcdecl.error("functions cannot be `scope`");
|
||||
}
|
||||
|
||||
if (f.isreturn && !funcdecl.needThis() && !funcdecl.isNested())
|
||||
{
|
||||
/* Non-static nested functions have a hidden 'this' pointer to which
|
||||
|
|
|
@ -1632,7 +1632,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
|
|||
if (farg.op == EXP.error || farg.type.ty == Terror)
|
||||
return nomatch();
|
||||
|
||||
if (!(fparam.storageClass & STC.lazy_) && farg.type.ty == Tvoid)
|
||||
if (!fparam.isLazy() && farg.type.ty == Tvoid)
|
||||
return nomatch();
|
||||
|
||||
Type tt;
|
||||
|
@ -1837,7 +1837,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
|
|||
}
|
||||
Type argtype = farg.type;
|
||||
|
||||
if (!(fparam.storageClass & STC.lazy_) && argtype.ty == Tvoid && farg.op != EXP.function_)
|
||||
if (!fparam.isLazy() && argtype.ty == Tvoid && farg.op != EXP.function_)
|
||||
return nomatch();
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=12876
|
||||
|
@ -1958,7 +1958,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
|
|||
if (!farg.type.isMutable()) // https://issues.dlang.org/show_bug.cgi?id=11916
|
||||
return nomatch();
|
||||
}
|
||||
if (m == MATCH.nomatch && (fparam.storageClass & STC.lazy_) && prmtype.ty == Tvoid && farg.type.ty != Tvoid)
|
||||
if (m == MATCH.nomatch && fparam.isLazy() && prmtype.ty == Tvoid && farg.type.ty != Tvoid)
|
||||
m = MATCH.convert;
|
||||
if (m != MATCH.nomatch)
|
||||
{
|
||||
|
@ -7723,7 +7723,7 @@ extern (C++) final class TemplateMixin : TemplateInstance
|
|||
}
|
||||
if (!tempdecl)
|
||||
{
|
||||
error("`%s` isn't a template", s.toChars());
|
||||
error("- `%s` is a %s, not a template", s.toChars(), s.kind());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -443,7 +443,7 @@ private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
|
|||
}
|
||||
|
||||
if (!s)
|
||||
return ue.e1.type.Type.getProperty(sc, loc, ident, 0);
|
||||
return ue.e1.type.getProperty(sc, loc, ident, 0);
|
||||
|
||||
FuncDeclaration f = s.isFuncDeclaration();
|
||||
if (f)
|
||||
|
@ -1856,7 +1856,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
|||
}
|
||||
|
||||
L1:
|
||||
if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
|
||||
if (!(p.isLazy() && p.type.ty == Tvoid))
|
||||
{
|
||||
if (ubyte wm = arg.type.deduceWild(p.type, p.isReference()))
|
||||
{
|
||||
|
@ -1953,7 +1953,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
|||
Type targ = arg.type; // keep original type for isCopyable() because alias this
|
||||
// resolution may hide an uncopyable type
|
||||
|
||||
if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
|
||||
if (!(p.isLazy() && p.type.ty == Tvoid))
|
||||
{
|
||||
Type tprm = p.type.hasWild()
|
||||
? p.type.substWildTo(wildmatch)
|
||||
|
@ -2018,7 +2018,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
|||
}
|
||||
arg = arg.toLvalue(sc, arg);
|
||||
}
|
||||
else if (p.storageClass & STC.lazy_)
|
||||
else if (p.isLazy())
|
||||
{
|
||||
// Convert lazy argument to a delegate
|
||||
auto t = (p.type.ty == Tvoid) ? p.type : arg.type;
|
||||
|
@ -2050,7 +2050,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
|||
// Turning heap allocations into stack allocations is dangerous without dip1000, since `scope` inference
|
||||
// may be unreliable when scope violations only manifest as deprecation warnings.
|
||||
// However, existing `@nogc` code may rely on it, so still do it when the parameter is explicitly marked `scope`
|
||||
const explicitScope = (p.storageClass & STC.lazy_) ||
|
||||
const explicitScope = p.isLazy() ||
|
||||
((p.storageClass & STC.scope_) && !(p.storageClass & STC.scopeinferred));
|
||||
if ((pStc & (STC.scope_ | STC.lazy_)) &&
|
||||
((global.params.useDIP1000 == FeatureState.enabled) || explicitScope) &&
|
||||
|
@ -2261,7 +2261,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
|||
if (arg.type.needsDestruction())
|
||||
{
|
||||
Parameter p = (i >= nparams ? null : tf.parameterList[i]);
|
||||
if (!(p && (p.storageClass & (STC.lazy_ | STC.ref_ | STC.out_))))
|
||||
if (!(p && (p.isLazy() || p.isReference())))
|
||||
{
|
||||
if (firstdtor == -1)
|
||||
firstdtor = i;
|
||||
|
@ -2302,7 +2302,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
|||
|
||||
Parameter parameter = (i >= nparams ? null : tf.parameterList[i]);
|
||||
const bool isRef = parameter && parameter.isReference();
|
||||
const bool isLazy = (parameter && (parameter.storageClass & STC.lazy_));
|
||||
const bool isLazy = parameter && parameter.isLazy();
|
||||
|
||||
/* Skip lazy parameters
|
||||
*/
|
||||
|
@ -3722,6 +3722,36 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When using `@nogc` exception handling, lower `throw new E(args)` to
|
||||
// `throw (__tmp = _d_newThrowable!E(), __tmp.__ctor(args), __tmp)`.
|
||||
if (global.params.ehnogc && exp.thrownew &&
|
||||
!cd.isCOMclass() && !cd.isCPPclass())
|
||||
{
|
||||
assert(cd.ctor);
|
||||
|
||||
Expression id = new IdentifierExp(exp.loc, Id.empty);
|
||||
id = new DotIdExp(exp.loc, id, Id.object);
|
||||
|
||||
auto tiargs = new Objects();
|
||||
tiargs.push(exp.newtype);
|
||||
id = new DotTemplateInstanceExp(exp.loc, id, Id._d_newThrowable, tiargs);
|
||||
id = new CallExp(exp.loc, id).expressionSemantic(sc);
|
||||
|
||||
Expression idVal;
|
||||
Expression tmp = extractSideEffect(sc, "__tmpThrowable", idVal, id, true);
|
||||
// auto castTmp = new CastExp(exp.loc, tmp, exp.type);
|
||||
|
||||
auto ctor = new DotIdExp(exp.loc, tmp, Id.ctor).expressionSemantic(sc);
|
||||
auto ctorCall = new CallExp(exp.loc, ctor, exp.arguments);
|
||||
|
||||
id = Expression.combine(idVal, exp.argprefix).expressionSemantic(sc);
|
||||
id = Expression.combine(id, ctorCall).expressionSemantic(sc);
|
||||
// id = Expression.combine(id, castTmp).expressionSemantic(sc);
|
||||
|
||||
result = id.expressionSemantic(sc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (auto ts = tb.isTypeStruct())
|
||||
{
|
||||
|
@ -6582,6 +6612,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
result = e;
|
||||
return;
|
||||
}
|
||||
else if (auto ad = exp.var.isAliasDeclaration())
|
||||
{
|
||||
if (auto t = ad.getType())
|
||||
{
|
||||
result = new TypeExp(exp.loc, t).expressionSemantic(sc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
exp.e1 = exp.e1.addDtorHook(sc);
|
||||
|
||||
|
@ -7006,9 +7044,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
/* Because nested functions cannot be overloaded,
|
||||
* mark here that we took its address because castTo()
|
||||
* may not be called with an exact match.
|
||||
*
|
||||
* https://issues.dlang.org/show_bug.cgi?id=19285 :
|
||||
* We also need to make sure we aren't inside a typeof. Ideally the compiler
|
||||
* would do typeof(...) semantic analysis speculatively then collect information
|
||||
* about what it used rather than relying on what are effectively semantically-global
|
||||
* variables but it doesn't.
|
||||
*/
|
||||
if (!ve.hasOverloads || (f.isNested() && !f.needThis()))
|
||||
if (!sc.isFromSpeculativeSemanticContext() && (!ve.hasOverloads || (f.isNested() && !f.needThis())))
|
||||
{
|
||||
// TODO: Refactor to use a proper interface that can keep track of causes.
|
||||
f.tookAddressOf++;
|
||||
}
|
||||
|
||||
if (f.isNested() && !f.needThis())
|
||||
{
|
||||
if (f.isFuncLiteralDeclaration())
|
||||
|
@ -12855,11 +12903,8 @@ Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
|
|||
|
||||
if (Declaration v = exp.ti.toAlias().isDeclaration())
|
||||
{
|
||||
if (v.isFuncDeclaration() || v.isVarDeclaration())
|
||||
{
|
||||
return new DotVarExp(exp.loc, exp.e1, v)
|
||||
.expressionSemantic(sc);
|
||||
}
|
||||
return new DotVarExp(exp.loc, exp.e1, v)
|
||||
.expressionSemantic(sc);
|
||||
}
|
||||
return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
|
||||
.expressionSemantic(sc);
|
||||
|
@ -12966,8 +13011,19 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
|
|||
|
||||
bool visitVar(VarExp e)
|
||||
{
|
||||
if (!allowRef && e.var.type.isShared())
|
||||
// https://issues.dlang.org/show_bug.cgi?id=22626
|
||||
// Synchronized functions don't need to use core.atomic
|
||||
// when accessing `this`.
|
||||
if (sc.func && sc.func.isSynchronized())
|
||||
{
|
||||
if (e.var.isThisDeclaration())
|
||||
return false;
|
||||
else
|
||||
return sharedError(e);
|
||||
}
|
||||
else if (!allowRef && e.var.type.isShared())
|
||||
return sharedError(e);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -12987,15 +13043,22 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
|
|||
return check(e.e1, false);
|
||||
}
|
||||
|
||||
bool visitThis(ThisExp e)
|
||||
{
|
||||
if (sc.func && sc.func.isSynchronized())
|
||||
return false;
|
||||
|
||||
return sharedError(e);
|
||||
}
|
||||
|
||||
bool visitDotVar(DotVarExp e)
|
||||
{
|
||||
//printf("dotvarexp = %s\n", e.toChars());
|
||||
auto fd = e.var.isFuncDeclaration();
|
||||
const sharedFunc = fd && fd.type.isShared;
|
||||
|
||||
if (!allowRef && e.type.isShared() && !sharedFunc)
|
||||
return sharedError(e);
|
||||
|
||||
// Allow using `DotVarExp` within value types
|
||||
if (!allowRef && e.type.isShared() && !sharedFunc && !(sc.func && sc.func.isSynchronized()))
|
||||
return sharedError(e);
|
||||
if (e.e1.type.isTypeSArray() || e.e1.type.isTypeStruct())
|
||||
return check(e.e1, allowRef);
|
||||
|
||||
|
@ -13044,6 +13107,7 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
|
|||
case EXP.star: return visitPtr(e.isPtrExp());
|
||||
case EXP.dotVariable: return visitDotVar(e.isDotVarExp());
|
||||
case EXP.index: return visitIndex(e.isIndexExp());
|
||||
case EXP.this_: return visitThis(e.isThisExp());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1773,7 +1773,7 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
if (!tp)
|
||||
continue;
|
||||
|
||||
if (fparam.storageClass & (STC.lazy_ | STC.out_ | STC.ref_))
|
||||
if (fparam.isLazy() || fparam.isReference())
|
||||
{
|
||||
if (!traverseIndirections(tp, t))
|
||||
return false;
|
||||
|
@ -2528,7 +2528,7 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
foreach (n, p; parameterList)
|
||||
{
|
||||
p = p.syntaxCopy();
|
||||
if (!(p.storageClass & STC.lazy_))
|
||||
if (!p.isLazy())
|
||||
p.storageClass = (p.storageClass | STC.ref_) & ~STC.out_;
|
||||
p.defaultArg = null; // won't be the same with ref
|
||||
result.push(p);
|
||||
|
|
|
@ -311,6 +311,7 @@ immutable Msgtable[] msgtable =
|
|||
{ "__ArrayPostblit" },
|
||||
{ "__ArrayDtor" },
|
||||
{ "_d_delThrowable" },
|
||||
{ "_d_newThrowable" },
|
||||
{ "_d_assert_fail" },
|
||||
{ "dup" },
|
||||
{ "_aaApply" },
|
||||
|
|
|
@ -529,7 +529,6 @@ extern (C++) abstract class Type : ASTNode
|
|||
* Returns:
|
||||
* An enum value of either `Covariant.yes` or a reason it's not covariant.
|
||||
*/
|
||||
extern (D)
|
||||
final Covariant covariant(Type t, StorageClass* pstc = null, bool cppCovariant = false)
|
||||
{
|
||||
version (none)
|
||||
|
@ -4361,7 +4360,7 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
{
|
||||
foreach (i, fparam; parameterList)
|
||||
{
|
||||
if (fparam.storageClass & STC.lazy_)
|
||||
if (fparam.isLazy())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -4675,7 +4674,7 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
Type tprm = p.type;
|
||||
Type targ = arg.type;
|
||||
|
||||
if (!(p.storageClass & STC.lazy_ && tprm.ty == Tvoid && targ.ty != Tvoid))
|
||||
if (!(p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid))
|
||||
{
|
||||
const isRef = p.isReference();
|
||||
wildmatch |= targ.deduceWild(tprm, isRef);
|
||||
|
@ -4718,7 +4717,7 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
Type targ = arg.type;
|
||||
Type tprm = wildmatch ? p.type.substWildTo(wildmatch) : p.type;
|
||||
|
||||
if (p.storageClass & STC.lazy_ && tprm.ty == Tvoid && targ.ty != Tvoid)
|
||||
if (p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid)
|
||||
m = MATCH.convert;
|
||||
else
|
||||
{
|
||||
|
@ -6825,6 +6824,12 @@ extern (C++) final class Parameter : ASTNode
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Returns: Whether the function parameter is lazy
|
||||
bool isLazy() const @safe pure nothrow @nogc
|
||||
{
|
||||
return (this.storageClass & (STC.lazy_)) != 0;
|
||||
}
|
||||
|
||||
/// Returns: Whether the function parameter is a reference (out / ref)
|
||||
bool isReference() const @safe pure nothrow @nogc
|
||||
{
|
||||
|
|
|
@ -128,6 +128,14 @@ enum VarArgValues
|
|||
};
|
||||
typedef unsigned char VarArg;
|
||||
|
||||
enum class Covariant
|
||||
{
|
||||
distinct = 0, /// types are distinct
|
||||
yes = 1, /// types are covariant
|
||||
no = 2, /// arguments match as far as overloading goes, but types are not covariant
|
||||
fwdref = 3, /// cannot determine covariance because of forward references
|
||||
};
|
||||
|
||||
class Type : public ASTNode
|
||||
{
|
||||
public:
|
||||
|
@ -218,6 +226,7 @@ public:
|
|||
// kludge for template.isType()
|
||||
DYNCAST dyncast() const override final { return DYNCAST_TYPE; }
|
||||
size_t getUniqueID() const;
|
||||
Covariant covariant(Type *, StorageClass * = NULL, bool = false);
|
||||
const char *toChars() const override;
|
||||
char *toPrettyChars(bool QualifyTypes = false);
|
||||
static void _init();
|
||||
|
@ -560,6 +569,8 @@ public:
|
|||
Expression *defaultArg, UserAttributeDeclaration *userAttribDecl);
|
||||
Parameter *syntaxCopy();
|
||||
Type *isLazyArray();
|
||||
bool isLazy() const;
|
||||
bool isReference() const;
|
||||
// kludge for template.isType()
|
||||
DYNCAST dyncast() const override { return DYNCAST_PARAMETER; }
|
||||
void accept(Visitor *v) override { v->visit(this); }
|
||||
|
|
|
@ -1460,7 +1460,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
|
||||
if (token.value != TOK.leftCurly)
|
||||
{
|
||||
error("members of template declaration expected");
|
||||
error("`{` expected after template parameter list, not `%s`", token.toChars());
|
||||
goto Lerr;
|
||||
}
|
||||
decldefs = parseBlock(null);
|
||||
|
|
|
@ -147,4 +147,5 @@ struct Scope
|
|||
structalign_t alignment();
|
||||
|
||||
bool isDeprecated() const;
|
||||
bool isFromSpeculativeSemanticContext() const;
|
||||
};
|
||||
|
|
|
@ -761,7 +761,7 @@ extern (C++) final class ForwardingStatement : Statement
|
|||
|
||||
extern (D) this(const ref Loc loc, Statement statement)
|
||||
{
|
||||
auto sym = new ForwardingScopeDsymbol(null);
|
||||
auto sym = new ForwardingScopeDsymbol();
|
||||
sym.symtab = new DsymbolTable();
|
||||
this(loc, sym, statement);
|
||||
}
|
||||
|
|
|
@ -502,10 +502,10 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
override void visit(ForwardingStatement ss)
|
||||
{
|
||||
assert(ss.sym);
|
||||
for (Scope* csc = sc; !ss.sym.forward; csc = csc.enclosing)
|
||||
for (Scope* csc = sc; !ss.sym.parent; csc = csc.enclosing)
|
||||
{
|
||||
assert(csc);
|
||||
ss.sym.forward = csc.scopesym;
|
||||
ss.sym.parent = csc.scopesym;
|
||||
}
|
||||
sc = sc.push(ss.sym);
|
||||
sc.sbreak = ss;
|
||||
|
@ -2891,7 +2891,8 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
/* Void-return function can have void / noreturn typed expression
|
||||
* on return statement.
|
||||
*/
|
||||
const convToVoid = rs.exp.type.ty == Tvoid || rs.exp.type.ty == Tnoreturn;
|
||||
auto texp = rs.exp.type;
|
||||
const convToVoid = texp.ty == Tvoid || texp.ty == Tnoreturn;
|
||||
|
||||
if (tbret && tbret.ty == Tvoid || convToVoid)
|
||||
{
|
||||
|
@ -2903,6 +2904,15 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
rs.exp = rs.exp.expressionSemantic(sc);
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23063
|
||||
if (texp.isTypeNoreturn() && !rs.exp.isAssertExp() && !rs.exp.isThrowExp() && !rs.exp.isCallExp())
|
||||
{
|
||||
auto msg = new StringExp(rs.exp.loc, "Accessed expression of type `noreturn`");
|
||||
msg.type = Type.tstring;
|
||||
rs.exp = new AssertExp(rs.loc, IntegerExp.literal!0, msg);
|
||||
rs.exp.type = texp;
|
||||
}
|
||||
|
||||
/* Replace:
|
||||
* return exp;
|
||||
* with:
|
||||
|
@ -3698,6 +3708,13 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
|
||||
if (oss.tok != TOK.onScopeExit)
|
||||
{
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23159
|
||||
if (!global.params.useExceptions)
|
||||
{
|
||||
oss.error("`%s` cannot be used with -betterC", Token.toChars(oss.tok));
|
||||
return setError();
|
||||
}
|
||||
|
||||
// scope(success) and scope(failure) are rewritten to try-catch(-finally) statement,
|
||||
// so the generated catch block cannot be placed in finally block.
|
||||
// See also Catch::semantic.
|
||||
|
@ -4312,7 +4329,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState
|
|||
if (!skip && dim == 2)
|
||||
{
|
||||
// Declare key
|
||||
if (p.storageClass & (STC.out_ | STC.ref_ | STC.lazy_))
|
||||
if (p.isReference() || p.isLazy())
|
||||
{
|
||||
fs.error("no storage class for key `%s`", p.ident.toChars());
|
||||
return returnEarly();
|
||||
|
|
|
@ -64,48 +64,6 @@ import dmd.sideeffect;
|
|||
import dmd.target;
|
||||
import dmd.tokens;
|
||||
|
||||
/**************************
|
||||
* This evaluates exp while setting length to be the number
|
||||
* of elements in the tuple t.
|
||||
*/
|
||||
private Expression semanticLength(Scope* sc, Type t, Expression exp)
|
||||
{
|
||||
if (auto tt = t.isTypeTuple())
|
||||
{
|
||||
ScopeDsymbol sym = new ArrayScopeSymbol(sc, tt);
|
||||
sym.parent = sc.scopesym;
|
||||
sc = sc.push(sym);
|
||||
sc = sc.startCTFE();
|
||||
exp = exp.expressionSemantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
sc = sc.endCTFE();
|
||||
sc.pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
sc = sc.startCTFE();
|
||||
exp = exp.expressionSemantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
sc = sc.endCTFE();
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
private Expression semanticLength(Scope* sc, TupleDeclaration tup, Expression exp)
|
||||
{
|
||||
ScopeDsymbol sym = new ArrayScopeSymbol(sc, tup);
|
||||
sym.parent = sc.scopesym;
|
||||
|
||||
sc = sc.push(sym);
|
||||
sc = sc.startCTFE();
|
||||
exp = exp.expressionSemantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
sc = sc.endCTFE();
|
||||
sc.pop();
|
||||
|
||||
return exp;
|
||||
}
|
||||
|
||||
/*************************************
|
||||
* Resolve a tuple index, `s[oindex]`, by figuring out what `s[oindex]` represents.
|
||||
* Setting one of pe/pt/ps.
|
||||
|
@ -452,101 +410,6 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb
|
|||
pt = t.merge();
|
||||
}
|
||||
|
||||
/************************************
|
||||
* Transitively search a type for all function types.
|
||||
* If any function types with parameters are found that have parameter identifiers
|
||||
* or default arguments, remove those and create a new type stripped of those.
|
||||
* This is used to determine the "canonical" version of a type which is useful for
|
||||
* comparisons.
|
||||
* Params:
|
||||
* t = type to scan
|
||||
* Returns:
|
||||
* `t` if no parameter identifiers or default arguments found, otherwise a new type that is
|
||||
* the same as t but with no parameter identifiers or default arguments.
|
||||
*/
|
||||
private Type stripDefaultArgs(Type t)
|
||||
{
|
||||
static Parameters* stripParams(Parameters* parameters)
|
||||
{
|
||||
static Parameter stripParameter(Parameter p)
|
||||
{
|
||||
Type t = stripDefaultArgs(p.type);
|
||||
return (t != p.type || p.defaultArg || p.ident || p.userAttribDecl)
|
||||
? new Parameter(p.storageClass, t, null, null, null)
|
||||
: null;
|
||||
}
|
||||
|
||||
if (parameters)
|
||||
{
|
||||
foreach (i, p; *parameters)
|
||||
{
|
||||
Parameter ps = stripParameter(p);
|
||||
if (ps)
|
||||
{
|
||||
// Replace params with a copy we can modify
|
||||
Parameters* nparams = new Parameters(parameters.dim);
|
||||
|
||||
foreach (j, ref np; *nparams)
|
||||
{
|
||||
Parameter pj = (*parameters)[j];
|
||||
if (j < i)
|
||||
np = pj;
|
||||
else if (j == i)
|
||||
np = ps;
|
||||
else
|
||||
{
|
||||
Parameter nps = stripParameter(pj);
|
||||
np = nps ? nps : pj;
|
||||
}
|
||||
}
|
||||
return nparams;
|
||||
}
|
||||
}
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
if (t is null)
|
||||
return t;
|
||||
|
||||
if (auto tf = t.isTypeFunction())
|
||||
{
|
||||
Type tret = stripDefaultArgs(tf.next);
|
||||
Parameters* params = stripParams(tf.parameterList.parameters);
|
||||
if (tret == tf.next && params == tf.parameterList.parameters)
|
||||
return t;
|
||||
TypeFunction tr = tf.copy().isTypeFunction();
|
||||
tr.parameterList.parameters = params;
|
||||
tr.next = tret;
|
||||
//printf("strip %s\n <- %s\n", tr.toChars(), t.toChars());
|
||||
return tr;
|
||||
}
|
||||
else if (auto tt = t.isTypeTuple())
|
||||
{
|
||||
Parameters* args = stripParams(tt.arguments);
|
||||
if (args == tt.arguments)
|
||||
return t;
|
||||
TypeTuple tr = t.copy().isTypeTuple();
|
||||
tr.arguments = args;
|
||||
return tr;
|
||||
}
|
||||
else if (t.ty == Tenum)
|
||||
{
|
||||
// TypeEnum::nextOf() may be != NULL, but it's not necessary here.
|
||||
return t;
|
||||
}
|
||||
else
|
||||
{
|
||||
Type tn = t.nextOf();
|
||||
Type n = stripDefaultArgs(tn);
|
||||
if (n == tn)
|
||||
return t;
|
||||
TypeNext tr = cast(TypeNext)t.copy();
|
||||
tr.next = n;
|
||||
return tr;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* We've mistakenly parsed `t` as a type.
|
||||
* Redo `t` as an Expression only if there are no type modifiers.
|
||||
|
@ -603,53 +466,6 @@ Expression typeToExpression(Type t)
|
|||
}
|
||||
}
|
||||
|
||||
/* Helper function for `typeToExpression`. Contains common code
|
||||
* for TypeQualified derived classes.
|
||||
*/
|
||||
Expression typeToExpressionHelper(TypeQualified t, Expression e, size_t i = 0)
|
||||
{
|
||||
//printf("toExpressionHelper(e = %s %s)\n", EXPtoString(e.op).ptr, e.toChars());
|
||||
foreach (id; t.idents[i .. t.idents.dim])
|
||||
{
|
||||
//printf("\t[%d] e: '%s', id: '%s'\n", i, e.toChars(), id.toChars());
|
||||
|
||||
final switch (id.dyncast())
|
||||
{
|
||||
// ... '. ident'
|
||||
case DYNCAST.identifier:
|
||||
e = new DotIdExp(e.loc, e, cast(Identifier)id);
|
||||
break;
|
||||
|
||||
// ... '. name!(tiargs)'
|
||||
case DYNCAST.dsymbol:
|
||||
auto ti = (cast(Dsymbol)id).isTemplateInstance();
|
||||
assert(ti);
|
||||
e = new DotTemplateInstanceExp(e.loc, e, ti.name, ti.tiargs);
|
||||
break;
|
||||
|
||||
// ... '[type]'
|
||||
case DYNCAST.type: // https://issues.dlang.org/show_bug.cgi?id=1215
|
||||
e = new ArrayExp(t.loc, e, new TypeExp(t.loc, cast(Type)id));
|
||||
break;
|
||||
|
||||
// ... '[expr]'
|
||||
case DYNCAST.expression: // https://issues.dlang.org/show_bug.cgi?id=1215
|
||||
e = new ArrayExp(t.loc, e, cast(Expression)id);
|
||||
break;
|
||||
|
||||
case DYNCAST.object:
|
||||
case DYNCAST.tuple:
|
||||
case DYNCAST.parameter:
|
||||
case DYNCAST.statement:
|
||||
case DYNCAST.condition:
|
||||
case DYNCAST.templateparameter:
|
||||
case DYNCAST.initializer:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Perform semantic analysis on a type.
|
||||
* Params:
|
||||
|
@ -1431,7 +1247,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
|
|||
errors = true;
|
||||
}
|
||||
}
|
||||
else if (!(fparam.storageClass & STC.lazy_) && t.ty == Tvoid)
|
||||
else if (!fparam.isLazy() && t.ty == Tvoid)
|
||||
{
|
||||
.error(loc, "cannot have parameter of type `%s`", fparam.type.toChars());
|
||||
errors = true;
|
||||
|
@ -2157,47 +1973,6 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
|
|||
}
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Compile the MixinType, returning the type or expression AST.
|
||||
*
|
||||
* Doesn't run semantic() on the returned object.
|
||||
* Params:
|
||||
* tm = mixin to compile as a type or expression
|
||||
* loc = location for error messages
|
||||
* sc = context
|
||||
* Return:
|
||||
* null if error, else RootObject AST as parsed
|
||||
*/
|
||||
RootObject compileTypeMixin(TypeMixin tm, Loc loc, Scope* sc)
|
||||
{
|
||||
OutBuffer buf;
|
||||
if (expressionsToString(buf, sc, tm.exps))
|
||||
return null;
|
||||
|
||||
const errors = global.errors;
|
||||
const len = buf.length;
|
||||
buf.writeByte(0);
|
||||
const str = buf.extractSlice()[0 .. len];
|
||||
scope p = new Parser!ASTCodegen(loc, sc._module, str, false);
|
||||
p.nextToken();
|
||||
//printf("p.loc.linnum = %d\n", p.loc.linnum);
|
||||
|
||||
auto o = p.parseTypeOrAssignExp(TOK.endOfFile);
|
||||
if (errors != global.errors)
|
||||
{
|
||||
assert(global.errors != errors); // should have caught all these cases
|
||||
return null;
|
||||
}
|
||||
if (p.token.value != TOK.endOfFile)
|
||||
{
|
||||
.error(loc, "incomplete mixin type `%s`", str.ptr);
|
||||
return null;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
/************************************
|
||||
* If an identical type to `type` is in `type.stringtable`, return
|
||||
* the latter one. Otherwise, add it to `type.stringtable`.
|
||||
|
@ -3243,6 +3018,7 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
|
|||
{
|
||||
pt = mt.obj.isType();
|
||||
ps = mt.obj.isDsymbol();
|
||||
pe = mt.obj.isExpression();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3310,7 +3086,10 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
|
|||
case EXP.overloadSet:
|
||||
mt.obj = e.isOverExp().type;
|
||||
break;
|
||||
case EXP.error:
|
||||
break;
|
||||
default:
|
||||
mt.obj = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3318,14 +3097,19 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
|
|||
if (mt.obj)
|
||||
{
|
||||
if (auto t = mt.obj.isType())
|
||||
returnType(t.addMod(mt.mod));
|
||||
{
|
||||
t = t.addMod(mt.mod);
|
||||
mt.obj = t;
|
||||
returnType(t);
|
||||
}
|
||||
else if (auto s = mt.obj.isDsymbol())
|
||||
returnSymbol(s);
|
||||
else
|
||||
assert(0);
|
||||
else if (auto e = mt.obj.isExpression())
|
||||
returnExp(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(global.errors);
|
||||
mt.obj = Type.terror;
|
||||
return returnError();
|
||||
}
|
||||
|
@ -4817,6 +4601,193 @@ extern (C++) Expression defaultInit(Type mt, const ref Loc loc, const bool isCfi
|
|||
}
|
||||
}
|
||||
|
||||
/******************************* Private *****************************************/
|
||||
|
||||
private:
|
||||
|
||||
/* Helper function for `typeToExpression`. Contains common code
|
||||
* for TypeQualified derived classes.
|
||||
*/
|
||||
Expression typeToExpressionHelper(TypeQualified t, Expression e, size_t i = 0)
|
||||
{
|
||||
//printf("toExpressionHelper(e = %s %s)\n", EXPtoString(e.op).ptr, e.toChars());
|
||||
foreach (id; t.idents[i .. t.idents.dim])
|
||||
{
|
||||
//printf("\t[%d] e: '%s', id: '%s'\n", i, e.toChars(), id.toChars());
|
||||
|
||||
final switch (id.dyncast())
|
||||
{
|
||||
// ... '. ident'
|
||||
case DYNCAST.identifier:
|
||||
e = new DotIdExp(e.loc, e, cast(Identifier)id);
|
||||
break;
|
||||
|
||||
// ... '. name!(tiargs)'
|
||||
case DYNCAST.dsymbol:
|
||||
auto ti = (cast(Dsymbol)id).isTemplateInstance();
|
||||
assert(ti);
|
||||
e = new DotTemplateInstanceExp(e.loc, e, ti.name, ti.tiargs);
|
||||
break;
|
||||
|
||||
// ... '[type]'
|
||||
case DYNCAST.type: // https://issues.dlang.org/show_bug.cgi?id=1215
|
||||
e = new ArrayExp(t.loc, e, new TypeExp(t.loc, cast(Type)id));
|
||||
break;
|
||||
|
||||
// ... '[expr]'
|
||||
case DYNCAST.expression: // https://issues.dlang.org/show_bug.cgi?id=1215
|
||||
e = new ArrayExp(t.loc, e, cast(Expression)id);
|
||||
break;
|
||||
|
||||
case DYNCAST.object:
|
||||
case DYNCAST.tuple:
|
||||
case DYNCAST.parameter:
|
||||
case DYNCAST.statement:
|
||||
case DYNCAST.condition:
|
||||
case DYNCAST.templateparameter:
|
||||
case DYNCAST.initializer:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
/**************************
|
||||
* This evaluates exp while setting length to be the number
|
||||
* of elements in the tuple t.
|
||||
*/
|
||||
Expression semanticLength(Scope* sc, Type t, Expression exp)
|
||||
{
|
||||
if (auto tt = t.isTypeTuple())
|
||||
{
|
||||
ScopeDsymbol sym = new ArrayScopeSymbol(sc, tt);
|
||||
sym.parent = sc.scopesym;
|
||||
sc = sc.push(sym);
|
||||
sc = sc.startCTFE();
|
||||
exp = exp.expressionSemantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
sc = sc.endCTFE();
|
||||
sc.pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
sc = sc.startCTFE();
|
||||
exp = exp.expressionSemantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
sc = sc.endCTFE();
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
Expression semanticLength(Scope* sc, TupleDeclaration tup, Expression exp)
|
||||
{
|
||||
ScopeDsymbol sym = new ArrayScopeSymbol(sc, tup);
|
||||
sym.parent = sc.scopesym;
|
||||
|
||||
sc = sc.push(sym);
|
||||
sc = sc.startCTFE();
|
||||
exp = exp.expressionSemantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
sc = sc.endCTFE();
|
||||
sc.pop();
|
||||
|
||||
return exp;
|
||||
}
|
||||
|
||||
/************************************
|
||||
* Transitively search a type for all function types.
|
||||
* If any function types with parameters are found that have parameter identifiers
|
||||
* or default arguments, remove those and create a new type stripped of those.
|
||||
* This is used to determine the "canonical" version of a type which is useful for
|
||||
* comparisons.
|
||||
* Params:
|
||||
* t = type to scan
|
||||
* Returns:
|
||||
* `t` if no parameter identifiers or default arguments found, otherwise a new type that is
|
||||
* the same as t but with no parameter identifiers or default arguments.
|
||||
*/
|
||||
Type stripDefaultArgs(Type t)
|
||||
{
|
||||
static Parameters* stripParams(Parameters* parameters)
|
||||
{
|
||||
static Parameter stripParameter(Parameter p)
|
||||
{
|
||||
Type t = stripDefaultArgs(p.type);
|
||||
return (t != p.type || p.defaultArg || p.ident || p.userAttribDecl)
|
||||
? new Parameter(p.storageClass, t, null, null, null)
|
||||
: null;
|
||||
}
|
||||
|
||||
if (parameters)
|
||||
{
|
||||
foreach (i, p; *parameters)
|
||||
{
|
||||
Parameter ps = stripParameter(p);
|
||||
if (ps)
|
||||
{
|
||||
// Replace params with a copy we can modify
|
||||
Parameters* nparams = new Parameters(parameters.dim);
|
||||
|
||||
foreach (j, ref np; *nparams)
|
||||
{
|
||||
Parameter pj = (*parameters)[j];
|
||||
if (j < i)
|
||||
np = pj;
|
||||
else if (j == i)
|
||||
np = ps;
|
||||
else
|
||||
{
|
||||
Parameter nps = stripParameter(pj);
|
||||
np = nps ? nps : pj;
|
||||
}
|
||||
}
|
||||
return nparams;
|
||||
}
|
||||
}
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
if (t is null)
|
||||
return t;
|
||||
|
||||
if (auto tf = t.isTypeFunction())
|
||||
{
|
||||
Type tret = stripDefaultArgs(tf.next);
|
||||
Parameters* params = stripParams(tf.parameterList.parameters);
|
||||
if (tret == tf.next && params == tf.parameterList.parameters)
|
||||
return t;
|
||||
TypeFunction tr = tf.copy().isTypeFunction();
|
||||
tr.parameterList.parameters = params;
|
||||
tr.next = tret;
|
||||
//printf("strip %s\n <- %s\n", tr.toChars(), t.toChars());
|
||||
return tr;
|
||||
}
|
||||
else if (auto tt = t.isTypeTuple())
|
||||
{
|
||||
Parameters* args = stripParams(tt.arguments);
|
||||
if (args == tt.arguments)
|
||||
return t;
|
||||
TypeTuple tr = t.copy().isTypeTuple();
|
||||
tr.arguments = args;
|
||||
return tr;
|
||||
}
|
||||
else if (t.ty == Tenum)
|
||||
{
|
||||
// TypeEnum::nextOf() may be != NULL, but it's not necessary here.
|
||||
return t;
|
||||
}
|
||||
else
|
||||
{
|
||||
Type tn = t.nextOf();
|
||||
Type n = stripDefaultArgs(tn);
|
||||
if (n == tn)
|
||||
return t;
|
||||
TypeNext tr = cast(TypeNext)t.copy();
|
||||
tr.next = n;
|
||||
return tr;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************
|
||||
* Get the value of the .max/.min property of `ed` as an Expression.
|
||||
|
@ -4829,7 +4800,7 @@ extern (C++) Expression defaultInit(Type mt, const ref Loc loc, const bool isCfi
|
|||
* Returns:
|
||||
* corresponding value of .max/.min
|
||||
*/
|
||||
private Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identifier id)
|
||||
Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identifier id)
|
||||
{
|
||||
//printf("EnumDeclaration::getMaxValue()\n");
|
||||
|
||||
|
@ -4935,3 +4906,43 @@ private Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identif
|
|||
}
|
||||
return ed.errors ? errorReturn() : pvalToResult(*pval, loc);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Compile the MixinType, returning the type or expression AST.
|
||||
*
|
||||
* Doesn't run semantic() on the returned object.
|
||||
* Params:
|
||||
* tm = mixin to compile as a type or expression
|
||||
* loc = location for error messages
|
||||
* sc = context
|
||||
* Return:
|
||||
* null if error, else RootObject AST as parsed
|
||||
*/
|
||||
RootObject compileTypeMixin(TypeMixin tm, Loc loc, Scope* sc)
|
||||
{
|
||||
OutBuffer buf;
|
||||
if (expressionsToString(buf, sc, tm.exps))
|
||||
return null;
|
||||
|
||||
const errors = global.errors;
|
||||
const len = buf.length;
|
||||
buf.writeByte(0);
|
||||
const str = buf.extractSlice()[0 .. len];
|
||||
scope p = new Parser!ASTCodegen(loc, sc._module, str, false);
|
||||
p.nextToken();
|
||||
//printf("p.loc.linnum = %d\n", p.loc.linnum);
|
||||
|
||||
auto o = p.parseTypeOrAssignExp(TOK.endOfFile);
|
||||
if (errors != global.errors)
|
||||
{
|
||||
assert(global.errors != errors); // should have caught all these cases
|
||||
return null;
|
||||
}
|
||||
if (p.token.value != TOK.endOfFile)
|
||||
{
|
||||
.error(loc, "incomplete mixin type `%s`", str.ptr);
|
||||
return null;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import dmd.dscope;
|
|||
import dmd.dclass;
|
||||
import dmd.dstruct;
|
||||
import dmd.errors;
|
||||
import dmd.expression;
|
||||
import dmd.globals;
|
||||
import dmd.gluelayer;
|
||||
import dmd.mtype;
|
||||
|
@ -28,11 +29,12 @@ import core.stdc.stdio;
|
|||
* Generates the `TypeInfo` object associated with `torig` if it
|
||||
* hasn't already been generated
|
||||
* Params:
|
||||
* e = if not null, then expression for pretty-printing errors
|
||||
* loc = the location for reporting line numbers in errors
|
||||
* torig = the type to generate the `TypeInfo` object for
|
||||
* sc = the scope
|
||||
*/
|
||||
extern (C++) void genTypeInfo(const ref Loc loc, Type torig, Scope* sc)
|
||||
extern (C++) void genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc)
|
||||
{
|
||||
// printf("genTypeInfo() %s\n", torig.toChars());
|
||||
|
||||
|
@ -43,7 +45,10 @@ extern (C++) void genTypeInfo(const ref Loc loc, Type torig, Scope* sc)
|
|||
{
|
||||
if (!global.params.useTypeInfo)
|
||||
{
|
||||
.error(loc, "`TypeInfo` cannot be used with -betterC");
|
||||
if (e)
|
||||
.error(loc, "expression `%s` uses the GC and cannot be used with switch `-betterC`", e.toChars());
|
||||
else
|
||||
.error(loc, "`TypeInfo` cannot be used with -betterC");
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2238,13 +2238,17 @@ public:
|
|||
new_call = build_nop (type, build_address (var));
|
||||
setup_exp = modify_expr (var, aggregate_initializer_decl (cd));
|
||||
}
|
||||
else if (global.params.ehnogc && e->thrownew)
|
||||
{
|
||||
/* Allocating a `@nogc' Exception with `_d_newThrowable' has already
|
||||
been handled by the front-end. */
|
||||
gcc_unreachable ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Generate: _d_newclass() */
|
||||
tree arg = build_address (get_classinfo_decl (cd));
|
||||
libcall_fn libcall = (global.params.ehnogc && e->thrownew)
|
||||
? LIBCALL_NEWTHROW : LIBCALL_NEWCLASS;
|
||||
new_call = build_libcall (libcall, tb, 1, arg);
|
||||
new_call = build_libcall (LIBCALL_NEWCLASS, tb, 1, arg);
|
||||
}
|
||||
|
||||
/* Set the context pointer for nested classes. */
|
||||
|
|
|
@ -61,7 +61,6 @@ DEF_D_RUNTIME (ARRAYBOUNDS_INDEXP, "_d_arraybounds_indexp", RT(VOID),
|
|||
|
||||
/* Used when calling new on a class. */
|
||||
DEF_D_RUNTIME (NEWCLASS, "_d_newclass", RT(OBJECT), P1(CONST_CLASSINFO), 0)
|
||||
DEF_D_RUNTIME (NEWTHROW, "_d_newThrowable", RT(OBJECT), P1(CONST_CLASSINFO), 0)
|
||||
|
||||
/* Used when calling delete on a stack-allocated class or interface. */
|
||||
DEF_D_RUNTIME (CALLFINALIZER, "_d_callfinalizer", RT(VOID), P1(VOIDPTR), 0)
|
||||
|
|
28
gcc/testsuite/gdc.test/compilable/imports/defines.c
Normal file
28
gcc/testsuite/gdc.test/compilable/imports/defines.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* */
|
||||
|
||||
#define CC 'c'
|
||||
_Static_assert(CC == 'c', "1");
|
||||
|
||||
#define I32 3
|
||||
_Static_assert(I32 == 3, "3");
|
||||
|
||||
#define U32 4U
|
||||
_Static_assert(U32 == 4U, "4");
|
||||
|
||||
#define I64 5L
|
||||
_Static_assert(I64 == 5U, "5");
|
||||
|
||||
#define U64 6UL
|
||||
_Static_assert(U64 == 6UL, "6");
|
||||
|
||||
#define F32 7.0f
|
||||
_Static_assert(F32 == 7.0f, "7");
|
||||
|
||||
#define F64 8.0f
|
||||
_Static_assert(F64 == 8.0, "8");
|
||||
|
||||
#define F80 9.0f
|
||||
_Static_assert(F80 == 9.0L, "9");
|
||||
|
||||
#define SSS "hello"
|
||||
_Static_assert(SSS[0] == 'h', "10");
|
|
@ -109,3 +109,12 @@ auto foo13550() @nogc
|
|||
}
|
||||
return &bar;
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19285
|
||||
|
||||
void f(bool cond, string s) @nogc {
|
||||
auto inner() { return s; }
|
||||
alias Unused1 = typeof(inner); // OK
|
||||
alias Unused2 = typeof(&inner); // (Does not) INFERS GC (anymore)
|
||||
enum Unused3 = __traits(compiles , &inner);
|
||||
}
|
||||
|
|
23
gcc/testsuite/gdc.test/compilable/test22626.d
Normal file
23
gcc/testsuite/gdc.test/compilable/test22626.d
Normal file
|
@ -0,0 +1,23 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=22626
|
||||
// REQUIRED_ARGS: -preview=nosharedaccess
|
||||
|
||||
shared int k;
|
||||
|
||||
class Oops
|
||||
{
|
||||
shared int a;
|
||||
shared int* pa;
|
||||
synchronized void oops()
|
||||
{
|
||||
// this should compile since the function is synchronized
|
||||
// and `a` is accessed through `this`.
|
||||
a = 2;
|
||||
|
||||
// this shouldn't compile because synchronized guards
|
||||
// only accesses to the first level of dereferencing
|
||||
static assert (!__traits(compiles, *pa = 2));
|
||||
|
||||
// this shouldn't compile `k` is a field of class `Oops`
|
||||
static assert (!__traits(compiles, k = 2));
|
||||
}
|
||||
}
|
38
gcc/testsuite/gdc.test/compilable/test23076.d
Normal file
38
gcc/testsuite/gdc.test/compilable/test23076.d
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* REQUIRED_ARGS: -O -inline
|
||||
*/
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23076
|
||||
|
||||
struct S
|
||||
{
|
||||
int depthLow = 0;
|
||||
int depthHigh = 30000;
|
||||
|
||||
void fun(int* pixels)
|
||||
{
|
||||
float b = depthLow;
|
||||
int depthA = cast(int)(b);
|
||||
int depthB = cast(short)(cast(float)depthHigh * cast(float)depthLow);
|
||||
pixels[depthA] = depthB;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************/
|
||||
|
||||
float mul3(float a, float b, float t)
|
||||
{
|
||||
return t * b * a;
|
||||
}
|
||||
|
||||
class A
|
||||
{
|
||||
ushort depthLow = 0;
|
||||
ushort depthHigh = 30000;
|
||||
|
||||
void fun(short* pixels)
|
||||
{
|
||||
short depthA = (cast(short)(mul3(depthHigh, depthLow, 0)));
|
||||
short depthB = (cast(short)(mul3(depthLow, depthHigh, 0)));
|
||||
pixels[depthA] = depthB;
|
||||
}
|
||||
}
|
19
gcc/testsuite/gdc.test/compilable/test23142.d
Normal file
19
gcc/testsuite/gdc.test/compilable/test23142.d
Normal file
|
@ -0,0 +1,19 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23142
|
||||
|
||||
struct Foo
|
||||
{
|
||||
int x;
|
||||
|
||||
scope:
|
||||
void func()
|
||||
{
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
}
|
||||
|
||||
static void func2()
|
||||
{
|
||||
}
|
||||
}
|
58
gcc/testsuite/gdc.test/compilable/test23174.d
Normal file
58
gcc/testsuite/gdc.test/compilable/test23174.d
Normal file
|
@ -0,0 +1,58 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23174
|
||||
|
||||
alias AliasSeq(T...) = T;
|
||||
|
||||
template staticMap(alias fun, args...)
|
||||
{
|
||||
alias staticMap = AliasSeq!();
|
||||
static foreach(arg; args)
|
||||
staticMap = AliasSeq!(staticMap, fun!arg);
|
||||
}
|
||||
|
||||
template Filter(alias pred, args...)
|
||||
{
|
||||
alias Filter = AliasSeq!();
|
||||
static foreach (arg; args)
|
||||
static if (pred!arg)
|
||||
Filter = AliasSeq!(Filter, arg);
|
||||
}
|
||||
|
||||
struct Fields(T)
|
||||
{
|
||||
private static alias toField(alias e) = Field!(__traits(identifier, e));
|
||||
alias fields = staticMap!(toField, T.tupleof);
|
||||
|
||||
static alias map(alias F) = staticMap!(F, fields);
|
||||
static alias filter(alias pred) = Filter!(pred, fields);
|
||||
}
|
||||
|
||||
struct Field(string n)
|
||||
{
|
||||
enum name = n;
|
||||
}
|
||||
|
||||
struct Foo
|
||||
{
|
||||
int a;
|
||||
}
|
||||
|
||||
void test23174()
|
||||
{
|
||||
Foo value;
|
||||
|
||||
enum toName(alias e) = e.name;
|
||||
enum pred(alias e) = true;
|
||||
|
||||
alias a = Fields!(Foo).filter!(pred); // works
|
||||
static assert(is(a == AliasSeq!(Field!"a")));
|
||||
|
||||
alias b = Fields!(Foo).map!(toName); // works
|
||||
static assert(b == AliasSeq!("a"));
|
||||
|
||||
alias c = Fields!(Foo).init.filter!(pred); // works
|
||||
static assert(is(c == AliasSeq!(Field!"a")));
|
||||
|
||||
// OK <- Error: alias `d` cannot alias an expression `Fields().tuple("a")`
|
||||
alias d = Fields!(Foo).init.map!(toName);
|
||||
static assert(d == AliasSeq!("a"));
|
||||
}
|
14
gcc/testsuite/gdc.test/compilable/testdefines.d
Normal file
14
gcc/testsuite/gdc.test/compilable/testdefines.d
Normal file
|
@ -0,0 +1,14 @@
|
|||
// EXTRA_FILES: imports/defines.c
|
||||
import imports.defines;
|
||||
|
||||
static assert(CC == 'c');
|
||||
static assert(I32 == 3);
|
||||
static assert(U32 == 4);
|
||||
static assert(I64 == 5);
|
||||
static assert(U64 == 6);
|
||||
|
||||
static assert(F32 == 7.0f);
|
||||
static assert(F64 == 8.0);
|
||||
static assert(F80 == 9.0L);
|
||||
|
||||
static assert(SSS == "hello");
|
|
@ -13,9 +13,28 @@ int bar()
|
|||
}
|
||||
}
|
||||
|
||||
void throwQualifiers() @safe @nogc pure
|
||||
{
|
||||
throw new Exception("baz");
|
||||
}
|
||||
|
||||
bool testThrowQualifiers()
|
||||
{
|
||||
try
|
||||
{
|
||||
throwQualifiers();
|
||||
} catch (Exception e)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void foo()
|
||||
{
|
||||
enum r = bar();
|
||||
static assert(r == 7);
|
||||
|
||||
static assert(testThrowQualifiers());
|
||||
}
|
||||
|
|
10
gcc/testsuite/gdc.test/fail_compilation/mixin_template.d
Normal file
10
gcc/testsuite/gdc.test/fail_compilation/mixin_template.d
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/mixin_template.d(10): Error: mixin `mixin_template.f!1` - `f` is a function, not a template
|
||||
---
|
||||
*/
|
||||
string f() {
|
||||
return "int i;";
|
||||
}
|
||||
mixin f!1;
|
|
@ -118,3 +118,21 @@ enum forceInClassRef = inClassRef();
|
|||
*/
|
||||
|
||||
enum throwEnum = throw new Exception("");
|
||||
|
||||
|
||||
/*
|
||||
https://issues.dlang.org/show_bug.cgi?id=23063
|
||||
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/noreturn.d(135): Error: `"Accessed expression of type `noreturn`"`
|
||||
fail_compilation/noreturn.d(138): called from here: `func()`
|
||||
---
|
||||
*/
|
||||
noreturn func()
|
||||
{
|
||||
noreturn a;
|
||||
return a;
|
||||
}
|
||||
|
||||
enum f = func();
|
||||
|
|
9
gcc/testsuite/gdc.test/fail_compilation/template_decl.d
Normal file
9
gcc/testsuite/gdc.test/fail_compilation/template_decl.d
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/template_decl.d(8): Error: `{` expected after template parameter list, not `(`
|
||||
fail_compilation/template_decl.d(8): Error: declaration expected, not `(`
|
||||
---
|
||||
*/
|
||||
template b(alias d)() {
|
||||
}
|
16
gcc/testsuite/gdc.test/fail_compilation/test21477.d
Normal file
16
gcc/testsuite/gdc.test/fail_compilation/test21477.d
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* REQUIRED_ARGS: -betterC
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/test21477.d(103): Error: expression `[1]` uses the GC and cannot be used with switch `-betterC`
|
||||
---
|
||||
*/
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=21477
|
||||
|
||||
#line 100
|
||||
|
||||
int test()
|
||||
{
|
||||
int[] foo = [1];
|
||||
return 0;
|
||||
}
|
22
gcc/testsuite/gdc.test/fail_compilation/test23159.d
Normal file
22
gcc/testsuite/gdc.test/fail_compilation/test23159.d
Normal file
|
@ -0,0 +1,22 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23159
|
||||
|
||||
// REQUIRED_ARGS: -betterC
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/test23159.d(14): Error: `scope(failure)` cannot be used with -betterC
|
||||
fail_compilation/test23159.d(18): Error: `scope(success)` cannot be used with -betterC
|
||||
---
|
||||
*/
|
||||
|
||||
void main()
|
||||
{
|
||||
scope(failure)
|
||||
{
|
||||
int a;
|
||||
}
|
||||
scope(success)
|
||||
{
|
||||
int a;
|
||||
}
|
||||
}
|
|
@ -116,3 +116,21 @@ pragma(msg, __traits(hasCopyConstructor));
|
|||
pragma(msg, __traits(hasCopyConstructor, S()));
|
||||
pragma(msg, __traits(hasPostblit));
|
||||
pragma(msg, __traits(hasPostblit, S()));
|
||||
|
||||
/********************************************
|
||||
https://issues.dlang.org/show_bug.cgi?id=23178
|
||||
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/traits.d(701): Error: alias `traits.a` cannot alias an expression `true`
|
||||
fail_compilation/traits.d(702): Error: alias `traits.b` cannot alias an expression `false`
|
||||
fail_compilation/traits.d(703): Error: alias `traits.c` cannot alias an expression `"Object"`
|
||||
fail_compilation/traits.d(704): while evaluating `pragma(msg, a)`
|
||||
---
|
||||
*/
|
||||
#line 700
|
||||
|
||||
alias a = __traits(compiles, 1);
|
||||
alias b = __traits(isIntegral, 1.1);
|
||||
alias c = __traits(identifier, Object);
|
||||
pragma(msg, a, b, c);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
f89da31331ef5df50d3bc7a26efd1b7acdefde8c
|
||||
454471d8077d12ec6bf0ae8fcd9571aad1bce7be
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/druntime repository.
|
||||
|
|
|
@ -200,9 +200,9 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
|
|||
core/stdc/tgmath.d core/stdc/time.d core/stdc/wchar_.d \
|
||||
core/stdc/wctype.d core/sync/barrier.d core/sync/condition.d \
|
||||
core/sync/config.d core/sync/event.d core/sync/exception.d \
|
||||
core/sync/mutex.d core/sync/rwmutex.d core/sync/semaphore.d \
|
||||
core/thread/context.d core/thread/fiber.d core/thread/osthread.d \
|
||||
core/thread/package.d core/thread/threadbase.d \
|
||||
core/sync/mutex.d core/sync/package.d core/sync/rwmutex.d \
|
||||
core/sync/semaphore.d core/thread/context.d core/thread/fiber.d \
|
||||
core/thread/osthread.d core/thread/package.d core/thread/threadbase.d \
|
||||
core/thread/threadgroup.d core/thread/types.d core/time.d \
|
||||
core/vararg.d core/volatile.d gcc/attribute.d gcc/attributes.d \
|
||||
gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
|
||||
|
|
|
@ -226,17 +226,18 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
|
|||
core/stdc/tgmath.lo core/stdc/time.lo core/stdc/wchar_.lo \
|
||||
core/stdc/wctype.lo core/sync/barrier.lo \
|
||||
core/sync/condition.lo core/sync/config.lo core/sync/event.lo \
|
||||
core/sync/exception.lo core/sync/mutex.lo core/sync/rwmutex.lo \
|
||||
core/sync/semaphore.lo core/thread/context.lo \
|
||||
core/thread/fiber.lo core/thread/osthread.lo \
|
||||
core/thread/package.lo core/thread/threadbase.lo \
|
||||
core/thread/threadgroup.lo core/thread/types.lo core/time.lo \
|
||||
core/vararg.lo core/volatile.lo gcc/attribute.lo \
|
||||
gcc/attributes.lo gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo \
|
||||
gcc/emutls.lo gcc/gthread.lo gcc/sections/common.lo \
|
||||
gcc/sections/elf.lo gcc/sections/macho.lo \
|
||||
gcc/sections/package.lo gcc/sections/pecoff.lo \
|
||||
gcc/unwind/arm.lo gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
|
||||
core/sync/exception.lo core/sync/mutex.lo core/sync/package.lo \
|
||||
core/sync/rwmutex.lo core/sync/semaphore.lo \
|
||||
core/thread/context.lo core/thread/fiber.lo \
|
||||
core/thread/osthread.lo core/thread/package.lo \
|
||||
core/thread/threadbase.lo core/thread/threadgroup.lo \
|
||||
core/thread/types.lo core/time.lo core/vararg.lo \
|
||||
core/volatile.lo gcc/attribute.lo gcc/attributes.lo \
|
||||
gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo gcc/emutls.lo \
|
||||
gcc/gthread.lo gcc/sections/common.lo gcc/sections/elf.lo \
|
||||
gcc/sections/macho.lo gcc/sections/package.lo \
|
||||
gcc/sections/pecoff.lo gcc/unwind/arm.lo \
|
||||
gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
|
||||
gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
|
||||
object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \
|
||||
rt/arrayassign.lo rt/arraycat.lo rt/cast_.lo rt/config.lo \
|
||||
|
@ -866,9 +867,9 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
|
|||
core/stdc/tgmath.d core/stdc/time.d core/stdc/wchar_.d \
|
||||
core/stdc/wctype.d core/sync/barrier.d core/sync/condition.d \
|
||||
core/sync/config.d core/sync/event.d core/sync/exception.d \
|
||||
core/sync/mutex.d core/sync/rwmutex.d core/sync/semaphore.d \
|
||||
core/thread/context.d core/thread/fiber.d core/thread/osthread.d \
|
||||
core/thread/package.d core/thread/threadbase.d \
|
||||
core/sync/mutex.d core/sync/package.d core/sync/rwmutex.d \
|
||||
core/sync/semaphore.d core/thread/context.d core/thread/fiber.d \
|
||||
core/thread/osthread.d core/thread/package.d core/thread/threadbase.d \
|
||||
core/thread/threadgroup.d core/thread/types.d core/time.d \
|
||||
core/vararg.d core/volatile.d gcc/attribute.d gcc/attributes.d \
|
||||
gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
|
||||
|
@ -1305,6 +1306,7 @@ core/sync/config.lo: core/sync/$(am__dirstamp)
|
|||
core/sync/event.lo: core/sync/$(am__dirstamp)
|
||||
core/sync/exception.lo: core/sync/$(am__dirstamp)
|
||||
core/sync/mutex.lo: core/sync/$(am__dirstamp)
|
||||
core/sync/package.lo: core/sync/$(am__dirstamp)
|
||||
core/sync/rwmutex.lo: core/sync/$(am__dirstamp)
|
||||
core/sync/semaphore.lo: core/sync/$(am__dirstamp)
|
||||
core/thread/$(am__dirstamp):
|
||||
|
|
|
@ -76,14 +76,14 @@ else
|
|||
* The attribute can only be attached to methods or constructors which
|
||||
* have Objective-C linkage. That is, a method or a constructor in a
|
||||
* class or interface declared as $(D_CODE extern(Objective-C)).
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* $(LI It cannot be attached to a method or constructor that is a template),
|
||||
* $(LI It cannot be attached to a method or constructor that is a template)
|
||||
*
|
||||
* $(LI
|
||||
* The number of colons in the string need to match the number of
|
||||
* arguments the method accept.
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* $(LI It can only be used once in a method declaration)
|
||||
* )
|
||||
|
@ -181,21 +181,21 @@ version (UdaOptional)
|
|||
* $(UL
|
||||
* $(LI
|
||||
* There can only be one such attribute per symbol.
|
||||
* ),
|
||||
* )
|
||||
* $(LI
|
||||
* The attribute can only be attached to an `extern(C++)` symbol
|
||||
* (`struct`, `class`, `enum`, function, and their templated counterparts).
|
||||
* ),
|
||||
* )
|
||||
* $(LI
|
||||
* The attribute cannot be applied to C++ namespaces.
|
||||
* This is to prevent confusion with the C++ semantic, which allows it to
|
||||
* be applied to namespaces.
|
||||
* ),
|
||||
* )
|
||||
* $(LI
|
||||
* The string arguments must only contain valid characters
|
||||
* for C++ name mangling which currently include alphanumerics
|
||||
* and the underscore character.
|
||||
* ),
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* This UDA is not transitive, and inner scope do not inherit outer scopes'
|
||||
|
@ -252,11 +252,11 @@ version (UdaGNUAbiTag) struct gnuAbiTag
|
|||
* $(LI
|
||||
* the expression is the top-level expression in a statement or the
|
||||
* left-hand expression in a comma expression, and
|
||||
* ),
|
||||
* )
|
||||
* $(LI
|
||||
* the expression is not an assignment (`=`, `+=`, etc.), increment
|
||||
* (`++`), or decrement (`--`) expression.
|
||||
* ),
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* If the declaration of a `struct` or `union` type has the `@mustuse`
|
||||
|
|
|
@ -21,8 +21,7 @@ bool __equals(T1, T2)(scope const T1[] lhs, scope const T2[] rhs)
|
|||
@nogc nothrow pure @trusted
|
||||
if (__traits(isScalar, T1) && __traits(isScalar, T2))
|
||||
{
|
||||
if (lhs.length != rhs.length)
|
||||
return false;
|
||||
const length = lhs.length;
|
||||
|
||||
static if (T1.sizeof == T2.sizeof
|
||||
// Signedness needs to match for types that promote to int.
|
||||
|
@ -31,20 +30,21 @@ if (__traits(isScalar, T1) && __traits(isScalar, T2))
|
|||
&& (T1.sizeof >= 4 || __traits(isUnsigned, T1) == __traits(isUnsigned, T2))
|
||||
&& !__traits(isFloating, T1) && !__traits(isFloating, T2))
|
||||
{
|
||||
if (!__ctfe)
|
||||
if (__ctfe)
|
||||
return length == rhs.length && isEqual(lhs.ptr, rhs.ptr, length);
|
||||
else
|
||||
{
|
||||
// This would improperly allow equality of integers and pointers
|
||||
// but the CTFE branch will stop this function from compiling then.
|
||||
import core.stdc.string : memcmp;
|
||||
return lhs.length == 0 ||
|
||||
0 == memcmp(cast(const void*) lhs.ptr, cast(const void*) rhs.ptr, lhs.length * T1.sizeof);
|
||||
return length == rhs.length &&
|
||||
(!length || 0 == memcmp(cast(const void*) lhs.ptr, cast(const void*) rhs.ptr, length * T1.sizeof));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const i; 0 .. lhs.length)
|
||||
if (lhs.ptr[i] != rhs.ptr[i])
|
||||
return false;
|
||||
return true;
|
||||
else
|
||||
{
|
||||
return length == rhs.length && isEqual(lhs.ptr, rhs.ptr, length);
|
||||
}
|
||||
}
|
||||
|
||||
bool __equals(T1, T2)(scope T1[] lhs, scope T2[] rhs)
|
||||
|
@ -89,6 +89,19 @@ if (!__traits(isScalar, T1) || !__traits(isScalar, T2))
|
|||
}
|
||||
}
|
||||
|
||||
/******************************
|
||||
* Helper function for __equals().
|
||||
* Outlined to enable __equals() to be inlined, as dmd cannot inline loops.
|
||||
*/
|
||||
private
|
||||
bool isEqual(T1, T2)(scope const T1* t1, scope const T2* t2, size_t length)
|
||||
{
|
||||
foreach (const i; 0 .. length)
|
||||
if (t1[i] != t2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
assert(__equals([], []));
|
||||
|
|
|
@ -2648,16 +2648,19 @@ if (!Init.length ||
|
|||
}
|
||||
|
||||
/**
|
||||
* Allocate an exception of type `T` from the exception pool and call its constructor.
|
||||
* It has the same interface as `rt.lifetime._d_newclass()`.
|
||||
* `T` must be Throwable or derived from it, must declare an explicit ctor
|
||||
* and cannot be a COM or C++ class.
|
||||
* Allocate an exception of type `T` from the exception pool.
|
||||
* `T` must be `Throwable` or derived from it and cannot be a COM or C++ class.
|
||||
*
|
||||
* Note:
|
||||
* This function does not call the constructor of `T` because that would require
|
||||
* `forward!args`, which causes errors with -dip1008. This inconvenience will be
|
||||
* removed once -dip1008 works as intended.
|
||||
*
|
||||
* Returns:
|
||||
* constructed instance of the type
|
||||
* allocated instance of type `T`
|
||||
*/
|
||||
T _d_newThrowable(T, Args...)(auto ref Args args) @trusted
|
||||
if (is(T : Throwable) && is(typeof(T.__ctor(forward!args))) &&
|
||||
__traits(getLinkage, T) == "D")
|
||||
T _d_newThrowable(T)() @trusted
|
||||
if (is(T : Throwable) && __traits(getLinkage, T) == "D")
|
||||
{
|
||||
debug(PRINTF) printf("_d_newThrowable(%s)\n", cast(char*) T.stringof);
|
||||
|
||||
|
@ -2687,33 +2690,22 @@ T _d_newThrowable(T, Args...)(auto ref Args args) @trusted
|
|||
|
||||
(cast(Throwable) p).refcount() = 1;
|
||||
|
||||
auto t = cast(T) p;
|
||||
t.__ctor(forward!args);
|
||||
|
||||
return t;
|
||||
return cast(T) p;
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
class E : Exception
|
||||
{
|
||||
int x;
|
||||
|
||||
this(int x, string msg = "", Throwable nextInChain = null)
|
||||
this(string msg = "", Throwable nextInChain = null)
|
||||
{
|
||||
super(msg, nextInChain);
|
||||
this.x = x;
|
||||
}
|
||||
}
|
||||
|
||||
auto exc = _d_newThrowable!Exception("Exception");
|
||||
Throwable exc = _d_newThrowable!Exception();
|
||||
Throwable e = _d_newThrowable!E();
|
||||
|
||||
assert(exc.refcount() == 1);
|
||||
assert(exc.msg == "Exception");
|
||||
|
||||
static assert(!__traits(compiles, _d_newThrowable!E()));
|
||||
|
||||
auto e = _d_newThrowable!E(42, "E", null);
|
||||
assert(e.refcount() == 1);
|
||||
assert(e.x == 42);
|
||||
assert(e.msg == "E");
|
||||
}
|
||||
|
|
|
@ -23,14 +23,27 @@ else
|
|||
enum StdNamespace = "std";
|
||||
}
|
||||
|
||||
/**
|
||||
* Possible values of the `__cplusplus` macro provided by C++ compilers
|
||||
*
|
||||
* For foolproofness, use ordering comparison, e.g. `__cplusplus >= CppStdRevision.cpp17`.
|
||||
*/
|
||||
enum CppStdRevision : uint
|
||||
{
|
||||
cpp98 = 199711,
|
||||
cpp11 = 201103,
|
||||
cpp14 = 201402,
|
||||
cpp17 = 201703
|
||||
cpp17 = 201703,
|
||||
cpp20 = 202002,
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target C++ version, encoded as C++ compilers do
|
||||
*
|
||||
* C++ compilers provide a `__cplusplus` macro which returns an integer
|
||||
* representing the targetted standard. This manifest provides the same
|
||||
* interface, retrieved from the compiler via a `__traits`.
|
||||
*/
|
||||
enum __cplusplus = __traits(getTargetInfo, "cppStd");
|
||||
|
||||
// wrangle C++ features
|
||||
|
|
|
@ -18,6 +18,16 @@ alias Elf32_Word Elf32_Hashelt;
|
|||
alias Elf32_Word Elf32_Size;
|
||||
alias Elf32_Sword Elf32_Ssize;
|
||||
|
||||
struct Elf32_Dyn
|
||||
{
|
||||
Elf32_Sword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf32_Word d_val;
|
||||
Elf32_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
alias Elf_Note Elf32_Nhdr;
|
||||
|
||||
struct Elf32_Cap
|
||||
|
|
|
@ -18,6 +18,16 @@ alias Elf64_Word Elf64_Hashelt;
|
|||
alias Elf64_Xword Elf64_Size;
|
||||
alias Elf64_Sxword Elf64_Ssize;
|
||||
|
||||
struct Elf64_Dyn
|
||||
{
|
||||
Elf64_Sxword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf64_Xword d_val;
|
||||
Elf64_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
extern (D) pure
|
||||
{
|
||||
auto ELF64_R_TYPE_DATA(I)(I i) { return (cast(Elf64_Xword) i << 32) >> 40; }
|
||||
|
|
|
@ -617,26 +617,6 @@ enum PF_R = (1 << 2);
|
|||
enum PF_MASKOS = 0x0ff00000;
|
||||
enum PF_MASKPROC = 0xf0000000;
|
||||
|
||||
struct Elf32_Dyn
|
||||
{
|
||||
Elf32_Sword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf32_Word d_val;
|
||||
Elf32_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
struct Elf64_Dyn
|
||||
{
|
||||
Elf64_Sxword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf64_Xword d_val;
|
||||
Elf64_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
enum DT_NULL = 0;
|
||||
enum DT_NEEDED = 1;
|
||||
enum DT_PLTRELSZ = 2;
|
||||
|
|
|
@ -18,6 +18,16 @@ alias Elf32_Word Elf32_Hashelt;
|
|||
alias Elf32_Word Elf32_Size;
|
||||
alias Elf32_Sword Elf32_Ssize;
|
||||
|
||||
struct Elf32_Dyn
|
||||
{
|
||||
Elf32_Sword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf32_Word d_val;
|
||||
Elf32_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
alias Elf_Note Elf32_Nhdr;
|
||||
|
||||
struct Elf32_Cap
|
||||
|
|
|
@ -18,6 +18,16 @@ alias Elf64_Word Elf64_Hashelt;
|
|||
alias Elf64_Xword Elf64_Size;
|
||||
alias Elf64_Sxword Elf64_Ssize;
|
||||
|
||||
struct Elf64_Dyn
|
||||
{
|
||||
Elf64_Sxword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf64_Xword d_val;
|
||||
Elf64_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
extern (D)
|
||||
{
|
||||
auto ELF64_R_TYPE_DATA(I)(I i) { return (cast(Elf64_Xword) i << 32) >> 40; }
|
||||
|
|
|
@ -75,6 +75,26 @@ enum NT_ARM_HW_WATCH = 0x403;
|
|||
|
||||
enum NT_VERSION = 1;
|
||||
|
||||
struct Elf32_Dyn
|
||||
{
|
||||
Elf32_Sword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf32_Word d_val;
|
||||
Elf32_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
struct Elf64_Dyn
|
||||
{
|
||||
Elf64_Sxword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf64_Xword d_val;
|
||||
Elf64_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
enum NT_GNU_ABI_TAG = 1;
|
||||
enum NT_GNU_HWCAP = 2;
|
||||
enum NT_GNU_BUILD_ID = 3;
|
||||
|
|
|
@ -18,6 +18,16 @@ alias Elf32_Word Elf32_Hashelt;
|
|||
alias Elf32_Word Elf32_Size;
|
||||
alias Elf32_Sword Elf32_Ssize;
|
||||
|
||||
struct Elf32_Dyn
|
||||
{
|
||||
Elf32_Sword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf32_Word d_val;
|
||||
Elf32_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
alias Elf_Note Elf32_Nhdr;
|
||||
|
||||
struct Elf32_Cap
|
||||
|
|
|
@ -18,6 +18,16 @@ alias Elf64_Word Elf64_Hashelt;
|
|||
alias Elf64_Xword Elf64_Size;
|
||||
alias Elf64_Sxword Elf64_Ssize;
|
||||
|
||||
struct Elf64_Dyn
|
||||
{
|
||||
Elf64_Sxword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf64_Xword d_val;
|
||||
Elf64_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
extern (D)
|
||||
{
|
||||
auto ELF64_R_TYPE_DATA(I)(I i) { return (cast(Elf64_Xword) i << 32) >> 40; }
|
||||
|
|
|
@ -19,6 +19,16 @@ alias Elf32_Word Elf32_Hashelt;
|
|||
alias Elf32_Word Elf32_Size;
|
||||
alias Elf32_Sword Elf32_Ssize;
|
||||
|
||||
struct Elf32_Dyn
|
||||
{
|
||||
Elf32_Sword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf32_Word d_val;
|
||||
Elf32_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
alias Elf_Note Elf32_Nhdr;
|
||||
|
||||
struct Elf32_Cap
|
||||
|
|
|
@ -19,6 +19,16 @@ alias Elf64_Word Elf64_Hashelt;
|
|||
alias Elf64_Xword Elf64_Size;
|
||||
alias Elf64_Sxword Elf64_Ssize;
|
||||
|
||||
struct Elf64_Dyn
|
||||
{
|
||||
Elf64_Sxword d_tag;
|
||||
union _d_un
|
||||
{
|
||||
Elf64_Xword d_val;
|
||||
Elf64_Addr d_ptr;
|
||||
} _d_un d_un;
|
||||
}
|
||||
|
||||
extern (D) pure
|
||||
{
|
||||
auto ELF64_R_TYPE_DATA(I)(I i) { return (cast(Elf64_Xword) i << 32) >> 40; }
|
||||
|
|
|
@ -11,18 +11,12 @@ nothrow:
|
|||
|
||||
import core.stdc.stdint;
|
||||
|
||||
alias uint32_t Elf32_Addr;
|
||||
alias uint16_t Elf32_Half;
|
||||
alias uint32_t Elf32_Off;
|
||||
alias int32_t Elf32_Sword;
|
||||
alias uint32_t Elf32_Word;
|
||||
public import core.sys.elf :
|
||||
Elf32_Addr, Elf32_Half, Elf32_Off,
|
||||
Elf32_Sword, Elf32_Word,
|
||||
Elf64_Addr, Elf64_Half, Elf64_Off,
|
||||
Elf64_Sword, Elf64_Sxword,
|
||||
Elf64_Word, Elf64_Xword;
|
||||
|
||||
alias uint64_t Elf64_Addr;
|
||||
alias uint16_t Elf64_Half;
|
||||
alias uint64_t Elf64_Off;
|
||||
alias int32_t Elf64_Sword;
|
||||
alias int64_t Elf64_Sxword;
|
||||
alias uint32_t Elf64_Word;
|
||||
alias uint64_t Elf64_Xword;
|
||||
alias uint64_t Elf64_Lword;
|
||||
alias uint64_t Elf32_Lword;
|
||||
|
|
|
@ -10,6 +10,7 @@ extern (C):
|
|||
nothrow:
|
||||
|
||||
public import core.sys.solaris.sys.elftypes;
|
||||
public import core.sys.elf;
|
||||
import core.stdc.config;
|
||||
|
||||
struct Elf32_Dyn
|
||||
|
@ -33,45 +34,8 @@ struct Elf64_Dyn
|
|||
} _d_un d_un;
|
||||
}
|
||||
|
||||
enum DT_NULL = 0;
|
||||
enum DT_NEEDED = 1;
|
||||
enum DT_PLTRELSZ = 2;
|
||||
enum DT_PLTGOT = 3;
|
||||
enum DT_HASH = 4;
|
||||
enum DT_STRTAB = 5;
|
||||
enum DT_SYMTAB = 6;
|
||||
enum DT_RELA = 7;
|
||||
enum DT_RELASZ = 8;
|
||||
enum DT_RELAENT = 9;
|
||||
enum DT_STRSZ = 10;
|
||||
enum DT_SYMENT = 11;
|
||||
enum DT_INIT = 12;
|
||||
enum DT_FINI = 13;
|
||||
enum DT_SONAME = 14;
|
||||
enum DT_RPATH = 15;
|
||||
enum DT_SYMBOLIC = 16;
|
||||
enum DT_REL = 17;
|
||||
enum DT_RELSZ = 18;
|
||||
enum DT_RELENT = 19;
|
||||
enum DT_PLTREL = 20;
|
||||
enum DT_DEBUG = 21;
|
||||
enum DT_TEXTREL = 22;
|
||||
enum DT_JMPREL = 23;
|
||||
enum DT_BIND_NOW = 24;
|
||||
enum DT_INIT_ARRAY = 25;
|
||||
enum DT_FINI_ARRAY = 26;
|
||||
enum DT_INIT_ARRAYSZ = 27;
|
||||
enum DT_FINI_ARRAYSZ = 28;
|
||||
enum DT_RUNPATH = 29;
|
||||
enum DT_FLAGS = 30;
|
||||
|
||||
enum DT_ENCODING = 32;
|
||||
enum DT_PREINIT_ARRAY = 32;
|
||||
enum DT_PREINIT_ARRAYSZ = 33;
|
||||
|
||||
enum DT_MAXPOSTAGS = 34;
|
||||
|
||||
enum DT_LOOS = 0x6000000d;
|
||||
enum DT_SUNW_AUXILIARY = 0x6000000d;
|
||||
enum DT_SUNW_RTLDINF = 0x6000000e;
|
||||
enum DT_SUNW_FILTER = 0x6000000f;
|
||||
|
@ -92,205 +56,15 @@ enum DT_SUNW_LDMACH = 0x6000001b;
|
|||
enum DT_SUNW_CAPCHAINENT = 0x6000001d;
|
||||
enum DT_SUNW_CAPCHAINSZ = 0x6000001f;
|
||||
|
||||
enum DT_HIOS = 0x6ffff000;
|
||||
|
||||
enum DT_DEPRECATED_SPARC_REGISTER = 0x7000001;
|
||||
|
||||
enum DT_VALRNGLO = 0x6ffffd00;
|
||||
|
||||
enum DT_GNU_PRELINKED = 0x6ffffdf5;
|
||||
enum DT_GNU_CONFLICTSZ = 0x6ffffdf6;
|
||||
enum DT_GNU_LIBLISTSZ = 0x6ffffdf7;
|
||||
enum DT_CHECKSUM = 0x6ffffdf8;
|
||||
enum DT_PLTPADSZ = 0x6ffffdf9;
|
||||
enum DT_MOVEENT = 0x6ffffdfa;
|
||||
enum DT_MOVESZ = 0x6ffffdfb;
|
||||
enum DT_FEATURE_1 = 0x6ffffdfc;
|
||||
enum DT_POSFLAG_1 = 0x6ffffdfd;
|
||||
enum DT_SYMINSZ = 0x6ffffdfe;
|
||||
enum DT_SYMINENT = 0x6ffffdff;
|
||||
enum DT_VALRNGHI = 0x6ffffdff;
|
||||
|
||||
enum DT_ADDRRNGLO = 0x6ffffe00;
|
||||
|
||||
enum DT_GNU_HASH = 0x6ffffef5;
|
||||
enum DT_TLSDESC_PLT = 0x6ffffef6;
|
||||
enum DT_TLSDESC_GOT = 0x6ffffef7;
|
||||
enum DT_GNU_CONFLICT = 0x6ffffef8;
|
||||
enum DT_GNU_LIBLIST = 0x6ffffef9;
|
||||
|
||||
enum DT_CONFIG = 0x6ffffefa;
|
||||
enum DT_DEPAUDIT = 0x6ffffefb;
|
||||
enum DT_AUDIT = 0x6ffffefc;
|
||||
enum DT_PLTPAD = 0x6ffffefd;
|
||||
enum DT_MOVETAB = 0x6ffffefe;
|
||||
enum DT_SYMINFO = 0x6ffffeff;
|
||||
enum DT_ADDRRNGHI = 0x6ffffeff;
|
||||
|
||||
enum DT_VERSYM = 0x6ffffff0;
|
||||
|
||||
enum DT_RELACOUNT = 0x6ffffff9;
|
||||
enum DT_RELCOUNT = 0x6ffffffa;
|
||||
enum DT_FLAGS_1 = 0x6ffffffb;
|
||||
enum DT_VERDEF = 0x6ffffffc;
|
||||
enum DT_VERDEFNUM = 0x6ffffffd;
|
||||
enum DT_VERNEED = 0x6ffffffe;
|
||||
enum DT_VERNEEDNUM = 0x6fffffff;
|
||||
|
||||
enum DT_LOPROC = 0x70000000;
|
||||
enum DT_AUXILIARY = 0x7ffffffd;
|
||||
enum DT_USED = 0x7ffffffe;
|
||||
enum DT_FILTER = 0x7fffffff;
|
||||
enum DT_HIPROC = 0x7fffffff;
|
||||
|
||||
enum DF_ORIGIN = 0x00000001;
|
||||
enum DF_SYMBOLIC = 0x00000002;
|
||||
enum DF_TEXTREL = 0x00000004;
|
||||
enum DF_BIND_NOW = 0x00000008;
|
||||
enum DF_STATIC_TLS = 0x00000010;
|
||||
|
||||
enum DF_P1_LAZYLOAD = 0x00000001;
|
||||
enum DF_P1_GROUPPERM = 0x00000002;
|
||||
enum DF_P1_DEFERRED = 0x00000004;
|
||||
|
||||
enum DF_1_NOW = 0x00000001;
|
||||
enum DF_1_GLOBAL = 0x00000002;
|
||||
enum DF_1_GROUP = 0x00000004;
|
||||
enum DF_1_NODELETE = 0x00000008;
|
||||
enum DF_1_LOADFLTR = 0x00000010;
|
||||
enum DF_1_INITFIRST = 0x00000020;
|
||||
enum DF_1_NOOPEN = 0x00000040;
|
||||
enum DF_1_ORIGIN = 0x00000080;
|
||||
enum DF_1_DIRECT = 0x00000100;
|
||||
enum DF_1_TRANS = 0x00000200;
|
||||
enum DF_1_INTERPOSE = 0x00000400;
|
||||
enum DF_1_NODEFLIB = 0x00000800;
|
||||
enum DF_1_NODUMP = 0x00001000;
|
||||
enum DF_1_CONFALT = 0x00002000;
|
||||
enum DF_1_ENDFILTEE = 0x00004000;
|
||||
enum DF_1_DISPRELDNE = 0x00008000;
|
||||
enum DF_1_DISPRELPND = 0x00010000;
|
||||
enum DF_1_NODIRECT = 0x00020000;
|
||||
enum DF_1_IGNMULDEF = 0x00040000;
|
||||
enum DF_1_NOKSYMS = 0x00080000;
|
||||
enum DF_1_NOHDR = 0x00100000;
|
||||
enum DF_1_EDITED = 0x00200000;
|
||||
enum DF_1_NORELOC = 0x00400000;
|
||||
enum DF_1_SYMINTPOSE = 0x00800000;
|
||||
enum DF_1_GLOBAUDIT = 0x01000000;
|
||||
enum DF_1_SINGLETON = 0x02000000;
|
||||
|
||||
enum DTF_1_PARINIT = 0x00000001;
|
||||
enum DTF_1_CONFEXP = 0x00000002;
|
||||
|
||||
struct Elf32_Verdef
|
||||
{
|
||||
Elf32_Half vd_version;
|
||||
Elf32_Half vd_flags;
|
||||
Elf32_Half vd_ndx;
|
||||
Elf32_Half vd_cnt;
|
||||
Elf32_Word vd_hash;
|
||||
Elf32_Word vd_aux;
|
||||
Elf32_Word vd_next;
|
||||
}
|
||||
|
||||
struct Elf32_Verdaux
|
||||
{
|
||||
Elf32_Word vda_name;
|
||||
Elf32_Word vda_next;
|
||||
}
|
||||
|
||||
struct Elf32_Verneed
|
||||
{
|
||||
Elf32_Half vn_version;
|
||||
Elf32_Half vn_cnt;
|
||||
Elf32_Word vn_file;
|
||||
Elf32_Word vn_aux;
|
||||
Elf32_Word vn_next;
|
||||
}
|
||||
|
||||
struct Elf32_Vernaux
|
||||
{
|
||||
Elf32_Word vna_hash;
|
||||
Elf32_Half vna_flags;
|
||||
Elf32_Half vna_other;
|
||||
Elf32_Word vna_name;
|
||||
Elf32_Word vna_next;
|
||||
}
|
||||
|
||||
alias Elf32_Half Elf32_Versym;
|
||||
|
||||
struct Elf32_Syminfo
|
||||
{
|
||||
Elf32_Half si_boundto;
|
||||
Elf32_Half si_flags;
|
||||
}
|
||||
|
||||
struct Elf64_Verdef
|
||||
{
|
||||
Elf64_Half vd_version;
|
||||
Elf64_Half vd_flags;
|
||||
Elf64_Half vd_ndx;
|
||||
Elf64_Half vd_cnt;
|
||||
Elf64_Word vd_hash;
|
||||
Elf64_Word vd_aux;
|
||||
Elf64_Word vd_next;
|
||||
}
|
||||
|
||||
struct Elf64_Verdaux
|
||||
{
|
||||
Elf64_Word vda_name;
|
||||
Elf64_Word vda_next;
|
||||
}
|
||||
|
||||
struct Elf64_Verneed
|
||||
{
|
||||
Elf64_Half vn_version;
|
||||
Elf64_Half vn_cnt;
|
||||
Elf64_Word vn_file;
|
||||
Elf64_Word vn_aux;
|
||||
Elf64_Word vn_next;
|
||||
}
|
||||
|
||||
struct Elf64_Vernaux
|
||||
{
|
||||
Elf64_Word vna_hash;
|
||||
Elf64_Half vna_flags;
|
||||
Elf64_Half vna_other;
|
||||
Elf64_Word vna_name;
|
||||
Elf64_Word vna_next;
|
||||
}
|
||||
|
||||
alias Elf64_Half Elf64_Versym;
|
||||
|
||||
struct Elf64_Syminfo
|
||||
{
|
||||
Elf64_Half si_boundto;
|
||||
Elf64_Half si_flags;
|
||||
}
|
||||
|
||||
enum VER_NDX_LOCAL = 0;
|
||||
enum VER_NDX_GLOBAL = 1;
|
||||
enum VER_NDX_LORESERVE = 0xff00;
|
||||
enum VER_NDX_ELIMINATE = 0xff01;
|
||||
|
||||
enum VER_FLG_BASE = 0x1;
|
||||
enum VER_FLG_WEAK = 0x2;
|
||||
enum VER_FLG_INFO = 0x4;
|
||||
|
||||
enum VER_DEF_NONE = 0;
|
||||
enum VER_DEF_CURRENT = 1;
|
||||
enum VER_DEF_NUM = 2;
|
||||
|
||||
enum VER_NEED_NONE = 0;
|
||||
enum VER_NEED_CURRENT = 1;
|
||||
enum VER_NEED_NUM = 2;
|
||||
|
||||
enum SYMINFO_FLG_DIRECT = 0x0001;
|
||||
enum SYMINFO_FLG_FILTER = 0x0002;
|
||||
enum SYMINFO_FLG_PASSTHRU = SYMINFO_FLG_FILTER;
|
||||
enum SYMINFO_FLG_COPY = 0x0004;
|
||||
enum SYMINFO_FLG_LAZYLOAD = 0x0008;
|
||||
enum SYMINFO_FLG_DIRECTBIND = 0x0010;
|
||||
enum SYMINFO_FLG_NOEXTDIRECT = 0x0020;
|
||||
enum SYMINFO_FLG_AUXILIARY = 0x0040;
|
||||
|
@ -298,15 +72,8 @@ enum SYMINFO_FLG_INTERPOSE = 0x0080;
|
|||
enum SYMINFO_FLG_CAP = 0x0100;
|
||||
enum SYMINFO_FLG_DEFERRED = 0x0200;
|
||||
|
||||
enum SYMINFO_BT_SELF = 0xffff;
|
||||
enum SYMINFO_BT_PARENT = 0xfffe;
|
||||
enum SYMINFO_BT_NONE = 0xfffd;
|
||||
enum SYMINFO_BT_EXTERN = 0xfffc;
|
||||
enum SYMINFO_BT_LOWRESERVE = 0xff00;
|
||||
|
||||
enum SYMINFO_NONE = 0;
|
||||
enum SYMINFO_CURRENT = 1;
|
||||
enum SYMINFO_NUM = 2;
|
||||
|
||||
alias link_map Link_map;
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ class ThreadBase
|
|||
}
|
||||
|
||||
this(void delegate() dg, size_t sz = 0) @trusted pure nothrow @nogc
|
||||
in( cast(void delegate() const) dg)
|
||||
in( cast(const void delegate()) dg)
|
||||
{
|
||||
this(sz);
|
||||
m_call = dg;
|
||||
|
|
|
@ -18,51 +18,6 @@ debug(PRINTF)
|
|||
import core.stdc.stdio;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Allocate an exception of type `ci` from the exception pool.
|
||||
* It has the same interface as `rt.lifetime._d_newclass()`.
|
||||
* The class type must be Throwable or derived from it,
|
||||
* and cannot be a COM or C++ class. The compiler must enforce
|
||||
* this.
|
||||
* Returns:
|
||||
* default initialized instance of the type
|
||||
*/
|
||||
|
||||
extern (C) Throwable _d_newThrowable(const TypeInfo_Class ci)
|
||||
{
|
||||
debug(PRINTF) printf("_d_newThrowable(ci = %p, %s)\n", ci, cast(char *)ci.name);
|
||||
|
||||
assert(!(ci.m_flags & TypeInfo_Class.ClassFlags.isCOMclass));
|
||||
assert(!(ci.m_flags & TypeInfo_Class.ClassFlags.isCPPclass));
|
||||
|
||||
import core.stdc.stdlib : malloc;
|
||||
auto init = ci.initializer;
|
||||
void* p = malloc(init.length);
|
||||
if (!p)
|
||||
{
|
||||
import core.exception : onOutOfMemoryError;
|
||||
onOutOfMemoryError();
|
||||
}
|
||||
|
||||
debug(PRINTF) printf(" p = %p\n", p);
|
||||
|
||||
// initialize it
|
||||
p[0 .. init.length] = init[];
|
||||
|
||||
if (!(ci.m_flags & TypeInfo_Class.ClassFlags.noPointers))
|
||||
{
|
||||
// Inform the GC about the pointers in the object instance
|
||||
import core.memory : GC;
|
||||
|
||||
GC.addRange(p, init.length, ci);
|
||||
}
|
||||
|
||||
debug(PRINTF) printf("initialization done\n");
|
||||
Throwable t = cast(Throwable)p;
|
||||
t.refcount() = 1;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Delete exception instance `t` from the exception pool.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
d46814c86392007ebb4fb73cb684ef9e8caa605a
|
||||
1206fc94f967b0183667a109049cbf596deaa696
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/phobos repository.
|
||||
|
|
|
@ -71,13 +71,13 @@ class MmFile
|
|||
* - On POSIX, $(REF ErrnoException, std, exception).
|
||||
* - On Windows, $(REF WindowsException, std, windows, syserror).
|
||||
*/
|
||||
this(string filename)
|
||||
this(string filename) scope
|
||||
{
|
||||
this(filename, Mode.read, 0, null);
|
||||
}
|
||||
|
||||
version (linux) this(File file, Mode mode = Mode.read, ulong size = 0,
|
||||
void* address = null, size_t window = 0)
|
||||
void* address = null, size_t window = 0) scope
|
||||
{
|
||||
// Save a copy of the File to make sure the fd stays open.
|
||||
this.file = file;
|
||||
|
@ -85,7 +85,7 @@ class MmFile
|
|||
}
|
||||
|
||||
version (linux) private this(int fildes, Mode mode, ulong size,
|
||||
void* address, size_t window)
|
||||
void* address, size_t window) scope
|
||||
{
|
||||
int oflag;
|
||||
int fmode;
|
||||
|
@ -169,7 +169,7 @@ class MmFile
|
|||
* - On Windows, $(REF WindowsException, std, windows, syserror).
|
||||
*/
|
||||
this(string filename, Mode mode, ulong size, void* address,
|
||||
size_t window = 0)
|
||||
size_t window = 0) scope
|
||||
{
|
||||
this.filename = filename;
|
||||
this.mMode = mode;
|
||||
|
@ -364,7 +364,7 @@ class MmFile
|
|||
/**
|
||||
* Flushes pending output and closes the memory mapped file.
|
||||
*/
|
||||
~this()
|
||||
~this() scope
|
||||
{
|
||||
debug (MMFILE) printf("MmFile.~this()\n");
|
||||
unmap();
|
||||
|
|
|
@ -1313,6 +1313,7 @@ version (D_BetterC) {} else
|
|||
// Types with invariants
|
||||
// Disabled in BetterC due to use of exceptions
|
||||
version (D_BetterC) {} else
|
||||
version (D_Invariants)
|
||||
@system unittest
|
||||
{
|
||||
import std.exception : assertThrown;
|
||||
|
@ -1330,22 +1331,13 @@ version (D_BetterC) {} else
|
|||
invariant { assert(i >= 0); }
|
||||
}
|
||||
|
||||
// Only run test if contract checking is enabled
|
||||
try
|
||||
{
|
||||
S probe = S(-1);
|
||||
assert(&probe);
|
||||
}
|
||||
catch (AssertError _)
|
||||
{
|
||||
SumType!S x;
|
||||
x.match!((ref v) { v.i = -1; });
|
||||
assertThrown!AssertError(assert(&x));
|
||||
SumType!S x;
|
||||
x.match!((ref v) { v.i = -1; });
|
||||
assertThrown!AssertError(assert(&x));
|
||||
|
||||
SumType!C y = new C();
|
||||
y.match!((ref v) { v.i = -1; });
|
||||
assertThrown!AssertError(assert(&y));
|
||||
}
|
||||
SumType!C y = new C();
|
||||
y.match!((ref v) { v.i = -1; });
|
||||
assertThrown!AssertError(assert(&y));
|
||||
}
|
||||
|
||||
// Calls value postblit on self-assignment
|
||||
|
|
Loading…
Add table
Reference in a new issue