digitalmars.D.bugs - [Issue 18868] New: Separate compilation generates two static this
- d-bugmail puremagic.com (68/68) May 16 2018 https://issues.dlang.org/show_bug.cgi?id=18868
https://issues.dlang.org/show_bug.cgi?id=18868 Issue ID: 18868 Summary: Separate compilation generates two static this functions, runs it twice Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: critical Priority: P1 Component: dmd Assignee: nobody puremagic.com Reporter: johanengelen weka.io Testcase that shows that the static this is called twice. ``` // File: fls.d template FLS(T) { int offset = -1; static this() { assert (offset == -1); offset += 2; } } ``` ``` // File: a.d shared static this() { } import fls; alias floop = FLS!(int); ``` ``` // File: b.d import fls; alias floop = FLS!(int); void main() {} ``` Build+run script: ``` ~/weka/ldc/installcurrent/bin/ldc2 -c a.d -of=a.o ~/weka/ldc/installcurrent/bin/ldc2 -c b.d -of=b.o ~/weka/ldc/installcurrent/bin/ldc2 fls.d a.o b.o ./fls ``` Fails with DMD (tested with 2.080) and LDC. What is happening: 1. Because of separate compilation and template instantiation, the static ctor is codegenned in two compilation units and added to both moduleinfos such that it will be called on startup of each module (`a` and `b`) 2. After linking, two modules will call that same static ctor. 3. The static ctor contains code to catch multiple call case! Upon second or more calls it simply returns. The checking is using a __gate variable. For example: `....._sharedStaticCtor67().__gate` However, as you can see there is this number "67" there. It is a number that is deterministic but may vary across separate compilations depending, among others, on how many other static ctors there are. 4. In one compilation case, the number is "x", in the other compilation case the number is "not x". Thus we now have two _different_ staticctor functions and gate variables, that access and write to the _same_ `offset` variable. So the appearance is that the static ctor is run twice. This is a similar problem as what we had with unittest function naming that was semi-non-deterministic. https://issues.dlang.org/show_bug.cgi?id=16995 https://issues.dlang.org/show_bug.cgi?id=18097 https://github.com/dlang/dmd/pull/7761 I think the fix is easy: instead of using a counter number, use the line+column number like what we do now for the unittest functions. --
May 16 2018