`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