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:
Iain Buclaw 2022-06-24 19:41:41 +02:00
parent c0ad48527c
commit d97f3bca6e
29 changed files with 464 additions and 226 deletions

View File

@ -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);
}
}
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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())

View File

@ -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");

View File

@ -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;

View File

@ -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`.
*

View File

@ -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");

View File

@ -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.

View File

@ -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();

View File

@ -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())

View File

@ -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);
}
}

View File

@ -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_)

View File

@ -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

View File

@ -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); });
}
}
/**

View File

@ -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))

View File

@ -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,

View File

@ -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();

View File

@ -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)
{}
};

View File

@ -219,9 +219,13 @@ struct ImportedBuffer final
{
typedef ActualBuffer Buffer;
ActualBuffer buffer2;
ImportedBuffer()
ImportedBuffer() :
buffer2()
{
}
ImportedBuffer(ActualBuffer buffer2) :
buffer2(buffer2)
{}
};
---
*/

View File

@ -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);

View File

@ -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)
{}
};
---
*/

View 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;}
}

View 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");

View File

@ -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;
}

View 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;
}

View File

@ -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.