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.
This commit is contained in:
parent
c0ad48527c
commit
d97f3bca6e
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
128
gcc/d/dmd/dtoh.d
128
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) || 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)
|
||||
{
|
||||
if (!memberField(vd))
|
||||
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 (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(")");
|
||||
continue;
|
||||
}
|
||||
if (vd._init && vd._init.isVoidInitializer())
|
||||
continue;
|
||||
|
||||
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(")");
|
||||
}
|
||||
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 (!memberField(vd) || vd.overlapped)
|
||||
continue;
|
||||
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
buf.writestringln(",");
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
buf.writestringln(",");
|
||||
|
||||
writeIdentifier(vd, true);
|
||||
buf.writeByte('(');
|
||||
writeIdentifier(vd, true);
|
||||
buf.writeByte(')');
|
||||
}
|
||||
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`.
|
||||
*
|
||||
|
@ -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");
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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())
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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_)
|
||||
|
@ -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
|
||||
|
@ -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); });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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))
|
||||
|
@ -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,
|
||||
|
@ -61,9 +61,21 @@ struct S final
|
||||
int32_t innerPrivate;
|
||||
int32_t innerBar;
|
||||
};
|
||||
S()
|
||||
S() :
|
||||
y(),
|
||||
z(),
|
||||
outerPrivate(),
|
||||
innerPrivate(),
|
||||
innerBar()
|
||||
{
|
||||
}
|
||||
S(int32_t y, double z = NAN, int32_t outerPrivate = 0, int32_t innerPrivate = 0, int32_t innerBar = 0) :
|
||||
y(y),
|
||||
z(z),
|
||||
outerPrivate(outerPrivate),
|
||||
innerPrivate(innerPrivate),
|
||||
innerBar(innerBar)
|
||||
{}
|
||||
};
|
||||
|
||||
extern void foo();
|
||||
|
@ -173,12 +173,16 @@ struct A final
|
||||
|
||||
A() :
|
||||
a(),
|
||||
s()
|
||||
s(),
|
||||
x(),
|
||||
y()
|
||||
{
|
||||
}
|
||||
A(int32_t a, S s = S()) :
|
||||
A(int32_t a, S s = S(), int32_t x = 0, int32_t y = 0) :
|
||||
a(a),
|
||||
s(s)
|
||||
s(s),
|
||||
x(x),
|
||||
y(y)
|
||||
{}
|
||||
};
|
||||
|
||||
@ -196,11 +200,13 @@ private:
|
||||
char smallarray[1$?:32=u|64=LLU$];
|
||||
public:
|
||||
Array() :
|
||||
length()
|
||||
length(),
|
||||
data()
|
||||
{
|
||||
}
|
||||
Array(uint32_t length) :
|
||||
length(length)
|
||||
Array(uint32_t length, _d_dynamicArray< char > data = {}) :
|
||||
length(length),
|
||||
data(data)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -219,9 +219,13 @@ struct ImportedBuffer final
|
||||
{
|
||||
typedef ActualBuffer Buffer;
|
||||
ActualBuffer buffer2;
|
||||
ImportedBuffer()
|
||||
ImportedBuffer() :
|
||||
buffer2()
|
||||
{
|
||||
}
|
||||
ImportedBuffer(ActualBuffer buffer2) :
|
||||
buffer2(buffer2)
|
||||
{}
|
||||
};
|
||||
---
|
||||
*/
|
||||
|
@ -64,9 +64,15 @@ struct HasMangleMember final
|
||||
int32_t someAttrC;
|
||||
int32_t someAttrCpp;
|
||||
void hasDefaultVar(int32_t i = someAttrC);
|
||||
HasMangleMember()
|
||||
HasMangleMember() :
|
||||
someAttrC(),
|
||||
someAttrCpp()
|
||||
{
|
||||
}
|
||||
HasMangleMember(int32_t someAttrC, int32_t someAttrCpp = 0) :
|
||||
someAttrC(someAttrC),
|
||||
someAttrCpp(someAttrCpp)
|
||||
{}
|
||||
};
|
||||
|
||||
extern "C" void hasDefaultVar(int32_t i = someVarC);
|
||||
|
@ -50,9 +50,21 @@ protected:
|
||||
private:
|
||||
int32_t e;
|
||||
public:
|
||||
S1()
|
||||
S1() :
|
||||
a(),
|
||||
b(),
|
||||
c(),
|
||||
d(),
|
||||
e()
|
||||
{
|
||||
}
|
||||
S1(int32_t a, int32_t b = 0, int32_t c = 0, int32_t d = 0, int32_t e = 0) :
|
||||
a(a),
|
||||
b(b),
|
||||
c(c),
|
||||
d(d),
|
||||
e(e)
|
||||
{}
|
||||
};
|
||||
|
||||
class S2 final
|
||||
@ -102,10 +114,12 @@ public:
|
||||
public:
|
||||
int32_t publicInner;
|
||||
PublicInnerStruct() :
|
||||
privateInner(),
|
||||
publicInner()
|
||||
{
|
||||
}
|
||||
PublicInnerStruct(int32_t publicInner) :
|
||||
PublicInnerStruct(int32_t privateInner, int32_t publicInner = 0) :
|
||||
privateInner(privateInner),
|
||||
publicInner(publicInner)
|
||||
{}
|
||||
};
|
||||
@ -118,10 +132,12 @@ private:
|
||||
public:
|
||||
int32_t publicInner;
|
||||
PrivateInnerClass() :
|
||||
privateInner(),
|
||||
publicInner()
|
||||
{
|
||||
}
|
||||
PrivateInnerClass(int32_t publicInner) :
|
||||
PrivateInnerClass(int32_t privateInner, int32_t publicInner = 0) :
|
||||
privateInner(privateInner),
|
||||
publicInner(publicInner)
|
||||
{}
|
||||
};
|
||||
@ -142,9 +158,13 @@ private:
|
||||
|
||||
public:
|
||||
typedef PrivateInnerEnum PublicAlias;
|
||||
Outer()
|
||||
Outer() :
|
||||
privateOuter()
|
||||
{
|
||||
}
|
||||
Outer(int32_t privateOuter) :
|
||||
privateOuter(privateOuter)
|
||||
{}
|
||||
};
|
||||
---
|
||||
*/
|
||||
|
30
gcc/testsuite/gdc.test/compilable/test23168.d
Normal file
30
gcc/testsuite/gdc.test/compilable/test23168.d
Normal file
@ -0,0 +1,30 @@
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23168
|
||||
// Issue 23168 - [DIP1000] return scope wrongly rewritten for structs with no indirections
|
||||
|
||||
@safe:
|
||||
struct Ptr
|
||||
{
|
||||
int* fun() return scope { return null; }
|
||||
}
|
||||
|
||||
int* funf(ref return scope Ptr p) { return null; }
|
||||
|
||||
int* use()
|
||||
{
|
||||
Ptr ptr;
|
||||
return ptr.fun;
|
||||
return funf(ptr);
|
||||
}
|
||||
|
||||
// Prevent forward reference 'regression'
|
||||
// See https://github.com/dlang/dmd/pull/14232#issuecomment-1162906573
|
||||
struct S
|
||||
{
|
||||
void f() scope {}
|
||||
alias x = _get_value;
|
||||
|
||||
static if (true)
|
||||
int _get_value() {return 3;}
|
||||
else
|
||||
int _get_value() {return 4;}
|
||||
}
|
14
gcc/testsuite/gdc.test/compilable/test23169.d
Normal file
14
gcc/testsuite/gdc.test/compilable/test23169.d
Normal file
@ -0,0 +1,14 @@
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23169
|
||||
// Issue 23169 - [DIP1000] Mangling does not distinguish return and return scope
|
||||
|
||||
struct Ptr
|
||||
{
|
||||
int* impl;
|
||||
void* fun0() return scope {return impl;}
|
||||
void* fun1() scope return {return impl;}
|
||||
void* fun2() return {return &this;}
|
||||
}
|
||||
|
||||
static assert(Ptr.fun0.mangleof == "_D9test231693Ptr4fun0MFNjNlZPv");
|
||||
static assert(Ptr.fun1.mangleof == "_D9test231693Ptr4fun1MFNlNjZPv");
|
||||
static assert(Ptr.fun2.mangleof == "_D9test231693Ptr4fun2MFNjZPv");
|
@ -191,3 +191,13 @@ void test22019()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23205
|
||||
|
||||
void test23205()
|
||||
{
|
||||
mixin template tpl() { int x; }
|
||||
mixin tpl!();
|
||||
x = 123;
|
||||
}
|
||||
|
43
gcc/testsuite/gdc.test/runnable/test23010.d
Normal file
43
gcc/testsuite/gdc.test/runnable/test23010.d
Normal file
@ -0,0 +1,43 @@
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23010
|
||||
|
||||
alias AliasSeq(T...) = T;
|
||||
|
||||
mixin template faz() {
|
||||
alias T = AliasSeq!(int);
|
||||
T bar = 12345;
|
||||
|
||||
void write1() {
|
||||
assert(bar[0] == 12345);
|
||||
}
|
||||
|
||||
AliasSeq!(string, float) foo = AliasSeq!("qwerty", 1.25f);
|
||||
|
||||
void write2() {
|
||||
assert(foo == AliasSeq!("qwerty", 1.25f));
|
||||
foo = AliasSeq!("asdfg", 2.5f); // this even crashed before
|
||||
assert(foo == AliasSeq!("asdfg", 2.5f));
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
mixin faz!();
|
||||
write1;
|
||||
write2;
|
||||
fun;
|
||||
}
|
||||
|
||||
// Testing static symbol generation ('toobj.d' changes)
|
||||
|
||||
static AliasSeq!(int, string) tup;
|
||||
|
||||
void fun()
|
||||
{
|
||||
auto v = tup;
|
||||
|
||||
struct S(T...) {
|
||||
static T b;
|
||||
}
|
||||
|
||||
alias T = S!(int, float);
|
||||
auto p = T.b;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
e150cca179515ce5113e828aac94c20c0b983b7c
|
||||
148608b7935c3f9a4ea3a26f74cb90cd07efc91c
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/druntime repository.
|
||||
|
Loading…
Reference in New Issue
Block a user