On Friday, 10 August 2018 at 08:31:21 UTC, learnfirst1 wrote:


#!/usr/bin/env rdmd
import core.stdc.stdio;

template G(size_t line = __LINE__, A...){
        int i = 3;
        static extern(C) pragma(crt_constructor) void init2(){
                printf("init: %d\n", line);
        }
}

pragma(crt_constructor) extern(C) void init1(){
      printf("init from global\n");
}

struct A {
        mixin G!();
}

extern(C) void main(){
        mixin G!() g;
        printf("g.i=%d\n", g.i);
g.init2(); // remove this can build, but g.init2 not get called!
}

-----------------

build error:
Undefined symbols for architecture x86_64: "__D4test4mainUZ1g5init2UNbNiZv", referenced from:

It is indeed. Reduced example:

template G(){
    extern(C) pragma(crt_constructor) void init(){}
}
void main(){
    mixin G!();
    init();
}

For nested functions, extern(C) is simply ignored[0]. Since pragma(crt_constructor) requires that the symbol it's applied to uses C linkage (and an error message to that effect is shown if you write pragma(crt_constructor) void fun() {} in module scope: Error: function `fun` must be extern(C) for pragma(crt_constructor)

In addition, if you try to apply pragma(crt_constructor) to a nested function, you get this error message, showing further that nested functions can't be crt_constructors:
Error: unrecognized pragma(crt_constructor)

The correct behavior would be for the compiler to show the latter error message for a mixin'd function as well.

Filed a bug:
https://issues.dlang.org/show_bug.cgi?id=19153

--
  Simen

[0]: from https://dlang.org/spec/attribute.html#linkage:
Note that extern(C) can be provided for all types of declarations, including struct or class, even though there is no corresponding match on the C side. In that case, the attribute is ignored. This behavior applies for nested functions and nested variables as well.

Reply via email to