return VSN;
}
+void dump(Node *N) {
+ OutputStream OS = OutputStream::create(nullptr, nullptr, 1024);
+ N->output(OS, OF_Default);
+ OS << '\0';
+ char *Name = OS.getBuffer();
+
+ printf(Name);
+ printf("\n");
+ std::free(Name);
+}
+
FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName,
bool IsDestructor) {
DynamicStructorIdentifierNode *DSIN =
Arena.alloc<DynamicStructorIdentifierNode>();
DSIN->IsDestructor = IsDestructor;
- // What follows is a main symbol name. This may include namespaces or class
- // back references.
+ bool IsKnownStaticDataMember = false;
+ if (MangledName.consumeFront('?'))
+ IsKnownStaticDataMember = true;
+
QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName);
SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN);
if (Symbol->kind() == NodeKind::VariableSymbol) {
DSIN->Variable = static_cast<VariableSymbolNode *>(Symbol);
- if (!MangledName.consumeFront('@')) {
+
+ // Older versions of clang mangled this type of symbol incorrectly. They
+ // would omit the leading ? and they would only emit a single @ at the end.
+ // The correct mangling is a leading ? and 2 trailing @ signs. Handle
+ // both cases.
+ int AtCount = IsKnownStaticDataMember ? 2 : 1;
+ for (int I = 0; I < AtCount; ++I) {
+ if (MangledName.consumeFront('@'))
+ continue;
Error = true;
return nullptr;
}
FSN = demangleFunctionEncoding(MangledName);
FSN->Name = synthesizeQualifiedName(Arena, DSIN);
} else {
+ if (IsKnownStaticDataMember) {
+ // This was supposed to be a static data member, but we got a function.
+ Error = true;
+ return nullptr;
+ }
+
FSN = static_cast<FunctionSymbolNode *>(Symbol);
DSIN->Name = Symbol->Name;
FSN->Name = synthesizeQualifiedName(Arena, DSIN);
while (!Error && !MangledName.startsWith('@')) {
if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") ||
- MangledName.consumeFront("$$$V")) {
- // Empty parameter pack.
+ MangledName.consumeFront("$$$V") || MangledName.consumeFront("$$Z")) {
+ // parameter pack separator
continue;
}
??$templ_fun_with_pack@$S@@YAXXZ
; CHECK: void __cdecl templ_fun_with_pack<>(void)
+; $$Z is a parameter pack separator.
+??$func@H$$ZH@@YAHAEBU?$Foo@H@@0@Z
+; CHECK: int __cdecl func<int, int>(struct Foo<int> const &, struct Foo<int> const &)
+
??$templ_fun_with_ty_pack@$$$V@@YAXXZ
; CHECK: void __cdecl templ_fun_with_ty_pack<>(void)
??$templ_fun_with_ty_pack@$$V@@YAXXZ