`ref T` should be a type!!

Herb Sutter hsutter at microsoft.com
Sat Apr 6 15:27:47 UTC 2019


On Thursday, 4 April 2019 at 17:25:05 UTC, Andrei Alexandrescu 
wrote:
> On 4/4/19 1:20 PM, Manu wrote:
>> Also, FWIW, I think this is a fairly recent change (ie, last 5 
>> years).
>
> Good to know, thanks! Found this, too:
>
> https://stackoverflow.com/questions/32447978/odd-vs-name-mangling-behavior/32448512
>
> I'll email Herb.

Andrei sent me mail and I did a little digging. Much of the 
following is courtesy Jonathan Caves (thanks Jon!).

Pasting what I sent to Andrei with light edits:


Short answer: Yes, but most C++ code won't (and doesn't) notice 
because to see the different mangling you have to declare the 
function differently in two translation units, *and* have 
different "first" declarations in those TUs. So this is invisible 
for any function you declare in a shared header (because everyone 
sees the same first declaration). And it's invisible when you 
declare without top-level const and then define with top-level 
const on a parameter (because everyone uses the first 
declaration).


Longer answer: Yes, this is a long standing known issue – our 
name decorator was developed long before C++98 codified a lot of 
stuff.

Note that there are two mangling issues involved that come up in 
your example (or minor variations of it): [dcl.fct]/5 says that 
function parameters ignore top-level const and treat [] as *:

> After determining the type of each parameter, any parameter of 
> type
> “array of T” or of function type T is adjusted to be “pointer 
> to T”.
> After producing the list of parameter types, any top-level 
> cv-qualifiers
> modifying a parameter type are deleted when forming the 
> function type.

So these are supposed to be equivalent redeclarations of f and g:

~~~
// Case 1
void f(int);
void f(int const); // same, redeclaration

// Case 2
void g(int*);
void g(int[]); // same, redeclaration
~~~

And in VC++ they are correctly equivalent, in the language. 
However, for name mangling, VC++ selects mangling based on the 
first declaration it seems, and it does mangle each of these 
pairs differently, so if two TUs have different first 
declarations of each of f and g, they can’t link.

Again, to make this actually visible to users, they have to see 
different *first* declarations. For starters that means they’re 
not using a shared header.

I understand that someone you know found it caused trouble with 
linking foreign code with C++, though presumably that’s because 
they had to write their own declaration by hand (in C++, or in 
the other language)? I’ve mostly seen that sort of thing when 
people have to write their own declarations, and in those cases 
they also had general fragility (e.g., writing int vs long, that 
sort of thing – because they have to be careful to get the 
declarations exactly right because they’re writing them manually, 
same trouble that Java JNI and .NET P/Invoke have in general, you 
have to make the parameters perfect).

The worry about ‘fixing’ the name decorator is that it would be 
an ABI breaking change and so we have always be reticent in 
making any changes. That said, if we had customer examples that 
this was causing serious problems, we’d consider it. If you have 
production examples you could share or link to that would be 
helpful. Mostly, we don’t hear about this and I couldn’t find a 
report of it in our current online bug tracking systems (but I 
may have missed it) – most people are like you and rarely notice 
it even though it’s been like this for ~25 years. :) Because you 
have to be writing code in a fairly special way, effectively 
writing somebody else's function declaration by hand instead of 
using the .h they provided, and write it differently than in that 
.h, to be able to notice.


More information about the Digitalmars-d mailing list