forked from OSchip/llvm-project
Add support for various C++14 demanglings.
Mostly this includes <auto> and <decltype-auto> return values. Additionally, this fixes a fairly obscure back-referencing bug that was encountered in one of the C++14 tests, which is that if you have something like Foo<&bar, &bar> then the `bar` forms a backreference. llvm-svn: 340896
This commit is contained in:
parent
38d2edd60d
commit
b2fef1a0b0
|
@ -191,6 +191,8 @@ static bool isTagType(StringView S) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool isCustomType(StringView S) { return S[0] == '?'; }
|
||||
|
||||
static bool isPointerType(StringView S) {
|
||||
if (S.startsWith("$$Q")) // foo &&
|
||||
return true;
|
||||
|
@ -288,6 +290,7 @@ private:
|
|||
// Parser functions. This is a recursive-descent parser.
|
||||
TypeNode *demangleType(StringView &MangledName, QualifierMangleMode QMM);
|
||||
PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName);
|
||||
CustomTypeNode *demangleCustomType(StringView &MangledName);
|
||||
TagTypeNode *demangleClassType(StringView &MangledName);
|
||||
PointerTypeNode *demanglePointerType(StringView &MangledName);
|
||||
PointerTypeNode *demangleMemberPointerType(StringView &MangledName);
|
||||
|
@ -304,6 +307,7 @@ private:
|
|||
int64_t demangleSigned(StringView &MangledName);
|
||||
|
||||
void memorizeString(StringView s);
|
||||
void memorizeIdentifier(IdentifierNode *Identifier);
|
||||
|
||||
/// Allocate a copy of \p Borrowed into memory that we own.
|
||||
StringView copyString(StringView Borrowed);
|
||||
|
@ -972,6 +976,19 @@ NamedIdentifierNode *Demangler::demangleBackRefName(StringView &MangledName) {
|
|||
return Backrefs.Names[I];
|
||||
}
|
||||
|
||||
void Demangler::memorizeIdentifier(IdentifierNode *Identifier) {
|
||||
// Render this class template name into a string buffer so that we can
|
||||
// memorize it for the purpose of back-referencing.
|
||||
OutputStream OS = OutputStream::create(nullptr, nullptr, 1024);
|
||||
Identifier->output(OS, OF_Default);
|
||||
OS << '\0';
|
||||
char *Name = OS.getBuffer();
|
||||
|
||||
StringView Owned = copyString(Name);
|
||||
memorizeString(Owned);
|
||||
std::free(Name);
|
||||
}
|
||||
|
||||
IdentifierNode *
|
||||
Demangler::demangleTemplateInstantiationName(StringView &MangledName,
|
||||
NameBackrefBehavior NBB) {
|
||||
|
@ -990,18 +1007,8 @@ Demangler::demangleTemplateInstantiationName(StringView &MangledName,
|
|||
if (Error)
|
||||
return nullptr;
|
||||
|
||||
if (NBB & NBB_Template) {
|
||||
// Render this class template name into a string buffer so that we can
|
||||
// memorize it for the purpose of back-referencing.
|
||||
OutputStream OS = OutputStream::create(nullptr, nullptr, 1024);
|
||||
Identifier->output(OS, OF_Default);
|
||||
OS << '\0';
|
||||
char *Name = OS.getBuffer();
|
||||
|
||||
StringView Owned = copyString(Name);
|
||||
memorizeString(Owned);
|
||||
std::free(Name);
|
||||
}
|
||||
if (NBB & NBB_Template)
|
||||
memorizeIdentifier(Identifier);
|
||||
|
||||
return Identifier;
|
||||
}
|
||||
|
@ -1749,6 +1756,8 @@ TypeNode *Demangler::demangleType(StringView &MangledName,
|
|||
MangledName.consumeFront("$$A6");
|
||||
Ty = demangleFunctionType(MangledName, false);
|
||||
}
|
||||
} else if (isCustomType(MangledName)) {
|
||||
Ty = demangleCustomType(MangledName);
|
||||
} else {
|
||||
Ty = demanglePrimitiveType(MangledName);
|
||||
assert(Ty && !Error);
|
||||
|
@ -1837,6 +1846,19 @@ Demangler::demangleFunctionEncoding(StringView &MangledName) {
|
|||
return Symbol;
|
||||
}
|
||||
|
||||
CustomTypeNode *Demangler::demangleCustomType(StringView &MangledName) {
|
||||
assert(MangledName.startsWith('?'));
|
||||
MangledName.popFront();
|
||||
|
||||
CustomTypeNode *CTN = Arena.alloc<CustomTypeNode>();
|
||||
CTN->Identifier = demangleUnqualifiedTypeName(MangledName, true);
|
||||
if (!MangledName.consumeFront('@'))
|
||||
Error = true;
|
||||
if (Error)
|
||||
return nullptr;
|
||||
return CTN;
|
||||
}
|
||||
|
||||
// Reads a primitive type.
|
||||
PrimitiveTypeNode *Demangler::demanglePrimitiveType(StringView &MangledName) {
|
||||
if (MangledName.consumeFront("$$T"))
|
||||
|
@ -2131,8 +2153,12 @@ Demangler::demangleTemplateParameterList(StringView &MangledName) {
|
|||
// I - virtual inheritance <name> <number> <number> <number>
|
||||
// J - unspecified inheritance <name> <number> <number> <number>
|
||||
char InheritanceSpecifier = MangledName.popFront();
|
||||
SymbolNode *S =
|
||||
MangledName.startsWith('?') ? parse(MangledName) : nullptr;
|
||||
SymbolNode *S = nullptr;
|
||||
if (MangledName.startsWith('?')) {
|
||||
S = parse(MangledName);
|
||||
memorizeIdentifier(S->Name->getUnqualifiedIdentifier());
|
||||
}
|
||||
|
||||
switch (InheritanceSpecifier) {
|
||||
case 'J':
|
||||
TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
|
||||
|
|
|
@ -565,9 +565,10 @@ void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
|
|||
Type->outputPost(OS, Flags);
|
||||
}
|
||||
|
||||
void CustomNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
OS << Name;
|
||||
void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
|
||||
Identifier->output(OS, Flags);
|
||||
}
|
||||
void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
|
||||
|
||||
void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const {
|
||||
Components->output(OS, Flags, "::");
|
||||
|
|
|
@ -148,7 +148,10 @@ enum class CallingConv : uint8_t {
|
|||
|
||||
enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef };
|
||||
|
||||
enum OutputFlags { OF_Default = 0, OF_NoCallingConvention = 1 };
|
||||
enum OutputFlags {
|
||||
OF_Default = 0,
|
||||
OF_NoCallingConvention = 1,
|
||||
};
|
||||
|
||||
// Types
|
||||
enum class PrimitiveKind {
|
||||
|
@ -392,8 +395,8 @@ struct FunctionSignatureNode : public TypeNode {
|
|||
explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) {}
|
||||
FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) {}
|
||||
|
||||
virtual void outputPre(OutputStream &OS, OutputFlags Flags) const;
|
||||
virtual void outputPost(OutputStream &OS, OutputFlags Flags) const;
|
||||
void outputPre(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPost(OutputStream &OS, OutputFlags Flags) const override;
|
||||
|
||||
// Valid if this FunctionTypeNode is the Pointee of a PointerType or
|
||||
// MemberPointerType.
|
||||
|
@ -566,13 +569,13 @@ struct IntrinsicNode : public TypeNode {
|
|||
void output(OutputStream &OS, OutputFlags Flags) const override {}
|
||||
};
|
||||
|
||||
struct CustomNode : public Node {
|
||||
CustomNode() : Node(NodeKind::Custom) {}
|
||||
struct CustomTypeNode : public TypeNode {
|
||||
CustomTypeNode() : TypeNode(NodeKind::Custom) {}
|
||||
|
||||
void output(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPre(OutputStream &OS, OutputFlags Flags) const override;
|
||||
void outputPost(OutputStream &OS, OutputFlags Flags) const override;
|
||||
|
||||
// The string to print.
|
||||
StringView Name;
|
||||
IdentifierNode *Identifier;
|
||||
};
|
||||
|
||||
struct NodeArrayNode : public Node {
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
; These tests are based on clang/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
|
||||
; RUN: llvm-undname < %s | FileCheck %s
|
||||
|
||||
; CHECK-NOT: Invalid mangled name
|
||||
|
||||
??$x@X@@3HA
|
||||
; CHECK: int x<void>
|
||||
|
||||
?FunctionWithLocalType@@YA?A?<auto>@@XZ
|
||||
; CHECK: <auto> __cdecl FunctionWithLocalType(void)
|
||||
|
||||
?ValueFromFunctionWithLocalType@@3ULocalType@?1??FunctionWithLocalType@@YA?A?<auto>@@XZ@A
|
||||
; CHECK: struct `<auto> __cdecl FunctionWithLocalType(void)'::`2'::LocalType ValueFromFunctionWithLocalType
|
||||
|
||||
??R<lambda_0>@@QBE?A?<auto>@@XZ
|
||||
; CHECK: <auto> __thiscall <lambda_0>::operator()(void) const
|
||||
|
||||
?ValueFromLambdaWithLocalType@@3ULocalType@?1???R<lambda_0>@@QBE?A?<auto>@@XZ@A
|
||||
; CHECK: struct `<auto> __thiscall <lambda_0>::operator()(void) const'::`2'::LocalType ValueFromLambdaWithLocalType
|
||||
|
||||
?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?3@XZ@A
|
||||
; CHECK: struct `<auto> __thiscall `<auto> __cdecl TemplateFuncionWithLocalLambda<int>(int)'::`1'::<lambda_1>::operator()(void) const'::`3'::LocalType ValueFromTemplateFuncionWithLocalLambda
|
||||
|
||||
??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z
|
||||
; CHECK: <auto> __cdecl TemplateFuncionWithLocalLambda<int>(int)
|
||||
|
||||
??R<lambda_1>@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBE?A?1@XZ
|
||||
; CHECK: <auto> __thiscall `<auto> __cdecl TemplateFuncionWithLocalLambda<int>(int)'::`1'::<lambda_1>::operator()(void) const
|
||||
|
||||
??$WithPMD@$GA@A@?0@@3HA
|
||||
; CHECK: int WithPMD<{0, 0, -1}>
|
||||
|
||||
?Zoo@@3U?$Foo@$1??$x@H@@3HA$1?1@3HA@@A
|
||||
; CHECK: struct Foo<&int x<int>, &int x<int>> Zoo
|
||||
|
||||
??$unaligned_x@PFAH@@3PFAHA
|
||||
; CHECK: int __unaligned *unaligned_x<int __unaligned *>
|
Loading…
Reference in New Issue