From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mout-p-202.mailbox.org (mout-p-202.mailbox.org [IPv6:2001:67c:2050:0:465::202]) by sourceware.org (Postfix) with ESMTPS id 6E8E3385C414 for ; Tue, 15 Aug 2023 15:18:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6E8E3385C414 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=gdcproject.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gdcproject.org Received: from smtp1.mailbox.org (smtp1.mailbox.org [10.196.197.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-202.mailbox.org (Postfix) with ESMTPS id 4RQFJZ5V5vz9sm6; Tue, 15 Aug 2023 17:18:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gdcproject.org; s=MBO0001; t=1692112686; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=E9ufyuvmaWQiupcp9w6e00ed9YpyewiN0MCNuTgO9ec=; b=NzNDp6jQLxy1SV9Q6M7weQnE1O06uu5DbduWNbgb2UA0zJXXX9WMnj7B7hJj1QdlwmRk64 9T75fIbcnBFW9ZECKjKaW4GratGf9kpsCf4k0fx3RnWd9wRcXxA2IaRkmLGvS9ntV8FeAv lDk74zC4JD6MZLw3KQYLuih10rGv4qpcax0w2zazdU+FxSE1pANVEeqkNuw5lZQ8S2JoNS k149cAOx7wA4v5tXYVwVFeqU5D8Jc81ZNWGUvYwKSA6FlRsTdQm9Y4UgrCZHejl1nj9b3X 7zhKA7aSHQwLcqKKGvP973QEs5JlJ+hp5g57rFDIqnQ5W0ruxeHSSk6dr+IkNw== From: Iain Buclaw To: gcc-patches@gcc.gnu.org Cc: Iain Buclaw Subject: [committed][GCC 12] d: Fix internal compiler error: in layout_aggregate_type, at d/types.cc:574 Date: Tue, 15 Aug 2023 17:18:04 +0200 Message-Id: <20230815151804.3588843-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_NUMSUBJECT,KAM_SHORT,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS,TXREP,WEIRD_PORT autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Hi, This patch fixes an ICE that is specific to the D front-end language version in GDC 12. Bootstrapped and regression tested on x86_64-linux-gnu/-m32, committed to releases/gcc-12. The pr110959.d test case has also been committed to mainline to catch the unlikely event of a regression. Regards, Iain. --- PR d/110959 gcc/d/ChangeLog: * dmd/canthrow.d (Dsymbol_canThrow): Use foreachVar. * dmd/declaration.d (TupleDeclaration::needThis): Likewise. (TupleDeclaration::foreachVar): New function. (VarDeclaration::setFieldOffset): Use foreachVar. * dmd/dinterpret.d (Interpreter::visit (DeclarationExp)): Likewise. * dmd/dsymbolsem.d (DsymbolSemanticVisitor::visit (VarDeclaration)): Don't push tuple field members to the scope symbol table. (determineFields): Handle pushing tuple field members here instead. * dmd/dtoh.d (ToCppBuffer::visit (VarDeclaration)): Visit all tuple fields. (ToCppBuffer::visit (TupleDeclaration)): New function. * dmd/expression.d (expandAliasThisTuples): Use foreachVar. * dmd/foreachvar.d (VarWalker::visit (DeclarationExp)): Likewise. * dmd/ob.d (genKill): Likewise. (checkObErrors): Likewise. * dmd/semantic2.d (Semantic2Visitor::visit (TupleDeclaration)): Visit all tuple fields. gcc/testsuite/ChangeLog: * gdc.dg/pr110959.d: New test. * gdc.test/runnable/test23010.d: New test. --- gcc/d/dmd/canthrow.d | 13 +---- gcc/d/dmd/declaration.d | 63 +++++++++++++-------- gcc/d/dmd/dinterpret.d | 17 +++--- gcc/d/dmd/dsymbolsem.d | 17 +++--- gcc/d/dmd/dtoh.d | 11 ++++ gcc/d/dmd/expression.d | 8 ++- gcc/d/dmd/foreachvar.d | 14 +---- gcc/d/dmd/ob.d | 22 +------ gcc/d/dmd/semantic2.d | 5 ++ gcc/testsuite/gdc.dg/pr110959.d | 32 +++++++++++ gcc/testsuite/gdc.test/runnable/test23010.d | 43 ++++++++++++++ 11 files changed, 153 insertions(+), 92 deletions(-) create mode 100644 gcc/testsuite/gdc.dg/pr110959.d create mode 100644 gcc/testsuite/gdc.test/runnable/test23010.d diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d index a38cbb1610b..fe6e1e344b9 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/declaration.d b/gcc/d/dmd/declaration.d index 7b50c050487..6c83c196f72 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 DsymbolExp (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 se = e.isDsymbolExp()) + dg(se.s); } - return false; + } + + /*********************************************************** + * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration + * inside DsymbolExp (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 se = e.isDsymbolExp()) + if(auto ret = dg(se.s)) + 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 e96f1806982..485b2dec1a1 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -2291,16 +2291,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) @@ -2310,7 +2306,7 @@ public: { einit = interpretRegion(ie.exp, istate, goal); if (exceptionOrCant(einit)) - return; + return 1; } else if (v2._init.isVoidInitializer()) { @@ -2320,11 +2316,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/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index c5766787bf0..dfaaff93d35 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -650,7 +650,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); @@ -659,14 +659,6 @@ 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); (*exps)[i] = e; } @@ -6819,7 +6811,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 17abb7d3b00..ecc637eff53 100644 --- a/gcc/d/dmd/dtoh.d +++ b/gcc/d/dmd/dtoh.d @@ -877,7 +877,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; @@ -1667,6 +1671,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 107e85b0793..832ab7dda37 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/foreachvar.d b/gcc/d/dmd/foreachvar.d index 53ed62efd70..63281b5760c 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/ob.d b/gcc/d/dmd/ob.d index 121a266b428..5ff73c983f0 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/semantic2.d b/gcc/d/dmd/semantic2.d index 73dcaa6c960..bf18a2140fb 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/testsuite/gdc.dg/pr110959.d b/gcc/testsuite/gdc.dg/pr110959.d new file mode 100644 index 00000000000..b1da90fad83 --- /dev/null +++ b/gcc/testsuite/gdc.dg/pr110959.d @@ -0,0 +1,32 @@ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110959 +// { dg-do compile } +class ArsdExceptionBase : object.Exception { + this(string operation, string file = __FILE__, size_t line = __LINE__, Throwable next = null) { + super(operation, file, line, next); + } +} + +template ArsdException(alias Type, DataTuple...) { + static if(DataTuple.length) + alias Parent = ArsdException!(Type, DataTuple[0 .. $-1]); + else + alias Parent = ArsdExceptionBase; + + class ArsdException : Parent { + DataTuple data; + + this(DataTuple data, string file = __FILE__, size_t line = __LINE__) { + this.data = data; + static if(is(Parent == ArsdExceptionBase)) + super(null, file, line); + else + super(data[0 .. $-1], file, line); + } + + static opCall(R...)(R r, string file = __FILE__, size_t line = __LINE__) { + return new ArsdException!(Type, DataTuple, R)(r, file, line); + } + } +} + +__gshared pr110959 = ArsdException!"Test"(4, "four"); diff --git a/gcc/testsuite/gdc.test/runnable/test23010.d b/gcc/testsuite/gdc.test/runnable/test23010.d new file mode 100644 index 00000000000..1cbacfc9279 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/test23010.d @@ -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; +} -- 2.39.2