Thread overview
[Issue 7024] New: inconsistent mangling of shared in extern(C++)
Nov 28, 2011
dawg@dawgfoto.de
Nov 28, 2011
deadalnix
Nov 28, 2011
dawg@dawgfoto.de
Nov 29, 2011
dawg@dawgfoto.de
Dec 01, 2011
Iain Buclaw
Dec 01, 2011
dawg@dawgfoto.de
Dec 02, 2011
deadalnix
Dec 02, 2011
dawg@dawgfoto.de
Dec 03, 2011
deadalnix
Dec 03, 2011
dawg@dawgfoto.de
November 28, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7024

           Summary: inconsistent mangling of shared in extern(C++)
           Product: D
           Version: D2
          Platform: Other
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: dawg@dawgfoto.de


--- Comment #0 from dawg@dawgfoto.de 2011-11-28 02:32:50 PST ---
module fail;

extern(C++) void foo1(void*);
extern(C++) void bar1(shared void*);

pragma(msg, foo1.mangleof);
pragma(msg, bar1.mangleof); // shared is ignored here, because C++ doesn't have
shared, this make sense.

extern(C++) void foo2(void function(void*));
extern(C++) void bar2(void function(shared void*));

pragma(msg, foo2.mangleof);
pragma(msg, bar2.mangleof); // shared is ignored here, because C++ doesn't have
shared, this make sense.

extern(C++) void foo3(void function(void*), void*);
extern(C++) void bar3(void function(shared void*), void*);

pragma(msg, foo3.mangleof);
pragma(msg, bar3.mangleof); // shared generate a different mangling here.

extern(C++) void foo4(void function(void*), shared void*);
extern(C++) void bar4(void function(shared void*), shared void*);

pragma(msg, foo4.mangleof); // Same mangling as bar3.
pragma(msg, bar4.mangleof); // back to correct mangling (the one expected by
g++).

extern(C++) void foo5(void* function(void*), void*);
extern(C++) void bar5(void* function(shared void*), void*);

pragma(msg, foo5.mangleof);
pragma(msg, bar5.mangleof); // shared generate a different mangling here.

extern(C++) void foo6(void* function(void*), shared void*);
extern(C++) void bar6(void* function(shared void*), shared void*);

pragma(msg, foo6.mangleof); // shared generate a different mangling here. pragma(msg, bar6.mangleof); // function pointer mangled as in bar5, but second parameter get a "0" in the mangling that none of the mangling above had.

----

It is expected that shared be ignored as in the foo1/bar1 case.

filed on behalf of deadalnix.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 28, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7024


deadalnix <deadalnix@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |deadalnix@gmail.com


--- Comment #1 from deadalnix <deadalnix@gmail.com> 2011-11-28 03:26:40 PST ---
Hi,

As I said in the topic, I was using GDC to generate informations. I didn't try with DMD so it is not sure the problem actually exists on this compiler.

I'm currently repporting the issue to GDC bugtracker.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 28, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7024



--- Comment #2 from dawg@dawgfoto.de 2011-11-28 05:15:24 PST ---
Yes, it exists with dmd too.

It is an error with the compression in name mangling.
http://sourcery.mentor.com/public/cxx-abi/abi.html#mangling-compression
The compiler fails to substitute 'void*' and 'shared void*'.
But for both shared is ignored for mangling.

It needs to be decided whether all qualifiers (probably except for const) be silently stripped or if they should result in an error/warning.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 29, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7024



--- Comment #3 from dawg@dawgfoto.de 2011-11-29 10:05:37 PST ---
current workaround:

Don't use shared/immutable/inout with extern(C++) declarations.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 01, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7024


Iain Buclaw <ibuclaw@ubuntu.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ibuclaw@ubuntu.com


--- Comment #4 from Iain Buclaw <ibuclaw@ubuntu.com> 2011-12-01 09:46:53 PST ---
Rather than trying to fix the C++ mangling, wouldn't it make more sense to disallow 'shared' in extern(C++) declarations?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 01, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7024



--- Comment #5 from dawg@dawgfoto.de 2011-12-01 12:50:37 PST ---
It'd be a cleaner cut to disallow immutable/shared/inout for extern(C++) declarations. Not sure though how big the impact is.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 02, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7024



--- Comment #6 from deadalnix <deadalnix@gmail.com> 2011-12-02 10:59:31 PST ---
(In reply to comment #4)
> Rather than trying to fix the C++ mangling, wouldn't it make more sense to disallow 'shared' in extern(C++) declarations?

As thoses concept doesn't exists in C++, this is up to the C++ programmer to ensure that something is shared or not. Sometime, C++ code is just made to handle shared data, it is just not explicit.

In this case, you ends up using convoluted casts to handle everything.

I have a practical case : start a thread from C++, but that could interract
with D (so you must go throw D's way of starting thread). You end up writing
something like this :
alias extern(C++) void* function(void*) EntryPoint;
extern(C++) void* D_start_thread(EntryPoint entryPoint, void* userData) {
    Tid tid = spawn(function void(EntryPoint entryPoint, shared void* userData)
{
        entryPoint(cast(void*) userData);
    }, entryPoint, cast(shared void*) userData);

    return cast(void*) [tid].ptr;
}

So I would recommand to ignore shared in mangling of C++ function and mangle immutable as const. It is up to the programmer to ensure that thoses are right qualifiers.

inout can't be handled nicely so it should generate a compile time error.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 02, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7024



--- Comment #7 from dawg@dawgfoto.de 2011-12-02 12:22:18 PST ---
The baseline of D type system is to disallow things that can't be guaranteed.
C++ definitely can't guarantee any of the three.
To avoid explicit casting at every caller place, you could add
a D wrapper that does the calling.

extern(C++) void _spawn(void function() fun, void* data);

void spawn(extern(C++) void function() fun, shared void* data)
{
  _spawn(fun, cast(void*)data);
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 03, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7024



--- Comment #8 from deadalnix <deadalnix@gmail.com> 2011-12-03 04:42:25 PST ---
(In reply to comment #7)
> The baseline of D type system is to disallow things that can't be guaranteed.
> C++ definitely can't guarantee any of the three.
> To avoid explicit casting at every caller place, you could add
> a D wrapper that does the calling.
> 
> extern(C++) void _spawn(void function() fun, void* data);
> 
> void spawn(extern(C++) void function() fun, shared void* data)
> {
>   _spawn(fun, cast(void*)data);
> }

This piece of code miss completely the point of the one before.

But back to the problem, obviously, C++ cannot guarantee, with it's type system, that something is immutable, shared, or whatever. This is why a bindong is required, and the same thing must be express the D way and the C++ way to interact.

It is up to the person writting the binding to ensure that it is correct. C++ can have immutable data, or shared one's. It isn't guaranteed by the type system, but can be guaranteed by the logic of the application. So it make sense to express those in bindings.

C++ cannot guarantee anything that D guarantee. It can corrupt memory, share non shared data across thread, etc . . . So if we agree on this argument, extern(C++) must be simply and completely removed from D's specification and implementation.

When it comes to binding, it is up to the person writting the binding to ensure that code on both sides express the same thing, and it cannot, and never will, be enforced by a specification.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 03, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7024



--- Comment #9 from dawg@dawgfoto.de 2011-12-03 06:44:56 PST ---
- The current D policy is to not base such things on trust but
   require explicit casting.

 - You have no way to guarantee atomic access for shared in C++.

 - Overloaded extern(C++) functions will clash during linking or
   even worse resolve to the same symbol.

The only pro argument is less typing for the caller,
where the example code just showed another solution to this.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------