From patchwork Tue Oct 27 10:51:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1388419 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=LkKJrawD; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CL7n60HGjz9sSs for ; Tue, 27 Oct 2020 21:51:54 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D68C63894C2E; Tue, 27 Oct 2020 10:51:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D68C63894C2E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1603795911; bh=8V05Dgc0dCHQU8a60g0iijNXFX+itgiwTLNA65MQaso=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=LkKJrawDo0Qx3qunX90qKPzHZ/27hndXaTGqL4Q39YuM/7sPQ9pFdONny1YP09RsG 9UROKRwvroE9EKrupSWUY0Dif86SSddDbcMYgnSHR8iUEoWMGpAGF1xIaMNuZW4MQg I5+qZkwBgBZhTgWB6QptG4Mc2hiFTnS2D8KrxszE= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [IPv6:2001:67c:2050::465:101]) by sourceware.org (Postfix) with ESMTPS id 66FF53861823 for ; Tue, 27 Oct 2020 10:51:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 66FF53861823 Received: from smtp2.mailbox.org (smtp2.mailbox.org [80.241.60.241]) (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-101.mailbox.org (Postfix) with ESMTPS id 4CL7mz0jT9zQl9F; Tue, 27 Oct 2020 11:51:47 +0100 (CET) X-Virus-Scanned: amavisd-new at heinlein-support.de Received: from smtp2.mailbox.org ([80.241.60.241]) by spamfilter04.heinlein-hosting.de (spamfilter04.heinlein-hosting.de [80.241.56.122]) (amavisd-new, port 10030) with ESMTP id zv2PBG-WA4Bo; Tue, 27 Oct 2020 11:51:43 +0100 (CET) To: gcc-patches@gcc.gnu.org Subject: [committed] d: Merge upstream dmd 0fcdaab32 Date: Tue, 27 Oct 2020 11:51:33 +0100 Message-Id: <20201027105133.931480-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-MBO-SPAM-Probability: X-Rspamd-Score: -0.34 / 15.00 / 15.00 X-Rspamd-Queue-Id: C3892170C X-Rspamd-UID: 4649ef X-Spam-Status: No, score=-15.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Buclaw via Gcc-patches From: Iain Buclaw Reply-To: Iain Buclaw Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch merges the D front-end implementation with upstream dmd 0fcdaab32, fixing a bug where there was undefined template references when compiling upstream dmd mainline. In `TemplateInstance::semantic`, there exists special handling of matching template instances for the same template declaration to ensure that only at most one instance gets codegen'd. If the primary instance `inst` originated from a non-root module, the `minst` field will be updated so it is now coming from a root module, however all Dsymbol `inst->members` of the instance still have their `_scope->minst` pointing at the original non-root module. We must now propagate `minst` to all members so that forward referenced dependencies that get instantiated will also be appended to the root module, otherwise there will be undefined references at link-time. This doesn't affect compilations where all modules are compiled together, as every module is a root module in that situation. What this primarily affects are cases where there is a mix of root and non-root modules, and a template was first instantiated in a non-root context, then later instantiated again in a root context. Regstrapped on x86_64-linux-gnu/-m32/-mx32, committed to mainline. Regards Iain --- gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 0fcdaab32 --- gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/dtemplate.c | 66 ++++++++++++- .../compilable/imports/test21299/func.d | 8 ++ .../compilable/imports/test21299/mtype.d | 8 ++ .../imports/test21299/rootstringtable.d | 96 +++++++++++++++++++ .../gdc.test/compilable/test21299a.d | 4 + .../gdc.test/compilable/test21299b.d | 4 + .../gdc.test/compilable/test21299c.d | 5 + .../gdc.test/compilable/test21299d.d | 27 ++++++ 9 files changed, 216 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gdc.test/compilable/imports/test21299/func.d create mode 100644 gcc/testsuite/gdc.test/compilable/imports/test21299/mtype.d create mode 100644 gcc/testsuite/gdc.test/compilable/imports/test21299/rootstringtable.d create mode 100644 gcc/testsuite/gdc.test/compilable/test21299a.d create mode 100644 gcc/testsuite/gdc.test/compilable/test21299b.d create mode 100644 gcc/testsuite/gdc.test/compilable/test21299c.d create mode 100644 gcc/testsuite/gdc.test/compilable/test21299d.d diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 5f6193f76b7..7b561e4044e 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -70aabfb511d55f2bfbdccbac7868519d9d4b63da +0fcdaab32c7645820820f6e1474343ccfb7560e5 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/dtemplate.c b/gcc/d/dmd/dtemplate.c index a86daeee633..caa8a5ba9f4 100644 --- a/gcc/d/dmd/dtemplate.c +++ b/gcc/d/dmd/dtemplate.c @@ -33,6 +33,7 @@ #include "hdrgen.h" #include "id.h" #include "attrib.h" +#include "cond.h" #include "tokens.h" #define IDX_NOTFOUND (0x12345678) // index is not found @@ -6088,17 +6089,18 @@ Lerror: if (minst && minst->isRoot() && !(inst->minst && inst->minst->isRoot())) { /* Swap the position of 'inst' and 'this' in the instantiation graph. - * Then, the primary instance `inst` will be changed to a root instance. + * Then, the primary instance `inst` will be changed to a root instance, + * along with all members of `inst` having their scopes updated. * * Before: - * non-root -> A!() -> B!()[inst] -> C!() + * non-root -> A!() -> B!()[inst] -> C!() { members[non-root] } * | * root -> D!() -> B!()[this] * * After: * non-root -> A!() -> B!()[this] * | - * root -> D!() -> B!()[inst] -> C!() + * root -> D!() -> B!()[inst] -> C!() { members[root] } */ Module *mi = minst; TemplateInstance *ti = tinst; @@ -6107,6 +6109,64 @@ Lerror: inst->minst = mi; inst->tinst = ti; + /* https://issues.dlang.org/show_bug.cgi?id=21299 + `minst` has been updated on the primary instance `inst` so it is + now coming from a root module, however all Dsymbol `inst.members` + of the instance still have their `_scope.minst` pointing at the + original non-root module. We must now propagate `minst` to all + members so that forward referenced dependencies that get + instantiated will also be appended to the root module, otherwise + there will be undefined references at link-time. */ + class InstMemberWalker : public Visitor + { + public: + TemplateInstance *inst; + + InstMemberWalker(TemplateInstance *inst) + : inst(inst) { } + + void visit(Dsymbol *d) + { + if (d->_scope) + d->_scope->minst = inst->minst; + } + + void visit(ScopeDsymbol *sds) + { + if (!sds->members) + return; + for (size_t i = 0; i < sds->members->length; i++) + { + Dsymbol *s = (*sds->members)[i]; + s->accept(this); + } + visit((Dsymbol *)sds); + } + + void visit(AttribDeclaration *ad) + { + Dsymbols *d = ad->include(NULL); + if (!d) + return; + for (size_t i = 0; i < d->length; i++) + { + Dsymbol *s = (*d)[i]; + s->accept(this); + } + visit((Dsymbol *)ad); + } + + void visit(ConditionalDeclaration *cd) + { + if (cd->condition->inc) + visit((AttribDeclaration *)cd); + else + visit((Dsymbol *)cd); + } + }; + InstMemberWalker v(inst); + inst->accept(&v); + if (minst) // if inst was not speculative { /* Add 'inst' once again to the root module members[], then the diff --git a/gcc/testsuite/gdc.test/compilable/imports/test21299/func.d b/gcc/testsuite/gdc.test/compilable/imports/test21299/func.d new file mode 100644 index 00000000000..fe3321faff7 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/test21299/func.d @@ -0,0 +1,8 @@ +module imports.test21299.func; +import imports.test21299.mtype; +import imports.test21299.rootstringtable; +class FuncDeclaration { + StringTable!Type stringtable; + StringTable2!Type stringtable2; + StringTable3!Type stringtable3; +} diff --git a/gcc/testsuite/gdc.test/compilable/imports/test21299/mtype.d b/gcc/testsuite/gdc.test/compilable/imports/test21299/mtype.d new file mode 100644 index 00000000000..01bac82c2e4 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/test21299/mtype.d @@ -0,0 +1,8 @@ +module imports.test21299.mtype; +import imports.test21299.func; +import imports.test21299.rootstringtable; +class Type { + StringTable!Type stringtable; + StringTable2!Type stringtable2; + StringTable3!Type stringtable3; +} diff --git a/gcc/testsuite/gdc.test/compilable/imports/test21299/rootstringtable.d b/gcc/testsuite/gdc.test/compilable/imports/test21299/rootstringtable.d new file mode 100644 index 00000000000..12a2d92899b --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/test21299/rootstringtable.d @@ -0,0 +1,96 @@ +module imports.test21299.rootstringtable; +struct StringValue(T) +{ + char* lstring() + { + return cast(char*)&this; + } +} + +struct StringTable(T) +{ + StringValue!T* insert() + { + allocValue; + return getValue; + } + + uint allocValue() + { + StringValue!(T) sv; + sv.lstring[0] = 0; + return 0; + } + + StringValue!T* getValue() + { + return cast(StringValue!T*)&this; + } +} + +// Other tests are the same as the original issue, but use other kinds of +// nesting Dsymbols that need to be handled by templateInstanceSemantic(). +struct StringValue2(T) +{ + char* lstring() + { + return cast(char*)&this; + } +} + +struct StringTable2(T) +{ + @nogc // AttribDeclaration (also covers pragma, extern(), static foreach, ...) + { + StringValue2!T* insert() + { + allocValue; + return getValue; + } + + uint allocValue() + { + StringValue2!(T) sv; + sv.lstring[0] = 0; + return 0; + } + + StringValue2!T* getValue() + { + return cast(StringValue2!T*)&this; + } + } +} + +// +struct StringValue3(T) +{ + char* lstring() + { + return cast(char*)&this; + } +} + +struct StringTable3(T) +{ + static if (true) // ConditionalDeclaration (static if) + { + StringValue3!T* insert() + { + allocValue; + return getValue; + } + + uint allocValue() + { + StringValue3!(T) sv; + sv.lstring[0] = 0; + return 0; + } + + StringValue3!T* getValue() + { + return cast(StringValue3!T*)&this; + } + } +} diff --git a/gcc/testsuite/gdc.test/compilable/test21299a.d b/gcc/testsuite/gdc.test/compilable/test21299a.d new file mode 100644 index 00000000000..049ee6ae35b --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test21299a.d @@ -0,0 +1,4 @@ +// EXTRA_SOURCES: imports/test21299/mtype.d imports/test21299/rootstringtable.d +// REQUIRED_ARGS: -main +// LINK +module test21299a; diff --git a/gcc/testsuite/gdc.test/compilable/test21299b.d b/gcc/testsuite/gdc.test/compilable/test21299b.d new file mode 100644 index 00000000000..b9d992acfb9 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test21299b.d @@ -0,0 +1,4 @@ +// EXTRA_SOURCES: imports/test21299/func.d imports/test21299/rootstringtable.d +// REQUIRED_ARGS: -main +// LINK: +module test21299b; diff --git a/gcc/testsuite/gdc.test/compilable/test21299c.d b/gcc/testsuite/gdc.test/compilable/test21299c.d new file mode 100644 index 00000000000..88ed21f3ea6 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test21299c.d @@ -0,0 +1,5 @@ +// EXTRA_SOURCES: imports/test21299/mtype.d imports/test21299/func.d imports/test21299/rootstringtable.d +// COMPILE_SEPARATELY: +// LINK: +module test21299c; +void main() {} diff --git a/gcc/testsuite/gdc.test/compilable/test21299d.d b/gcc/testsuite/gdc.test/compilable/test21299d.d new file mode 100644 index 00000000000..67ec60a582b --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test21299d.d @@ -0,0 +1,27 @@ +// REQUIRED_ARGS: -main +// LINK: +module test21299d; + +struct DefaultPredicates +{ + struct IsEqual(T) + { + static opCall(in T, in T) + { + return 0; + } + } +} + +void moveToEnd(T, Pred = DefaultPredicates.IsEqual!T)(T[] array, T element, Pred pred = Pred.init) +{ + pred(array[0], element); +} + +class Task +{ + void removeTerminationHook(void delegate() hook) + { + moveToEnd([], hook); + } +}