diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-01-09 23:56:49 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-01-12 23:18:25 +0100 |
commit | a2e540bf0150b1a2f05924ce6d5210dc0048471d (patch) | |
tree | b46d2d634704cfea7200180a0d03ddc5303aab0b /gcc/d/dmd | |
parent | f4fa0b7d493a4ba217d989d3df75bbe3730874fc (diff) | |
download | gcc-a2e540bf0150b1a2f05924ce6d5210dc0048471d.zip gcc-a2e540bf0150b1a2f05924ce6d5210dc0048471d.tar.gz gcc-a2e540bf0150b1a2f05924ce6d5210dc0048471d.tar.bz2 |
d: Merge dmd, druntime c7902293d7, phobos 03aeafd20
D front-end changes:
- Import dmd v2.110.0-rc.1.
- An error is now given for subtracting pointers of different
types.
D runtime changes:
- Import druntime v2.110.0-rc.1.
Phobos changes:
- Import phobos v2.110.0-rc.1.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd c7902293d7.
* dmd/VERSION: Bump version to v2.110.0-rc.1.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime c7902293d7.
* libdruntime/Makefile.am (DRUNTIME_DSOURCES): Rename
core/thread/fiber.d to core/thread/fiber/package.d. Add
core/thread/fiber/base.d.
* libdruntime/Makefile.in: Regenerate.
* src/MERGE: Merge upstream phobos 63fdb282f.
gcc/testsuite/ChangeLog:
* gdc.dg/asm3.d: Adjust test.
* gdc.dg/torture/pr96435.d: Adjust test.
Diffstat (limited to 'gcc/d/dmd')
33 files changed, 342 insertions, 266 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index e5884c6..b145d1b 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -c57da0cf5945cfb45eed06f1fd820435cda3ee3a +c7902293d7df9d02546562cb09fc8439004a70d1 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/VERSION b/gcc/d/dmd/VERSION index eef25e2..5aab7a2 100644 --- a/gcc/d/dmd/VERSION +++ b/gcc/d/dmd/VERSION @@ -1 +1 @@ -v2.110.0-beta.1 +v2.110.0-rc.1 diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d index cffc412..f66f14a 100644 --- a/gcc/d/dmd/cond.d +++ b/gcc/d/dmd/cond.d @@ -322,7 +322,7 @@ extern (C++) final class StaticForeach : RootObject { foreach (params; pparams) { - auto p = aggrfe ? (*aggrfe.parameters)[i] : rangefe.prm; + auto p = aggrfe ? (*aggrfe.parameters)[i] : rangefe.param; params.push(new Parameter(aloc, p.storageClass, p.type, p.ident, null, null)); } } diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d index 8f17a6e..156c5f8 100644 --- a/gcc/d/dmd/ctfeexpr.d +++ b/gcc/d/dmd/ctfeexpr.d @@ -465,8 +465,7 @@ Expression resolveSlice(Expression e, UnionExp* pue = null) *pue = Slice(e.type, se.e1, se.lwr, se.upr); return pue.exp(); } - else - return Slice(e.type, se.e1, se.lwr, se.upr).copy(); + return Slice(e.type, se.e1, se.lwr, se.upr).copy(); } /* Determine the array length, without interpreting it. diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index c15322f..7c675eb 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -491,7 +491,7 @@ MATCH implicitConvTo(Expression e, Type t) case Tint16: if (ty == Tuns64 && value & ~0x7FFFU) return MATCH.nomatch; - else if (cast(short)value != value) + if (cast(short)value != value) return MATCH.nomatch; break; @@ -3261,7 +3261,7 @@ Expression scaleFactor(BinExp be, Scope* sc) if (eoff.op == EXP.int64 && eoff.toInteger() == 0) { } - else if (sc.setUnsafe(false, be.loc, "pointer arithmetic not allowed in @safe functions")) + else if (sc.setUnsafe(false, be.loc, "pointer arithmetic")) { return ErrorExp.get(); } diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h index a98213d..7f37f89 100644 --- a/gcc/d/dmd/declaration.h +++ b/gcc/d/dmd/declaration.h @@ -632,6 +632,8 @@ public: bool nothrowInprocess(bool v); bool nogcInprocess() const; bool nogcInprocess(bool v); + bool saferD() const; + bool saferD(bool v); bool scopeInprocess() const; bool scopeInprocess(bool v); bool inlineScanned() const; diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d index 76627be..8648231 100644 --- a/gcc/d/dmd/dscope.d +++ b/gcc/d/dmd/dscope.d @@ -72,8 +72,51 @@ private extern (D) struct BitFields bool canFree; /// is on free list bool fullinst; /// fully instantiate templates bool ctfeBlock; /// inside a `if (__ctfe)` block - bool dip1000; /// dip1000 errors enabled for this scope - bool dip25; /// dip25 errors enabled for this scope +} + +/// State of -preview switches +/// +/// By making them part of a Scope, we reduce reliance on dmd.globals, +/// and can enable/disable them per module / edition. +private struct Previews +{ + // Run `dmd -preview=h` for the meaning of these switches + private extern (D) static struct BitFields + { + bool bitfields; + bool dip1000; + bool dip1008; + bool dip1021; + bool dip25; + bool fixAliasThis; + bool fixImmutableConv; + bool in_; + bool inclusiveInContracts; + bool noSharedAccess; + bool rvalueRefParam; + bool safer; + FeatureState systemVariables; + } + + import dmd.common.bitfields : generateBitFields; + mixin(generateBitFields!(BitFields, ushort)); + + void setFromParams(ref Param params) @nogc nothrow pure @safe + { + this.bitfields = params.bitfields; + this.dip1000 = params.useDIP1000 == FeatureState.enabled; + this.dip1008 = params.ehnogc; + this.dip1021 = params.useDIP1021; // == FeatureState.enabled; + this.dip25 = params.useDIP25 == FeatureState.enabled; + this.fixAliasThis = params.fixAliasThis; + this.fixImmutableConv = params.fixImmutableConv; + this.in_ = params.previewIn; + this.inclusiveInContracts = params.inclusiveInContracts; + this.noSharedAccess = params.noSharedAccess == FeatureState.enabled; + this.rvalueRefParam = params.rvalueRefParam == FeatureState.enabled; + this.safer = params.safer == FeatureState.enabled; + this.systemVariables = params.systemVariables; + } } extern (C++) struct Scope @@ -136,7 +179,9 @@ extern (C++) struct Scope DeprecatedDeclaration depdecl; /// customized deprecation message import dmd.common.bitfields : generateBitFields; - mixin(generateBitFields!(BitFields, uint)); + mixin(generateBitFields!(BitFields, ushort)); + + Previews previews; // user defined attributes UserAttributeDeclaration userAttribDecl; @@ -181,10 +226,8 @@ extern (C++) struct Scope m = m.parent; m.addMember(null, sc.scopesym); m.parent = null; // got changed by addMember() - if (global.params.useDIP1000 == FeatureState.enabled) - sc.dip1000 = true; - if (global.params.useDIP25 == FeatureState.enabled) - sc.dip25 = true; + sc.previews.setFromParams(global.params); + if (_module.filetype == FileType.c) sc.inCfile = true; // Create the module scope underneath the global scope @@ -236,9 +279,7 @@ extern (C++) struct Scope s.ignoresymbolvisibility = this.ignoresymbolvisibility; s.inCfile = this.inCfile; s.ctfeBlock = this.ctfeBlock; - s.dip1000 = this.dip1000; - s.dip25 = this.dip25; - + s.previews = this.previews; s.lastdc = null; assert(&this != s); return s; @@ -519,7 +560,7 @@ extern (C++) struct Scope } NotFound: - if (global.params.fixAliasThis) + if (sc.previews.fixAliasThis) { Expression exp = new ThisExp(loc); if (Dsymbol aliasSym = checkAliasThis(sc.scopesym.isAggregateDeclaration(), ident, flags, &exp)) @@ -856,13 +897,13 @@ extern (C++) struct Scope /// Returns: whether to raise DIP1000 warnings (FeatureStabe.default) or errors (FeatureState.enabled) extern (D) FeatureState useDIP1000() { - return (this.dip1000 || hasEdition(Edition.v2024)) ? FeatureState.enabled : FeatureState.disabled; + return (this.previews.dip1000 || hasEdition(Edition.v2024)) ? FeatureState.enabled : FeatureState.disabled; } /// Returns: whether to raise DIP25 warnings (FeatureStabe.default) or errors (FeatureState.enabled) extern (D) FeatureState useDIP25() { - return (this.dip25 || hasEdition(Edition.v2024)) ? FeatureState.enabled : FeatureState.disabled; + return (this.previews.dip25 || hasEdition(Edition.v2024)) ? FeatureState.enabled : FeatureState.disabled; } /// Returns: whether this scope compiles with `edition` or later diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d index 3aed16a..e3feefe 100644 --- a/gcc/d/dmd/dsymbol.d +++ b/gcc/d/dmd/dsymbol.d @@ -577,7 +577,7 @@ extern (C++) class Dsymbol : ASTNode continue; if (sa == p1) return true; - else if (p2 && sa == p2) + if (p2 && sa == p2) return true; } outer = ti.tempdecl.toParent(); diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 7e98436..1ab646f4 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -717,7 +717,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor // Calculate type size + safety checks if (dsym.storage_class & STC.gshared && !dsym.isMember()) { - sc.setUnsafe(false, dsym.loc, "__gshared not allowed in safe functions; use shared"); + sc.setUnsafe(false, dsym.loc, "using `__gshared` instead of `shared`"); } Dsymbol parent = dsym.toParent(); @@ -1146,22 +1146,22 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (dsym.type.hasPointers()) // also computes type size sc.setUnsafe(false, dsym.loc, - "`void` initializers for pointers not allowed in safe functions"); + "`void` initializing a pointer"); else if (dsym.type.hasInvariant()) sc.setUnsafe(false, dsym.loc, - "`void` initializers for structs with invariants are not allowed in safe functions"); + "`void` initializing a struct with an invariant"); else if (dsym.type.toBasetype().ty == Tbool) sc.setUnsafePreview(global.params.systemVariables, false, dsym.loc, - "a `bool` must be 0 or 1, so void intializing it is not allowed in safe functions"); + "void intializing a bool (which must always be 0 or 1)"); else if (dsym.type.hasUnsafeBitpatterns()) sc.setUnsafePreview(global.params.systemVariables, false, dsym.loc, - "`void` initializers for types with unsafe bit patterns are not allowed in safe functions"); + "`void` initializing a type with unsafe bit patterns"); } else if (!dsym._init && !(dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field | STC.parameter)) && dsym.type.hasVoidInitPointers()) { - sc.setUnsafe(false, dsym.loc, "`void` initializers for pointers not allowed in safe functions"); + sc.setUnsafe(false, dsym.loc, "`void` initializers for pointers"); } } @@ -1323,7 +1323,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor { import dmd.escape : setUnsafeDIP1000; const inSafeFunc = sc.func && sc.func.isSafeBypassingInference(); // isSafeBypassingInference may call setUnsafe(). - if (setUnsafeDIP1000(*sc, false, dsym.loc, "`scope` allocation of `%s` requires that constructor be annotated with `scope`", dsym)) + if (setUnsafeDIP1000(*sc, false, dsym.loc, "`scope` allocation of `%s` with a non-`scope` constructor", dsym)) errorSupplemental(ne.member.loc, "is the location of the constructor"); } ne.onstack = 1; @@ -1577,7 +1577,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (dsym.errors) return; - if (!(global.params.bitfields || sc.inCfile)) + if (!(sc.previews.bitfields || sc.inCfile)) { version (IN_GCC) .error(dsym.loc, "%s `%s` use `-fpreview=bitfields` for bitfield support", dsym.kind, dsym.toPrettyChars); diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index d46e466..5bb7049 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -211,11 +211,11 @@ Dsymbol getDsymbol(RootObject oarg) // Try to convert Expression to symbol if (auto ve = ea.isVarExp()) return ve.var; - else if (auto fe = ea.isFuncExp()) + if (auto fe = ea.isFuncExp()) return fe.td ? fe.td : fe.fd; - else if (auto te = ea.isTemplateExp()) + if (auto te = ea.isTemplateExp()) return te.td; - else if (auto te = ea.isScopeExp()) + if (auto te = ea.isScopeExp()) return te.sds; else return null; diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index 3e18051..947abf0 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -354,7 +354,7 @@ bool checkParamArgumentEscape(ref Scope sc, FuncDeclaration fdc, Identifier parI if (assertmsg) { result |= sc.setUnsafeDIP1000(gag, arg.loc, - desc ~ " `%s` assigned to non-scope parameter calling `assert()`", v); + "assigning" ~ desc ~ " `%s` to non-scope parameter calling `assert()`", v); return; } @@ -362,9 +362,9 @@ bool checkParamArgumentEscape(ref Scope sc, FuncDeclaration fdc, Identifier parI const(char)* msg = (isThis) ? (desc ~ " `%s` calling non-scope member function `%s.%s()`") : - (fdc && parId) ? (desc ~ " `%s` assigned to non-scope parameter `%s` calling `%s`") : - (fdc && !parId) ? (desc ~ " `%s` assigned to non-scope anonymous parameter calling `%s`") : - (!fdc && parId) ? (desc ~ " `%s` assigned to non-scope parameter `%s`") : + (fdc && parId) ? ("assigning " ~ desc ~ " `%s` to non-scope parameter `%s` calling `%s`") : + (fdc && !parId) ? ("assigning " ~ desc ~ " `%s` to non-scope anonymous parameter calling `%s`") : + (!fdc && parId) ? ("assigning " ~ desc ~ " `%s` to non-scope parameter `%s`") : (desc ~ " `%s` assigned to non-scope anonymous parameter"); if (isThis ? @@ -440,8 +440,8 @@ bool checkParamArgumentEscape(ref Scope sc, FuncDeclaration fdc, Identifier parI if (parStc & STC.scope_) return; const(char)* msg = parId ? - "reference to stack allocated value returned by `%s` assigned to non-scope parameter `%s`" : - "reference to stack allocated value returned by `%s` assigned to non-scope anonymous parameter"; + "assigning reference to stack allocated value returned by `%s` to non-scope parameter `%s`" : + "assigning reference to stack allocated value returned by `%s` to non-scope anonymous parameter"; result |= sc.setUnsafeDIP1000(gag, ee.loc, msg, ee, parId); } @@ -726,16 +726,16 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef) { case EnclosedBy.none: assert(0); case EnclosedBy.returnScope: - msg = "scope variable `%s` assigned to return scope `%s`"; + msg = "assigning scope variable `%s` to return scope `%s`"; break; case EnclosedBy.longerScope: - msg = "scope variable `%s` assigned to `%s` with longer lifetime"; + msg = "assigning scope variable `%s` to `%s` with longer lifetime"; break; case EnclosedBy.refVar: - msg = "scope variable `%s` assigned to `ref` variable `%s` with longer lifetime"; + msg = "assigning scope variable `%s` to `ref` variable `%s` with longer lifetime"; break; case EnclosedBy.global: - msg = "scope variable `%s` assigned to global variable `%s`"; + msg = "assigning scope variable `%s` to global variable `%s`"; break; } @@ -762,7 +762,7 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef) } return; } - result |= sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to non-scope `%s`", v, e1); + result |= sc.setUnsafeDIP1000(gag, ae.loc, "assigning scope variable `%s` to non-scope `%s`", v, e1); } else { @@ -794,7 +794,7 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef) else { result |= sc.setUnsafeDIP1000(gag, ae.loc, - "address of local variable `%s` assigned to return scope `%s`", v, va); + "assigning address of local variable `%s` to return scope `%s`", v, va); } } @@ -809,7 +809,7 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef) // If va's lifetime encloses v's, then error if (va && !(vaIsFirstRef && v.isReturn()) && va.enclosesLifetimeOf(v)) { - if (sc.setUnsafeDIP1000(gag, ae.loc, "address of variable `%s` assigned to `%s` with longer lifetime", v, va)) + if (sc.setUnsafeDIP1000(gag, ae.loc, "assigning address of variable `%s` to `%s` with longer lifetime", v, va)) { result = true; return; @@ -829,7 +829,7 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef) return; } - result |= sc.setUnsafeDIP1000(gag, ae.loc, "reference to local variable `%s` assigned to non-scope `%s`", v, e1); + result |= sc.setUnsafeDIP1000(gag, ae.loc, "assigning reference to local variable `%s` to non-scope `%s`", v, e1); } void onFunc(FuncDeclaration func, bool called) @@ -869,7 +869,7 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef) return; } result |= sc.setUnsafeDIP1000(gag, ae.loc, - "reference to local `%s` assigned to non-scope `%s` in @safe code", v, e1); + "assigning reference to local `%s` to non-scope `%s`", v, e1); } } @@ -889,8 +889,8 @@ bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef) } const(char)* msg = (ee.op == EXP.structLiteral) ? - "address of struct literal `%s` assigned to `%s` with longer lifetime" : - "address of expression temporary returned by `%s` assigned to `%s` with longer lifetime"; + "assigning address of struct literal `%s` to `%s` with longer lifetime" : + "assigning address of expression temporary returned by `%s` to `%s` with longer lifetime"; result |= sc.setUnsafeDIP1000(gag, ee.loc, msg, ee, e1); } @@ -930,7 +930,7 @@ bool checkThrowEscape(ref Scope sc, Expression e, bool gag) // despite being `scope` { // https://issues.dlang.org/show_bug.cgi?id=17029 - result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be thrown", v); + result |= sc.setUnsafeDIP1000(gag, e.loc, "throwing scope variable `%s`", v); return; } else @@ -989,7 +989,7 @@ bool checkNewEscape(ref Scope sc, Expression e, bool gag) !(p.parent == sc.func)) { // https://issues.dlang.org/show_bug.cgi?id=20868 - result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be copied into allocated memory", v); + result |= sc.setUnsafeDIP1000(gag, e.loc, "copying scope variable `%s` into allocated memory", v); return; } } @@ -1009,9 +1009,9 @@ bool checkNewEscape(ref Scope sc, Expression e, bool gag) bool escapingRef(VarDeclaration v, FeatureState fs) { const(char)* msg = v.isParameter() ? - "copying `%s` into allocated memory escapes a reference to parameter `%s`" : - "copying `%s` into allocated memory escapes a reference to local variable `%s`"; - return setUnsafePreview(&sc, fs, gag, e.loc, msg, e, v); + "escaping a reference to parameter `%s` by copying `%s` into allocated memory" : + "escaping a reference to local variable `%s` by copying `%s` into allocated memory"; + return setUnsafePreview(&sc, fs, gag, e.loc, msg, v, e); } Dsymbol p = v.toParent2(); @@ -1064,14 +1064,14 @@ bool checkNewEscape(ref Scope sc, Expression e, bool gag) { if (called) result |= sc.setUnsafeDIP1000(gag, e.loc, - "nested function `%s` returns `scope` values and escapes them into allocated memory", fd); + "escaping a `scope` value returned from nested function `%s` into allocated memory", fd); } void onExp(Expression ee, bool retRefTransition) { if (log) printf("byexp %s\n", ee.toChars()); if (!gag) - sc.eSink.error(ee.loc, "storing reference to stack allocated value returned by `%s` into allocated memory causes it to escape", + sc.eSink.error(ee.loc, "escaping reference to stack allocated value returned by `%s` into allocated memory", ee.toChars()); result = true; } @@ -1210,7 +1210,7 @@ private bool checkReturnEscapeImpl(ref Scope sc, Expression e, bool refs, bool g else { // https://issues.dlang.org/show_bug.cgi?id=17029 - result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be returned", v); + result |= sc.setUnsafeDIP1000(gag, e.loc, "returning scope variable `%s`", v); return; } } @@ -1233,13 +1233,12 @@ private bool checkReturnEscapeImpl(ref Scope sc, Expression e, bool refs, bool g // depending on the flag passed to the CLI for DIP25 void escapingRef(VarDeclaration v, FeatureState featureState) { - const(char)* msg = v.isParameter() ? - "returning `%s` escapes a reference to parameter `%s`" : - "returning `%s` escapes a reference to local variable `%s`"; - + const(char)* safeMsg = v.isParameter() ? + "escaping a reference to parameter `%s` by returning `%s`" : + "escaping a reference to local variable `%s` by returning `%s` "; if (v.isParameter() && v.isReference()) { - if (setUnsafePreview(&sc, featureState, gag, e.loc, msg, e, v) || + if (setUnsafePreview(&sc, featureState, gag, e.loc, safeMsg, v, e) || sc.func.isSafeBypassingInference()) { result = true; @@ -1260,10 +1259,13 @@ private bool checkReturnEscapeImpl(ref Scope sc, Expression e, bool refs, bool g { if (retRefTransition) { - result |= sc.setUnsafeDIP1000(gag, e.loc, msg, e, v); + result |= sc.setUnsafeDIP1000(gag, e.loc, safeMsg, v, e); } else { + const(char)* msg = v.isParameter() ? + "returning `%s` escapes a reference to parameter `%s`" : + "returning `%s` escapes a reference to local variable `%s`"; if (!gag) previewErrorFunc(sc.isDeprecated(), featureState)(e.loc, msg, e.toChars(), v.toChars()); result = true; @@ -2228,7 +2230,7 @@ private bool checkScopeVarAddr(VarDeclaration v, Expression e, ref Scope sc, boo // take address of `scope` variable not allowed, requires transitive scope return sc.setUnsafeDIP1000(gag, e.loc, - "cannot take address of `scope` variable `%s` since `scope` applies to first indirection only", v); + "taking address of `scope` variable `%s` with pointers", v); } /**************************** diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index 413d31a..3020387 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -1607,8 +1607,8 @@ Lagain: { if (sd.isSystem()) { - if (sc.setUnsafePreview(global.params.systemVariables, false, loc, - "cannot access `@system` variable `%s` in @safe code", sd)) + if (sc.setUnsafePreview(sc.previews.systemVariables, false, loc, + "access `@system` variable `%s`", sd)) { if (auto v = sd.isVarDeclaration()) { @@ -2237,8 +2237,7 @@ private bool checkPurity(VarDeclaration v, const ref Loc loc, Scope* sc) */ if (v.storage_class & STC.gshared) { - if (sc.setUnsafe(false, loc, - "`@safe` function `%s` cannot access `__gshared` data `%s`", sc.func, v)) + if (sc.setUnsafe(false, loc, "accessing `__gshared` data `%s`", v)) { err = true; } @@ -3328,7 +3327,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, } else if (p.storageClass & STC.ref_) { - if (global.params.rvalueRefParam == FeatureState.enabled && + if (sc.previews.rvalueRefParam && !arg.isLvalue() && targ.isCopyable()) { /* allow rvalues to be passed to ref parameters by copying @@ -3729,7 +3728,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, /* Test compliance with DIP1021 Argument Ownership and Function Calls */ - if (global.params.useDIP1021 && (tf.trust == TRUST.safe || tf.trust == TRUST.default_) || + if (sc.previews.dip1021 && (tf.trust == TRUST.safe || tf.trust == TRUST.default_) || tf.isLive) err |= checkMutableArguments(*sc, fd, tf, ethis, arguments, false); @@ -4012,7 +4011,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } } - if (global.params.fixAliasThis) + if (sc.previews.fixAliasThis) { if (ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol()) { @@ -4028,7 +4027,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } - if (!global.params.fixAliasThis && hasThis(sc)) + if (!sc.previews.fixAliasThis && hasThis(sc)) { for (AggregateDeclaration ad = sc.getStructClassScope(); ad;) { @@ -5175,7 +5174,7 @@ 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 && + if (sc.previews.dip1008 && exp.thrownew && !cd.isCOMclass() && !cd.isCPPclass()) { assert(cd.ctor); @@ -8596,8 +8595,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor */ if (1) { - if (sc.setUnsafe(false, exp.loc, - "cannot take address of lazy parameter `%s` in `@safe` function `%s`", ve, sc.func)) + if (sc.setUnsafe(false, exp.loc, "taking address of lazy parameter `%s`", ve)) { setError(); return; @@ -8746,9 +8744,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (sc.func && !sc.intypeof && !sc.debug_) { - sc.setUnsafe(false, exp.loc, - "`this` reference necessary to take address of member `%s` in `@safe` function `%s`", - f, sc.func); + sc.setUnsafe(false, exp.loc, "taking address of member `%s` without `this` reference", f); } } } @@ -9240,7 +9236,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!isSafeCast(ex, t1b, tob, msg)) { if (sc.setUnsafe(false, exp.loc, - "cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to)) + "cast from `%s` to `%s`", exp.e1.type, exp.to)) { if (msg.length) errorSupplemental(exp.loc, "%.*s", msg.fTuple.expand); @@ -9250,7 +9246,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor else if (msg.length) // deprecated unsafe { const err = sc.setUnsafePreview(FeatureState.default_, false, exp.loc, - "cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to); + "cast from `%s` to `%s`", exp.e1.type, exp.to); // if message was printed if (sc.func && sc.func.isSafeBypassingInference() && !sc.isDeprecated()) deprecationSupplemental(exp.loc, "%.*s", msg.fTuple.expand); @@ -9503,7 +9499,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setError(); } - if (sc.setUnsafe(false, exp.loc, "pointer slicing not allowed in safe functions")) + if (sc.setUnsafe(false, exp.loc, "pointer slicing")) return setError(); } else if (t1b.ty == Tarray) @@ -9991,7 +9987,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.e2.op == EXP.int64 && exp.e2.toInteger() == 0) { } - else if (sc.setUnsafe(false, exp.loc, "`@safe` function `%s` cannot index pointer `%s`", sc.func, exp.e1)) + else if (sc.setUnsafe(false, exp.loc, "indexing pointer `%s`", exp.e1)) { return setError(); } @@ -11449,17 +11445,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { if (t2.nextOf().implicitConvTo(t1.nextOf())) { - if (sc.setUnsafe(false, exp.loc, "cannot copy `%s` to `%s` in `@safe` code", t2, t1)) + if (sc.setUnsafe(false, exp.loc, "copying `%s` to `%s`", t2, t1)) return setError(); } else { // copying from non-void to void was overlooked, deprecate if (sc.setUnsafePreview(FeatureState.default_, false, exp.loc, - "cannot copy `%s` to `%s` in `@safe` code", t2, t1)) + "copying `%s` to `%s`", t2, t1)) return setError(); } - if (global.params.fixImmutableConv && !t2.implicitConvTo(t1)) + if (sc.previews.fixImmutableConv && !t2.implicitConvTo(t1)) { error(exp.loc, "cannot copy `%s` to `%s`", t2.toChars(), t1.toChars()); @@ -11848,7 +11844,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor (exp.e2.implicitConvTo(exp.e1.type) || (tb2.nextOf().implicitConvTo(tb1next) && // Do not strip const(void)[] - (!global.params.fixImmutableConv || tb1next.ty != Tvoid) && + (!sc.previews.fixImmutableConv || tb1next.ty != Tvoid) && (tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial))))) { // EXP.concatenateAssign @@ -12245,12 +12241,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!p1.equivalent(p2)) { - // Deprecation to remain for at least a year, after which this should be - // changed to an error // See https://github.com/dlang/dmd/pull/7332 - deprecation(exp.loc, - "cannot subtract pointers to different types: `%s` and `%s`.", + error(exp.loc, "cannot subtract pointers to different types: `%s` and `%s`.", t1.toChars(), t2.toChars()); + return setError(); } // Need to divide the result by the stride @@ -12590,7 +12584,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod) { // Do not strip const(void)[] - if (!global.params.fixImmutableConv || tb.nextOf().ty != Tvoid) + if (!sc.previews.fixImmutableConv || tb.nextOf().ty != Tvoid) exp.type = exp.type.nextOf().toHeadMutable().arrayOf(); } if (Type tbn = tb.nextOf()) @@ -14890,8 +14884,8 @@ private bool checkSharedAccessBin(BinExp binExp, Scope* sc) */ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) { - if (global.params.noSharedAccess != FeatureState.enabled || - !sc || + if (!sc || + !sc.previews.noSharedAccess || sc.intypeof || sc.ctfe) { @@ -15588,7 +15582,7 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action with (_this) if (!trusted && !e1.type.pointerTo().implicitConvTo(to.pointerTo())) sc.setUnsafePreview(FeatureState.default_, false, loc, - "cast from `%s` to `%s` cannot be used as an lvalue in @safe code", + "using the result of a cast from `%s` to `%s` as an lvalue", e1.type, to); return _this; @@ -15956,7 +15950,7 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression Expression visitDelegatePtr(DelegatePtrExp exp) { - if (sc.setUnsafe(false, exp.loc, "cannot modify delegate pointer in `@safe` code `%s`", exp)) + if (sc.setUnsafe(false, exp.loc, "modifying delegate pointer `%s`", exp)) { return ErrorExp.get(); } @@ -15965,7 +15959,7 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression Expression visitDelegateFuncptr(DelegateFuncptrExp exp) { - if (sc.setUnsafe(false, exp.loc, "cannot modify delegate function pointer in `@safe` code `%s`", exp)) + if (sc.setUnsafe(false, exp.loc, "modifying delegate function pointer `%s`", exp)) { return ErrorExp.get(); } @@ -16034,7 +16028,7 @@ private bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v) { if (sc.useDIP1000 != FeatureState.enabled && !(v.storage_class & STC.temp) && - sc.setUnsafe(false, exp.loc, "cannot take address of local `%s` in `@safe` function `%s`", v, sc.func)) + sc.setUnsafe(false, exp.loc, "taking the address of stack-allocated local variable `%s`", v)) { return false; } @@ -16307,7 +16301,7 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions if ((!stype.alignment.isDefault() && stype.alignment.get() < target.ptrsize || (v.offset & (target.ptrsize - 1))) && (sc.setUnsafe(false, loc, - "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, v))) + "field `%s.%s` assigning to misaligned pointers", sd, v))) { return false; } diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index 9c5a3d0..40d39ae 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -113,6 +113,7 @@ private struct FUNCFLAG bool safetyInprocess; /// working on determining safety bool nothrowInprocess; /// working on determining nothrow bool nogcInprocess; /// working on determining @nogc + bool saferD; /// do -preview=safer checks if this function has default safety bool scopeInprocess; /// infer `return` and `scope` for parameters bool inlineScanned; /// function has been scanned for inline possibilities bool hasCatches; /// function has try-catch statements diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d index eba9397..39da025 100644 --- a/gcc/d/dmd/funcsem.d +++ b/gcc/d/dmd/funcsem.d @@ -1616,9 +1616,26 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, const(char)* lastprms = parametersTypeToChars(tf1.parameterList); const(char)* nextprms = parametersTypeToChars(tf2.parameterList); - .error(loc, "`%s.%s` called with argument types `%s` matches both:\n%s: `%s%s%s`\nand:\n%s: `%s%s%s`", + string match = ""; + final switch (m.last) + { + case MATCH.convert: + match = "after implicit conversions"; + break; + case MATCH.constant: + match = "after qualifier conversion"; + break; + case MATCH.exact: + match = "exactly"; + break; + case MATCH.nomatch: + assert(0); + } + + .error(loc, "`%s.%s` called with argument types `%s` matches multiple overloads %.*s:\n%s: `%s%s%s`\nand:\n%s: `%s%s%s`", s.parent.toPrettyChars(), s.ident.toChars(), fargsBuf.peekChars(), + match.fTuple.expand, m.lastf.loc.toChars(), m.lastf.toPrettyChars(), lastprms, tf1.modToChars(), m.nextf.loc.toChars(), m.nextf.toPrettyChars(), nextprms, tf2.modToChars()); return null; diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d index 901561f..77bb498 100644 --- a/gcc/d/dmd/globals.d +++ b/gcc/d/dmd/globals.d @@ -400,6 +400,7 @@ extern (C++) struct Global params.v.color = detectTerminal(); } + params.v.errorPrintMode = ErrorPrintMode.printErrorContext; // Enable error context globally by default compileEnv.versionNumber = parseVersionNumber(versionString()); /* Initialize date, time, and timestamp diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index cfe4262..a5e897d 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -418,10 +418,10 @@ private void statementToBuffer(Statement s, ref OutBuffer buf, ref HdrGenState h { buf.writestring(Token.toString(s.op)); buf.writestring(" ("); - if (s.prm.type) - typeToBuffer(s.prm.type, s.prm.ident, buf, hgs); + if (s.param.type) + typeToBuffer(s.param.type, s.param.ident, buf, hgs); else - buf.writestring(s.prm.ident.toString()); + buf.writestring(s.param.ident.toString()); buf.writestring("; "); s.lwr.expressionToBuffer(buf, hgs); buf.writestring(" .. "); @@ -465,7 +465,7 @@ private void statementToBuffer(Statement s, ref OutBuffer buf, ref HdrGenState h void visitIf(IfStatement s) { buf.writestring("if ("); - printConditionAssignment(s.prm, s.condition); + printConditionAssignment(s.param, s.condition); buf.writeByte(')'); buf.writenl(); if (s.ifbody.isScopeStatement()) @@ -1168,14 +1168,14 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) void foreachRangeWithoutBody(ForeachRangeStatement s) { - /* s.op ( prm ; lwr .. upr ) + /* s.op ( param ; lwr .. upr ) */ buf.writestring(Token.toString(s.op)); buf.writestring(" ("); - if (s.prm.type) - typeToBuffer(s.prm.type, s.prm.ident, buf, hgs); + if (s.param.type) + typeToBuffer(s.param.type, s.param.ident, buf, hgs); else - buf.writestring(s.prm.ident.toString()); + buf.writestring(s.param.ident.toString()); buf.writestring("; "); s.lwr.expressionToBuffer(buf, hgs); buf.writestring(" .. "); diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d index 0c13bc7..aec6807 100644 --- a/gcc/d/dmd/initsem.d +++ b/gcc/d/dmd/initsem.d @@ -1592,7 +1592,7 @@ Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope* (vd.offset & (target.ptrsize - 1)))) { if (sc.setUnsafe(false, argLoc, - "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, vd)) + "field `%s.%s` assigning to misaligned pointers", sd, vd)) { errors = true; elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors diff --git a/gcc/d/dmd/intrange.d b/gcc/d/dmd/intrange.d index d89fbb2..242cac0 100644 --- a/gcc/d/dmd/intrange.d +++ b/gcc/d/dmd/intrange.d @@ -69,7 +69,7 @@ struct SignExtendedNumber } if (value < a.value) return -1; - else if (value > a.value) + if (value > a.value) return 1; else return 0; @@ -121,10 +121,10 @@ struct SignExtendedNumber SignExtendedNumber opBinary(string op : "+")(SignExtendedNumber rhs) { uinteger_t sum = value + rhs.value; - bool carry = sum < value && sum < rhs.value; + const carry = sum < value && sum < rhs.value; if (negative != rhs.negative) return SignExtendedNumber(sum, !carry); - else if (negative) + if (negative) return SignExtendedNumber(carry ? sum : 0, true); else return SignExtendedNumber(carry ? ulong.max : sum, false); @@ -154,7 +154,7 @@ struct SignExtendedNumber { if (!negative) return this; - else if (rhs.negative) + if (rhs.negative) return max(); else return rhs.value == 0 ? rhs : this; @@ -248,7 +248,7 @@ struct SignExtendedNumber // shifts will give huge result. if (value == 0) return this; - else if (rhs.negative) + if (rhs.negative) return extreme(negative); uinteger_t v = copySign(value, negative); @@ -277,7 +277,7 @@ struct SignExtendedNumber { if (rhs.negative || rhs.value > 63) return negative ? SignExtendedNumber(-1, true) : SignExtendedNumber(0); - else if (isMinimum()) + if (isMinimum()) return rhs.value == 0 ? this : SignExtendedNumber(-1UL << (64 - rhs.value), true); uinteger_t x = value ^ -cast(int)negative; @@ -445,11 +445,10 @@ struct IntRange { if (!type.isIntegral() || type.toBasetype().isTypeVector()) return this; - else if (!type.isUnsigned()) + if (!type.isUnsigned()) return castSigned(type.sizemask()); - else if (type.toBasetype().ty == Tdchar) + if (type.toBasetype().ty == Tdchar) return castDchar(); - else return castUnsigned(type.sizemask()); } @@ -457,10 +456,9 @@ struct IntRange { if (!type.isIntegral() || type.toBasetype().isTypeVector()) return castUnsigned(ulong.max); - else if (type.toBasetype().ty == Tdchar) + if (type.toBasetype().ty == Tdchar) return castDchar(); - else - return castUnsigned(type.sizemask()); + return castUnsigned(type.sizemask()); } bool contains(IntRange a) @safe @@ -478,14 +476,11 @@ struct IntRange { if (imax.negative) return this; - else if (!imin.negative) + if (!imin.negative) return IntRange(-imax, -imin); - else - { - SignExtendedNumber imaxAbsNeg = -imax; - return IntRange(imaxAbsNeg < imin ? imaxAbsNeg : imin, - SignExtendedNumber(0)); - } + SignExtendedNumber imaxAbsNeg = -imax; + return IntRange(imaxAbsNeg < imin ? imaxAbsNeg : imin, + SignExtendedNumber(0)); } IntRange unionWith(const ref IntRange other) const @safe @@ -573,13 +568,13 @@ struct IntRange swap(l, r); // r spans [-1,0] } - auto minAndNeg = minAnd(l, IntRange(r.imin, SignExtendedNumber(-1))); - auto minAndPos = minAnd(l, IntRange(SignExtendedNumber(0), r.imax)); - auto maxAndNeg = maxAnd(l, IntRange(r.imin, SignExtendedNumber(-1))); - auto maxAndPos = maxAnd(l, IntRange(SignExtendedNumber(0), r.imax)); + const minAndNeg = minAnd(l, IntRange(r.imin, SignExtendedNumber(-1))); + const minAndPos = minAnd(l, IntRange(SignExtendedNumber(0), r.imax)); + const maxAndNeg = maxAnd(l, IntRange(r.imin, SignExtendedNumber(-1))); + const maxAndPos = maxAnd(l, IntRange(SignExtendedNumber(0), r.imax)); - auto min = minAndNeg < minAndPos ? minAndNeg : minAndPos; - auto max = maxAndNeg > maxAndPos ? maxAndNeg : maxAndPos; + const min = minAndNeg < minAndPos ? minAndNeg : minAndPos; + const max = maxAndNeg > maxAndPos ? maxAndNeg : maxAndPos; auto range = IntRange(min, max); return range; @@ -681,22 +676,19 @@ struct IntRange { return IntRange(imin / rhs.imax, imax / rhs.imin); } - else if (rhs.imin.negative && !rhs.imax.negative) // divisor spans [-1, 0, 1] + if (rhs.imin.negative && !rhs.imax.negative) // divisor spans [-1, 0, 1] { SignExtendedNumber[4] bdy = [-imin, imin, -imax, imax]; return IntRange.fromNumbers4(bdy.ptr); } - else - { - // [a,b] / [c,d] = [min (a/c, a/d, b/c, b/d), max (a/c, a/d, b/c, b/d)] - SignExtendedNumber[4] bdy; - bdy[0] = imin / rhs.imin; - bdy[1] = imin / rhs.imax; - bdy[2] = imax / rhs.imin; - bdy[3] = imax / rhs.imax; + // [a,b] / [c,d] = [min (a/c, a/d, b/c, b/d), max (a/c, a/d, b/c, b/d)] + SignExtendedNumber[4] bdy; + bdy[0] = imin / rhs.imin; + bdy[1] = imin / rhs.imax; + bdy[2] = imax / rhs.imin; + bdy[3] = imax / rhs.imax; - return IntRange.fromNumbers4(bdy.ptr); - } + return IntRange.fromNumbers4(bdy.ptr); } IntRange opBinary(string op : "%")(IntRange rhs) diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d index 174a2d9..b1b5a4f 100644 --- a/gcc/d/dmd/json.d +++ b/gcc/d/dmd/json.d @@ -992,35 +992,34 @@ void json_generate(ref Modules modules, ref OutBuffer buf) // of modules representing their syntax. json.generateModules(modules); json.removeComma(); + return; } - else - { - // Generate the new format which is an object where each - // output option is its own field. - json.objectStart(); - if (global.params.jsonFieldFlags & JsonFieldFlags.compilerInfo) - { - json.propertyStart("compilerInfo"); - json.generateCompilerInfo(); - } - if (global.params.jsonFieldFlags & JsonFieldFlags.buildInfo) - { - json.propertyStart("buildInfo"); - json.generateBuildInfo(); - } - if (global.params.jsonFieldFlags & JsonFieldFlags.modules) - { - json.propertyStart("modules"); - json.generateModules(modules); - } - if (global.params.jsonFieldFlags & JsonFieldFlags.semantics) - { - json.propertyStart("semantics"); - json.generateSemantics(); - } - json.objectEnd(); + // Generate the new format which is an object where each + // output option is its own field. + + json.objectStart(); + if (global.params.jsonFieldFlags & JsonFieldFlags.compilerInfo) + { + json.propertyStart("compilerInfo"); + json.generateCompilerInfo(); + } + if (global.params.jsonFieldFlags & JsonFieldFlags.buildInfo) + { + json.propertyStart("buildInfo"); + json.generateBuildInfo(); + } + if (global.params.jsonFieldFlags & JsonFieldFlags.modules) + { + json.propertyStart("modules"); + json.generateModules(modules); + } + if (global.params.jsonFieldFlags & JsonFieldFlags.semantics) + { + json.propertyStart("semantics"); + json.generateSemantics(); } + json.objectEnd(); } /** diff --git a/gcc/d/dmd/mangle/cpp.d b/gcc/d/dmd/mangle/cpp.d index 9ce3f9c..67c9b53 100644 --- a/gcc/d/dmd/mangle/cpp.d +++ b/gcc/d/dmd/mangle/cpp.d @@ -15,10 +15,6 @@ * Follows Itanium C++ ABI 1.86 section 5.1 * http://refspecs.linux-foundation.org/cxxabi-1.86.html#mangling * which is where the grammar comments come from. - * - * Bugs: - * https://issues.dlang.org/query.cgi - * enter `C++, mangling` as the keywords. */ module dmd.mangle.cpp; diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d index 4a060c9..ff1e173 100644 --- a/gcc/d/dmd/nogc.d +++ b/gcc/d/dmd/nogc.d @@ -46,6 +46,7 @@ public: FuncDeclaration f; bool checkOnly; // don't print errors bool err; + bool nogcExceptions; // -preview=dip1008 enabled extern (D) this(FuncDeclaration f) scope @safe { @@ -143,7 +144,7 @@ public: } if (e.onstack) return; - if (global.params.ehnogc && e.thrownew) + if (nogcExceptions && e.thrownew) return; // separate allocator is called for this, not the GC if (setGC(e, "cannot use `new` in `@nogc` %s `%s`")) @@ -224,6 +225,7 @@ Expression checkGC(Scope* sc, Expression e) { scope NOGCVisitor gcv = new NOGCVisitor(f); gcv.checkOnly = betterC; + gcv.nogcExceptions = sc.previews.dip1008; walkPostorder(e, gcv); if (gcv.err) { diff --git a/gcc/d/dmd/ob.d b/gcc/d/dmd/ob.d index ee4b652..2019e82 100644 --- a/gcc/d/dmd/ob.d +++ b/gcc/d/dmd/ob.d @@ -7,8 +7,6 @@ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ob.d, _ob.d) * Documentation: https://dlang.org/phobos/dmd_escape.html * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/ob.d - * Bug reports: use 'live' keyword: - * https://issues.dlang.org/buglist.cgi?bug_status=NEW&bug_status=REOPENED&keywords=live * References: https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md Argument Ownership and Function Calls */ diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index fd42838..b408f8b 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -5683,7 +5683,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } /*** - * Parse an assignment condition for if or while statements. + * Parse an assignment condition for `if`, `switch` or `while` statements. * * Returns: * The variable that is declared inside the condition diff --git a/gcc/d/dmd/root/string.d b/gcc/d/dmd/root/string.d index 383c59d..847af0e 100644 --- a/gcc/d/dmd/root/string.d +++ b/gcc/d/dmd/root/string.d @@ -365,13 +365,23 @@ auto splitLines(const char[] text) public this(const char[] text) { this.text = text; + this.index = 0; + this.eolIndex = 0; + this.nextIndex = 0; } - public bool empty() { return index == text.length; } + public bool empty() { advance(); return index >= text.length; } public void popFront() { advance(); index = nextIndex; } - public const(char)[] front() { advance(); return text[index .. eolIndex]; } + public const(char)[] front() + { + advance(); + if (index > eolIndex || index >= text.length) { + return ""; + } + return text[index .. eolIndex]; + } private void advance() { @@ -418,7 +428,7 @@ auto splitLines(const char[] text) if (i + 2 < text.length && text[i + 1] == 0x80 && (text[i + 2] == 0xA8 || text[i + 2] == 0xA9) - ) + ) { eolIndex = i; nextIndex = i + 3; @@ -430,6 +440,10 @@ auto splitLines(const char[] text) break; } } + + // No newline found; set indices to the end of the text + eolIndex = text.length; + nextIndex = text.length; } } diff --git a/gcc/d/dmd/safe.d b/gcc/d/dmd/safe.d index 86dff7b..f6427a3 100644 --- a/gcc/d/dmd/safe.d +++ b/gcc/d/dmd/safe.d @@ -17,6 +17,7 @@ import core.stdc.stdio; import dmd.aggregate; import dmd.astenums; +import dmd.common.outbuffer; import dmd.dcast : implicitConvTo; import dmd.dclass; import dmd.declaration; @@ -67,11 +68,10 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) if (!ad) return false; - import dmd.globals : global; if (v.isSystem()) { - if (sc.setUnsafePreview(global.params.systemVariables, !printmsg, e.loc, - "cannot access `@system` field `%s.%s` in `@safe` code", ad, v)) + if (sc.setUnsafePreview(sc.previews.systemVariables, !printmsg, e.loc, + "accessing `@system` field `%s.%s`", ad, v)) return true; } @@ -91,7 +91,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) if (v.overlapped) { if (sc.func.isSafeBypassingInference() && sc.setUnsafe(!printmsg, e.loc, - "field `%s.%s` cannot access pointers in `@safe` code that overlap other fields", ad, v)) + "accessing overlapped field `%s.%s` with pointers", ad, v)) { return true; } @@ -104,7 +104,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) // To turn into an error, remove `isSafeBypassingInference` check in the // above if statement and remove the else branch sc.setUnsafePreview(FeatureState.default_, !printmsg, e.loc, - "field `%s.%s` cannot access pointers in `@safe` code that overlap other fields", ad, v); + "accessing overlapped field `%s.%s` with pointers", ad, v); } } } @@ -114,7 +114,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) if (v.overlapped) { if (sc.setUnsafe(!printmsg, e.loc, - "field `%s.%s` cannot access structs with invariants in `@safe` code that overlap other fields", + "accessing overlapped field `%s.%s` with a structs invariant", ad, v)) return true; } @@ -125,7 +125,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) // Should probably be turned into an error in a new edition if (v.type.hasUnsafeBitpatterns() && v.overlapped && sc.setUnsafePreview( FeatureState.default_, !printmsg, e.loc, - "cannot access overlapped field `%s.%s` with unsafe bit patterns in `@safe` code", ad, v) + "accessing overlapped field `%s.%s` with unsafe bit patterns", ad, v) ) { return true; @@ -140,7 +140,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) (v.offset & (target.ptrsize - 1))) { if (sc.setUnsafe(!printmsg, e.loc, - "field `%s.%s` cannot modify misaligned pointers in `@safe` code", ad, v)) + "modifying misaligned pointers through field `%s.%s`", ad, v)) return true; } } @@ -148,7 +148,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg) if (v.overlapUnsafe) { if (sc.setUnsafe(!printmsg, e.loc, - "field `%s.%s` cannot modify fields in `@safe` code that overlap fields with other storage classes", + "modifying field `%s.%s` which overlaps with fields with other storage classes", ad, v)) { return true; @@ -181,6 +181,10 @@ bool isSafeCast(Expression e, Type tfrom, Type tto, ref string msg) auto tfromb = tfrom.toBasetype(); auto ttob = tto.toBasetype(); + // Casting to void* is always safe, https://github.com/dlang/dmd/issues/20514 + if (ttob.isTypePointer() && ttob.nextOf().toBasetype().ty == Tvoid) + return true; + if (ttob.ty == Tclass && tfromb.ty == Tclass) { ClassDeclaration cdfrom = tfromb.isClassHandle(); @@ -310,9 +314,9 @@ bool checkUnsafeDotExp(Scope* sc, Expression e, Identifier id, int flag) if (!(flag & DotExpFlag.noDeref)) // this use is attempting a dereference { if (id == Id.ptr) - return sc.setUnsafe(false, e.loc, "`%s.ptr` cannot be used in `@safe` code, use `&%s[0]` instead", e, e); + return sc.setUnsafe(false, e.loc, "using `%s.ptr` (instead of `&%s[0])`", e, e); else - return sc.setUnsafe(false, e.loc, "`%s.%s` cannot be used in `@safe` code", e, id); + return sc.setUnsafe(false, e.loc, "using `%s.%s`", e, id); } return false; } @@ -323,8 +327,7 @@ bool checkUnsafeDotExp(Scope* sc, Expression e, Identifier id, int flag) */ bool isSaferD(FuncDeclaration fd) { - return fd.type.toTypeFunction().trust == TRUST.default_ && - global.params.safer == FeatureState.enabled; + return fd.type.toTypeFunction().trust == TRUST.default_ && fd.saferD; } bool isSafe(FuncDeclaration fd) @@ -378,7 +381,15 @@ extern (D) void reportSafeError(FuncDeclaration fd, bool gag, Loc loc, else if (fd.isSafe() || fd.isSaferD()) { if (!gag && format) - .error(loc, format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + { + OutBuffer buf; + buf.printf(format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + if (fd.isSafe()) + buf.writestring(" is not allowed in a `@safe` function"); + else + buf.writestring(" is not allowed in a function with default safety with `-preview=safer`"); + .error(loc, buf.extractChars()); + } } } @@ -457,7 +468,11 @@ bool setUnsafe(Scope* sc, { if (sc.varDecl.storage_class & STC.safe) { - .error(loc, format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + OutBuffer buf; + buf.printf(format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + buf.printf(" can't initialize `@safe` variable `%s`", sc.varDecl.toChars()); + .error(loc, buf.extractChars()); + return true; } else if (!(sc.varDecl.storage_class & STC.trusted)) @@ -476,7 +491,10 @@ bool setUnsafe(Scope* sc, { // Message wil be gagged, but still call error() to update global.errors and for // -verrors=spec - .error(loc, format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + OutBuffer buf; + buf.printf(format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + buf.writestring(" is not allowed in a `@safe` function"); + .error(loc, buf.extractChars()); return true; } return false; @@ -534,7 +552,10 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char) { if (!gag && !sc.isDeprecated()) { - deprecation(loc, format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + OutBuffer buf; + buf.printf(format, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + buf.writestring(" will become `@system` in a future release"); + deprecation(loc, buf.extractChars()); } } else if (!sc.func.safetyViolation) diff --git a/gcc/d/dmd/scope.h b/gcc/d/dmd/scope.h index ac11266..0bde3d7 100644 --- a/gcc/d/dmd/scope.h +++ b/gcc/d/dmd/scope.h @@ -102,7 +102,8 @@ struct Scope final DeprecatedDeclaration *depdecl; // customized deprecation message - unsigned flags; + uint16_t flags; + uint16_t previews; // state of preview switches bool ctor() const; bool ctor(bool v); @@ -130,10 +131,6 @@ struct Scope final bool fullinst(bool v); bool ctfeBlock() const; bool ctfeBlock(bool v); - bool dip1000() const; - bool dip1000(bool v); - bool dip25() const; - bool dip25(bool v); UserAttributeDeclaration *userAttribDecl; // user defined attributes diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index 1ea1ca1..92e00e8 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -298,6 +298,7 @@ private extern(C++) final class Semantic3Visitor : Visitor return; funcdecl.semanticRun = PASS.semantic3; funcdecl.hasSemantic3Errors = false; + funcdecl.saferD = sc.previews.safer; if (!funcdecl.type || funcdecl.type.ty != Tfunction) return; @@ -975,7 +976,7 @@ private extern(C++) final class Semantic3Visitor : Visitor sc2 = sc2.pop(); } - if (global.params.inclusiveInContracts) + if (sc.previews.inclusiveInContracts) { funcdecl.frequire = funcdecl.mergeFrequireInclusivePreview( funcdecl.frequire, funcdecl.fdrequireParams); @@ -1393,7 +1394,7 @@ private extern(C++) final class Semantic3Visitor : Visitor } // Do live analysis - if (global.params.useDIP1021 && funcdecl.fbody && funcdecl.type.ty != Terror && + if (sc.previews.dip1021 && funcdecl.fbody && funcdecl.type.ty != Terror && funcdecl.type.isTypeFunction().isLive) { oblive(funcdecl); diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d index 5c759b0..25c9eef 100644 --- a/gcc/d/dmd/statement.d +++ b/gcc/d/dmd/statement.d @@ -890,7 +890,7 @@ extern (C++) final class ForeachStatement : Statement extern (C++) final class ForeachRangeStatement : Statement { TOK op; // TOK.foreach_ or TOK.foreach_reverse_ - Parameter prm; // loop index variable + Parameter param; // loop index variable Expression lwr; Expression upr; Statement _body; @@ -898,11 +898,11 @@ extern (C++) final class ForeachRangeStatement : Statement VarDeclaration key; - extern (D) this(const ref Loc loc, TOK op, Parameter prm, Expression lwr, Expression upr, Statement _body, Loc endloc) @safe + extern (D) this(const ref Loc loc, TOK op, Parameter param, Expression lwr, Expression upr, Statement _body, Loc endloc) @safe { super(loc, STMT.ForeachRange); this.op = op; - this.prm = prm; + this.param = param; this.lwr = lwr; this.upr = upr; this._body = _body; @@ -911,7 +911,7 @@ extern (C++) final class ForeachRangeStatement : Statement override ForeachRangeStatement syntaxCopy() { - return new ForeachRangeStatement(loc, op, prm.syntaxCopy(), lwr.syntaxCopy(), upr.syntaxCopy(), _body ? _body.syntaxCopy() : null, endloc); + return new ForeachRangeStatement(loc, op, param.syntaxCopy(), lwr.syntaxCopy(), upr.syntaxCopy(), _body ? _body.syntaxCopy() : null, endloc); } override bool hasBreak() const pure nothrow @@ -935,17 +935,17 @@ extern (C++) final class ForeachRangeStatement : Statement */ extern (C++) final class IfStatement : Statement { - Parameter prm; + Parameter param; Expression condition; Statement ifbody; Statement elsebody; VarDeclaration match; // for MatchExpression results Loc endloc; // location of closing curly bracket - extern (D) this(const ref Loc loc, Parameter prm, Expression condition, Statement ifbody, Statement elsebody, Loc endloc) @safe + extern (D) this(const ref Loc loc, Parameter param, Expression condition, Statement ifbody, Statement elsebody, Loc endloc) @safe { super(loc, STMT.If); - this.prm = prm; + this.param = param; this.condition = condition; this.ifbody = ifbody; this.elsebody = elsebody; @@ -955,7 +955,7 @@ extern (C++) final class IfStatement : Statement override IfStatement syntaxCopy() { return new IfStatement(loc, - prm ? prm.syntaxCopy() : null, + param ? param.syntaxCopy() : null, condition.syntaxCopy(), ifbody ? ifbody.syntaxCopy() : null, elsebody ? elsebody.syntaxCopy() : null, diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h index 9437238..e420cf4 100644 --- a/gcc/d/dmd/statement.h +++ b/gcc/d/dmd/statement.h @@ -346,7 +346,7 @@ class ForeachRangeStatement final : public Statement { public: TOK op; // TOKforeach or TOKforeach_reverse - Parameter *prm; // loop index variable + Parameter *param; // loop index variable Expression *lwr; Expression *upr; Statement *_body; @@ -364,7 +364,7 @@ public: class IfStatement final : public Statement { public: - Parameter *prm; + Parameter *param; Expression *condition; Statement *ifbody; Statement *elsebody; diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index d259abf..932830d 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -1471,25 +1471,25 @@ Statement statementSemanticVisit(Statement s, Scope* sc) return setError(); } - if (fs.prm.type) + if (fs.param.type) { - fs.prm.type = fs.prm.type.typeSemantic(loc, sc); - fs.prm.type = fs.prm.type.addStorageClass(fs.prm.storageClass); - fs.lwr = fs.lwr.implicitCastTo(sc, fs.prm.type); + fs.param.type = fs.param.type.typeSemantic(loc, sc); + fs.param.type = fs.param.type.addStorageClass(fs.param.storageClass); + fs.lwr = fs.lwr.implicitCastTo(sc, fs.param.type); - if (fs.upr.implicitConvTo(fs.prm.type) || (fs.prm.storageClass & STC.ref_)) + if (fs.upr.implicitConvTo(fs.param.type) || (fs.param.storageClass & STC.ref_)) { - fs.upr = fs.upr.implicitCastTo(sc, fs.prm.type); + fs.upr = fs.upr.implicitCastTo(sc, fs.param.type); } else { - // See if upr-1 fits in prm.type + // See if upr-1 fits in param.type Expression limit = new MinExp(loc, fs.upr, IntegerExp.literal!1); limit = limit.expressionSemantic(sc); limit = limit.optimize(WANTvalue); - if (!limit.implicitConvTo(fs.prm.type)) + if (!limit.implicitConvTo(fs.param.type)) { - fs.upr = fs.upr.implicitCastTo(sc, fs.prm.type); + fs.upr = fs.upr.implicitCastTo(sc, fs.param.type); } } } @@ -1502,26 +1502,26 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { /* Just picking the first really isn't good enough. */ - fs.prm.type = fs.lwr.type; + fs.param.type = fs.lwr.type; } else if (fs.lwr.type == fs.upr.type) { /* Same logic as CondExp ?lwr:upr */ - fs.prm.type = fs.lwr.type; + fs.param.type = fs.lwr.type; } else { scope AddExp ea = new AddExp(loc, fs.lwr, fs.upr); if (typeCombine(ea, sc)) return setError(); - fs.prm.type = ea.type; + fs.param.type = ea.type; fs.lwr = ea.e1; fs.upr = ea.e2; } - fs.prm.type = fs.prm.type.addStorageClass(fs.prm.storageClass); + fs.param.type = fs.param.type.addStorageClass(fs.param.storageClass); } - if (fs.prm.type.ty == Terror || fs.lwr.op == EXP.error || fs.upr.op == EXP.error) + if (fs.param.type.ty == Terror || fs.lwr.op == EXP.error || fs.upr.op == EXP.error) { return setError(); } @@ -1566,7 +1566,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (fs.op == TOK.foreach_reverse_) { cond = new PostExp(EXP.minusMinus, loc, new VarExp(loc, fs.key)); - if (fs.prm.type.isScalar()) + if (fs.param.type.isScalar()) { // key-- > tmp cond = new CmpExp(EXP.greaterThan, loc, cond, new VarExp(loc, tmp)); @@ -1579,7 +1579,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) } else { - if (fs.prm.type.isScalar()) + if (fs.param.type.isScalar()) { // key < tmp cond = new CmpExp(EXP.lessThan, loc, new VarExp(loc, fs.key), new VarExp(loc, tmp)); @@ -1598,30 +1598,30 @@ Statement statementSemanticVisit(Statement s, Scope* sc) //increment = new AddAssignExp(loc, new VarExp(loc, fs.key), IntegerExp.literal!1); increment = new PreExp(EXP.prePlusPlus, loc, new VarExp(loc, fs.key)); } - if ((fs.prm.storageClass & STC.ref_) && fs.prm.type.equals(fs.key.type)) + if ((fs.param.storageClass & STC.ref_) && fs.param.type.equals(fs.key.type)) { fs.key.range = null; - auto v = new AliasDeclaration(loc, fs.prm.ident, fs.key); + auto v = new AliasDeclaration(loc, fs.param.ident, fs.key); fs._body = new CompoundStatement(loc, new ExpStatement(loc, v), fs._body); } else { - ie = new ExpInitializer(loc, new CastExp(loc, new VarExp(loc, fs.key), fs.prm.type)); - auto v = new VarDeclaration(loc, fs.prm.type, fs.prm.ident, ie); - v.storage_class |= STC.temp | STC.foreach_ | (fs.prm.storageClass & STC.ref_); + ie = new ExpInitializer(loc, new CastExp(loc, new VarExp(loc, fs.key), fs.param.type)); + auto v = new VarDeclaration(loc, fs.param.type, fs.param.ident, ie); + v.storage_class |= STC.temp | STC.foreach_ | (fs.param.storageClass & STC.ref_); fs._body = new CompoundStatement(loc, new ExpStatement(loc, v), fs._body); - if (fs.key.range && !fs.prm.type.isMutable()) + if (fs.key.range && !fs.param.type.isMutable()) { /* Limit the range of the key to the specified range */ v.range = new IntRange(fs.key.range.imin, fs.key.range.imax - SignExtendedNumber(1)); } } - if (fs.prm.storageClass & STC.ref_) + if (fs.param.storageClass & STC.ref_) { - if (fs.key.type.constConv(fs.prm.type) == MATCH.nomatch) + if (fs.key.type.constConv(fs.param.type) == MATCH.nomatch) { - error(fs.loc, "argument type mismatch, `%s` to `ref %s`", fs.key.type.toChars(), fs.prm.type.toChars()); + error(fs.loc, "argument type mismatch, `%s` to `ref %s`", fs.key.type.toChars(), fs.param.type.toChars()); return setError(); } } @@ -1644,15 +1644,15 @@ Statement statementSemanticVisit(Statement s, Scope* sc) sym.parent = sc.scopesym; sym.endlinnum = ifs.endloc.linnum; Scope* scd = sc.push(sym); - if (ifs.prm) + if (ifs.param) { - /* Declare prm, which we will set to be the + /* Declare param, which we will set to be the * result of condition. */ auto ei = new ExpInitializer(ifs.loc, ifs.condition); - ifs.match = new VarDeclaration(ifs.loc, ifs.prm.type, ifs.prm.ident, ei); + ifs.match = new VarDeclaration(ifs.loc, ifs.param.type, ifs.param.ident, ei); ifs.match.parent = scd.func; - ifs.match.storage_class |= ifs.prm.storageClass; + ifs.match.storage_class |= ifs.param.storageClass; ifs.match.dsymbolSemantic(scd); auto de = new DeclarationExp(ifs.loc, ifs.match); @@ -1688,8 +1688,8 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (checkNonAssignmentArrayOp(ifs.condition)) ifs.condition = ErrorExp.get(); - // Convert to boolean after declaring prm so this works: - // if (S prm = S()) {} + // Convert to boolean after declaring param so this works: + // if (S param = S()) {} // where S is a struct that defines opCast!bool. ifs.condition = ifs.condition.toBoolean(scd); @@ -2677,7 +2677,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) // If we previously assumed the function could be ref when // checking for `shared`, make sure we were right - if (global.params.noSharedAccess == FeatureState.enabled && rs.exp.type.isShared()) + if (sc.previews.noSharedAccess && rs.exp.type.isShared()) { .error(fd.loc, "%s `%s` function returns `shared` but cannot be inferred `ref`", fd.kind, fd.toPrettyChars); supplemental(); @@ -3634,7 +3634,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) deprecation(cas.loc, "`asm` statement cannot be marked `@safe`, use `@system` or `@trusted` instead"); if (!(cas.stc & (STC.trusted | STC.safe))) { - sc.setUnsafe(false, cas.loc, "`asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not"); + sc.setUnsafe(false, cas.loc, "`asm` statement without `@trusted` annotation"); } sc.pop(); @@ -3997,12 +3997,12 @@ private FuncExp foreachBodyToFunction(Scope* sc, ForeachStatement fs, TypeFuncti p.type = p.type.addStorageClass(p.storageClass); if (tfld) { - Parameter prm = tfld.parameterList[i]; - //printf("\tprm = %s%s\n", (prm.storageClass&STC.ref_?"ref ":"").ptr, prm.ident.toChars()); - stc = (prm.storageClass & STC.ref_) | (p.storageClass & STC.scope_); - if ((p.storageClass & STC.ref_) != (prm.storageClass & STC.ref_)) + Parameter param = tfld.parameterList[i]; + //printf("\tparam = %s%s\n", (param.storageClass&STC.ref_?"ref ":"").ptr, param.ident.toChars()); + stc = (param.storageClass & STC.ref_) | (p.storageClass & STC.scope_); + if ((p.storageClass & STC.ref_) != (param.storageClass & STC.ref_)) { - if (!(prm.storageClass & STC.ref_)) + if (!(param.storageClass & STC.ref_)) { error(fs.loc, "`foreach`: cannot make `%s` `ref`", p.ident.toChars()); return null; @@ -4115,7 +4115,7 @@ void catchSemantic(Catch c, Scope* sc) } if (!c.internalCatch) { - if (sc.setUnsafe(false, c.loc, "cannot catch C++ class objects in `@safe` code")) + if (sc.setUnsafe(false, c.loc, "catching C++ class objects")) c.errors = true; } } @@ -4127,18 +4127,18 @@ void catchSemantic(Catch c, Scope* sc) else if (!c.internalCatch && ClassDeclaration.exception && cd != ClassDeclaration.exception && !ClassDeclaration.exception.isBaseOf(cd, null) && sc.setUnsafe(false, c.loc, - "can only catch class objects derived from `Exception` in `@safe` code, not `%s`", c.type)) + "catching class objects derived from `%s` instead of `Exception`", c.type)) { c.errors = true; } - else if (global.params.ehnogc) + else if (sc.previews.dip1008) { stc |= STC.scope_; } // DIP1008 requires destruction of the Throwable, even if the user didn't specify an identifier auto ident = c.ident; - if (!ident && global.params.ehnogc) + if (!ident && sc.previews.dip1008) ident = Identifier.generateAnonymousId("var"); if (ident) @@ -4148,7 +4148,7 @@ void catchSemantic(Catch c, Scope* sc) c.var.dsymbolSemantic(sc); sc.insert(c.var); - if (global.params.ehnogc && stc & STC.scope_) + if (sc.previews.dip1008 && stc & STC.scope_) { /* Add a destructor for c.var * try { handler } finally { if (!__ctfe) _d_delThrowable(var); } diff --git a/gcc/d/dmd/templatesem.d b/gcc/d/dmd/templatesem.d index 8be9730..a69edef 100644 --- a/gcc/d/dmd/templatesem.d +++ b/gcc/d/dmd/templatesem.d @@ -1362,7 +1362,7 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat { // Allow conversion from T[lwr .. upr] to ref T[upr-lwr] } - else if (global.params.rvalueRefParam == FeatureState.enabled) + else if (sc.previews.rvalueRefParam) { // Allow implicit conversion to ref } diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index 2ec88f2..c631e64 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -1122,7 +1122,7 @@ private extern(D) MATCH argumentMatchParameter (FuncDeclaration fd, TypeFunction // Need to make this a rvalue through a temporary m = MATCH.convert; } - else if (global.params.rvalueRefParam != FeatureState.enabled || + else if (!(sc && sc.previews.rvalueRefParam) || p.storageClass & STC.out_ || !arg.type.isCopyable()) // can't copy to temp for ref parameter { @@ -2335,8 +2335,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc) // default arg must be an lvalue if (isRefOrOut && !isAuto && - !(fparam.storageClass & STC.constscoperef) && - global.params.rvalueRefParam != FeatureState.enabled) + !(fparam.storageClass & STC.constscoperef) && !sc.previews.rvalueRefParam) e = e.toLvalue(sc, "create default argument for `ref` / `out` parameter from"); fparam.defaultArg = e; diff --git a/gcc/d/dmd/visitor/transitive.d b/gcc/d/dmd/visitor/transitive.d index 952460c..c3ce13e 100644 --- a/gcc/d/dmd/visitor/transitive.d +++ b/gcc/d/dmd/visitor/transitive.d @@ -153,8 +153,8 @@ package(dmd.visitor) mixin template ParseVisitMethods(AST) override void visit(AST.ForeachRangeStatement s) { //printf("Visiting ForeachRangeStatement\n"); - if (s.prm.type) - visitType(s.prm.type); + if (s.param.type) + visitType(s.param.type); s.lwr.accept(this); s.upr.accept(this); if (s._body) @@ -174,8 +174,8 @@ package(dmd.visitor) mixin template ParseVisitMethods(AST) override void visit(AST.IfStatement s) { //printf("Visiting IfStatement\n"); - if (s.prm && s.prm.type) - visitType(s.prm.type); + if (s.param && s.param.type) + visitType(s.param.type); s.condition.accept(this); s.ifbody.accept(this); if (s.elsebody) |