Bug 13394 – invariant fail to link since 2.066 when using separate compilation
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-08-28T22:12:00Z
Last change time
2014-09-02T02:14:25Z
Keywords
link-failure, pull
Assigned to
nobody
Creator
deadalnix
Comments
Comment #0 by deadalnix — 2014-08-28T22:12:22Z
a.d :
module a;
import std.utf;
class A {
this() { }
}
class Btpl(T) : T {
this()() { }
invariant {}
}
alias B = Btpl!A;
-------------
b.d :
module b;
import a;
void main() {
new B();
}
-------------
$ dmd -c a.d && dmd -c b.d && dmd *.o
Undefined symbols for architecture x86_64:
"_D1a15__T4BtplTC1a1AZ4Btpl11__invariantMxFZv", referenced from:
_D1a15__T4BtplTC1a1AZ4Btpl11__T6__ctorZ6__ctorMFZC1a15__T4BtplTC1a1AZ4Btpl in b.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
--- errorlevel 1
It has to be noted that importing std.utf seems to play a role here, which is weird.
Comment #1 by k.hara.pg — 2014-08-29T04:11:28Z
Introduced in: https://github.com/D-Programming-Language/dmd/pull/3775
====
When a.d is compiled, compiler instantiates Btpl!A and outputs its invariant objcode to a.obj.
Next b.d is compiled, the `new B` expression instantiates the Btpl!A template constructor. It implicitly calls the invariant in post-condition, bug Btpl!A is explicitly instantiated in the non-root module (== a module which not directly compiled from command line) a. So compiler assumes that the Btpl!A.invariant objcode will be provided in linking phase and skips its codegen.
However, currently dmd always adds the inferred function attributes into the symbol name of instantiated functions. Therefore, dmd a.d will emit the objcode of Btpl!A.invariant with the symbol name:
_D1a15__T4BtplTC1a1AZ4Btpl11__invariantMxFNaNbNiNfZv
But dmd b.d does not invoke semantic3 of Btpl!A.invariant. Then b.obj refer the invariant by using the symbol name:
_D1a15__T4BtplTC1a1AZ4Btpl11__invariantMxFZv
<-- does not contain the inferred attributes NaNbNiNf
Then link-failure happens.
Comment #2 by deadalnix — 2014-08-29T04:30:38Z
(In reply to Kenji Hara from comment #1)
> Introduced in: https://github.com/D-Programming-Language/dmd/pull/3775
>
> ====
>
> When a.d is compiled, compiler instantiates Btpl!A and outputs its invariant
> objcode to a.obj.
>
> Next b.d is compiled, the `new B` expression instantiates the Btpl!A
> template constructor. It implicitly calls the invariant in post-condition,
> bug Btpl!A is explicitly instantiated in the non-root module (== a module
> which not directly compiled from command line) a. So compiler assumes that
> the Btpl!A.invariant objcode will be provided in linking phase and skips its
> codegen.
>
> However, currently dmd always adds the inferred function attributes into the
> symbol name of instantiated functions. Therefore, dmd a.d will emit the
> objcode of Btpl!A.invariant with the symbol name:
> _D1a15__T4BtplTC1a1AZ4Btpl11__invariantMxFNaNbNiNfZv
>
> But dmd b.d does not invoke semantic3 of Btpl!A.invariant. Then b.obj refer
> the invariant by using the symbol name:
> _D1a15__T4BtplTC1a1AZ4Btpl11__invariantMxFZv
> <-- does not contain the inferred attributes NaNbNiNf
>
> Then link-failure happens.
That is interesting. Do you know why the import alter the behavior of DMD ?
Comment #3 by k.hara.pg — 2014-08-29T05:02:57Z
(In reply to deadalnix from comment #2)
> That is interesting. Do you know why the import alter the behavior of DMD ?
In my Windows environment, importing std.utf in a.d was unnecessary to reproduce the link-failure.