From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1873) id AD5873850431; Mon, 13 Jun 2022 11:06:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AD5873850431 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Iain Buclaw To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-1062] d: Merge upstream dmd 821ed393d, druntime 454471d8, phobos 1206fc94f. X-Act-Checkin: gcc X-Git-Author: Iain Buclaw X-Git-Refname: refs/heads/master X-Git-Oldrev: 13ea4a6e830da1f245136601e636dec62e74d1a7 X-Git-Newrev: ec486b739b83ffdbe40c5ececb20d16c94d6b0d0 Message-Id: <20220613110659.AD5873850431@sourceware.org> Date: Mon, 13 Jun 2022 11:06:59 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Jun 2022 11:06:59 -0000 https://gcc.gnu.org/g:ec486b739b83ffdbe40c5ececb20d16c94d6b0d0 commit r13-1062-gec486b739b83ffdbe40c5ececb20d16c94d6b0d0 Author: Iain Buclaw Date: Mon Jun 13 10:41:57 2022 +0200 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. Diff: --- gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/attrib.d | 6 +- gcc/d/dmd/cparse.d | 88 +++- gcc/d/dmd/cppmangle.d | 2 +- gcc/d/dmd/dcast.d | 4 +- gcc/d/dmd/dinterpret.d | 38 +- gcc/d/dmd/dscope.d | 17 +- gcc/d/dmd/dsymbol.d | 18 +- gcc/d/dmd/dsymbol.h | 2 - gcc/d/dmd/dsymbolsem.d | 7 - gcc/d/dmd/dtemplate.d | 8 +- gcc/d/dmd/expressionsem.d | 100 ++++- gcc/d/dmd/func.d | 4 +- gcc/d/dmd/id.d | 1 + gcc/d/dmd/mtype.d | 13 +- gcc/d/dmd/mtype.h | 11 + gcc/d/dmd/parse.d | 2 +- gcc/d/dmd/scope.h | 1 + gcc/d/dmd/statement.d | 2 +- gcc/d/dmd/statementsem.d | 25 +- gcc/d/dmd/typesem.d | 471 +++++++++++---------- gcc/d/dmd/typinf.d | 9 +- gcc/d/expr.cc | 10 +- gcc/d/runtime.def | 1 - .../gdc.test/compilable/imports/defines.c | 28 ++ gcc/testsuite/gdc.test/compilable/nogc.d | 9 + gcc/testsuite/gdc.test/compilable/test22626.d | 23 + gcc/testsuite/gdc.test/compilable/test23076.d | 38 ++ gcc/testsuite/gdc.test/compilable/test23142.d | 19 + gcc/testsuite/gdc.test/compilable/test23174.d | 58 +++ gcc/testsuite/gdc.test/compilable/testdefines.d | 14 + gcc/testsuite/gdc.test/compilable/testdip1008.d | 19 + .../gdc.test/fail_compilation/mixin_template.d | 10 + gcc/testsuite/gdc.test/fail_compilation/noreturn.d | 18 + .../gdc.test/fail_compilation/template_decl.d | 9 + .../gdc.test/fail_compilation/test21477.d | 16 + .../gdc.test/fail_compilation/test23159.d | 22 + gcc/testsuite/gdc.test/fail_compilation/traits.d | 18 + libphobos/libdruntime/MERGE | 2 +- libphobos/libdruntime/Makefile.am | 6 +- libphobos/libdruntime/Makefile.in | 30 +- libphobos/libdruntime/core/attribute.d | 18 +- .../libdruntime/core/internal/array/equality.d | 33 +- libphobos/libdruntime/core/lifetime.d | 40 +- libphobos/libdruntime/core/stdcpp/xutility.d | 15 +- .../libdruntime/core/sys/dragonflybsd/sys/elf32.d | 10 + .../libdruntime/core/sys/dragonflybsd/sys/elf64.d | 10 + libphobos/libdruntime/core/sys/elf/package.d | 20 - libphobos/libdruntime/core/sys/freebsd/sys/elf32.d | 10 + libphobos/libdruntime/core/sys/freebsd/sys/elf64.d | 10 + libphobos/libdruntime/core/sys/linux/elf.d | 20 + libphobos/libdruntime/core/sys/netbsd/sys/elf32.d | 10 + libphobos/libdruntime/core/sys/netbsd/sys/elf64.d | 10 + libphobos/libdruntime/core/sys/openbsd/sys/elf32.d | 10 + libphobos/libdruntime/core/sys/openbsd/sys/elf64.d | 10 + .../libdruntime/core/sys/solaris/sys/elftypes.d | 18 +- libphobos/libdruntime/core/sys/solaris/sys/link.d | 235 +--------- libphobos/libdruntime/core/thread/threadbase.d | 2 +- libphobos/libdruntime/rt/ehalloc.d | 45 -- libphobos/src/MERGE | 2 +- libphobos/src/std/mmfile.d | 10 +- libphobos/src/std/sumtype.d | 22 +- 62 files changed, 1029 insertions(+), 712 deletions(-) diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index c37da0585d9..d39658a808e 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -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. diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d index 1e84b55d181..b569a9c3b46 100644 --- a/gcc/d/dmd/attrib.d +++ b/gcc/d/dmd/attrib.d @@ -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); } diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d index 344933ace83..62ba889cc13 100644 --- a/gcc/d/dmd/cparse.d +++ b/gcc/d/dmd/cparse.d @@ -5156,26 +5156,80 @@ final class CParser(AST) : Parser!AST { auto id = n.ident; scan(&n); - if (n.value == TOK.endOfLine) // #define identifier - { - nextDefineLine(); - continue; - } - if (n.value == TOK.int32Literal) + + AST.Type t; + + switch (n.value) { - 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(); diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d index 6235342a4f4..fed83b8f403 100644 --- a/gcc/d/dmd/cppmangle.d +++ b/gcc/d/dmd/cppmangle.d @@ -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); diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index 4607d6fee7c..12051d92215 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.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) diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d index 5e7527d7041..bb25210019f 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -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. diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d index b546e372003..9c30978551b 100644 --- a/gcc/d/dmd/dscope.d +++ b/gcc/d/dmd/dscope.d @@ -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; + } } diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d index 3b3a527dc52..2b608f6974c 100644 --- a/gcc/d/dmd/dsymbol.d +++ b/gcc/d/dmd/dsymbol.d @@ -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); } diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h index 23a2c775d4c..bea4b776ec5 100644 --- a/gcc/d/dmd/dsymbol.h +++ b/gcc/d/dmd/dsymbol.h @@ -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; diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index e49127220a0..6dbc129baaf 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -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 diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index a450ea559ac..c0a8e9f4664 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -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; } } diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index cb720271ae7..dcc5b5095ed 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -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()); } } diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index 04039483930..d42925990a9 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -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); diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d index 4993a9eb1b2..5142daa5137 100644 --- a/gcc/d/dmd/id.d +++ b/gcc/d/dmd/id.d @@ -311,6 +311,7 @@ immutable Msgtable[] msgtable = { "__ArrayPostblit" }, { "__ArrayDtor" }, { "_d_delThrowable" }, + { "_d_newThrowable" }, { "_d_assert_fail" }, { "dup" }, { "_aaApply" }, diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index 052c23d4420..6b5389dfebb 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -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 { diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h index 3565913ed27..3e614d88180 100644 --- a/gcc/d/dmd/mtype.h +++ b/gcc/d/dmd/mtype.h @@ -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); } diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index 15b7658a49a..89f8ae3470f 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -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); diff --git a/gcc/d/dmd/scope.h b/gcc/d/dmd/scope.h index a163e7577a2..b29c59943f3 100644 --- a/gcc/d/dmd/scope.h +++ b/gcc/d/dmd/scope.h @@ -147,4 +147,5 @@ struct Scope structalign_t alignment(); bool isDeprecated() const; + bool isFromSpeculativeSemanticContext() const; }; diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d index 06546256d17..a519f3b4c4c 100644 --- a/gcc/d/dmd/statement.d +++ b/gcc/d/dmd/statement.d @@ -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); } diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index ed47b916c0a..06e28a4819d 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -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(); diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index 4c9ca28f2fc..31ecbd246e6 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -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; +} diff --git a/gcc/d/dmd/typinf.d b/gcc/d/dmd/typinf.d index 21447ae9a3d..b701be38e42 100644 --- a/gcc/d/dmd/typinf.d +++ b/gcc/d/dmd/typinf.d @@ -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(); } } diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 7edcbc47abc..179f9a5f4fd 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -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. */ diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def index 1ad0369a75d..459a28386a0 100644 --- a/gcc/d/runtime.def +++ b/gcc/d/runtime.def @@ -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) diff --git a/gcc/testsuite/gdc.test/compilable/imports/defines.c b/gcc/testsuite/gdc.test/compilable/imports/defines.c new file mode 100644 index 00000000000..6bd07366544 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/defines.c @@ -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"); diff --git a/gcc/testsuite/gdc.test/compilable/nogc.d b/gcc/testsuite/gdc.test/compilable/nogc.d index 27518019d6d..6ce5094371f 100644 --- a/gcc/testsuite/gdc.test/compilable/nogc.d +++ b/gcc/testsuite/gdc.test/compilable/nogc.d @@ -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); +} diff --git a/gcc/testsuite/gdc.test/compilable/test22626.d b/gcc/testsuite/gdc.test/compilable/test22626.d new file mode 100644 index 00000000000..5f72eb635c0 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test22626.d @@ -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)); + } +} diff --git a/gcc/testsuite/gdc.test/compilable/test23076.d b/gcc/testsuite/gdc.test/compilable/test23076.d new file mode 100644 index 00000000000..10a0c2f1601 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23076.d @@ -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; + } +} diff --git a/gcc/testsuite/gdc.test/compilable/test23142.d b/gcc/testsuite/gdc.test/compilable/test23142.d new file mode 100644 index 00000000000..28bb6916978 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23142.d @@ -0,0 +1,19 @@ +// https://issues.dlang.org/show_bug.cgi?id=23142 + +struct Foo +{ + int x; + +scope: + void func() + { + } + + unittest + { + } + + static void func2() + { + } +} diff --git a/gcc/testsuite/gdc.test/compilable/test23174.d b/gcc/testsuite/gdc.test/compilable/test23174.d new file mode 100644 index 00000000000..9047fd7f8a9 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23174.d @@ -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")); +} diff --git a/gcc/testsuite/gdc.test/compilable/testdefines.d b/gcc/testsuite/gdc.test/compilable/testdefines.d new file mode 100644 index 00000000000..4507266c751 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/testdefines.d @@ -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"); diff --git a/gcc/testsuite/gdc.test/compilable/testdip1008.d b/gcc/testsuite/gdc.test/compilable/testdip1008.d index 5e024fe68ec..54d404c993f 100644 --- a/gcc/testsuite/gdc.test/compilable/testdip1008.d +++ b/gcc/testsuite/gdc.test/compilable/testdip1008.d @@ -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()); } diff --git a/gcc/testsuite/gdc.test/fail_compilation/mixin_template.d b/gcc/testsuite/gdc.test/fail_compilation/mixin_template.d new file mode 100644 index 00000000000..b088da88e3a --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/mixin_template.d @@ -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; diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn.d index 696081a36b6..d47d44917ba 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/noreturn.d +++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn.d @@ -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(); diff --git a/gcc/testsuite/gdc.test/fail_compilation/template_decl.d b/gcc/testsuite/gdc.test/fail_compilation/template_decl.d new file mode 100644 index 00000000000..d986dd65065 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/template_decl.d @@ -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)() { +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21477.d b/gcc/testsuite/gdc.test/fail_compilation/test21477.d new file mode 100644 index 00000000000..c9c7c7fcd50 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test21477.d @@ -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; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23159.d b/gcc/testsuite/gdc.test/fail_compilation/test23159.d new file mode 100644 index 00000000000..cdafc613b59 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test23159.d @@ -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; + } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/traits.d b/gcc/testsuite/gdc.test/fail_compilation/traits.d index 8c16afe75b2..21f3f57edd5 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/traits.d +++ b/gcc/testsuite/gdc.test/fail_compilation/traits.d @@ -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); diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index d503bae835c..8b2839da46c 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -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. diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am index 260bb63340c..d963aa9bd3d 100644 --- a/libphobos/libdruntime/Makefile.am +++ b/libphobos/libdruntime/Makefile.am @@ -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 \ diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in index b7e2f347278..45e086a5f0d 100644 --- a/libphobos/libdruntime/Makefile.in +++ b/libphobos/libdruntime/Makefile.in @@ -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): diff --git a/libphobos/libdruntime/core/attribute.d b/libphobos/libdruntime/core/attribute.d index 69b20f0bd3c..8a1dc8add89 100644 --- a/libphobos/libdruntime/core/attribute.d +++ b/libphobos/libdruntime/core/attribute.d @@ -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` diff --git a/libphobos/libdruntime/core/internal/array/equality.d b/libphobos/libdruntime/core/internal/array/equality.d index b12e2f24ccf..d3fdd655796 100644 --- a/libphobos/libdruntime/core/internal/array/equality.d +++ b/libphobos/libdruntime/core/internal/array/equality.d @@ -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([], [])); diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d index 6502e595e00..371308def79 100644 --- a/libphobos/libdruntime/core/lifetime.d +++ b/libphobos/libdruntime/core/lifetime.d @@ -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"); - assert(exc.refcount() == 1); - assert(exc.msg == "Exception"); - - static assert(!__traits(compiles, _d_newThrowable!E())); + Throwable exc = _d_newThrowable!Exception(); + Throwable e = _d_newThrowable!E(); - auto e = _d_newThrowable!E(42, "E", null); + assert(exc.refcount() == 1); assert(e.refcount() == 1); - assert(e.x == 42); - assert(e.msg == "E"); } diff --git a/libphobos/libdruntime/core/stdcpp/xutility.d b/libphobos/libdruntime/core/stdcpp/xutility.d index fa61701e1cf..0142d0b9455 100644 --- a/libphobos/libdruntime/core/stdcpp/xutility.d +++ b/libphobos/libdruntime/core/stdcpp/xutility.d @@ -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 diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf32.d b/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf32.d index 2662fdb0fff..c796cd8fa74 100644 --- a/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf32.d +++ b/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf32.d @@ -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 diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf64.d b/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf64.d index 6431bd2347a..89e3ca38a89 100644 --- a/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf64.d +++ b/libphobos/libdruntime/core/sys/dragonflybsd/sys/elf64.d @@ -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; } diff --git a/libphobos/libdruntime/core/sys/elf/package.d b/libphobos/libdruntime/core/sys/elf/package.d index 5de897ab420..69e52093dc3 100644 --- a/libphobos/libdruntime/core/sys/elf/package.d +++ b/libphobos/libdruntime/core/sys/elf/package.d @@ -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; diff --git a/libphobos/libdruntime/core/sys/freebsd/sys/elf32.d b/libphobos/libdruntime/core/sys/freebsd/sys/elf32.d index 134cdf0650f..4e8ae2843fb 100644 --- a/libphobos/libdruntime/core/sys/freebsd/sys/elf32.d +++ b/libphobos/libdruntime/core/sys/freebsd/sys/elf32.d @@ -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 diff --git a/libphobos/libdruntime/core/sys/freebsd/sys/elf64.d b/libphobos/libdruntime/core/sys/freebsd/sys/elf64.d index 69528217941..c56460c123b 100644 --- a/libphobos/libdruntime/core/sys/freebsd/sys/elf64.d +++ b/libphobos/libdruntime/core/sys/freebsd/sys/elf64.d @@ -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; } diff --git a/libphobos/libdruntime/core/sys/linux/elf.d b/libphobos/libdruntime/core/sys/linux/elf.d index 2cd933170a1..168b936f921 100644 --- a/libphobos/libdruntime/core/sys/linux/elf.d +++ b/libphobos/libdruntime/core/sys/linux/elf.d @@ -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; diff --git a/libphobos/libdruntime/core/sys/netbsd/sys/elf32.d b/libphobos/libdruntime/core/sys/netbsd/sys/elf32.d index ce7d8bade3f..48386f60212 100644 --- a/libphobos/libdruntime/core/sys/netbsd/sys/elf32.d +++ b/libphobos/libdruntime/core/sys/netbsd/sys/elf32.d @@ -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 diff --git a/libphobos/libdruntime/core/sys/netbsd/sys/elf64.d b/libphobos/libdruntime/core/sys/netbsd/sys/elf64.d index 7fa9a8b4de4..3eeaa90cf10 100644 --- a/libphobos/libdruntime/core/sys/netbsd/sys/elf64.d +++ b/libphobos/libdruntime/core/sys/netbsd/sys/elf64.d @@ -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; } diff --git a/libphobos/libdruntime/core/sys/openbsd/sys/elf32.d b/libphobos/libdruntime/core/sys/openbsd/sys/elf32.d index 342282b857b..c56112186aa 100644 --- a/libphobos/libdruntime/core/sys/openbsd/sys/elf32.d +++ b/libphobos/libdruntime/core/sys/openbsd/sys/elf32.d @@ -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 diff --git a/libphobos/libdruntime/core/sys/openbsd/sys/elf64.d b/libphobos/libdruntime/core/sys/openbsd/sys/elf64.d index b76d669b304..47f84d44daf 100644 --- a/libphobos/libdruntime/core/sys/openbsd/sys/elf64.d +++ b/libphobos/libdruntime/core/sys/openbsd/sys/elf64.d @@ -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; } diff --git a/libphobos/libdruntime/core/sys/solaris/sys/elftypes.d b/libphobos/libdruntime/core/sys/solaris/sys/elftypes.d index a43cc5ad606..fe8cfef3958 100644 --- a/libphobos/libdruntime/core/sys/solaris/sys/elftypes.d +++ b/libphobos/libdruntime/core/sys/solaris/sys/elftypes.d @@ -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; diff --git a/libphobos/libdruntime/core/sys/solaris/sys/link.d b/libphobos/libdruntime/core/sys/solaris/sys/link.d index d9d47c09142..9176b1794f9 100644 --- a/libphobos/libdruntime/core/sys/solaris/sys/link.d +++ b/libphobos/libdruntime/core/sys/solaris/sys/link.d @@ -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; diff --git a/libphobos/libdruntime/core/thread/threadbase.d b/libphobos/libdruntime/core/thread/threadbase.d index 505be000c56..217a33a0cf0 100644 --- a/libphobos/libdruntime/core/thread/threadbase.d +++ b/libphobos/libdruntime/core/thread/threadbase.d @@ -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; diff --git a/libphobos/libdruntime/rt/ehalloc.d b/libphobos/libdruntime/rt/ehalloc.d index 1dcd69a284f..65f92e3d015 100644 --- a/libphobos/libdruntime/rt/ehalloc.d +++ b/libphobos/libdruntime/rt/ehalloc.d @@ -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. diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index ddf730ef333..30e9e80092f 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -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. diff --git a/libphobos/src/std/mmfile.d b/libphobos/src/std/mmfile.d index e4000d4db27..f8f8a9088b6 100644 --- a/libphobos/src/std/mmfile.d +++ b/libphobos/src/std/mmfile.d @@ -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(); diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d index 869c36fdfe8..f3d3152b347 100644 --- a/libphobos/src/std/sumtype.d +++ b/libphobos/src/std/sumtype.d @@ -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