aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-06-22 17:03:33 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2022-06-22 17:57:56 +0200
commit445d8deffb6c9bc1f4a5ed0a8e02d7f31d3caec7 (patch)
tree4b9aa4224d827abfe081adf2289af34436d3e552 /gcc/d
parentd844478ab47a16c8ae65f253fd1cdc685c7951fc (diff)
downloadgcc-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/MERGE2
-rw-r--r--gcc/d/dmd/aggregate.h36
-rw-r--r--gcc/d/dmd/clone.d9
-rw-r--r--gcc/d/dmd/denum.d14
-rw-r--r--gcc/d/dmd/dstruct.d33
-rw-r--r--gcc/d/dmd/dsymbolsem.d29
-rw-r--r--gcc/d/dmd/enum.h13
-rw-r--r--gcc/d/dmd/escape.d40
-rw-r--r--gcc/d/dmd/expression.d2
-rw-r--r--gcc/d/dmd/func.d21
-rw-r--r--gcc/d/dmd/parse.d4
-rw-r--r--gcc/d/dmd/statementsem.d25
-rw-r--r--gcc/d/dmd/typesem.d31
-rw-r--r--gcc/d/typeinfo.cc4
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;