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:
Iain Buclaw 2022-06-13 10:41:57 +02:00
parent 13ea4a6e83
commit ec486b739b
62 changed files with 1029 additions and 712 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -311,6 +311,7 @@ immutable Msgtable[] msgtable =
{ "__ArrayPostblit" },
{ "__ArrayDtor" },
{ "_d_delThrowable" },
{ "_d_newThrowable" },
{ "_d_assert_fail" },
{ "dup" },
{ "_aaApply" },

View file

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

View file

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

View file

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

View file

@ -147,4 +147,5 @@ struct Scope
structalign_t alignment();
bool isDeprecated() const;
bool isFromSpeculativeSemanticContext() const;
};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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");

View file

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

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

View 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;
}
}

View 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()
{
}
}

View 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"));
}

View 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");

View file

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

View 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;

View file

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

View 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)() {
}

View 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;
}

View 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;
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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([], []));

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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