November 08, 2006
Apart from implementation issues like #211, #375 and #466, D's current name mangling achieves the primary target:
> Make it possible for linkers to distinguish between different versions of overloaded functions.

However it fails to address the consistency issue:
> Make it possible for linkers to check that objects and functions are declared in exactly the same way in all modules.

The problem is that it isn't reversible,
causing all kinds of problems for runtime reflections.


issue 1: missing "static" information
#
# class C{
#    void foo(){}
#    static void bar(){}
# }
#
_D8mangling1C3fooFZv
_D8mangling1C3barFZv


issue 2: missing "struct"/"union" information
#
# union  Cat { int i; }
# struct Cow { int i; }
#
# Cat foo() { assert(0); }
# Cow bar() { assert(0); }

_init_8mangling3Cat
_init_8mangling3Cow
_D8mangling3fooFZS8mangling3Cat
_D8mangling3barFZS8mangling3Cow


issue 3: missing "const" information
#
# int X = 0;
# const int Y = 0;
#
_D8mangling1Xi
_D8mangling1Yi


issue 4: missing protection attributes

While the ELF object format used by Linux supports differentiation
of "private" and "public" (though see issue #463),
"package" and "protected" can't be differentiated.

issue 5: missing "final" information
#
# class C{
#    final void foo() {}
#    void bar() {}
# }
#
_D8mangling1C3fooFZv
_D8mangling1C3barFZv


Especially the "static" and "struct"/"enum" issues pose a problem for runtime reflection due to their effects on calling conventions.

Thomas


November 09, 2006
Thomas Kuehne wrote:
> Apart from implementation issues like #211, #375 and #466,
> D's current name mangling achieves the primary target:
>> Make it possible for linkers to distinguish between different
>> versions of overloaded functions.
> 
> However it fails to address the consistency issue:
>> Make it possible for linkers to check that objects and
>> functions are declared in exactly the same way in all modules.
> 
> The problem is that it isn't reversible,
> causing all kinds of problems for runtime reflections.
> 
> 
> issue 1: missing "static" information
> #
> # class C{
> #    void foo(){}
> #    static void bar(){}
> # }
> #
> _D8mangling1C3fooFZv
> _D8mangling1C3barFZv
> 
> 
> issue 2: missing "struct"/"union" information
> #
> # union  Cat { int i; }
> # struct Cow { int i; }
> #
> # Cat foo() { assert(0); }
> # Cow bar() { assert(0); }
> 
> _init_8mangling3Cat
> _init_8mangling3Cow
> _D8mangling3fooFZS8mangling3Cat
> _D8mangling3barFZS8mangling3Cow
> 
> 
> issue 3: missing "const" information
> #
> # int X = 0;
> # const int Y = 0;
> #
> _D8mangling1Xi
> _D8mangling1Yi
> 
> 
> issue 4: missing protection attributes
> 
> While the ELF object format used by Linux supports differentiation
> of "private" and "public" (though see issue #463), "package" and "protected" can't be differentiated.
> 
> issue 5: missing "final" information
> #
> # class C{
> #    final void foo() {}
> #    void bar() {}
> # }
> #
> _D8mangling1C3fooFZv
> _D8mangling1C3barFZv
> 
> 
> Especially the "static" and "struct"/"enum" issues pose a problem for
> runtime reflection due to their effects on calling conventions.
> 
> Thomas

Here's another irreversible demangling.

Normally, anything declared as "extern (Windows)"/extern(C)/... has no type information in its name mangling; only the undecorated name is used. Yet nested classes, types and functions inside such an extern(XXX) function have decorated names. This is a very obscure situation because normally, such entities won't have external linkage. It might be more important now that local variables are allowed as template alias parameters.

In example 1 below, the mangled name of fox is:
Cwolf3fox. Note that there's no length before 'wolf' (it's not 4wolf).
Example 2 shows a (highly contrived) situation where two distinct classes have the same
mangled name "Cwolf5dingo3fox".
If length information were included, the mangled names would be "C4wolf5dingo3fox"
and "C10wolf5dingo3fox".
In example 3 (which has no extern(Windows)), the mangled name is "C4wolf5dingo3fox".

---
Example 1.
extern(Windows) {

void wolf()
{
	class fox {}
	pragma(msg, fox.mangleof);
}

}
---
Example 2.

extern(Windows) {
void wolf()
{
	class dingo {
		class fox {}
		pragma(msg, fox.mangleof);
	}
}
void wolf5dingo()
{
	class fox {}
	pragma(msg, fox.mangleof);
}

}
---
Example 3: file called 'wolf.d'.

module wolf;

class dingo {
	class fox {}
	pragma(msg, fox.mangleof);
}

=================