Bug 18955 – extern(C++) default struct mangling is overridden when interacting with a `cppmangle = class` template
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Windows
Creation time
2018-06-08T04:29:44Z
Last change time
2018-09-29T16:28:02Z
Keywords
C++, industry
Assigned to
No Owner
Creator
Manu
Comments
Comment #0 by turkeyman — 2018-06-08T04:29:44Z
test.c:
------------------------------------------------
extern (C++, std)
{
extern (C++) struct char_traits(Char)
{
}
extern (C++, class) struct basic_string(T, Traits, Alloc)
{
}
alias string = basic_string!(char, char_traits!char);
}
extern (C++) void test(ref const(std.string) str) {}
------------------------------------------------
char_traits has no mangle spec, so it should mangle as struct, and it does...
except in this case where it's used an a template argument to basic_string which is mangled as a class, char_traits gets promoted to mangle as a class too, not only in the instantiation of basic_string but even when it appears on its own too.
char_traits should mangle as a struct, because that's how it's declared.
Comment #1 by turkeyman — 2018-06-08T04:32:06Z
This symptom is a result of the same logic that causes the related ICE at typesem.d:~1310
I don't understand the logic, perhaps Walter can take a look who understands the intent of that code?
Comment #2 by slavo5150 — 2018-07-12T11:11:20Z
`alias string = basic_string!(char, char_traits!char);` has two template arguments, but `extern (C++, class) struct basic_string(T, Traits, Alloc)` had 3.
This results in:
Error: template instance `basic_string!(char, char_traits!char)` does not match template declaration
I'm not sure what I should be doing to reproduce the problem.
Comment #3 by turkeyman — 2018-07-12T18:45:58Z
I'm sorry. I think I must have cut&paste fail-ed. Remove the `Alloc` arg:
-------------------------------
extern (C++, std)
{
struct char_traits(Char)
{
}
extern (C++, class) struct basic_string(T, Traits)
{
}
alias test_string = basic_string!(char, char_traits!char);
}
extern (C++) void test(ref const(std.test_string) str) {}
pragma(msg, test.mangleof);
-------------------------------
Compile that, it will emit:
?test@@YAXAEBV?$basic_string@DV?$char_traits@D@std@@@std@@@Z
But it should emit:
?test@@YAXAEBV?$basic_string@DU?$char_traits@D@std@@@std@@@Z
Notice the 'V?$char_traits' (class) should be a 'U?$char_traits' (struct); char_traits is a struct.
If you add:
extern (C++, struct) struct char_traits(Char)
ie, tell it explicitly to mangle the struct as a struct, it mangles correctly. Of course, a struct should mangle as a struct naturally though.
Comment #4 by schveiguy — 2018-07-13T17:51:22Z
Saw the name in the D blog, had to fix it... Darn OCD.
Comment #5 by turkeyman — 2018-07-13T18:21:42Z
Not sure what that post means..
Comment #6 by schveiguy — 2018-07-13T18:44:58Z
Sorry, I fixed a typo in the title of the bug report "tamplate".