[Issue 15318] New: Templates not emitted for two "partial cycles"

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Wed Nov 11 04:14:21 PST 2015


https://issues.dlang.org/show_bug.cgi?id=15318

          Issue ID: 15318
           Summary: Templates not emitted for two "partial cycles"
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: regression
          Priority: P1
         Component: dmd
          Assignee: nobody at puremagic.com
          Reporter: code at klickverbot.at

Consider the following program:

---
module A;

import C;
---
module B;

import E;
alias value = bar!5;
void foo() {
    import core.stdc.stdio;
    printf("%p\n", &value);
}
---
module C;

import E;
alias value = bar!5;
void foo() {
    import core.stdc.stdio;
    printf("%p\n", &value);
}
---
module D;

import B;
---
module E;

immutable bar(int v) = v;
---

If you compile it like this using DMD 2.068.2 or 2.069.1
---
dmd -c -offirst.o A.d B.d
dmd -c -ofsecond.o C.d D.d
dmd -main E.d first.o second.o
---
you'll get an undefined symbol for the bar!5 instance. The same occurs when
using -lib instead of "-c -of…", and E.d is of course unnecessary to compile in
this case, but just added for completeness.

The issue is that when compiling the first "package" (this test case is derived
from problems using by-package compilation in a big code base), i.e. A and B,
the symbol is determined to be instantiated by a non-root module (A -> C), so
even though it is instantiated in B, it doesn't get emitted into the object
file. But when compiling the second package, the D -> B import causes that
instance in C not to be emitted either.

One fix/workaround is to remove the following piece of logic from
TemplateInstance.needsCodegen():

--- dtemplate.d
    if (tnext && !tnext.needsCodegen() && tnext.minst)
    {
        minst = tnext.minst; // cache result
        assert(!minst.isRoot());
        return false;
    }
---

Now, of course, this fix is not ideal in the sense that it also causes more
work to be done in cases that are currently handled correctly. But
fundamentally I can't see how eliding instances that are being done directly in
root modules (B and C in this case) would ever be possible. There can always be
parts of the global module dependency graph for a whole executable that are not
visible from the local point of view when compiling a subset of the modules.
For instance, in the above example there is no way the compiler can know about
the existence of D when compiling A and B.

Marked as a regression, as the issue didn't occur using 2.067.1 in said large
real-world code base, but my suspicion is that the template instantiation logic
was broken before too.

--


More information about the Digitalmars-d-bugs mailing list