aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-06-24 19:41:41 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2022-06-24 20:49:58 +0200
commitd97f3bca6eec50ac4ec007d731d345db3e560c52 (patch)
treeb96c7e4a976986b4a8d755479a808db9bbb8b80c /gcc/d
parentc0ad48527c314a1e9354b7c26718b56ed4abc92c (diff)
downloadgcc-d97f3bca6eec50ac4ec007d731d345db3e560c52.zip
gcc-d97f3bca6eec50ac4ec007d731d345db3e560c52.tar.gz
gcc-d97f3bca6eec50ac4ec007d731d345db3e560c52.tar.bz2
d: Merge upstream dmd 529110f66, druntime 148608b7.
D front-end changes: - Import latest bug fixes to mainline. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 529110f66. * decl.cc (DeclVisitor::visit (TupleDeclaration *)): Update for new front-end interface. * types.cc (layout_aggregate_members): Likewise. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 148608b7.
Diffstat (limited to 'gcc/d')
-rw-r--r--gcc/d/decl.cc6
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/canthrow.d13
-rw-r--r--gcc/d/dmd/cparse.d34
-rw-r--r--gcc/d/dmd/declaration.d63
-rw-r--r--gcc/d/dmd/dinterpret.d17
-rw-r--r--gcc/d/dmd/dmangle.d18
-rw-r--r--gcc/d/dmd/dsymbolsem.d33
-rw-r--r--gcc/d/dmd/dtoh.d128
-rw-r--r--gcc/d/dmd/expression.d8
-rw-r--r--gcc/d/dmd/expressionsem.d104
-rw-r--r--gcc/d/dmd/foreachvar.d14
-rw-r--r--gcc/d/dmd/importc.d4
-rw-r--r--gcc/d/dmd/ob.d22
-rw-r--r--gcc/d/dmd/parse.d11
-rw-r--r--gcc/d/dmd/root/filename.d27
-rw-r--r--gcc/d/dmd/semantic2.d5
-rw-r--r--gcc/d/dmd/semantic3.d2
-rw-r--r--gcc/d/types.cc6
19 files changed, 305 insertions, 212 deletions
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 8676a1b..b82e2d5 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -225,9 +225,9 @@ public:
RootObject *o = (*d->objects)[i];
if (o->dyncast () == DYNCAST_EXPRESSION)
{
- DsymbolExp *de = ((Expression *) o)->isDsymbolExp ();
- if (de != NULL && de->s->isDeclaration ())
- this->build_dsymbol (de->s);
+ VarExp *ve = ((Expression *) o)->isVarExp ();
+ if (ve)
+ this->build_dsymbol (ve->var);
}
}
}
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index d1e3dc1..f5c42f0 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-6203135dcf0112d3211add0cbfb22fecc5df1af4
+529110f66d7d301d62d943a4e4482edaddeb46ea
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/canthrow.d b/gcc/d/dmd/canthrow.d
index a38cbb1..fe6e1e3 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -270,18 +270,7 @@ private CT Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow)
}
else if (auto td = s.isTupleDeclaration())
{
- for (size_t i = 0; i < td.objects.dim; i++)
- {
- RootObject o = (*td.objects)[i];
- if (o.dyncast() == DYNCAST.expression)
- {
- Expression eo = cast(Expression)o;
- if (auto se = eo.isDsymbolExp())
- {
- result |= Dsymbol_canThrow(se.s, func, mustNotThrow);
- }
- }
- }
+ td.foreachVar(&symbolDg);
}
return result;
}
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 62ba889..dff7634 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -2413,11 +2413,19 @@ final class CParser(AST) : Parser!AST
if (scw & scwx)
error("duplicate storage class");
scw |= scwx;
+ // C11 6.7.1-2 At most one storage-class may be given, except that
+ // _Thread_local may appear with static or extern.
const scw2 = scw & (SCW.xstatic | SCW.xextern | SCW.xauto | SCW.xregister | SCW.xtypedef);
if (scw2 & (scw2 - 1) ||
- scw & (SCW.xauto | SCW.xregister) && scw & (SCW.xinline | SCW.x_Noreturn))
+ scw & (SCW.x_Thread_local) && scw & (SCW.xauto | SCW.xregister | SCW.xtypedef))
{
- error("conflicting storage class");
+ error("multiple storage classes in declaration specifiers");
+ scw &= ~scwx;
+ }
+ if (level == LVL.local &&
+ scw & (SCW.x_Thread_local) && scw & (SCW.xinline | SCW.x_Noreturn))
+ {
+ error("`inline` and `_Noreturn` function specifiers not allowed for `_Thread_local`");
scw &= ~scwx;
}
if (level & (LVL.parameter | LVL.prototype) &&
@@ -2964,7 +2972,8 @@ final class CParser(AST) : Parser!AST
cparseGnuAttributes(specifier);
if (specifier.mod & MOD.xconst)
t = toConst(t);
- auto param = new AST.Parameter(STC.parameter, t, id, null, null);
+ auto param = new AST.Parameter(specifiersToSTC(LVL.parameter, specifier),
+ t, id, null, null);
parameters.push(param);
if (token.value == TOK.rightParenthesis)
break;
@@ -4630,6 +4639,15 @@ final class CParser(AST) : Parser!AST
stc = AST.STC.extern_ | AST.STC.gshared;
else if (specifier.scw & SCW.xstatic)
stc = AST.STC.gshared;
+ else if (specifier.scw & SCW.xregister)
+ stc = AST.STC.register;
+ }
+ else if (level == LVL.parameter)
+ {
+ if (specifier.scw & SCW.xregister)
+ stc = AST.STC.register | AST.STC.parameter;
+ else
+ stc = AST.STC.parameter;
}
else if (level == LVL.member)
{
@@ -5138,6 +5156,7 @@ final class CParser(AST) : Parser!AST
if (!defines || defines.length < 10) // minimum length of a #define line
return;
const length = defines.length;
+ defines.writeByte(0);
auto slice = defines.peekChars()[0 .. length];
resetDefineLines(slice); // reset lexer
@@ -5234,12 +5253,15 @@ final class CParser(AST) : Parser!AST
}
skipToNextLine();
}
- else if (n.value != TOK.endOfLine)
+ else
{
- skipToNextLine();
+ scan(&n);
+ if (n.value != TOK.endOfLine)
+ {
+ skipToNextLine();
+ }
}
nextDefineLine();
- assert(p - slice.ptr <= length);
}
}
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index bb0feb6..ffb33d3 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -656,23 +656,46 @@ extern (C++) final class TupleDeclaration : Declaration
override bool needThis()
{
//printf("TupleDeclaration::needThis(%s)\n", toChars());
- for (size_t i = 0; i < objects.dim; i++)
+ return isexp ? foreachVar((s) { return s.needThis(); }) != 0 : false;
+ }
+
+ /***********************************************************
+ * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
+ * inside VarExp (isexp == true).
+ * Params:
+ * dg = delegate to call for each Dsymbol
+ */
+ extern (D) void foreachVar(scope void delegate(Dsymbol) dg)
+ {
+ assert(isexp);
+ foreach (o; *objects)
{
- RootObject o = (*objects)[i];
- if (o.dyncast() == DYNCAST.expression)
- {
- Expression e = cast(Expression)o;
- if (DsymbolExp ve = e.isDsymbolExp())
- {
- Declaration d = ve.s.isDeclaration();
- if (d && d.needThis())
- {
- return true;
- }
- }
- }
+ if (auto e = o.isExpression())
+ if (auto ve = e.isVarExp())
+ dg(ve.var);
}
- return false;
+ }
+
+ /***********************************************************
+ * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration
+ * inside VarExp (isexp == true).
+ * If dg returns !=0, stops and returns that value else returns 0.
+ * Params:
+ * dg = delegate to call for each Dsymbol
+ * Returns:
+ * last value returned by dg()
+ */
+ extern (D) int foreachVar(scope int delegate(Dsymbol) dg)
+ {
+ assert(isexp);
+ foreach (o; *objects)
+ {
+ if (auto e = o.isExpression())
+ if (auto ve = e.isVarExp())
+ if(auto ret = dg(ve.var))
+ return ret;
+ }
+ return 0;
}
override inout(TupleDeclaration) isTupleDeclaration() inout
@@ -1142,15 +1165,7 @@ extern (C++) class VarDeclaration : Declaration
// If this variable was really a tuple, set the offsets for the tuple fields
TupleDeclaration v2 = aliassym.isTupleDeclaration();
assert(v2);
- for (size_t i = 0; i < v2.objects.dim; i++)
- {
- RootObject o = (*v2.objects)[i];
- assert(o.dyncast() == DYNCAST.expression);
- Expression e = cast(Expression)o;
- assert(e.op == EXP.dSymbol);
- DsymbolExp se = e.isDsymbolExp();
- se.s.setFieldOffset(ad, fieldState, isunion);
- }
+ v2.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); });
return;
}
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index bb25210..5841a25 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -2306,16 +2306,12 @@ public:
result = null;
// Reserve stack space for all tuple members
- if (!td.objects)
- return;
- foreach (o; *td.objects)
+ td.foreachVar((s)
{
- Expression ex = isExpression(o);
- DsymbolExp ds = ex ? ex.isDsymbolExp() : null;
- VarDeclaration v2 = ds ? ds.s.isVarDeclaration() : null;
+ VarDeclaration v2 = s.isVarDeclaration();
assert(v2);
if (v2.isDataseg() && !v2.isCTFE())
- continue;
+ return 0;
ctfeGlobals.stack.push(v2);
if (v2._init)
@@ -2325,7 +2321,7 @@ public:
{
einit = interpretRegion(ie.exp, istate, goal);
if (exceptionOrCant(einit))
- return;
+ return 1;
}
else if (v2._init.isVoidInitializer())
{
@@ -2335,11 +2331,12 @@ public:
{
e.error("declaration `%s` is not yet implemented in CTFE", e.toChars());
result = CTFEExp.cantexp;
- return;
+ return 1;
}
setValue(v2, einit);
}
- }
+ return 0;
+ });
return;
}
if (v.isStatic())
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index 7604296..25794e2 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -371,10 +371,20 @@ public:
if (ta.isnogc)
buf.writestring("Ni");
- if (ta.isreturn && !ta.isreturninferred)
- buf.writestring("Nj");
- else if (ta.isScopeQual && !ta.isscopeinferred)
- buf.writestring("Nl");
+ // `return scope` must be in that order
+ if (ta.isreturnscope && !ta.isreturninferred)
+ {
+ buf.writestring("NjNl");
+ }
+ else
+ {
+ // when return ref, the order is `scope return`
+ if (ta.isScopeQual && !ta.isscopeinferred)
+ buf.writestring("Nl");
+
+ if (ta.isreturn && !ta.isreturninferred)
+ buf.writestring("Nj");
+ }
if (ta.islive)
buf.writestring("Nm");
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 7fd4781..11a51f1 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -647,7 +647,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
else
ti = dsym._init ? dsym._init.syntaxCopy() : null;
- StorageClass storage_class = STC.temp | STC.local | dsym.storage_class;
+ StorageClass storage_class = STC.temp | dsym.storage_class;
if ((dsym.storage_class & STC.parameter) && (arg.storageClass & STC.parameter))
storage_class |= arg.storageClass;
auto v = new VarDeclaration(dsym.loc, arg.type, id, ti, storage_class);
@@ -656,15 +656,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
v.dsymbolSemantic(sc);
- if (sc.scopesym)
- {
- //printf("adding %s to %s\n", v.toChars(), sc.scopesym.toChars());
- if (sc.scopesym.members)
- // Note this prevents using foreach() over members, because the limits can change
- sc.scopesym.members.push(v);
- }
-
- Expression e = new DsymbolExp(dsym.loc, v);
+ Expression e = new VarExp(dsym.loc, v);
(*exps)[i] = e;
}
auto v2 = new TupleDeclaration(dsym.loc, dsym.ident, exps);
@@ -728,6 +720,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
else if (!dsym.type.hasPointers())
{
dsym.storage_class &= ~STC.scope_; // silently ignore; may occur in generic code
+ // https://issues.dlang.org/show_bug.cgi?id=23168
+ if (dsym.storage_class & STC.returnScope)
+ {
+ dsym.storage_class &= ~(STC.return_ | STC.returnScope);
+ }
}
}
@@ -3208,10 +3205,19 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
sc.stc |= STC.scope_;
// If 'this' has no pointers, remove 'scope' as it has no meaning
+ // Note: this is already covered by semantic of `VarDeclaration` and `TypeFunction`,
+ // but existing code relies on `hasPointers()` being called here to resolve forward references:
+ // https://github.com/dlang/dmd/pull/14232#issuecomment-1162906573
if (sc.stc & STC.scope_ && ad && ad.isStructDeclaration() && !ad.type.hasPointers())
{
sc.stc &= ~STC.scope_;
tf.isScopeQual = false;
+ if (tf.isreturnscope)
+ {
+ sc.stc &= ~(STC.return_ | STC.returnScope);
+ tf.isreturn = false;
+ tf.isreturnscope = false;
+ }
}
sc.linkage = funcdecl._linkage;
@@ -6840,7 +6846,12 @@ bool determineFields(AggregateDeclaration ad)
return 1;
if (v.aliassym)
- return 0; // If this variable was really a tuple, skip it.
+ {
+ // If this variable was really a tuple, process each element.
+ if (auto tup = v.aliassym.isTupleDeclaration())
+ return tup.foreachVar(tv => tv.apply(&func, ad));
+ return 0;
+ }
if (v.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.ctfe | STC.templateparameter))
return 0;
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 9afcc7f..c570068 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -873,7 +873,11 @@ public:
// Tuple field are expanded into multiple VarDeclarations
// (we'll visit them later)
if (vd.type && vd.type.isTypeTuple())
+ {
+ assert(vd.aliassym);
+ vd.toAlias().accept(this);
return;
+ }
if (vd.originalType && vd.type == AST.Type.tsize_t)
origType = vd.originalType;
@@ -1263,41 +1267,38 @@ public:
size_t varCount;
bool first = true;
buf.level++;
- foreach (m; *sd.members)
+ foreach (vd; sd.fields)
{
- if (auto vd = m.isVarDeclaration())
- {
- if (!memberField(vd))
- continue;
- varCount++;
+ if (!memberField(vd) || vd.overlapped)
+ continue;
+ varCount++;
- if (!vd._init && !vd.type.isTypeBasic() && !vd.type.isTypePointer && !vd.type.isTypeStruct &&
- !vd.type.isTypeClass && !vd.type.isTypeDArray && !vd.type.isTypeSArray)
- {
- continue;
- }
- if (vd._init && vd._init.isVoidInitializer())
- continue;
+ if (!vd._init && !vd.type.isTypeBasic() && !vd.type.isTypePointer && !vd.type.isTypeStruct &&
+ !vd.type.isTypeClass && !vd.type.isTypeDArray && !vd.type.isTypeSArray)
+ {
+ continue;
+ }
+ if (vd._init && vd._init.isVoidInitializer())
+ continue;
- if (first)
- {
- buf.writestringln(" :");
- first = false;
- }
- else
- {
- buf.writestringln(",");
- }
- writeIdentifier(vd, true);
- buf.writeByte('(');
+ if (first)
+ {
+ buf.writestringln(" :");
+ first = false;
+ }
+ else
+ {
+ buf.writestringln(",");
+ }
+ writeIdentifier(vd, true);
+ buf.writeByte('(');
- if (vd._init)
- {
- auto e = AST.initializerToExpression(vd._init);
- printExpressionFor(vd.type, e, true);
- }
- buf.printf(")");
+ if (vd._init)
+ {
+ auto e = AST.initializerToExpression(vd._init);
+ printExpressionFor(vd.type, e, true);
}
+ buf.printf(")");
}
buf.level--;
buf.writenl();
@@ -1308,49 +1309,43 @@ public:
{
buf.printf("%s(", sd.ident.toChars());
first = true;
- foreach (m; *sd.members)
+ foreach (vd; sd.fields)
{
- if (auto vd = m.isVarDeclaration())
+ if (!memberField(vd) || vd.overlapped)
+ continue;
+ if (!first)
+ buf.writestring(", ");
+ assert(vd.type);
+ assert(vd.ident);
+ typeToBuffer(vd.type, vd, true);
+ // Don't print default value for first parameter to not clash
+ // with the default ctor defined above
+ if (!first)
{
- if (!memberField(vd))
- continue;
- if (!first)
- buf.writestring(", ");
- assert(vd.type);
- assert(vd.ident);
- typeToBuffer(vd.type, vd, true);
- // Don't print default value for first parameter to not clash
- // with the default ctor defined above
- if (!first)
- {
- buf.writestring(" = ");
- printExpressionFor(vd.type, findDefaultInitializer(vd));
- }
- first = false;
+ buf.writestring(" = ");
+ printExpressionFor(vd.type, findDefaultInitializer(vd));
}
+ first = false;
}
buf.writestring(") :");
buf.level++;
buf.writenl();
first = true;
- foreach (m; *sd.members)
+ foreach (vd; sd.fields)
{
- if (auto vd = m.isVarDeclaration())
- {
- if (!memberField(vd))
- continue;
-
- if (first)
- first = false;
- else
- buf.writestringln(",");
-
- writeIdentifier(vd, true);
- buf.writeByte('(');
- writeIdentifier(vd, true);
- buf.writeByte(')');
- }
+ if (!memberField(vd) || vd.overlapped)
+ continue;
+
+ if (first)
+ first = false;
+ else
+ buf.writestringln(",");
+
+ writeIdentifier(vd, true);
+ buf.writeByte('(');
+ writeIdentifier(vd, true);
+ buf.writeByte(')');
}
buf.writenl();
buf.writestringln("{}");
@@ -1663,6 +1658,13 @@ public:
assert(false, "This node type should be handled in the EnumDeclaration");
}
+ override void visit(AST.TupleDeclaration tup)
+ {
+ debug (Debug_DtoH) mixin(traceVisit!tup);
+
+ tup.foreachVar((s) { s.accept(this); });
+ }
+
/**
* Prints a member/parameter/variable declaration into `buf`.
*
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index ceecf4b..397a41b 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -348,14 +348,16 @@ int expandAliasThisTuples(Expressions* exps, size_t starti = 0)
if (TupleDeclaration td = exp.isAliasThisTuple)
{
exps.remove(u);
- foreach (i, o; *td.objects)
+ size_t i;
+ td.foreachVar((s)
{
- auto d = o.isExpression().isDsymbolExp().s.isDeclaration();
+ auto d = s.isDeclaration();
auto e = new DotVarExp(exp.loc, exp, d);
assert(d.type);
e.type = d.type;
exps.insert(u + i, e);
- }
+ ++i;
+ });
version (none)
{
printf("expansion ->\n");
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index dcc5b50..99e003b 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -6004,10 +6004,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
se = se.toUTF8(sc);
- auto namez = se.toStringz().ptr;
+ auto namez = se.toStringz();
if (!global.filePath)
{
- e.error("need `-J` switch to import text file `%s`", namez);
+ e.error("need `-J` switch to import text file `%s`", namez.ptr);
return setError();
}
@@ -6036,8 +6036,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
- auto name = FileName.searchPath(global.filePath, namez, false);
- if (!name)
+ auto resolvedNamez = FileName.searchPath(global.filePath, namez, false);
+ if (!resolvedNamez)
{
e.error("file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
e.errorSupplemental("Path(s) searched (as provided by `-J`):");
@@ -6051,11 +6051,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
- sc._module.contentImportedFiles.push(name);
+ sc._module.contentImportedFiles.push(resolvedNamez.ptr);
if (global.params.verbose)
{
const slice = se.peekString();
- message("file %.*s\t(%s)", cast(int)slice.length, slice.ptr, name);
+ message("file %.*s\t(%s)", cast(int)slice.length, slice.ptr, resolvedNamez.ptr);
}
if (global.params.moduleDeps.buffer !is null)
{
@@ -6072,27 +6072,27 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
ob.writestring("string : ");
ob.write(se.peekString());
ob.writestring(" (");
- escapePath(ob, name);
+ escapePath(ob, resolvedNamez.ptr);
ob.writestring(")");
ob.writenl();
}
if (global.params.makeDeps.doOutput)
{
- global.params.makeDeps.files.push(name);
+ global.params.makeDeps.files.push(resolvedNamez.ptr);
}
{
- auto fileName = FileName(name.toDString);
+ auto fileName = FileName(resolvedNamez);
if (auto fmResult = global.fileManager.lookup(fileName))
{
se = new StringExp(e.loc, fmResult);
}
else
{
- auto readResult = File.read(name.toDString);
+ auto readResult = File.read(resolvedNamez);
if (!readResult.success)
{
- e.error("cannot read file `%s`", name);
+ e.error("cannot read file `%s`", resolvedNamez.ptr);
return setError();
}
else
@@ -6963,18 +6963,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.error("cannot take address of `%s`", exp.e1.toChars());
return setError();
}
- if (auto dve = exp.e1.isDotVarExp())
- {
- /* https://issues.dlang.org/show_bug.cgi?id=22749
- * Error about taking address of any bit-field, regardless of
- * whether SCOPE.Cfile is set.
- */
- if (auto bf = dve.var.isBitFieldDeclaration())
- {
- exp.error("cannot take address of bit-field `%s`", bf.toChars());
- return setError();
- }
- }
+ if (!checkAddressable(exp, sc))
+ return setError();
bool hasOverloads;
if (auto f = isFuncAddress(exp, &hasOverloads))
@@ -8323,6 +8313,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
t1b = t1b.castMod(tv1.mod);
exp.e1.type = t1b;
}
+ if (t1b.ty == Tsarray || t1b.ty == Tarray)
+ {
+ if (!checkAddressable(exp, sc))
+ return setError();
+ }
/* Run semantic on e2
*/
@@ -13152,6 +13147,69 @@ bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
return true;
}
+/**************************************
+ * This check ensures that the object in `exp` can have its address taken, or
+ * issue a diagnostic error.
+ * Params:
+ * e = expression to check
+ * sc = context
+ * Returns:
+ * true if the expression is addressable
+ */
+bool checkAddressable(Expression e, Scope* sc)
+{
+ Expression ex = e;
+ while (true)
+ {
+ switch (ex.op)
+ {
+ case EXP.dotVariable:
+ // https://issues.dlang.org/show_bug.cgi?id=22749
+ // Error about taking address of any bit-field, regardless of
+ // whether SCOPE.Cfile is set.
+ if (auto bf = ex.isDotVarExp().var.isBitFieldDeclaration())
+ {
+ e.error("cannot take address of bit-field `%s`", bf.toChars());
+ return false;
+ }
+ goto case EXP.cast_;
+
+ case EXP.index:
+ ex = ex.isBinExp().e1;
+ continue;
+
+ case EXP.address:
+ case EXP.array:
+ case EXP.cast_:
+ ex = ex.isUnaExp().e1;
+ continue;
+
+ case EXP.variable:
+ if (sc.flags & SCOPE.Cfile)
+ {
+ // C11 6.5.3.2: A variable that has its address taken cannot be
+ // stored in a register.
+ // C11 6.3.2.1: An array that has its address computed with `[]`
+ // or cast to an lvalue pointer cannot be stored in a register.
+ if (ex.isVarExp().var.storage_class & STC.register)
+ {
+ if (e.isIndexExp())
+ e.error("cannot index through register variable `%s`", ex.toChars());
+ else
+ e.error("cannot take address of register variable `%s`", ex.toChars());
+ return false;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+ return true;
+}
+
/*******************************
* Checks the attributes of a function.
diff --git a/gcc/d/dmd/foreachvar.d b/gcc/d/dmd/foreachvar.d
index 53ed62e..63281b5 100644
--- a/gcc/d/dmd/foreachvar.d
+++ b/gcc/d/dmd/foreachvar.d
@@ -75,19 +75,7 @@ void foreachVar(Expression e, void delegate(VarDeclaration) dgVar)
if (!v)
return;
if (TupleDeclaration td = v.toAlias().isTupleDeclaration())
- {
- if (!td.objects)
- return;
- foreach (o; *td.objects)
- {
- Expression ex = isExpression(o);
- DsymbolExp s = ex ? ex.isDsymbolExp() : null;
- assert(s);
- VarDeclaration v2 = s.s.isVarDeclaration();
- assert(v2);
- dgVar(v2);
- }
- }
+ td.foreachVar((s) { dgVar(s.isVarDeclaration()); });
else
dgVar(v);
Dsymbol s = v.toAlias();
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index bcfbd9a..afec5ef 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/dmd/importc.d
@@ -81,10 +81,14 @@ Expression arrayFuncConv(Expression e, Scope* sc)
auto t = e.type.toBasetype();
if (auto ta = t.isTypeDArray())
{
+ if (!checkAddressable(e, sc))
+ return ErrorExp.get();
e = e.castTo(sc, ta.next.pointerTo());
}
else if (auto ts = t.isTypeSArray())
{
+ if (!checkAddressable(e, sc))
+ return ErrorExp.get();
e = e.castTo(sc, ts.next.pointerTo());
}
else if (t.isTypeFunction())
diff --git a/gcc/d/dmd/ob.d b/gcc/d/dmd/ob.d
index 121a266..5ff73c9 100644
--- a/gcc/d/dmd/ob.d
+++ b/gcc/d/dmd/ob.d
@@ -1407,16 +1407,7 @@ void genKill(ref ObState obstate, ObNode* ob)
}
else if (auto td = s.isTupleDeclaration())
{
- foreach (o; *td.objects)
- {
- if (auto eo = o.isExpression())
- {
- if (auto se = eo.isDsymbolExp())
- {
- Dsymbol_visit(se.s);
- }
- }
- }
+ td.foreachVar(&Dsymbol_visit);
}
}
@@ -2107,16 +2098,7 @@ void checkObErrors(ref ObState obstate)
}
else if (auto td = s.isTupleDeclaration())
{
- foreach (o; *td.objects)
- {
- if (auto eo = o.isExpression())
- {
- if (auto se = eo.isDsymbolExp())
- {
- Dsymbol_visit(se.s);
- }
- }
- }
+ td.foreachVar(&Dsymbol_visit);
}
}
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index eb5e694..4e3fd53 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -5877,7 +5877,8 @@ LagainStc:
{
if (isDeclaration(&token, NeedDeclaratorId.mustIfDstyle, TOK.reserved, null))
goto Ldeclaration;
- if (peekNext() == TOK.leftParenthesis)
+ const tv = peekNext();
+ if (tv == TOK.leftParenthesis)
{
// mixin(string)
AST.Expression e = parseAssignExp();
@@ -5893,6 +5894,14 @@ LagainStc:
}
break;
}
+ else if (tv == TOK.template_)
+ {
+ // mixin template
+ nextToken();
+ AST.Dsymbol d = parseTemplateDeclaration(true);
+ s = new AST.ExpStatement(loc, d);
+ break;
+ }
AST.Dsymbol d = parseMixin();
s = new AST.ExpStatement(loc, d);
if (flags & ParseStatementFlags.scope_)
diff --git a/gcc/d/dmd/root/filename.d b/gcc/d/dmd/root/filename.d
index 3b7b75b0..226141d 100644
--- a/gcc/d/dmd/root/filename.d
+++ b/gcc/d/dmd/root/filename.d
@@ -734,16 +734,15 @@ nothrow:
* Returns:
* index of the first reserved character in path if found, size_t.max otherwise
*/
- extern (D) static size_t findReservedChar(const(char)* name) pure @nogc
+ extern (D) static size_t findReservedChar(const(char)[] name) pure @nogc @safe
{
version (Windows)
{
- size_t idx = 0;
// According to https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions
// the following characters are not allowed in path: < > : " | ? *
- for (const(char)* p = name; *p; p++, idx++)
+ foreach (idx; 0 .. name.length)
{
- char c = *p;
+ char c = name[idx];
if (c == '<' || c == '>' || c == ':' || c == '"' || c == '|' || c == '?' || c == '*')
{
return idx;
@@ -784,21 +783,21 @@ nothrow:
* Returns:
* true if path contains '..' reference to parent directory
*/
- extern (D) static bool refersToParentDir(const(char)* name) pure @nogc
+ extern (D) static bool refersToParentDir(const(char)[] name) pure @nogc @safe
{
- if (name[0] == '.' && name[1] == '.' && (!name[2] || isDirSeparator(name[2])))
+ size_t s = 0;
+ foreach (i; 0 .. name.length)
{
- return true;
- }
-
- for (const(char)* p = name; *p; p++)
- {
- char c = *p;
- if (isDirSeparator(c) && p[1] == '.' && p[2] == '.' && (!p[3] || isDirSeparator(p[3])))
+ if (isDirSeparator(name[i]))
{
- return true;
+ if (name[s..i] == "..")
+ return true;
+ s = i + 1;
}
}
+ if (name[s..$] == "..")
+ return true;
+
return false;
}
unittest
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index 73dcaa6..bf18a21 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -677,6 +677,11 @@ private extern(C++) final class Semantic2Visitor : Visitor
{
visit(cast(AggregateDeclaration) cd);
}
+
+ override void visit(TupleDeclaration td)
+ {
+ td.foreachVar((s) { s.accept(this); });
+ }
}
/**
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index a056c99..c5d7667 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -483,7 +483,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
if ((funcdecl.flags & FUNCFLAG.inferScope) && !(fparam.storageClass & STC.scope_))
stc |= STC.maybescope;
- stc |= fparam.storageClass & (STC.IOR | STC.return_ | STC.scope_ | STC.lazy_ | STC.final_ | STC.TYPECTOR | STC.nodtor | STC.returnScope);
+ stc |= fparam.storageClass & (STC.IOR | STC.return_ | STC.scope_ | STC.lazy_ | STC.final_ | STC.TYPECTOR | STC.nodtor | STC.returnScope | STC.register);
v.storage_class = stc;
v.dsymbolSemantic(sc2);
if (!sc2.insert(v))
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index b706c91..38cc7f5 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -392,10 +392,10 @@ layout_aggregate_members (Dsymbols *members, tree context, bool inherited_p)
RootObject *ro = (*td->objects)[j];
gcc_assert (ro->dyncast () == DYNCAST_EXPRESSION);
Expression *e = (Expression *) ro;
- gcc_assert (e->op == EXP::dSymbol);
- DsymbolExp *se = e->isDsymbolExp ();
+ gcc_assert (e->op == EXP::variable);
+ VarExp *ve = e->isVarExp ();
- tmembers.push (se->s);
+ tmembers.push (ve->var);
}
fields += layout_aggregate_members (&tmembers, context,