Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

Ticket #421 (closed defect: fixed)

Opened 2 years ago

Last modified 1 year ago

extern(C) silently stripped from function signature

Reported by: mwarning Assigned to: ChristianK
Priority: major Milestone:
Component: unspecified Version: hg tip
Keywords: Cc:

Description

LDC silently strips extern(C) from mixins.

import tango.core.Traits;
import tango.io.Stdout;

alias extern(C) void function() FT1;
alias extern (C) void function(FT1) FT2;
FT2 fd;

//from OS.d
template Foo( alias cFunc )
{
    alias ParameterTupleOf!(cFunc) P;
    mixin("public static void fd( P p ){  }");
}

void main()
{
    //ldc (1.057):       void function((void function() _param_0) p)
    //dmd 1.057:         void function((void C function() _param_0) p)
    Stdout(typeof(&Foo!(fd).fd).stringof).nl;
}

This bug is probably related to #357 and prevents ldc from being able to build GTKD (caused in gtk.d/OS.d).

Change History

08/16/10 16:20:10 changed by mwarning

We get a simpler test case when we omit the mixin.

08/28/10 08:10:55 changed by doob

This is a stopper for DWT2 (linux) as well.

12/14/10 22:07:42 changed by SiegeLord

This bug is indeed the same one as #357. The bug is caused by this code in dmd/mtype.c in TypeFunction::semantic:

            // each function needs its own copy of a tuple arg, since
            // they mustn't share arg flags like inreg, ...
            if (fparam->type->ty == Ttuple) {
                fparam->type = fparam->type->syntaxCopy();
                tf->inuse++;
                fparam->type = fparam->type->semantic(loc,sc);
                if (tf->inuse == 1) tf->inuse--;
            }

That syntax copy call copies the tuple, but unfortunately the "extern(C)" bit is not part of the syntax at the function declaration site. When the tuple is re-analyzed the function pointer is treated as simply void function().

I don't know what that code is for. It is not present in DMD's frontend. It was added in [772] along with a test-case. If this code is removed, then that test case still compiles fine, and this bug and #357 are fixed. I don't really know what the issue was though...

An alternate, hacky, workaround is to adjust this line in the same function:

tf->linkage = sc->linkage;

This line erases the linkage of the C function pointer when it is reanalyzed (the argument scope obviously has D linkage in the above example). It can be modified as follows:

if(tf->linkage == LINKd)
    tf->linkage = sc->linkage;

I don't know whether that is at all appropriate though... it does fix this bug however.

12/19/10 11:54:06 changed by mwarning

Removing the piece of code doesn't cause any regression in the mini tests (including tests/mini/compile_delegatetuple.d).

But dstress shows regressions:

Regression   PASS -> FAIL : bug_stor_layout_382_A in run/b/bug_stor_layout_382_A.d
Regression   PASS -> FAIL : bug_stmt_2384_A in run/b/bug_stmt_2384_A.d
Regression   PASS -> FAIL : bug_stmt_2384_B in run/b/bug_stmt_2384_B.d
Regression   PASS -> FAIL : bug_stmt_2384_C in run/b/bug_stmt_2384_C.d
Regression   PASS -> FAIL : bug_stmt_2384_D in run/b/bug_stmt_2384_D.d
Regression   PASS -> FAIL : tuple_20_A in run/t/tuple_20_A.d
if(tf->linkage == LINKd)
    tf->linkage = sc->linkage;

.. fixes both #412 and #357 without introducing regressions.

12/19/10 11:55:35 changed by mwarning

meh, I meant #421, not #412.

12/19/10 12:01:48 changed by mwarning

  • status changed from new to closed.
  • resolution set to fixed.

fixed in 1701:b3627edc659e

Copyright © 2008, LDC Development Team.