Thread overview
is this a bug ? mixin template static function missing!
August 10
#!/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:



August 10
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.
August 10
On Friday, 10 August 2018 at 10:24:55 UTC, Simen Kjærås wrote:
> On Friday, 10 August 2018 at 08:31:21 UTC, learnfirst1 wrote:
> 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
>

I think the static extern(C)  nested function should just work like global extern(C) function.   DMD still report missing symbols.   Or I am wrong about this ?

template G(){
    static extern(C) pragma(crt_constructor) void init(){}
}
void main(){
    mixin G!(); // Line 5
    init();
}
August 10
On Friday, 10 August 2018 at 10:24:55 UTC, Simen Kjærås wrote:
> On Friday, 10 August 2018 at 08:31:21 UTC, learnfirst1 wrote:
> Filed a bug:
> https://issues.dlang.org/show_bug.cgi?id=19153
>

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

same missing symbols.
August 10
On Friday, 10 August 2018 at 11:17:10 UTC, learnfirst1 wrote:
> I think the static extern(C)  nested function should just work like global extern(C) function.   DMD still report missing symbols.   Or I am wrong about this ?
>
> template G(){
>     static extern(C) pragma(crt_constructor) void init(){}
> }
> void main(){
>     mixin G!(); // Line 5
>     init();
> }

If you try the same without the mixin template, you'll see that it doesn't work:

void main() {
    static extern(C) pragma(crt_constructor) void init();
    init();
}

Depending on the order of static, extern(C) and pragma(crt_constructor), you can get at least two different error messages, but either way - it doesn't work.

It would be possible to make this work by changing the compiler, but according to spec, it shouldn't.

--
  Simen
August 10
On Friday, 10 August 2018 at 12:05:52 UTC, Simen Kjærås wrote:
> On Friday, 10 August 2018 at 11:17:10 UTC, learnfirst1 wrote:
> If you try the same without the mixin template, you'll see that it doesn't work:
>


struct Test {
    extern(C) pragma(crt_constructor) static void init(){ // work
        int i = 3;
    }
}

void main(){
    extern(C) pragma(crt_constructor) static void init(){ // not work
        int i = 3;
    }
}

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

It not work make no sense, since it can work on struct.


I am not be able to search the related spec docs,  only this link:  https://dlang.org/blog/2018/01/04/dmd-2-078-0-has-been-released/

Based on my understand, nested static  extern(C)  function is all about visibility.  It just like put private before it,  there is really no reason to treat them in diff way.