diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2020-10-23 09:41:11 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2020-10-27 11:50:35 +0100 |
commit | e419ede8915eeb879de3d9c026cd4213aaceb86a (patch) | |
tree | 03b7bf22cb46b94e4ad563d88dfbb0e73aaac92e /gcc/d/dmd | |
parent | 14e19b82c1e67ead60c3095ac23347317298904b (diff) | |
download | gcc-e419ede8915eeb879de3d9c026cd4213aaceb86a.zip gcc-e419ede8915eeb879de3d9c026cd4213aaceb86a.tar.gz gcc-e419ede8915eeb879de3d9c026cd4213aaceb86a.tar.bz2 |
d: Merge upstream dmd 0fcdaab32
Fixes 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.
Reviewed-on: https://github.com/dlang/dmd/pull/11867
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd 0fcdaab32
Diffstat (limited to 'gcc/d/dmd')
-rw-r--r-- | gcc/d/dmd/MERGE | 2 | ||||
-rw-r--r-- | gcc/d/dmd/dtemplate.c | 66 |
2 files changed, 64 insertions, 4 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 5f6193f..7b561e4 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 a86daee..caa8a5b 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 |