llvm.org GIT mirror llvm / ef6d904
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@340896 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 22 days ago
4 changed file(s) with 94 addition(s) and 27 deletion(s). Raw diff Collapse all Expand all
190190 return false;
191191 }
192192
193 static bool isCustomType(StringView S) { return S[0] == '?'; }
194
193195 static bool isPointerType(StringView S) {
194196 if (S.startsWith("$$Q")) // foo &&
195197 return true;
287289 // Parser functions. This is a recursive-descent parser.
288290 TypeNode *demangleType(StringView &MangledName, QualifierMangleMode QMM);
289291 PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName);
292 CustomTypeNode *demangleCustomType(StringView &MangledName);
290293 TagTypeNode *demangleClassType(StringView &MangledName);
291294 PointerTypeNode *demanglePointerType(StringView &MangledName);
292295 PointerTypeNode *demangleMemberPointerType(StringView &MangledName);
303306 int64_t demangleSigned(StringView &MangledName);
304307
305308 void memorizeString(StringView s);
309 void memorizeIdentifier(IdentifierNode *Identifier);
306310
307311 /// Allocate a copy of \p Borrowed into memory that we own.
308312 StringView copyString(StringView Borrowed);
971975 return Backrefs.Names[I];
972976 }
973977
978 void Demangler::memorizeIdentifier(IdentifierNode *Identifier) {
979 // Render this class template name into a string buffer so that we can
980 // memorize it for the purpose of back-referencing.
981 OutputStream OS = OutputStream::create(nullptr, nullptr, 1024);
982 Identifier->output(OS, OF_Default);
983 OS << '\0';
984 char *Name = OS.getBuffer();
985
986 StringView Owned = copyString(Name);
987 memorizeString(Owned);
988 std::free(Name);
989 }
990
974991 IdentifierNode *
975992 Demangler::demangleTemplateInstantiationName(StringView &MangledName,
976993 NameBackrefBehavior NBB) {
9891006 if (Error)
9901007 return nullptr;
9911008
992 if (NBB & NBB_Template) {
993 // Render this class template name into a string buffer so that we can
994 // memorize it for the purpose of back-referencing.
995 OutputStream OS = OutputStream::create(nullptr, nullptr, 1024);
996 Identifier->output(OS, OF_Default);
997 OS << '\0';
998 char *Name = OS.getBuffer();
999
1000 StringView Owned = copyString(Name);
1001 memorizeString(Owned);
1002 std::free(Name);
1003 }
1009 if (NBB & NBB_Template)
1010 memorizeIdentifier(Identifier);
10041011
10051012 return Identifier;
10061013 }
17481755 MangledName.consumeFront("$$A6");
17491756 Ty = demangleFunctionType(MangledName, false);
17501757 }
1758 } else if (isCustomType(MangledName)) {
1759 Ty = demangleCustomType(MangledName);
17511760 } else {
17521761 Ty = demanglePrimitiveType(MangledName);
17531762 assert(Ty && !Error);
18341843 FunctionSymbolNode *Symbol = Arena.alloc();
18351844 Symbol->Signature = FSN;
18361845 return Symbol;
1846 }
1847
1848 CustomTypeNode *Demangler::demangleCustomType(StringView &MangledName) {
1849 assert(MangledName.startsWith('?'));
1850 MangledName.popFront();
1851
1852 CustomTypeNode *CTN = Arena.alloc();
1853 CTN->Identifier = demangleUnqualifiedTypeName(MangledName, true);
1854 if (!MangledName.consumeFront('@'))
1855 Error = true;
1856 if (Error)
1857 return nullptr;
1858 return CTN;
18371859 }
18381860
18391861 // Reads a primitive type.
21302152 // I - virtual inheritance
21312153 // J - unspecified inheritance
21322154 char InheritanceSpecifier = MangledName.popFront();
2133 SymbolNode *S =
2134 MangledName.startsWith('?') ? parse(MangledName) : nullptr;
2155 SymbolNode *S = nullptr;
2156 if (MangledName.startsWith('?')) {
2157 S = parse(MangledName);
2158 memorizeIdentifier(S->Name->getUnqualifiedIdentifier());
2159 }
2160
21352161 switch (InheritanceSpecifier) {
21362162 case 'J':
21372163 TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
564564 Type->outputPost(OS, Flags);
565565 }
566566
567 void CustomNode::output(OutputStream &OS, OutputFlags Flags) const {
568 OS << Name;
569 }
567 void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
568 Identifier->output(OS, Flags);
569 }
570 void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
570571
571572 void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const {
572573 Components->output(OS, Flags, "::");
147147
148148 enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef };
149149
150 enum OutputFlags { OF_Default = 0, OF_NoCallingConvention = 1 };
150 enum OutputFlags {
151 OF_Default = 0,
152 OF_NoCallingConvention = 1,
153 };
151154
152155 // Types
153156 enum class PrimitiveKind {
391394 explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) {}
392395 FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) {}
393396
394 virtual void outputPre(OutputStream &OS, OutputFlags Flags) const;
395 virtual void outputPost(OutputStream &OS, OutputFlags Flags) const;
397 void outputPre(OutputStream &OS, OutputFlags Flags) const override;
398 void outputPost(OutputStream &OS, OutputFlags Flags) const override;
396399
397400 // Valid if this FunctionTypeNode is the Pointee of a PointerType or
398401 // MemberPointerType.
565568 void output(OutputStream &OS, OutputFlags Flags) const override {}
566569 };
567570
568 struct CustomNode : public Node {
569 CustomNode() : Node(NodeKind::Custom) {}
570
571 void output(OutputStream &OS, OutputFlags Flags) const override;
572
573 // The string to print.
574 StringView Name;
571 struct CustomTypeNode : public TypeNode {
572 CustomTypeNode() : TypeNode(NodeKind::Custom) {}
573
574 void outputPre(OutputStream &OS, OutputFlags Flags) const override;
575 void outputPost(OutputStream &OS, OutputFlags Flags) const override;
576
577 IdentifierNode *Identifier;
575578 };
576579
577580 struct NodeArrayNode : public Node {
0 ; These tests are based on clang/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
1 ; RUN: llvm-undname < %s | FileCheck %s
2
3 ; CHECK-NOT: Invalid mangled name
4
5 ??$x@X@@3HA
6 ; CHECK: int x
7
8 ?FunctionWithLocalType@@YA?A?@@XZ
9 ; CHECK: __cdecl FunctionWithLocalType(void)
10
11 ?ValueFromFunctionWithLocalType@@3ULocalType@?1??FunctionWithLocalType@@YA?A?@@XZ@A
12 ; CHECK: struct ` __cdecl FunctionWithLocalType(void)'::`2'::LocalType ValueFromFunctionWithLocalType
13
14 ??R@@QBE?A?@@XZ
15 ; CHECK: __thiscall ::operator()(void) const
16
17 ?ValueFromLambdaWithLocalType@@3ULocalType@?1???R@@QBE?A?@@XZ@A
18 ; CHECK: struct ` __thiscall ::operator()(void) const'::`2'::LocalType ValueFromLambdaWithLocalType
19
20 ?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z@QBE?A?3@XZ@A
21 ; CHECK: struct ` __thiscall ` __cdecl TemplateFuncionWithLocalLambda(int)'::`1'::::operator()(void) const'::`3'::LocalType ValueFromTemplateFuncionWithLocalLambda
22
23 ??$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z
24 ; CHECK: __cdecl TemplateFuncionWithLocalLambda(int)
25
26 ??R@?0???$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z@QBE?A?1@XZ
27 ; CHECK: __thiscall ` __cdecl TemplateFuncionWithLocalLambda(int)'::`1'::::operator()(void) const
28
29 ??$WithPMD@$GA@A@?0@@3HA
30 ; CHECK: int WithPMD<{0, 0, -1}>
31
32 ?Zoo@@3U?$Foo@$1??$x@H@@3HA$1?1@3HA@@A
33 ; CHECK: struct Foo<&int x, &int x> Zoo
34
35 ??$unaligned_x@PFAH@@3PFAHA
36 ; CHECK: int __unaligned *unaligned_x