diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2022-06-22 17:03:33 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2022-06-22 17:57:56 +0200 |
commit | 445d8deffb6c9bc1f4a5ed0a8e02d7f31d3caec7 (patch) | |
tree | 4b9aa4224d827abfe081adf2289af34436d3e552 /gcc/d | |
parent | d844478ab47a16c8ae65f253fd1cdc685c7951fc (diff) | |
download | gcc-445d8deffb6c9bc1f4a5ed0a8e02d7f31d3caec7.zip gcc-445d8deffb6c9bc1f4a5ed0a8e02d7f31d3caec7.tar.gz gcc-445d8deffb6c9bc1f4a5ed0a8e02d7f31d3caec7.tar.bz2 |
d: Merge upstream dmd 6203135dc, druntime e150cca1, phobos a4a18d21c.
D front-end changes:
- Input parameters can now be applied on extern(C++) functions to
bind to `const &' when the `-fpreview=in' flag is in effect.
D runtime changes:
- Run-time flag `--DRT-oncycle=deprecate' has been removed.
Phobos changes:
- Removed std.experimental.logger's capability to set the minimal
LogLevel at compile time.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd 6203135dc.
* typeinfo.cc (TypeInfoVisitor::visit (TypeInfoStructDeclaration *)):
Update for new front-end interface.
(SpeculativeTypeVisitor::visit (TypeStruct *)): Likewise.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime e150cca1.
* src/MERGE: Merge upstream phobos a4a18d21c.
* testsuite/libphobos.cycles/cycles.exp (cycle_test_list): Update
expected result of deprecate test.
Diffstat (limited to 'gcc/d')
-rw-r--r-- | gcc/d/dmd/MERGE | 2 | ||||
-rw-r--r-- | gcc/d/dmd/aggregate.h | 36 | ||||
-rw-r--r-- | gcc/d/dmd/clone.d | 9 | ||||
-rw-r--r-- | gcc/d/dmd/denum.d | 14 | ||||
-rw-r--r-- | gcc/d/dmd/dstruct.d | 33 | ||||
-rw-r--r-- | gcc/d/dmd/dsymbolsem.d | 29 | ||||
-rw-r--r-- | gcc/d/dmd/enum.h | 13 | ||||
-rw-r--r-- | gcc/d/dmd/escape.d | 40 | ||||
-rw-r--r-- | gcc/d/dmd/expression.d | 2 | ||||
-rw-r--r-- | gcc/d/dmd/func.d | 21 | ||||
-rw-r--r-- | gcc/d/dmd/parse.d | 4 | ||||
-rw-r--r-- | gcc/d/dmd/statementsem.d | 25 | ||||
-rw-r--r-- | gcc/d/dmd/typesem.d | 31 | ||||
-rw-r--r-- | gcc/d/typeinfo.cc | 4 |
14 files changed, 181 insertions, 82 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index d39658a..d1e3dc1 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -821ed393d428c7db5a48623e77d43f5647d5c6a2 +6203135dcf0112d3211add0cbfb22fecc5df1af4 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/aggregate.h b/gcc/d/dmd/aggregate.h index f27ca07..d91e35e 100644 --- a/gcc/d/dmd/aggregate.h +++ b/gcc/d/dmd/aggregate.h @@ -159,17 +159,6 @@ struct StructFlags class StructDeclaration : public AggregateDeclaration { public: - bool zeroInit; // !=0 if initialize with 0 fill - bool hasIdentityAssign; // true if has identity opAssign - bool hasBlitAssign; // true if opAssign is a blit - bool hasIdentityEquals; // true if has identity opEquals - bool hasNoFields; // has no fields - bool hasCopyCtor; // copy constructor - // Even if struct is defined as non-root symbol, some built-in operations - // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. - // For those, today TypeInfo_Struct is generated in COMDAT. - bool requestTypeInfo; - FuncDeclarations postblits; // Array of postblit functions FuncDeclaration *postblit; // aggregate postblit @@ -179,18 +168,37 @@ public: static FuncDeclaration *xerreq; // object.xopEquals static FuncDeclaration *xerrcmp; // object.xopCmp - structalign_t alignment; // alignment applied outside of the struct - ThreeState ispod; // if struct is POD - // ABI-specific type(s) if the struct can be passed in registers TypeTuple *argTypes; + structalign_t alignment; // alignment applied outside of the struct + ThreeState ispod; // if struct is POD +private: + uint8_t bitFields; +public: static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject); StructDeclaration *syntaxCopy(Dsymbol *s) override; Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final; const char *kind() const override; void finalizeSize() override final; bool isPOD(); + bool zeroInit() const; // !=0 if initialize with 0 fill + bool zeroInit(bool v); + bool hasIdentityAssign() const; // true if has identity opAssign + bool hasIdentityAssign(bool v); + bool hasBlitAssign() const; // true if opAssign is a blit + bool hasBlitAssign(bool v); + bool hasIdentityEquals() const; // true if has identity opEquals + bool hasIdentityEquals(bool v); + bool hasNoFields() const; // has no fields + bool hasNoFields(bool v); + bool hasCopyCtor() const; // copy constructor + bool hasCopyCtor(bool v); + // Even if struct is defined as non-root symbol, some built-in operations + // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. + // For those, today TypeInfo_Struct is generated in COMDAT. + bool requestTypeInfo() const; + bool requestTypeInfo(bool v); StructDeclaration *isStructDeclaration() override final { return this; } void accept(Visitor *v) override { v->visit(this); } diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d index 75a16bd..cf4ccbb 100644 --- a/gcc/d/dmd/clone.d +++ b/gcc/d/dmd/clone.d @@ -404,7 +404,12 @@ bool needOpEquals(StructDeclaration sd) { //printf("StructDeclaration::needOpEquals() %s\n", sd.toChars()); if (sd.isUnionDeclaration()) - goto Ldontneed; + { + /* If a union has only one field, treat it like a struct + */ + if (sd.fields.length != 1) + goto Ldontneed; + } if (sd.hasIdentityEquals) goto Lneed; /* If any of the fields has an opEquals, then we @@ -421,7 +426,7 @@ bool needOpEquals(StructDeclaration sd) if (tvbase.ty == Tstruct) { TypeStruct ts = cast(TypeStruct)tvbase; - if (ts.sym.isUnionDeclaration()) + if (ts.sym.isUnionDeclaration() && ts.sym.fields.length != 1) continue; if (needOpEquals(ts.sym)) goto Lneed; diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d index aba290b..ef322f1 100644 --- a/gcc/d/dmd/denum.d +++ b/gcc/d/dmd/denum.d @@ -54,9 +54,17 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol Expression maxval; Expression minval; Expression defaultval; // default initializer - bool isdeprecated; - bool added; - int inuse; + + // `bool` fields that are compacted into bit fields in a string mixin + private extern (D) static struct BitFields + { + bool isdeprecated; + bool added; + bool inuse; + } + + import dmd.common.bitfields : generateBitFields; + mixin(generateBitFields!(BitFields, ubyte)); extern (D) this(const ref Loc loc, Identifier ident, Type memtype) { diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d index de5f145..4126a8a 100644 --- a/gcc/d/dmd/dstruct.d +++ b/gcc/d/dmd/dstruct.d @@ -192,17 +192,6 @@ enum StructFlags : int */ extern (C++) class StructDeclaration : AggregateDeclaration { - bool zeroInit; // !=0 if initialize with 0 fill - bool hasIdentityAssign; // true if has identity opAssign - bool hasBlitAssign; // true if opAssign is a blit - bool hasIdentityEquals; // true if has identity opEquals - bool hasNoFields; // has no fields - bool hasCopyCtor; // copy constructor - // Even if struct is defined as non-root symbol, some built-in operations - // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. - // For those, today TypeInfo_Struct is generated in COMDAT. - bool requestTypeInfo; - FuncDeclarations postblits; // Array of postblit functions FuncDeclaration postblit; // aggregate postblit @@ -212,11 +201,29 @@ extern (C++) class StructDeclaration : AggregateDeclaration extern (C++) __gshared FuncDeclaration xerreq; // object.xopEquals extern (C++) __gshared FuncDeclaration xerrcmp; // object.xopCmp + // ABI-specific type(s) if the struct can be passed in registers + TypeTuple argTypes; + structalign_t alignment; // alignment applied outside of the struct ThreeState ispod; // if struct is POD - // ABI-specific type(s) if the struct can be passed in registers - TypeTuple argTypes; + // `bool` fields that are compacted into bit fields in a string mixin + private extern (D) static struct BitFields + { + bool zeroInit; // !=0 if initialize with 0 fill + bool hasIdentityAssign; // true if has identity opAssign + bool hasBlitAssign; // true if opAssign is a blit + bool hasIdentityEquals; // true if has identity opEquals + bool hasNoFields; // has no fields + bool hasCopyCtor; // copy constructor + // Even if struct is defined as non-root symbol, some built-in operations + // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. + // For those, today TypeInfo_Struct is generated in COMDAT. + bool requestTypeInfo; + } + + import dmd.common.bitfields : generateBitFields; + mixin(generateBitFields!(BitFields, ubyte)); extern (D) this(const ref Loc loc, Identifier id, bool inObject) { diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 6dbc129..7fd4781 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -49,6 +49,7 @@ import dmd.identifier; import dmd.importc; import dmd.init; import dmd.initsem; +import dmd.intrange; import dmd.hdrgen; import dmd.mtype; import dmd.mustuse; @@ -2177,6 +2178,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor assert(ed.memtype); int nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0 + // C11 6.7.2.2-2 value must be representable as an int. + // The sizemask represents all values that int will fit into, + // from 0..uint.max. We want to cover int.min..uint.max. + const mask = Type.tint32.sizemask(); + IntRange ir = IntRange(SignExtendedNumber(~(mask >> 1), true), + SignExtendedNumber(mask)); + void emSemantic(EnumMember em, ref int nextValue) { static void errorReturn(EnumMember em) @@ -2206,21 +2214,32 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor em.error("enum member must be an integral constant expression, not `%s` of type `%s`", e.toChars(), e.type.toChars()); return errorReturn(em); } - const sinteger_t v = ie.toInteger(); - if (v < int.min || v > uint.max) + if (!ir.contains(getIntRange(ie))) { // C11 6.7.2.2-2 em.error("enum member value `%s` does not fit in an `int`", e.toChars()); return errorReturn(em); } - em.value = new IntegerExp(em.loc, cast(int)v, Type.tint32); - nextValue = cast(int)v; + nextValue = cast(int)ie.toInteger(); + em.value = new IntegerExp(em.loc, nextValue, Type.tint32); } else { + // C11 6.7.2.2-3 add 1 to value of previous enumeration constant + bool first = (em == (*em.ed.members)[0]); + if (!first) + { + import core.checkedint : adds; + bool overflow; + nextValue = adds(nextValue, 1, overflow); + if (overflow) + { + em.error("initialization with `%d+1` causes overflow for type `int`", nextValue - 1); + return errorReturn(em); + } + } em.value = new IntegerExp(em.loc, nextValue, Type.tint32); } - ++nextValue; // C11 6.7.2.2-3 add 1 to value of previous enumeration constant em.semanticRun = PASS.semanticdone; } diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h index 9ec1300..723cebc 100644 --- a/gcc/d/dmd/enum.h +++ b/gcc/d/dmd/enum.h @@ -35,10 +35,15 @@ public: Expression *maxval; Expression *minval; Expression *defaultval; // default initializer - - bool isdeprecated; - bool added; - int inuse; +private: + uint8_t bitFields; +public: + bool isdeprecated() const; + bool isdeprecated(bool v); + bool added() const; + bool added(bool v); + bool inuse() const; + bool inuse(bool v); EnumDeclaration *syntaxCopy(Dsymbol *s) override; void addMember(Scope *sc, ScopeDsymbol *sds) override; diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index 97a6552..0646f57 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -328,12 +328,12 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, STC else if (par) { result |= sc.setUnsafeDIP1000(gag, arg.loc, - desc ~ " `%s` assigned to non-scope parameter `%s`", v, par); + desc ~ " `%s` assigned to non-scope parameter `%s` calling `%s`", v, par, fdc); } else { result |= sc.setUnsafeDIP1000(gag, arg.loc, - desc ~ " `%s` assigned to non-scope parameter `this`", v); + desc ~ " `%s` assigned to non-scope parameter `this` calling `%s`", v, fdc); } } @@ -1230,9 +1230,24 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) !(!refs && sc.func.isFuncDeclaration().getLevel(pfunc, sc.intypeof) > 0) ) { - // https://issues.dlang.org/show_bug.cgi?id=17029 - result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be returned", v); - continue; + if (v.isParameter() && !(v.storage_class & STC.return_)) + { + // https://issues.dlang.org/show_bug.cgi?id=23191 + if (!gag) + { + previewErrorFunc(sc.isDeprecated(), global.params.useDIP1000)(e.loc, + "scope parameter `%s` may not be returned", v.toChars() + ); + result = true; + continue; + } + } + else + { + // https://issues.dlang.org/show_bug.cgi?id=17029 + result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be returned", v); + continue; + } } } else if (v.storage_class & STC.variadic && p == sc.func) @@ -2492,9 +2507,11 @@ private void addMaybe(VarDeclaration va, VarDeclaration v) * fmt = printf-style format string * arg0 = (optional) argument for first %s format specifier * arg1 = (optional) argument for second %s format specifier + * arg2 = (optional) argument for third %s format specifier * Returns: whether an actual safe error (not deprecation) occured */ -private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg, RootObject arg0 = null, RootObject arg1 = null) +private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg, + RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { if (fs == FeatureState.disabled) { @@ -2502,7 +2519,7 @@ private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, con } else if (fs == FeatureState.enabled) { - return sc.setUnsafe(gag, loc, msg, arg0, arg1); + return sc.setUnsafe(gag, loc, msg, arg0, arg1, arg2); } else { @@ -2510,22 +2527,23 @@ private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, con { if (!gag) previewErrorFunc(sc.isDeprecated(), fs)( - loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "" + loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "" ); } else if (!sc.func.safetyViolation) { import dmd.func : AttributeViolation; - sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1); + sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2); } return false; } } // `setUnsafePreview` partially evaluated for dip1000 -private bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg, RootObject arg0 = null, RootObject arg1 = null) +private bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg, + RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { - return setUnsafePreview(sc, global.params.useDIP1000, gag, loc, msg, arg0, arg1); + return setUnsafePreview(sc, global.params.useDIP1000, gag, loc, msg, arg0, arg1, arg2); } /*************************************** diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 4d17105..ceecf4b 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -1438,7 +1438,7 @@ extern (C++) abstract class Expression : ASTNode else if (!sc.func.safetyViolation) { import dmd.func : AttributeViolation; - sc.func.safetyViolation = new AttributeViolation(this.loc, null, f, null); + sc.func.safetyViolation = new AttributeViolation(this.loc, null, f, null, null); } } return false; diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index d429259..83bc2ea 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -1476,17 +1476,19 @@ extern (C++) class FuncDeclaration : Declaration * fmt = printf-style format string * arg0 = (optional) argument for first %s format specifier * arg1 = (optional) argument for second %s format specifier + * arg2 = (optional) argument for third %s format specifier * Returns: whether there's a safe error */ extern (D) final bool setUnsafe( - bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, RootObject arg0 = null, RootObject arg1 = null) + bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, + RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { if (flags & FUNCFLAG.safetyInprocess) { flags &= ~FUNCFLAG.safetyInprocess; type.toTypeFunction().trust = TRUST.system; if (fmt || arg0) - safetyViolation = new AttributeViolation(loc, fmt, arg0, arg1); + safetyViolation = new AttributeViolation(loc, fmt, arg0, arg1, arg2); if (fes) fes.func.setUnsafe(); @@ -1494,7 +1496,7 @@ extern (C++) class FuncDeclaration : Declaration else if (isSafe()) { if (!gag && fmt) - .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : ""); + .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); return true; } @@ -4370,10 +4372,12 @@ extern (C++) final class NewDeclaration : FuncDeclaration * fmt = printf-style format string * arg0 = (optional) argument for first %s format specifier * arg1 = (optional) argument for second %s format specifier + * arg2 = (optional) argument for third %s format specifier * Returns: whether there's a safe error */ bool setUnsafe(Scope* sc, - bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, RootObject arg0 = null, RootObject arg1 = null) + bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, + RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { // TODO: // For @system variables, unsafe initializers at global scope should mark @@ -4394,13 +4398,13 @@ bool setUnsafe(Scope* sc, { // Message wil be gagged, but still call error() to update global.errors and for // -verrors=spec - .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : ""); + .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); return true; } return false; } - return sc.func.setUnsafe(gag, loc, fmt, arg0, arg1); + return sc.func.setUnsafe(gag, loc, fmt, arg0, arg1, arg2); } /// Stores a reason why a function failed to infer a function attribute like `@safe` or `pure` @@ -4421,6 +4425,8 @@ struct AttributeViolation RootObject arg0 = null; /// ditto RootObject arg1 = null; + /// ditto + RootObject arg2 = null; } /// Print the reason why `fd` was inferred `@system` as a supplemental error @@ -4438,7 +4444,8 @@ void errorSupplementalInferredSafety(FuncDeclaration fd, int maxDepth, bool depr errorFunc(s.loc, deprecation ? "which would be `@system` because of:" : "which was inferred `@system` because of:"); - errorFunc(s.loc, s.fmtStr, s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : ""); + errorFunc(s.loc, s.fmtStr, + s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : "", s.arg2 ? s.arg2.toChars() : ""); } else if (FuncDeclaration fd2 = cast(FuncDeclaration) s.arg0) { diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index 89f8ae3..eb5e694 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -4862,7 +4862,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (udas !is null) { if (storage_class != 0) - error("cannot put a storage-class in an alias declaration."); + error("cannot put a storage-class in an `alias` declaration."); // parseAttributes shouldn't have set these variables assert(link == linkage && !setAlignment && ealign is null); auto tpl_ = cast(AST.TemplateDeclaration) s; @@ -4887,7 +4887,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer parseAttributes(); // type if (udas) - error("user-defined attributes not allowed for alias declarations"); + error("user-defined attributes not allowed for `alias` declarations"); auto t = parseType(); diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index 06e28a4..f23b988 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -4401,19 +4401,21 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState Dsymbol ds = null; if (!(storageClass & STC.manifest)) { - if ((isStatic || tb.ty == Tfunction || storageClass&STC.alias_) && e.op == EXP.variable) - ds = (cast(VarExp)e).var; - else if (e.op == EXP.template_) - ds = (cast(TemplateExp)e).td; - else if (e.op == EXP.scope_) - ds = (cast(ScopeExp)e).sds; - else if (e.op == EXP.function_) + if (isStatic || tb.ty == Tfunction || storageClass & STC.alias_) { - auto fe = cast(FuncExp)e; - ds = fe.td ? cast(Dsymbol)fe.td : fe.fd; + if (auto ve = e.isVarExp()) + ds = ve.var; + else if (auto dve = e.isDotVarExp()) + ds = dve.var; } - else if (e.op == EXP.overloadSet) - ds = (cast(OverExp)e).vars; + if (auto te = e.isTemplateExp()) + ds = te.td; + else if (auto se = e.isScopeExp()) + ds = se.sds; + else if (auto fe = e.isFuncExp()) + ds = fe.td ? fe.td : fe.fd; + else if (auto oe = e.isOverExp()) + ds = oe.vars; } else if (storageClass & STC.alias_) { @@ -4530,6 +4532,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState auto field = Identifier.idPool(StaticForeach.tupleFieldName.ptr,StaticForeach.tupleFieldName.length); Expression access = new DotIdExp(loc, e, field); access = expressionSemantic(access, sc); + access = access.optimize(WANTvalue); if (!tuple) return returnEarly(); //printf("%s\n",tuple.toChars()); foreach (l; 0 .. dim) diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index 31ecbd2..8cacdb1 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -119,7 +119,7 @@ private void resolveTupleIndex(const ref Loc loc, Scope* sc, Dsymbol s, out Expr const(uinteger_t) d = eindex.toUInteger(); if (d >= tup.objects.dim) { - .error(loc, "tuple index `%llu` exceeds length %llu", d, cast(ulong)tup.objects.dim); + .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong)tup.objects.dim); pt = Type.terror; return; } @@ -554,7 +554,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) uinteger_t d = mtype.dim.toUInteger(); if (d >= tup.objects.dim) { - .error(loc, "tuple index %llu exceeds %llu", cast(ulong)d, cast(ulong)tup.objects.dim); + .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tup.objects.dim); return error(); } @@ -649,7 +649,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) uinteger_t d = mtype.dim.toUInteger(); if (d >= tt.arguments.dim) { - .error(loc, "tuple index %llu exceeds %llu", cast(ulong)d, cast(ulong)tt.arguments.dim); + .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tt.arguments.dim); return error(); } Type telem = (*tt.arguments)[cast(size_t)d].type; @@ -1224,6 +1224,25 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) continue; } + // -preview=in: Always add `ref` when used with `extern(C++)` functions + // Done here to allow passing opaque types with `in` + if (global.params.previewIn && (fparam.storageClass & (STC.in_ | STC.ref_)) == STC.in_) + { + switch (tf.linkage) + { + case LINK.cpp: + fparam.storageClass |= STC.ref_; + break; + case LINK.default_, LINK.d: + break; + default: + .error(loc, "cannot use `in` parameters with `extern(%s)` functions", + linkageToChars(tf.linkage)); + .errorSupplemental(loc, "parameter `%s` declared as `in` here", fparam.toChars()); + break; + } + } + if (t.ty == Tfunction) { .error(loc, "cannot have parameter of function type `%s`", fparam.type.toChars()); @@ -2572,7 +2591,7 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type const d = mt.dim.toUInteger(); if (d >= tup.objects.dim) { - error(loc, "tuple index `%llu` exceeds length %llu", d, cast(ulong) tup.objects.dim); + error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong) tup.objects.dim); return returnError(); } @@ -4891,9 +4910,9 @@ Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identifier id) */ Expression e = em.value; Expression ec = new CmpExp(id == Id.max ? EXP.greaterThan : EXP.lessThan, em.loc, e, *pval); - ed.inuse++; + ed.inuse = true; ec = ec.expressionSemantic(em._scope); - ed.inuse--; + ed.inuse = false; ec = ec.ctfeInterpret(); if (ec.op == EXP.error) { diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc index 1f8afdd..d1f0d59 100644 --- a/gcc/d/typeinfo.cc +++ b/gcc/d/typeinfo.cc @@ -1050,7 +1050,7 @@ public: this->layout_string (ti->deco); /* Default initializer for struct. */ - tree ptr = (sd->zeroInit) ? null_pointer_node + tree ptr = (sd->zeroInit ()) ? null_pointer_node : build_address (aggregate_initializer_decl (sd)); this->layout_field (d_array_value (array_type_node, size_int (sd->structsize), ptr)); @@ -1771,7 +1771,7 @@ public: { if (!ti->needsCodegen ()) { - if (ti->minst || sd->requestTypeInfo) + if (ti->minst || sd->requestTypeInfo ()) return; this->result_ |= true; |