Bug 4328 – templated unittests fail to link when instantiated from other file if compiler order isn't correct
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Linux
Creation time
2010-06-16T06:46:00Z
Last change time
2011-02-06T23:52:53Z
Assigned to
nobody
Creator
schveiguy
Comments
Comment #0 by schveiguy — 2010-06-16T06:46:44Z
testunittest.d:
struct S(T)
{
unittest
{
assert(0);
}
}
testunittestmain.d:
import testunittest;
void main()
{
S!int s;
}
When compiled this way:
dmd -unittest testunittest.d testunittestmain.d
The following error occurs:
testunittest.o: In function `_D12testunittest8__T1STiZ1S11__unittest3FZv':
testunittestmain.d:(.text._D12testunittest8__T1STiZ1S11__unittest3FZv+0x9): undefined reference to `_D12testunittest15__unittest_failFiZv'
collect2: ld returned 1 exit status
If I compile this way:
dmd -unittest testunittestmain.d testunittest.d
The compiler generally has no problem with order of files for linking, I would expect the same here.
Comment #1 by r.sagitario — 2010-08-27T08:15:20Z
even worse: the link fails if the template is in a library and the library is not compiled with unittests:
import std.stdio;
void main()
{
writef("\n");
}
dmd -unittest test.d
OPTLINK (R) for Win32 Release 8.00.2
Copyright (C) Digital Mars 1989-2009 All rights reserved.
http://www.digitalmars.com/ctg/optlink.html
test.obj(test)
Error 42: Symbol Undefined _D3std6format15__unittest_failFiZv
--- errorlevel 1
Strangely, the relased phobos.lib is compiled with unittests, while the makefile does not pass "-unittest". So this does only show up when I compile the runtime library myself.
Comment #2 by r.sagitario — 2010-08-27T08:39:32Z
Here's a workaround: similar to the assert handling, generate the unittest_fail function whenever there is a template in the module:
Index: template.c
===================================================================
--- template.c (revision 632)
+++ template.c (working copy)
@@ -429,6 +429,13 @@
sc->module->toModuleAssert();
}
+ if (/*global.params.useUnitTests &&*/ sc->module)
+ {
+ // Generate this function as it may be used
+ // when template is instantiated in other modules
+ sc->module->toModuleUnittest();
+ }
+
/* Remember Scope for later instantiations, but make
* a copy since attributes can change.
*/