Thread overview
[dmd-internals] DMC vs DMD C++ mangling
Apr 18, 2013
Daniel Murphy
Apr 19, 2013
Rainer Schuetze
Apr 20, 2013
Daniel Murphy
Apr 22, 2013
Don Clugston
Apr 22, 2013
Rainer Schuetze
April 18, 2013
Hi all,

I have come across one strange case where dmd and dmc produce different mangling for seemingly identical declarations.

D:
extern(C++) const(const(bool)*) gc_pi1; // mangled as ?gc_pi1@@3PB_NB

C++:
extern bool const * const gc_pi1; // mangled as ?gc_pi1@@3QB_NB

So we have '[PQ]B_NB' which translates to '[pointer/const pointer] const bool const' where both of the const modifiers (for some reason) apply to the bool, not the pointer.

Is dmd incorrectly printing 'P' instead of 'Q' or have I missed something?

Thanks,
Daniel.

PS If anybody with msvc installed could try this I would be very grateful.


April 19, 2013
On 18.04.2013 15:22, Daniel Murphy wrote:
> Hi all,
>
> I have come across one strange case where dmd and dmc produce different
> mangling for seemingly identical declarations.
>
> D:
> extern(C++) const(const(bool)*) gc_pi1; // mangled as ?gc_pi1@@3PB_NB
>
> C++:
> extern bool const * const gc_pi1; // mangled as ?gc_pi1@@3QB_NB
>
> So we have '[PQ]B_NB' which translates to '[pointer/const pointer] const
> bool const' where both of the const modifiers (for some reason) apply to
> the bool, not the pointer.

