aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2020-10-23 09:41:11 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2020-10-27 11:50:35 +0100
commite419ede8915eeb879de3d9c026cd4213aaceb86a (patch)
tree03b7bf22cb46b94e4ad563d88dfbb0e73aaac92e /gcc/d/dmd
parent14e19b82c1e67ead60c3095ac23347317298904b (diff)
downloadgcc-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/MERGE2
-rw-r--r--gcc/d/dmd/dtemplate.c66
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