If I understand Agner Fog (http://www.agner.org/optimize/calling_conventions.pdf) correctly, "QB_NB" is parsed as QBtype with "QB" translating to "type *const" and type "_NB" translating to "const bool". So the const modifiers bind to different entities.


>
> Is dmd incorrectly printing 'P' instead of 'Q' or have I missed something?

I suspect dmd might be omitting the transitive "const" to allow leaving "const char *" as is instead of requiring "const(char)*" when translating C++ headers to D.

>
> Thanks,
> Daniel.
>
> PS If anybody with msvc installed could try this I would be very grateful.

cl 15.0 and 16.0 (from VS2008 and VS2010) mangle it the same as dmc:

error LNK2019: unresolved external symbol "bool const * const gc_pi1" (?gc_pi1@@3QB_NB) referenced in function _main


_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals

April 20, 2013
On Sat, Apr 20, 2013 at 2:23 AM, Rainer Schuetze <r.sagitario@gmx.de> wrote:

> On 18.04.2013 15:22, Daniel Murphy wrote:
>
>> Hi all,
>>
>> I have come across one strange case where dmd and dmc produce different mangling for seemingly identical declarations.
>>
>> D:
>> extern(C++) const(const(bool)*) gc_pi1; // mangled as ?gc_pi1@@3PB_NB
>>
>> C++:
>> extern bool const * const gc_pi1; // mangled as ?gc_pi1@@3QB_NB
>>
>> So we have '[PQ]B_NB' which translates to '[pointer/const pointer] const bool const' where both of the const modifiers (for some reason) apply to the bool, not the pointer.
>>
>
> If I understand Agner Fog (http://www.agner.org/**
> optimize/calling_conventions.**pdf<http://www.agner.org/optimize/calling_conventions.pdf>)
> correctly, "QB_NB" is parsed as QBtype with "QB" translating to "type
> *const" and type "_NB" translating to "const bool". So the const modifiers
> bind to different entities.
>
>
Further tests show the rightmost cv-modifier is not bound to the final
target type, but the first target type (target of the outmost indirection).
 Agner's manual seems to imply that the rightmost cv-modifier is the
storage class of the declaration itself (although it doesn't explicitly say
this).

(All compiled with dmc)

extern bool const * const less_11; // ?less_11@@3 Q B _N B extern bool const *       less_10; // ?less_10@@3 P B _N B extern bool       * const less_01; // ?less_01@@3 Q A _N A extern bool       *       less_00; // ?less_00@@3 P A _N A

extern bool const * const * const more_111; // ?more_111@@3 Q B Q B _N B extern bool const * const *       more_110; // ?more_110@@3 P B Q B _N B extern bool const *       * const more_101; // ?more_101@@3 Q A P B _N A extern bool const *       *       more_100; // ?more_100@@3 P A P B _N A extern bool       * const * const more_011; // ?more_011@@3 Q B Q A _N B extern bool       * const *       more_010; // ?more_010@@3 P B Q A _N B extern bool       *       * const more_001; // ?more_001@@3 Q A P A _N A extern bool       *       *       more_000; // ?more_000@@3 P A P A _N A

extern bool const * const * const * const * const strange_11111; //
?strange_11111@@3 Q B Q B Q B Q B _N B
extern bool const * const * const * const *       strange_11110; //
?strange_11110@@3 P B Q B Q B Q B _N B
extern bool const * const * const *       * const strange_11101; //
?strange_11101@@3 Q A P B Q B Q B _N A
extern bool const * const * const *       *       strange_11100; //
?strange_11100@@3 P A P B Q B Q B _N A
extern bool const * const *       * const * const strange_11011; //
?strange_11011@@3 Q B Q A P B Q B _N B
extern bool const * const *       * const *       strange_11010; //
?strange_11010@@3 P B Q A P B Q B _N B
extern bool const * const *       *       * const strange_11001; //
?strange_11001@@3 Q A P A P B Q B _N A
extern bool const * const *       *       *       strange_11000; //
?strange_11000@@3 P A P A P B Q B _N A
extern bool const *       * const * const * const strange_10111; //
?strange_10111@@3 Q B Q B Q A P B _N B
extern bool const *       * const * const *       strange_10110; //
?strange_10110@@3 P B Q B Q A P B _N B
extern bool const *       * const *       * const strange_10101; //
?strange_10101@@3 Q A P B Q A P B _N A
extern bool const *       * const *       *       strange_10100; //
?strange_10100@@3 P A P B Q A P B _N A
extern bool const *       *       * const * const strange_10011; //
?strange_10011@@3 Q B Q A P A P B _N B
extern bool const *       *       * const *       strange_10010; //
?strange_10010@@3 P B Q A P A P B _N B
extern bool const *       *       *       * const strange_10001; //
?strange_10001@@3 Q A P A P A P B _N A
extern bool const *       *       *       *       strange_10000; //
?strange_10000@@3 P A P A P A P B _N A
extern bool       * const * const * const * const strange_01111; //
?strange_01111@@3 Q B Q B Q B Q A _N B
extern bool       * const * const * const *       strange_01110; //
?strange_01110@@3 P B Q B Q B Q A _N B
extern bool       * const * const *       * const strange_01101; //
?strange_01101@@3 Q A P B Q B Q A _N A
extern bool       * const * const *       *       strange_01100; //
?strange_01100@@3 P A P B Q B Q A _N A
extern bool       * const *       * const * const strange_01011; //
?strange_01011@@3 Q B Q A P B Q A _N B
extern bool       * const *       * const *       strange_01010; //
?strange_01010@@3 P B Q A P B Q A _N B
extern bool       * const *       *       * const strange_01001; //
?strange_01001@@3 Q A P A P B Q A _N A
extern bool       * const *       *       *       strange_01000; //
?strange_01000@@3 P A P A P B Q A _N A
extern bool       *       * const * const * const strange_00111; //
?strange_00111@@3 Q B Q B Q A P A _N B
extern bool       *       * const * const *       strange_00110; //
?strange_00110@@3 P B Q B Q A P A _N B
extern bool       *       * const *       * const strange_00101; //
?strange_00101@@3 Q A P B Q A P A _N A
extern bool       *       * const *       *       strange_00100; //
?strange_00100@@3 P A P B Q A P A _N A
extern bool       *       *       * const * const strange_00011; //
?strange_00011@@3 Q B Q A P A P A _N B
extern bool       *       *       * const *       strange_00010; //
?strange_00010@@3 P B Q A P A P A _N B
extern bool       *       *       *       * const strange_00001; //
?strange_00001@@3 Q A P A P A P A _N A
extern bool       *       *       *       *       strange_00000; //
?strange_00000@@3 P A P A P A P A _N A



> Is dmd incorrectly printing 'P' instead of 'Q' or have I missed something?
>>
>
> I suspect dmd might be omitting the transitive "const" to allow leaving "const char *" as is instead of requiring "const(char)*" when translating C++ headers to D.
>
>
Interesting.  I'm not sure that's a good idea.


>
>
>> Thanks,
>> Daniel.
>>
>> PS If anybody with msvc installed could try this I would be very grateful.
>>
>
> cl 15.0 and 16.0 (from VS2008 and VS2010) mangle it the same as dmc:
>
> error LNK2019: unresolved external symbol "bool const * const gc_pi1" (?gc_pi1@@3QB_NB) referenced in function _main
>

Thanks, I'm going to classify dmd's behavior as a bug.


April 22, 2013
On 20 April 2013 10:52, Daniel Murphy <yebblies@gmail.com> wrote:

> On Sat, Apr 20, 2013 at 2:23 AM, Rainer Schuetze <r.sagitario@gmx.de>wrote:
> Further tests show the rightmost cv-modifier is not bound to the final
> target type, but the first target type (target of the outmost indirection).
>  Agner's manual seems to imply that the rightmost cv-modifier is the
> storage class of the declaration itself (although it doesn't explicitly say
> this).
>

Send Agner an email about it. He's a great guy, and really responsive, I've sent him quite a few patches for code and documentation, and he's always folded them in.


April 22, 2013
On 20.04.2013 10:52, Daniel Murphy wrote:
> extern bool const * const * const *       * const strange_11101; //
> ?strange_11101@@3 Q A P B Q B Q B _N A
> extern bool const * const *       * const * const strange_11011; //
> ?strange_11011@@3 Q B Q A P B Q B _N B

I've verified a few of these with the Microsoft compiler, and it produces the same mangling as dmc. I'm still confused why the storage classes (the trailing A/B) for the two declarations above are supposed to be different...

_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals