File: | lib/Demangle/MicrosoftDemangle.cpp |
Warning: | line 2154, column 12 2nd function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- MicrosoftDemangle.cpp ----------------------------------------------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is dual licensed under the MIT and the University of Illinois Open | |||
6 | // Source Licenses. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | // This file defines a demangler for MSVC-style mangled symbols. | |||
11 | // | |||
12 | // This file has no dependencies on the rest of LLVM so that it can be | |||
13 | // easily reused in other programs such as libcxxabi. | |||
14 | // | |||
15 | //===----------------------------------------------------------------------===// | |||
16 | ||||
17 | #include "llvm/Demangle/MicrosoftDemangle.h" | |||
18 | #include "llvm/Demangle/Demangle.h" | |||
19 | #include "llvm/Demangle/MicrosoftDemangleNodes.h" | |||
20 | ||||
21 | #include "llvm/Demangle/Compiler.h" | |||
22 | #include "llvm/Demangle/StringView.h" | |||
23 | #include "llvm/Demangle/Utility.h" | |||
24 | ||||
25 | #include <array> | |||
26 | #include <cctype> | |||
27 | #include <cstdio> | |||
28 | #include <tuple> | |||
29 | ||||
30 | using namespace llvm; | |||
31 | using namespace ms_demangle; | |||
32 | ||||
33 | static bool startsWithDigit(StringView S) { | |||
34 | return !S.empty() && std::isdigit(S.front()); | |||
35 | } | |||
36 | ||||
37 | ||||
38 | struct NodeList { | |||
39 | Node *N = nullptr; | |||
40 | NodeList *Next = nullptr; | |||
41 | }; | |||
42 | ||||
43 | static bool isMemberPointer(StringView MangledName, bool &Error) { | |||
44 | Error = false; | |||
45 | switch (MangledName.popFront()) { | |||
46 | case '$': | |||
47 | // This is probably an rvalue reference (e.g. $$Q), and you cannot have an | |||
48 | // rvalue reference to a member. | |||
49 | return false; | |||
50 | case 'A': | |||
51 | // 'A' indicates a reference, and you cannot have a reference to a member | |||
52 | // function or member. | |||
53 | return false; | |||
54 | case 'P': | |||
55 | case 'Q': | |||
56 | case 'R': | |||
57 | case 'S': | |||
58 | // These 4 values indicate some kind of pointer, but we still don't know | |||
59 | // what. | |||
60 | break; | |||
61 | default: | |||
62 | Error = true; | |||
63 | return false; | |||
64 | } | |||
65 | ||||
66 | // If it starts with a number, then 6 indicates a non-member function | |||
67 | // pointer, and 8 indicates a member function pointer. | |||
68 | if (startsWithDigit(MangledName)) { | |||
69 | assert(MangledName[0] == '6' || MangledName[0] == '8')((MangledName[0] == '6' || MangledName[0] == '8') ? static_cast <void> (0) : __assert_fail ("MangledName[0] == '6' || MangledName[0] == '8'" , "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 69, __PRETTY_FUNCTION__)); | |||
70 | return (MangledName[0] == '8'); | |||
71 | } | |||
72 | ||||
73 | // Remove ext qualifiers since those can appear on either type and are | |||
74 | // therefore not indicative. | |||
75 | MangledName.consumeFront('E'); // 64-bit | |||
76 | MangledName.consumeFront('I'); // restrict | |||
77 | MangledName.consumeFront('F'); // unaligned | |||
78 | ||||
79 | assert(!MangledName.empty())((!MangledName.empty()) ? static_cast<void> (0) : __assert_fail ("!MangledName.empty()", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 79, __PRETTY_FUNCTION__)); | |||
80 | ||||
81 | // The next value should be either ABCD (non-member) or QRST (member). | |||
82 | switch (MangledName.front()) { | |||
83 | case 'A': | |||
84 | case 'B': | |||
85 | case 'C': | |||
86 | case 'D': | |||
87 | return false; | |||
88 | case 'Q': | |||
89 | case 'R': | |||
90 | case 'S': | |||
91 | case 'T': | |||
92 | return true; | |||
93 | default: | |||
94 | Error = true; | |||
95 | return false; | |||
96 | } | |||
97 | } | |||
98 | ||||
99 | static SpecialIntrinsicKind | |||
100 | consumeSpecialIntrinsicKind(StringView &MangledName) { | |||
101 | if (MangledName.consumeFront("?_7")) | |||
102 | return SpecialIntrinsicKind::Vftable; | |||
103 | if (MangledName.consumeFront("?_8")) | |||
104 | return SpecialIntrinsicKind::Vbtable; | |||
105 | if (MangledName.consumeFront("?_9")) | |||
106 | return SpecialIntrinsicKind::VcallThunk; | |||
107 | if (MangledName.consumeFront("?_A")) | |||
108 | return SpecialIntrinsicKind::Typeof; | |||
109 | if (MangledName.consumeFront("?_B")) | |||
110 | return SpecialIntrinsicKind::LocalStaticGuard; | |||
111 | if (MangledName.consumeFront("?_C")) | |||
112 | return SpecialIntrinsicKind::StringLiteralSymbol; | |||
113 | if (MangledName.consumeFront("?_P")) | |||
114 | return SpecialIntrinsicKind::UdtReturning; | |||
115 | if (MangledName.consumeFront("?_R0")) | |||
116 | return SpecialIntrinsicKind::RttiTypeDescriptor; | |||
117 | if (MangledName.consumeFront("?_R1")) | |||
118 | return SpecialIntrinsicKind::RttiBaseClassDescriptor; | |||
119 | if (MangledName.consumeFront("?_R2")) | |||
120 | return SpecialIntrinsicKind::RttiBaseClassArray; | |||
121 | if (MangledName.consumeFront("?_R3")) | |||
122 | return SpecialIntrinsicKind::RttiClassHierarchyDescriptor; | |||
123 | if (MangledName.consumeFront("?_R4")) | |||
124 | return SpecialIntrinsicKind::RttiCompleteObjLocator; | |||
125 | if (MangledName.consumeFront("?_S")) | |||
126 | return SpecialIntrinsicKind::LocalVftable; | |||
127 | if (MangledName.consumeFront("?__E")) | |||
128 | return SpecialIntrinsicKind::DynamicInitializer; | |||
129 | if (MangledName.consumeFront("?__F")) | |||
130 | return SpecialIntrinsicKind::DynamicAtexitDestructor; | |||
131 | if (MangledName.consumeFront("?__J")) | |||
132 | return SpecialIntrinsicKind::LocalStaticThreadGuard; | |||
133 | return SpecialIntrinsicKind::None; | |||
134 | } | |||
135 | ||||
136 | static bool startsWithLocalScopePattern(StringView S) { | |||
137 | if (!S.consumeFront('?')) | |||
138 | return false; | |||
139 | if (S.size() < 2) | |||
140 | return false; | |||
141 | ||||
142 | size_t End = S.find('?'); | |||
143 | if (End == StringView::npos) | |||
144 | return false; | |||
145 | StringView Candidate = S.substr(0, End); | |||
146 | if (Candidate.empty()) | |||
147 | return false; | |||
148 | ||||
149 | // \?[0-9]\? | |||
150 | // ?@? is the discriminator 0. | |||
151 | if (Candidate.size() == 1) | |||
152 | return Candidate[0] == '@' || (Candidate[0] >= '0' && Candidate[0] <= '9'); | |||
153 | ||||
154 | // If it's not 0-9, then it's an encoded number terminated with an @ | |||
155 | if (Candidate.back() != '@') | |||
156 | return false; | |||
157 | Candidate = Candidate.dropBack(); | |||
158 | ||||
159 | // An encoded number starts with B-P and all subsequent digits are in A-P. | |||
160 | // Note that the reason the first digit cannot be A is two fold. First, it | |||
161 | // would create an ambiguity with ?A which delimits the beginning of an | |||
162 | // anonymous namespace. Second, A represents 0, and you don't start a multi | |||
163 | // digit number with a leading 0. Presumably the anonymous namespace | |||
164 | // ambiguity is also why single digit encoded numbers use 0-9 rather than A-J. | |||
165 | if (Candidate[0] < 'B' || Candidate[0] > 'P') | |||
166 | return false; | |||
167 | Candidate = Candidate.dropFront(); | |||
168 | while (!Candidate.empty()) { | |||
169 | if (Candidate[0] < 'A' || Candidate[0] > 'P') | |||
170 | return false; | |||
171 | Candidate = Candidate.dropFront(); | |||
172 | } | |||
173 | ||||
174 | return true; | |||
175 | } | |||
176 | ||||
177 | static bool isTagType(StringView S) { | |||
178 | switch (S.front()) { | |||
179 | case 'T': // union | |||
180 | case 'U': // struct | |||
181 | case 'V': // class | |||
182 | case 'W': // enum | |||
183 | return true; | |||
184 | } | |||
185 | return false; | |||
186 | } | |||
187 | ||||
188 | static bool isCustomType(StringView S) { return S[0] == '?'; } | |||
189 | ||||
190 | static bool isPointerType(StringView S) { | |||
191 | if (S.startsWith("$$Q")) // foo && | |||
192 | return true; | |||
193 | ||||
194 | switch (S.front()) { | |||
195 | case 'A': // foo & | |||
196 | case 'P': // foo * | |||
197 | case 'Q': // foo *const | |||
198 | case 'R': // foo *volatile | |||
199 | case 'S': // foo *const volatile | |||
200 | return true; | |||
201 | } | |||
202 | return false; | |||
203 | } | |||
204 | ||||
205 | static bool isArrayType(StringView S) { return S[0] == 'Y'; } | |||
206 | ||||
207 | static bool isFunctionType(StringView S) { | |||
208 | return S.startsWith("$$A8@@") || S.startsWith("$$A6"); | |||
209 | } | |||
210 | ||||
211 | static FunctionRefQualifier | |||
212 | demangleFunctionRefQualifier(StringView &MangledName) { | |||
213 | if (MangledName.consumeFront('G')) | |||
214 | return FunctionRefQualifier::Reference; | |||
215 | else if (MangledName.consumeFront('H')) | |||
216 | return FunctionRefQualifier::RValueReference; | |||
217 | return FunctionRefQualifier::None; | |||
218 | } | |||
219 | ||||
220 | static std::pair<Qualifiers, PointerAffinity> | |||
221 | demanglePointerCVQualifiers(StringView &MangledName) { | |||
222 | if (MangledName.consumeFront("$$Q")) | |||
223 | return std::make_pair(Q_None, PointerAffinity::RValueReference); | |||
224 | ||||
225 | switch (MangledName.popFront()) { | |||
226 | case 'A': | |||
227 | return std::make_pair(Q_None, PointerAffinity::Reference); | |||
228 | case 'P': | |||
229 | return std::make_pair(Q_None, PointerAffinity::Pointer); | |||
230 | case 'Q': | |||
231 | return std::make_pair(Q_Const, PointerAffinity::Pointer); | |||
232 | case 'R': | |||
233 | return std::make_pair(Q_Volatile, PointerAffinity::Pointer); | |||
234 | case 'S': | |||
235 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), | |||
236 | PointerAffinity::Pointer); | |||
237 | default: | |||
238 | assert(false && "Ty is not a pointer type!")((false && "Ty is not a pointer type!") ? static_cast <void> (0) : __assert_fail ("false && \"Ty is not a pointer type!\"" , "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 238, __PRETTY_FUNCTION__)); | |||
239 | } | |||
240 | return std::make_pair(Q_None, PointerAffinity::Pointer); | |||
241 | } | |||
242 | ||||
243 | StringView Demangler::copyString(StringView Borrowed) { | |||
244 | char *Stable = Arena.allocUnalignedBuffer(Borrowed.size() + 1); | |||
245 | std::strcpy(Stable, Borrowed.begin()); | |||
246 | ||||
247 | return {Stable, Borrowed.size()}; | |||
248 | } | |||
249 | ||||
250 | SpecialTableSymbolNode * | |||
251 | Demangler::demangleSpecialTableSymbolNode(StringView &MangledName, | |||
252 | SpecialIntrinsicKind K) { | |||
253 | NamedIdentifierNode *NI = Arena.alloc<NamedIdentifierNode>(); | |||
254 | switch (K) { | |||
255 | case SpecialIntrinsicKind::Vftable: | |||
256 | NI->Name = "`vftable'"; | |||
257 | break; | |||
258 | case SpecialIntrinsicKind::Vbtable: | |||
259 | NI->Name = "`vbtable'"; | |||
260 | break; | |||
261 | case SpecialIntrinsicKind::LocalVftable: | |||
262 | NI->Name = "`local vftable'"; | |||
263 | break; | |||
264 | case SpecialIntrinsicKind::RttiCompleteObjLocator: | |||
265 | NI->Name = "`RTTI Complete Object Locator'"; | |||
266 | break; | |||
267 | default: | |||
268 | LLVM_BUILTIN_UNREACHABLE__builtin_unreachable(); | |||
269 | } | |||
270 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI); | |||
271 | SpecialTableSymbolNode *STSN = Arena.alloc<SpecialTableSymbolNode>(); | |||
272 | STSN->Name = QN; | |||
273 | bool IsMember = false; | |||
274 | char Front = MangledName.popFront(); | |||
275 | if (Front != '6' && Front != '7') { | |||
276 | Error = true; | |||
277 | return nullptr; | |||
278 | } | |||
279 | ||||
280 | std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName); | |||
281 | if (!MangledName.consumeFront('@')) | |||
282 | STSN->TargetName = demangleFullyQualifiedTypeName(MangledName); | |||
283 | return STSN; | |||
284 | } | |||
285 | ||||
286 | LocalStaticGuardVariableNode * | |||
287 | Demangler::demangleLocalStaticGuard(StringView &MangledName) { | |||
288 | LocalStaticGuardIdentifierNode *LSGI = | |||
289 | Arena.alloc<LocalStaticGuardIdentifierNode>(); | |||
290 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, LSGI); | |||
291 | LocalStaticGuardVariableNode *LSGVN = | |||
292 | Arena.alloc<LocalStaticGuardVariableNode>(); | |||
293 | LSGVN->Name = QN; | |||
294 | ||||
295 | if (MangledName.consumeFront("4IA")) | |||
296 | LSGVN->IsVisible = false; | |||
297 | else if (MangledName.consumeFront("5")) | |||
298 | LSGVN->IsVisible = true; | |||
299 | else { | |||
300 | Error = true; | |||
301 | return nullptr; | |||
302 | } | |||
303 | ||||
304 | if (!MangledName.empty()) | |||
305 | LSGI->ScopeIndex = demangleUnsigned(MangledName); | |||
306 | return LSGVN; | |||
307 | } | |||
308 | ||||
309 | static NamedIdentifierNode *synthesizeNamedIdentifier(ArenaAllocator &Arena, | |||
310 | StringView Name) { | |||
311 | NamedIdentifierNode *Id = Arena.alloc<NamedIdentifierNode>(); | |||
312 | Id->Name = Name; | |||
313 | return Id; | |||
314 | } | |||
315 | ||||
316 | static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena, | |||
317 | IdentifierNode *Identifier) { | |||
318 | QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>(); | |||
319 | QN->Components = Arena.alloc<NodeArrayNode>(); | |||
320 | QN->Components->Count = 1; | |||
321 | QN->Components->Nodes = Arena.allocArray<Node *>(1); | |||
322 | QN->Components->Nodes[0] = Identifier; | |||
323 | return QN; | |||
324 | } | |||
325 | ||||
326 | static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena, | |||
327 | StringView Name) { | |||
328 | NamedIdentifierNode *Id = synthesizeNamedIdentifier(Arena, Name); | |||
329 | return synthesizeQualifiedName(Arena, Id); | |||
330 | } | |||
331 | ||||
332 | static VariableSymbolNode *synthesizeVariable(ArenaAllocator &Arena, | |||
333 | TypeNode *Type, | |||
334 | StringView VariableName) { | |||
335 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); | |||
336 | VSN->Type = Type; | |||
337 | VSN->Name = synthesizeQualifiedName(Arena, VariableName); | |||
338 | return VSN; | |||
339 | } | |||
340 | ||||
341 | VariableSymbolNode *Demangler::demangleUntypedVariable( | |||
342 | ArenaAllocator &Arena, StringView &MangledName, StringView VariableName) { | |||
343 | NamedIdentifierNode *NI = synthesizeNamedIdentifier(Arena, VariableName); | |||
344 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI); | |||
345 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); | |||
346 | VSN->Name = QN; | |||
347 | if (MangledName.consumeFront("8")) | |||
348 | return VSN; | |||
349 | ||||
350 | Error = true; | |||
351 | return nullptr; | |||
352 | } | |||
353 | ||||
354 | VariableSymbolNode * | |||
355 | Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena, | |||
356 | StringView &MangledName) { | |||
357 | RttiBaseClassDescriptorNode *RBCDN = | |||
358 | Arena.alloc<RttiBaseClassDescriptorNode>(); | |||
359 | RBCDN->NVOffset = demangleUnsigned(MangledName); | |||
360 | RBCDN->VBPtrOffset = demangleSigned(MangledName); | |||
361 | RBCDN->VBTableOffset = demangleUnsigned(MangledName); | |||
362 | RBCDN->Flags = demangleUnsigned(MangledName); | |||
363 | if (Error) | |||
364 | return nullptr; | |||
365 | ||||
366 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); | |||
367 | VSN->Name = demangleNameScopeChain(MangledName, RBCDN); | |||
368 | MangledName.consumeFront('8'); | |||
369 | return VSN; | |||
370 | } | |||
371 | ||||
372 | FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName, | |||
373 | bool IsDestructor) { | |||
374 | DynamicStructorIdentifierNode *DSIN = | |||
375 | Arena.alloc<DynamicStructorIdentifierNode>(); | |||
376 | DSIN->IsDestructor = IsDestructor; | |||
377 | ||||
378 | bool IsKnownStaticDataMember = false; | |||
379 | if (MangledName.consumeFront('?')) | |||
380 | IsKnownStaticDataMember = true; | |||
381 | ||||
382 | QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName); | |||
383 | ||||
384 | SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN); | |||
385 | FunctionSymbolNode *FSN = nullptr; | |||
386 | Symbol->Name = QN; | |||
387 | ||||
388 | if (Symbol->kind() == NodeKind::VariableSymbol) { | |||
389 | DSIN->Variable = static_cast<VariableSymbolNode *>(Symbol); | |||
390 | ||||
391 | // Older versions of clang mangled this type of symbol incorrectly. They | |||
392 | // would omit the leading ? and they would only emit a single @ at the end. | |||
393 | // The correct mangling is a leading ? and 2 trailing @ signs. Handle | |||
394 | // both cases. | |||
395 | int AtCount = IsKnownStaticDataMember ? 2 : 1; | |||
396 | for (int I = 0; I < AtCount; ++I) { | |||
397 | if (MangledName.consumeFront('@')) | |||
398 | continue; | |||
399 | Error = true; | |||
400 | return nullptr; | |||
401 | } | |||
402 | ||||
403 | FSN = demangleFunctionEncoding(MangledName); | |||
404 | FSN->Name = synthesizeQualifiedName(Arena, DSIN); | |||
405 | } else { | |||
406 | if (IsKnownStaticDataMember) { | |||
407 | // This was supposed to be a static data member, but we got a function. | |||
408 | Error = true; | |||
409 | return nullptr; | |||
410 | } | |||
411 | ||||
412 | FSN = static_cast<FunctionSymbolNode *>(Symbol); | |||
413 | DSIN->Name = Symbol->Name; | |||
414 | FSN->Name = synthesizeQualifiedName(Arena, DSIN); | |||
415 | } | |||
416 | ||||
417 | return FSN; | |||
418 | } | |||
419 | ||||
420 | SymbolNode *Demangler::demangleSpecialIntrinsic(StringView &MangledName) { | |||
421 | SpecialIntrinsicKind SIK = consumeSpecialIntrinsicKind(MangledName); | |||
422 | if (SIK == SpecialIntrinsicKind::None) | |||
423 | return nullptr; | |||
424 | ||||
425 | switch (SIK) { | |||
426 | case SpecialIntrinsicKind::StringLiteralSymbol: | |||
427 | return demangleStringLiteral(MangledName); | |||
428 | case SpecialIntrinsicKind::Vftable: | |||
429 | case SpecialIntrinsicKind::Vbtable: | |||
430 | case SpecialIntrinsicKind::LocalVftable: | |||
431 | case SpecialIntrinsicKind::RttiCompleteObjLocator: | |||
432 | return demangleSpecialTableSymbolNode(MangledName, SIK); | |||
433 | case SpecialIntrinsicKind::VcallThunk: | |||
434 | return demangleVcallThunkNode(MangledName); | |||
435 | case SpecialIntrinsicKind::LocalStaticGuard: | |||
436 | return demangleLocalStaticGuard(MangledName); | |||
437 | case SpecialIntrinsicKind::RttiTypeDescriptor: { | |||
438 | TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result); | |||
439 | if (Error) | |||
440 | break; | |||
441 | if (!MangledName.consumeFront("@8")) | |||
442 | break; | |||
443 | if (!MangledName.empty()) | |||
444 | break; | |||
445 | return synthesizeVariable(Arena, T, "`RTTI Type Descriptor'"); | |||
446 | } | |||
447 | case SpecialIntrinsicKind::RttiBaseClassArray: | |||
448 | return demangleUntypedVariable(Arena, MangledName, | |||
449 | "`RTTI Base Class Array'"); | |||
450 | case SpecialIntrinsicKind::RttiClassHierarchyDescriptor: | |||
451 | return demangleUntypedVariable(Arena, MangledName, | |||
452 | "`RTTI Class Hierarchy Descriptor'"); | |||
453 | case SpecialIntrinsicKind::RttiBaseClassDescriptor: | |||
454 | return demangleRttiBaseClassDescriptorNode(Arena, MangledName); | |||
455 | case SpecialIntrinsicKind::DynamicInitializer: | |||
456 | return demangleInitFiniStub(MangledName, false); | |||
457 | case SpecialIntrinsicKind::DynamicAtexitDestructor: | |||
458 | return demangleInitFiniStub(MangledName, true); | |||
459 | default: | |||
460 | break; | |||
461 | } | |||
462 | Error = true; | |||
463 | return nullptr; | |||
464 | } | |||
465 | ||||
466 | IdentifierNode * | |||
467 | Demangler::demangleFunctionIdentifierCode(StringView &MangledName) { | |||
468 | assert(MangledName.startsWith('?'))((MangledName.startsWith('?')) ? static_cast<void> (0) : __assert_fail ("MangledName.startsWith('?')", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 468, __PRETTY_FUNCTION__)); | |||
469 | MangledName = MangledName.dropFront(); | |||
470 | ||||
471 | if (MangledName.consumeFront("__")) | |||
472 | return demangleFunctionIdentifierCode( | |||
473 | MangledName, FunctionIdentifierCodeGroup::DoubleUnder); | |||
474 | else if (MangledName.consumeFront("_")) | |||
475 | return demangleFunctionIdentifierCode(MangledName, | |||
476 | FunctionIdentifierCodeGroup::Under); | |||
477 | return demangleFunctionIdentifierCode(MangledName, | |||
478 | FunctionIdentifierCodeGroup::Basic); | |||
479 | } | |||
480 | ||||
481 | StructorIdentifierNode * | |||
482 | Demangler::demangleStructorIdentifier(StringView &MangledName, | |||
483 | bool IsDestructor) { | |||
484 | StructorIdentifierNode *N = Arena.alloc<StructorIdentifierNode>(); | |||
485 | N->IsDestructor = IsDestructor; | |||
486 | return N; | |||
487 | } | |||
488 | ||||
489 | ConversionOperatorIdentifierNode * | |||
490 | Demangler::demangleConversionOperatorIdentifier(StringView &MangledName) { | |||
491 | ConversionOperatorIdentifierNode *N = | |||
492 | Arena.alloc<ConversionOperatorIdentifierNode>(); | |||
493 | return N; | |||
494 | } | |||
495 | ||||
496 | LiteralOperatorIdentifierNode * | |||
497 | Demangler::demangleLiteralOperatorIdentifier(StringView &MangledName) { | |||
498 | LiteralOperatorIdentifierNode *N = | |||
499 | Arena.alloc<LiteralOperatorIdentifierNode>(); | |||
500 | N->Name = demangleSimpleString(MangledName, false); | |||
501 | return N; | |||
502 | } | |||
503 | ||||
504 | static IntrinsicFunctionKind | |||
505 | translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group) { | |||
506 | // Not all ? identifiers are intrinsics *functions*. This function only maps | |||
507 | // operator codes for the special functions, all others are handled elsewhere, | |||
508 | // hence the IFK::None entries in the table. | |||
509 | using IFK = IntrinsicFunctionKind; | |||
510 | static IFK Basic[36] = { | |||
511 | IFK::None, // ?0 # Foo::Foo() | |||
512 | IFK::None, // ?1 # Foo::~Foo() | |||
513 | IFK::New, // ?2 # operator new | |||
514 | IFK::Delete, // ?3 # operator delete | |||
515 | IFK::Assign, // ?4 # operator= | |||
516 | IFK::RightShift, // ?5 # operator>> | |||
517 | IFK::LeftShift, // ?6 # operator<< | |||
518 | IFK::LogicalNot, // ?7 # operator! | |||
519 | IFK::Equals, // ?8 # operator== | |||
520 | IFK::NotEquals, // ?9 # operator!= | |||
521 | IFK::ArraySubscript, // ?A # operator[] | |||
522 | IFK::None, // ?B # Foo::operator <type>() | |||
523 | IFK::Pointer, // ?C # operator-> | |||
524 | IFK::Dereference, // ?D # operator* | |||
525 | IFK::Increment, // ?E # operator++ | |||
526 | IFK::Decrement, // ?F # operator-- | |||
527 | IFK::Minus, // ?G # operator- | |||
528 | IFK::Plus, // ?H # operator+ | |||
529 | IFK::BitwiseAnd, // ?I # operator& | |||
530 | IFK::MemberPointer, // ?J # operator->* | |||
531 | IFK::Divide, // ?K # operator/ | |||
532 | IFK::Modulus, // ?L # operator% | |||
533 | IFK::LessThan, // ?M operator< | |||
534 | IFK::LessThanEqual, // ?N operator<= | |||
535 | IFK::GreaterThan, // ?O operator> | |||
536 | IFK::GreaterThanEqual, // ?P operator>= | |||
537 | IFK::Comma, // ?Q operator, | |||
538 | IFK::Parens, // ?R operator() | |||
539 | IFK::BitwiseNot, // ?S operator~ | |||
540 | IFK::BitwiseXor, // ?T operator^ | |||
541 | IFK::BitwiseOr, // ?U operator| | |||
542 | IFK::LogicalAnd, // ?V operator&& | |||
543 | IFK::LogicalOr, // ?W operator|| | |||
544 | IFK::TimesEqual, // ?X operator*= | |||
545 | IFK::PlusEqual, // ?Y operator+= | |||
546 | IFK::MinusEqual, // ?Z operator-= | |||
547 | }; | |||
548 | static IFK Under[36] = { | |||
549 | IFK::DivEqual, // ?_0 operator/= | |||
550 | IFK::ModEqual, // ?_1 operator%= | |||
551 | IFK::RshEqual, // ?_2 operator>>= | |||
552 | IFK::LshEqual, // ?_3 operator<<= | |||
553 | IFK::BitwiseAndEqual, // ?_4 operator&= | |||
554 | IFK::BitwiseOrEqual, // ?_5 operator|= | |||
555 | IFK::BitwiseXorEqual, // ?_6 operator^= | |||
556 | IFK::None, // ?_7 # vftable | |||
557 | IFK::None, // ?_8 # vbtable | |||
558 | IFK::None, // ?_9 # vcall | |||
559 | IFK::None, // ?_A # typeof | |||
560 | IFK::None, // ?_B # local static guard | |||
561 | IFK::None, // ?_C # string literal | |||
562 | IFK::VbaseDtor, // ?_D # vbase destructor | |||
563 | IFK::VecDelDtor, // ?_E # vector deleting destructor | |||
564 | IFK::DefaultCtorClosure, // ?_F # default constructor closure | |||
565 | IFK::ScalarDelDtor, // ?_G # scalar deleting destructor | |||
566 | IFK::VecCtorIter, // ?_H # vector constructor iterator | |||
567 | IFK::VecDtorIter, // ?_I # vector destructor iterator | |||
568 | IFK::VecVbaseCtorIter, // ?_J # vector vbase constructor iterator | |||
569 | IFK::VdispMap, // ?_K # virtual displacement map | |||
570 | IFK::EHVecCtorIter, // ?_L # eh vector constructor iterator | |||
571 | IFK::EHVecDtorIter, // ?_M # eh vector destructor iterator | |||
572 | IFK::EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator | |||
573 | IFK::CopyCtorClosure, // ?_O # copy constructor closure | |||
574 | IFK::None, // ?_P<name> # udt returning <name> | |||
575 | IFK::None, // ?_Q # <unknown> | |||
576 | IFK::None, // ?_R0 - ?_R4 # RTTI Codes | |||
577 | IFK::None, // ?_S # local vftable | |||
578 | IFK::LocalVftableCtorClosure, // ?_T # local vftable constructor closure | |||
579 | IFK::ArrayNew, // ?_U operator new[] | |||
580 | IFK::ArrayDelete, // ?_V operator delete[] | |||
581 | IFK::None, // ?_W <unused> | |||
582 | IFK::None, // ?_X <unused> | |||
583 | IFK::None, // ?_Y <unused> | |||
584 | IFK::None, // ?_Z <unused> | |||
585 | }; | |||
586 | static IFK DoubleUnder[36] = { | |||
587 | IFK::None, // ?__0 <unused> | |||
588 | IFK::None, // ?__1 <unused> | |||
589 | IFK::None, // ?__2 <unused> | |||
590 | IFK::None, // ?__3 <unused> | |||
591 | IFK::None, // ?__4 <unused> | |||
592 | IFK::None, // ?__5 <unused> | |||
593 | IFK::None, // ?__6 <unused> | |||
594 | IFK::None, // ?__7 <unused> | |||
595 | IFK::None, // ?__8 <unused> | |||
596 | IFK::None, // ?__9 <unused> | |||
597 | IFK::ManVectorCtorIter, // ?__A managed vector ctor iterator | |||
598 | IFK::ManVectorDtorIter, // ?__B managed vector dtor iterator | |||
599 | IFK::EHVectorCopyCtorIter, // ?__C EH vector copy ctor iterator | |||
600 | IFK::EHVectorVbaseCopyCtorIter, // ?__D EH vector vbase copy ctor iter | |||
601 | IFK::None, // ?__E dynamic initializer for `T' | |||
602 | IFK::None, // ?__F dynamic atexit destructor for `T' | |||
603 | IFK::VectorCopyCtorIter, // ?__G vector copy constructor iter | |||
604 | IFK::VectorVbaseCopyCtorIter, // ?__H vector vbase copy ctor iter | |||
605 | IFK::ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy ctor | |||
606 | // iter | |||
607 | IFK::None, // ?__J local static thread guard | |||
608 | IFK::None, // ?__K operator ""_name | |||
609 | IFK::CoAwait, // ?__L co_await | |||
610 | IFK::None, // ?__M <unused> | |||
611 | IFK::None, // ?__N <unused> | |||
612 | IFK::None, // ?__O <unused> | |||
613 | IFK::None, // ?__P <unused> | |||
614 | IFK::None, // ?__Q <unused> | |||
615 | IFK::None, // ?__R <unused> | |||
616 | IFK::None, // ?__S <unused> | |||
617 | IFK::None, // ?__T <unused> | |||
618 | IFK::None, // ?__U <unused> | |||
619 | IFK::None, // ?__V <unused> | |||
620 | IFK::None, // ?__W <unused> | |||
621 | IFK::None, // ?__X <unused> | |||
622 | IFK::None, // ?__Y <unused> | |||
623 | IFK::None, // ?__Z <unused> | |||
624 | }; | |||
625 | ||||
626 | int Index = (CH >= '0' && CH <= '9') ? (CH - '0') : (CH - 'A' + 10); | |||
627 | switch (Group) { | |||
628 | case FunctionIdentifierCodeGroup::Basic: | |||
629 | return Basic[Index]; | |||
630 | case FunctionIdentifierCodeGroup::Under: | |||
631 | return Under[Index]; | |||
632 | case FunctionIdentifierCodeGroup::DoubleUnder: | |||
633 | return DoubleUnder[Index]; | |||
634 | } | |||
635 | LLVM_BUILTIN_UNREACHABLE__builtin_unreachable(); | |||
636 | } | |||
637 | ||||
638 | IdentifierNode * | |||
639 | Demangler::demangleFunctionIdentifierCode(StringView &MangledName, | |||
640 | FunctionIdentifierCodeGroup Group) { | |||
641 | switch (Group) { | |||
642 | case FunctionIdentifierCodeGroup::Basic: | |||
643 | switch (char CH = MangledName.popFront()) { | |||
644 | case '0': | |||
645 | case '1': | |||
646 | return demangleStructorIdentifier(MangledName, CH == '1'); | |||
647 | case 'B': | |||
648 | return demangleConversionOperatorIdentifier(MangledName); | |||
649 | default: | |||
650 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( | |||
651 | translateIntrinsicFunctionCode(CH, Group)); | |||
652 | } | |||
653 | break; | |||
654 | case FunctionIdentifierCodeGroup::Under: | |||
655 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( | |||
656 | translateIntrinsicFunctionCode(MangledName.popFront(), Group)); | |||
657 | case FunctionIdentifierCodeGroup::DoubleUnder: | |||
658 | switch (char CH = MangledName.popFront()) { | |||
659 | case 'K': | |||
660 | return demangleLiteralOperatorIdentifier(MangledName); | |||
661 | default: | |||
662 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( | |||
663 | translateIntrinsicFunctionCode(CH, Group)); | |||
664 | } | |||
665 | } | |||
666 | // No Mangling Yet: Spaceship, // operator<=> | |||
667 | ||||
668 | return nullptr; | |||
669 | } | |||
670 | ||||
671 | SymbolNode *Demangler::demangleEncodedSymbol(StringView &MangledName, | |||
672 | QualifiedNameNode *Name) { | |||
673 | // Read a variable. | |||
674 | switch (MangledName.front()) { | |||
675 | case '0': | |||
676 | case '1': | |||
677 | case '2': | |||
678 | case '3': | |||
679 | case '4': { | |||
680 | StorageClass SC = demangleVariableStorageClass(MangledName); | |||
681 | return demangleVariableEncoding(MangledName, SC); | |||
682 | } | |||
683 | case '8': | |||
684 | return nullptr; | |||
685 | } | |||
686 | FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName); | |||
687 | ||||
688 | IdentifierNode *UQN = Name->getUnqualifiedIdentifier(); | |||
689 | if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) { | |||
690 | ConversionOperatorIdentifierNode *COIN = | |||
691 | static_cast<ConversionOperatorIdentifierNode *>(UQN); | |||
692 | COIN->TargetType = FSN->Signature->ReturnType; | |||
693 | } | |||
694 | return FSN; | |||
695 | } | |||
696 | ||||
697 | // Parser entry point. | |||
698 | SymbolNode *Demangler::parse(StringView &MangledName) { | |||
699 | // We can't demangle MD5 names, just output them as-is. | |||
700 | // Also, MSVC-style mangled symbols must start with '?'. | |||
701 | if (MangledName.startsWith("??@")) { | |||
702 | // This is an MD5 mangled name. We can't demangle it, just return the | |||
703 | // mangled name. | |||
704 | SymbolNode *S = Arena.alloc<SymbolNode>(NodeKind::Md5Symbol); | |||
705 | S->Name = synthesizeQualifiedName(Arena, MangledName); | |||
706 | return S; | |||
707 | } | |||
708 | ||||
709 | if (!MangledName.startsWith('?')) { | |||
710 | Error = true; | |||
711 | return nullptr; | |||
712 | } | |||
713 | ||||
714 | MangledName.consumeFront('?'); | |||
715 | ||||
716 | // ?$ is a template instantiation, but all other names that start with ? are | |||
717 | // operators / special names. | |||
718 | if (SymbolNode *SI = demangleSpecialIntrinsic(MangledName)) | |||
719 | return SI; | |||
720 | ||||
721 | // What follows is a main symbol name. This may include namespaces or class | |||
722 | // back references. | |||
723 | QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName); | |||
724 | if (Error) | |||
725 | return nullptr; | |||
726 | ||||
727 | SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN); | |||
728 | if (Symbol) { | |||
729 | Symbol->Name = QN; | |||
730 | } | |||
731 | ||||
732 | if (Error) | |||
733 | return nullptr; | |||
734 | ||||
735 | return Symbol; | |||
736 | } | |||
737 | ||||
738 | TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) { | |||
739 | if (!MangledName.consumeFront(".?A")) | |||
740 | return nullptr; | |||
741 | MangledName.consumeFront(".?A"); | |||
742 | if (MangledName.empty()) | |||
743 | return nullptr; | |||
744 | ||||
745 | return demangleClassType(MangledName); | |||
746 | } | |||
747 | ||||
748 | // <type-encoding> ::= <storage-class> <variable-type> | |||
749 | // <storage-class> ::= 0 # private static member | |||
750 | // ::= 1 # protected static member | |||
751 | // ::= 2 # public static member | |||
752 | // ::= 3 # global | |||
753 | // ::= 4 # static local | |||
754 | ||||
755 | VariableSymbolNode *Demangler::demangleVariableEncoding(StringView &MangledName, | |||
756 | StorageClass SC) { | |||
757 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); | |||
758 | ||||
759 | VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop); | |||
760 | VSN->SC = SC; | |||
761 | ||||
762 | // <variable-type> ::= <type> <cvr-qualifiers> | |||
763 | // ::= <type> <pointee-cvr-qualifiers> # pointers, references | |||
764 | switch (VSN->Type->kind()) { | |||
765 | case NodeKind::PointerType: { | |||
766 | PointerTypeNode *PTN = static_cast<PointerTypeNode *>(VSN->Type); | |||
767 | ||||
768 | Qualifiers ExtraChildQuals = Q_None; | |||
769 | PTN->Quals = Qualifiers(VSN->Type->Quals | | |||
770 | demanglePointerExtQualifiers(MangledName)); | |||
771 | ||||
772 | bool IsMember = false; | |||
773 | std::tie(ExtraChildQuals, IsMember) = demangleQualifiers(MangledName); | |||
774 | ||||
775 | if (PTN->ClassParent) { | |||
776 | QualifiedNameNode *BackRefName = | |||
777 | demangleFullyQualifiedTypeName(MangledName); | |||
778 | (void)BackRefName; | |||
779 | } | |||
780 | PTN->Pointee->Quals = Qualifiers(PTN->Pointee->Quals | ExtraChildQuals); | |||
781 | ||||
782 | break; | |||
783 | } | |||
784 | default: | |||
785 | VSN->Type->Quals = demangleQualifiers(MangledName).first; | |||
786 | break; | |||
787 | } | |||
788 | ||||
789 | return VSN; | |||
790 | } | |||
791 | ||||
792 | // Sometimes numbers are encoded in mangled symbols. For example, | |||
793 | // "int (*x)[20]" is a valid C type (x is a pointer to an array of | |||
794 | // length 20), so we need some way to embed numbers as part of symbols. | |||
795 | // This function parses it. | |||
796 | // | |||
797 | // <number> ::= [?] <non-negative integer> | |||
798 | // | |||
799 | // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10 | |||
800 | // ::= <hex digit>+ @ # when Numbrer == 0 or >= 10 | |||
801 | // | |||
802 | // <hex-digit> ::= [A-P] # A = 0, B = 1, ... | |||
803 | std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) { | |||
804 | bool IsNegative = MangledName.consumeFront('?'); | |||
805 | ||||
806 | if (startsWithDigit(MangledName)) { | |||
807 | uint64_t Ret = MangledName[0] - '0' + 1; | |||
808 | MangledName = MangledName.dropFront(1); | |||
809 | return {Ret, IsNegative}; | |||
810 | } | |||
811 | ||||
812 | uint64_t Ret = 0; | |||
813 | for (size_t i = 0; i < MangledName.size(); ++i) { | |||
814 | char C = MangledName[i]; | |||
815 | if (C == '@') { | |||
816 | MangledName = MangledName.dropFront(i + 1); | |||
817 | return {Ret, IsNegative}; | |||
818 | } | |||
819 | if ('A' <= C && C <= 'P') { | |||
820 | Ret = (Ret << 4) + (C - 'A'); | |||
821 | continue; | |||
822 | } | |||
823 | break; | |||
824 | } | |||
825 | ||||
826 | Error = true; | |||
827 | return {0ULL, false}; | |||
828 | } | |||
829 | ||||
830 | uint64_t Demangler::demangleUnsigned(StringView &MangledName) { | |||
831 | bool IsNegative = false; | |||
832 | uint64_t Number = 0; | |||
833 | std::tie(Number, IsNegative) = demangleNumber(MangledName); | |||
834 | if (IsNegative) | |||
835 | Error = true; | |||
836 | return Number; | |||
837 | } | |||
838 | ||||
839 | int64_t Demangler::demangleSigned(StringView &MangledName) { | |||
840 | bool IsNegative = false; | |||
841 | uint64_t Number = 0; | |||
842 | std::tie(Number, IsNegative) = demangleNumber(MangledName); | |||
843 | if (Number > INT64_MAX(9223372036854775807L)) | |||
844 | Error = true; | |||
845 | int64_t I = static_cast<int64_t>(Number); | |||
846 | return IsNegative ? -I : I; | |||
847 | } | |||
848 | ||||
849 | // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9. | |||
850 | // Memorize it. | |||
851 | void Demangler::memorizeString(StringView S) { | |||
852 | if (Backrefs.NamesCount >= BackrefContext::Max) | |||
853 | return; | |||
854 | for (size_t i = 0; i < Backrefs.NamesCount; ++i) | |||
855 | if (S == Backrefs.Names[i]->Name) | |||
856 | return; | |||
857 | NamedIdentifierNode *N = Arena.alloc<NamedIdentifierNode>(); | |||
858 | N->Name = S; | |||
859 | Backrefs.Names[Backrefs.NamesCount++] = N; | |||
860 | } | |||
861 | ||||
862 | NamedIdentifierNode *Demangler::demangleBackRefName(StringView &MangledName) { | |||
863 | assert(startsWithDigit(MangledName))((startsWithDigit(MangledName)) ? static_cast<void> (0) : __assert_fail ("startsWithDigit(MangledName)", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 863, __PRETTY_FUNCTION__)); | |||
864 | ||||
865 | size_t I = MangledName[0] - '0'; | |||
866 | if (I >= Backrefs.NamesCount) { | |||
867 | Error = true; | |||
868 | return nullptr; | |||
869 | } | |||
870 | ||||
871 | MangledName = MangledName.dropFront(); | |||
872 | return Backrefs.Names[I]; | |||
873 | } | |||
874 | ||||
875 | void Demangler::memorizeIdentifier(IdentifierNode *Identifier) { | |||
876 | // Render this class template name into a string buffer so that we can | |||
877 | // memorize it for the purpose of back-referencing. | |||
878 | OutputStream OS; | |||
879 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) | |||
880 | // FIXME: Propagate out-of-memory as an error? | |||
881 | std::terminate(); | |||
882 | Identifier->output(OS, OF_Default); | |||
883 | OS << '\0'; | |||
884 | char *Name = OS.getBuffer(); | |||
885 | ||||
886 | StringView Owned = copyString(Name); | |||
887 | memorizeString(Owned); | |||
888 | std::free(Name); | |||
889 | } | |||
890 | ||||
891 | IdentifierNode * | |||
892 | Demangler::demangleTemplateInstantiationName(StringView &MangledName, | |||
893 | NameBackrefBehavior NBB) { | |||
894 | assert(MangledName.startsWith("?$"))((MangledName.startsWith("?$")) ? static_cast<void> (0) : __assert_fail ("MangledName.startsWith(\"?$\")", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 894, __PRETTY_FUNCTION__)); | |||
895 | MangledName.consumeFront("?$"); | |||
896 | ||||
897 | BackrefContext OuterContext; | |||
898 | std::swap(OuterContext, Backrefs); | |||
899 | ||||
900 | IdentifierNode *Identifier = | |||
901 | demangleUnqualifiedSymbolName(MangledName, NBB_Simple); | |||
902 | if (!Error) | |||
903 | Identifier->TemplateParams = demangleTemplateParameterList(MangledName); | |||
904 | ||||
905 | std::swap(OuterContext, Backrefs); | |||
906 | if (Error) | |||
907 | return nullptr; | |||
908 | ||||
909 | if (NBB & NBB_Template) | |||
910 | memorizeIdentifier(Identifier); | |||
911 | ||||
912 | return Identifier; | |||
913 | } | |||
914 | ||||
915 | NamedIdentifierNode *Demangler::demangleSimpleName(StringView &MangledName, | |||
916 | bool Memorize) { | |||
917 | StringView S = demangleSimpleString(MangledName, Memorize); | |||
918 | if (Error) | |||
919 | return nullptr; | |||
920 | ||||
921 | NamedIdentifierNode *Name = Arena.alloc<NamedIdentifierNode>(); | |||
922 | Name->Name = S; | |||
923 | return Name; | |||
924 | } | |||
925 | ||||
926 | static bool isRebasedHexDigit(char C) { return (C >= 'A' && C <= 'P'); } | |||
927 | ||||
928 | static uint8_t rebasedHexDigitToNumber(char C) { | |||
929 | assert(isRebasedHexDigit(C))((isRebasedHexDigit(C)) ? static_cast<void> (0) : __assert_fail ("isRebasedHexDigit(C)", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 929, __PRETTY_FUNCTION__)); | |||
930 | return (C <= 'J') ? (C - 'A') : (10 + C - 'K'); | |||
931 | } | |||
932 | ||||
933 | uint8_t Demangler::demangleCharLiteral(StringView &MangledName) { | |||
934 | if (!MangledName.startsWith('?')) | |||
935 | return MangledName.popFront(); | |||
936 | ||||
937 | MangledName = MangledName.dropFront(); | |||
938 | if (MangledName.empty()) | |||
939 | goto CharLiteralError; | |||
940 | ||||
941 | if (MangledName.consumeFront('$')) { | |||
942 | // Two hex digits | |||
943 | if (MangledName.size() < 2) | |||
944 | goto CharLiteralError; | |||
945 | StringView Nibbles = MangledName.substr(0, 2); | |||
946 | if (!isRebasedHexDigit(Nibbles[0]) || !isRebasedHexDigit(Nibbles[1])) | |||
947 | goto CharLiteralError; | |||
948 | // Don't append the null terminator. | |||
949 | uint8_t C1 = rebasedHexDigitToNumber(Nibbles[0]); | |||
950 | uint8_t C2 = rebasedHexDigitToNumber(Nibbles[1]); | |||
951 | MangledName = MangledName.dropFront(2); | |||
952 | return (C1 << 4) | C2; | |||
953 | } | |||
954 | ||||
955 | if (startsWithDigit(MangledName)) { | |||
956 | const char *Lookup = ",/\\:. \n\t'-"; | |||
957 | char C = Lookup[MangledName[0] - '0']; | |||
958 | MangledName = MangledName.dropFront(); | |||
959 | return C; | |||
960 | } | |||
961 | ||||
962 | if (MangledName[0] >= 'a' && MangledName[0] <= 'z') { | |||
963 | char Lookup[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', | |||
964 | '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', | |||
965 | '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', | |||
966 | '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'}; | |||
967 | char C = Lookup[MangledName[0] - 'a']; | |||
968 | MangledName = MangledName.dropFront(); | |||
969 | return C; | |||
970 | } | |||
971 | ||||
972 | if (MangledName[0] >= 'A' && MangledName[0] <= 'Z') { | |||
973 | char Lookup[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', | |||
974 | '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', | |||
975 | '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', | |||
976 | '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'}; | |||
977 | char C = Lookup[MangledName[0] - 'A']; | |||
978 | MangledName = MangledName.dropFront(); | |||
979 | return C; | |||
980 | } | |||
981 | ||||
982 | CharLiteralError: | |||
983 | Error = true; | |||
984 | return '\0'; | |||
985 | } | |||
986 | ||||
987 | wchar_t Demangler::demangleWcharLiteral(StringView &MangledName) { | |||
988 | uint8_t C1, C2; | |||
989 | ||||
990 | C1 = demangleCharLiteral(MangledName); | |||
991 | if (Error) | |||
992 | goto WCharLiteralError; | |||
993 | C2 = demangleCharLiteral(MangledName); | |||
994 | if (Error) | |||
995 | goto WCharLiteralError; | |||
996 | ||||
997 | return ((wchar_t)C1 << 8) | (wchar_t)C2; | |||
998 | ||||
999 | WCharLiteralError: | |||
1000 | Error = true; | |||
1001 | return L'\0'; | |||
1002 | } | |||
1003 | ||||
1004 | static void writeHexDigit(char *Buffer, uint8_t Digit) { | |||
1005 | assert(Digit <= 15)((Digit <= 15) ? static_cast<void> (0) : __assert_fail ("Digit <= 15", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1005, __PRETTY_FUNCTION__)); | |||
1006 | *Buffer = (Digit < 10) ? ('0' + Digit) : ('A' + Digit - 10); | |||
1007 | } | |||
1008 | ||||
1009 | static void outputHex(OutputStream &OS, unsigned C) { | |||
1010 | if (C == 0) { | |||
1011 | OS << "\\x00"; | |||
1012 | return; | |||
1013 | } | |||
1014 | // It's easier to do the math if we can work from right to left, but we need | |||
1015 | // to print the numbers from left to right. So render this into a temporary | |||
1016 | // buffer first, then output the temporary buffer. Each byte is of the form | |||
1017 | // \xAB, which means that each byte needs 4 characters. Since there are at | |||
1018 | // most 4 bytes, we need a 4*4+1 = 17 character temporary buffer. | |||
1019 | char TempBuffer[17]; | |||
1020 | ||||
1021 | ::memset(TempBuffer, 0, sizeof(TempBuffer)); | |||
1022 | constexpr int MaxPos = 15; | |||
1023 | ||||
1024 | int Pos = MaxPos - 1; | |||
1025 | while (C != 0) { | |||
1026 | for (int I = 0; I < 2; ++I) { | |||
1027 | writeHexDigit(&TempBuffer[Pos--], C % 16); | |||
1028 | C /= 16; | |||
1029 | } | |||
1030 | TempBuffer[Pos--] = 'x'; | |||
1031 | TempBuffer[Pos--] = '\\'; | |||
1032 | assert(Pos >= 0)((Pos >= 0) ? static_cast<void> (0) : __assert_fail ( "Pos >= 0", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1032, __PRETTY_FUNCTION__)); | |||
1033 | } | |||
1034 | OS << StringView(&TempBuffer[Pos + 1]); | |||
1035 | } | |||
1036 | ||||
1037 | static void outputEscapedChar(OutputStream &OS, unsigned C) { | |||
1038 | switch (C) { | |||
1039 | case '\'': // single quote | |||
1040 | OS << "\\\'"; | |||
1041 | return; | |||
1042 | case '\"': // double quote | |||
1043 | OS << "\\\""; | |||
1044 | return; | |||
1045 | case '\\': // backslash | |||
1046 | OS << "\\\\"; | |||
1047 | return; | |||
1048 | case '\a': // bell | |||
1049 | OS << "\\a"; | |||
1050 | return; | |||
1051 | case '\b': // backspace | |||
1052 | OS << "\\b"; | |||
1053 | return; | |||
1054 | case '\f': // form feed | |||
1055 | OS << "\\f"; | |||
1056 | return; | |||
1057 | case '\n': // new line | |||
1058 | OS << "\\n"; | |||
1059 | return; | |||
1060 | case '\r': // carriage return | |||
1061 | OS << "\\r"; | |||
1062 | return; | |||
1063 | case '\t': // tab | |||
1064 | OS << "\\t"; | |||
1065 | return; | |||
1066 | case '\v': // vertical tab | |||
1067 | OS << "\\v"; | |||
1068 | return; | |||
1069 | default: | |||
1070 | break; | |||
1071 | } | |||
1072 | ||||
1073 | if (C > 0x1F && C < 0x7F) { | |||
1074 | // Standard ascii char. | |||
1075 | OS << (char)C; | |||
1076 | return; | |||
1077 | } | |||
1078 | ||||
1079 | outputHex(OS, C); | |||
1080 | } | |||
1081 | ||||
1082 | static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length) { | |||
1083 | const uint8_t *End = StringBytes + Length - 1; | |||
1084 | unsigned Count = 0; | |||
1085 | while (Length > 0 && *End == 0) { | |||
1086 | --Length; | |||
1087 | --End; | |||
1088 | ++Count; | |||
1089 | } | |||
1090 | return Count; | |||
1091 | } | |||
1092 | ||||
1093 | static unsigned countEmbeddedNulls(const uint8_t *StringBytes, | |||
1094 | unsigned Length) { | |||
1095 | unsigned Result = 0; | |||
1096 | for (unsigned I = 0; I < Length; ++I) { | |||
1097 | if (*StringBytes++ == 0) | |||
1098 | ++Result; | |||
1099 | } | |||
1100 | return Result; | |||
1101 | } | |||
1102 | ||||
1103 | static unsigned guessCharByteSize(const uint8_t *StringBytes, unsigned NumChars, | |||
1104 | unsigned NumBytes) { | |||
1105 | assert(NumBytes > 0)((NumBytes > 0) ? static_cast<void> (0) : __assert_fail ("NumBytes > 0", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1105, __PRETTY_FUNCTION__)); | |||
1106 | ||||
1107 | // If the number of bytes is odd, this is guaranteed to be a char string. | |||
1108 | if (NumBytes % 2 == 1) | |||
1109 | return 1; | |||
1110 | ||||
1111 | // All strings can encode at most 32 bytes of data. If it's less than that, | |||
1112 | // then we encoded the entire string. In this case we check for a 1-byte, | |||
1113 | // 2-byte, or 4-byte null terminator. | |||
1114 | if (NumBytes < 32) { | |||
1115 | unsigned TrailingNulls = countTrailingNullBytes(StringBytes, NumChars); | |||
1116 | if (TrailingNulls >= 4) | |||
1117 | return 4; | |||
1118 | if (TrailingNulls >= 2) | |||
1119 | return 2; | |||
1120 | return 1; | |||
1121 | } | |||
1122 | ||||
1123 | // The whole string was not able to be encoded. Try to look at embedded null | |||
1124 | // terminators to guess. The heuristic is that we count all embedded null | |||
1125 | // terminators. If more than 2/3 are null, it's a char32. If more than 1/3 | |||
1126 | // are null, it's a char16. Otherwise it's a char8. This obviously isn't | |||
1127 | // perfect and is biased towards languages that have ascii alphabets, but this | |||
1128 | // was always going to be best effort since the encoding is lossy. | |||
1129 | unsigned Nulls = countEmbeddedNulls(StringBytes, NumChars); | |||
1130 | if (Nulls >= 2 * NumChars / 3) | |||
1131 | return 4; | |||
1132 | if (Nulls >= NumChars / 3) | |||
1133 | return 2; | |||
1134 | return 1; | |||
1135 | } | |||
1136 | ||||
1137 | static unsigned decodeMultiByteChar(const uint8_t *StringBytes, | |||
1138 | unsigned CharIndex, unsigned CharBytes) { | |||
1139 | assert(CharBytes == 1 || CharBytes == 2 || CharBytes == 4)((CharBytes == 1 || CharBytes == 2 || CharBytes == 4) ? static_cast <void> (0) : __assert_fail ("CharBytes == 1 || CharBytes == 2 || CharBytes == 4" , "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1139, __PRETTY_FUNCTION__)); | |||
1140 | unsigned Offset = CharIndex * CharBytes; | |||
1141 | unsigned Result = 0; | |||
1142 | StringBytes = StringBytes + Offset; | |||
1143 | for (unsigned I = 0; I < CharBytes; ++I) { | |||
1144 | unsigned C = static_cast<unsigned>(StringBytes[I]); | |||
1145 | Result |= C << (8 * I); | |||
1146 | } | |||
1147 | return Result; | |||
1148 | } | |||
1149 | ||||
1150 | FunctionSymbolNode *Demangler::demangleVcallThunkNode(StringView &MangledName) { | |||
1151 | FunctionSymbolNode *FSN = Arena.alloc<FunctionSymbolNode>(); | |||
1152 | VcallThunkIdentifierNode *VTIN = Arena.alloc<VcallThunkIdentifierNode>(); | |||
1153 | FSN->Signature = Arena.alloc<ThunkSignatureNode>(); | |||
1154 | FSN->Signature->FunctionClass = FC_NoParameterList; | |||
1155 | ||||
1156 | FSN->Name = demangleNameScopeChain(MangledName, VTIN); | |||
1157 | if (!Error) | |||
1158 | Error = !MangledName.consumeFront("$B"); | |||
1159 | if (!Error) | |||
1160 | VTIN->OffsetInVTable = demangleUnsigned(MangledName); | |||
1161 | if (!Error) | |||
1162 | Error = !MangledName.consumeFront('A'); | |||
1163 | if (!Error) | |||
1164 | FSN->Signature->CallConvention = demangleCallingConvention(MangledName); | |||
1165 | return (Error) ? nullptr : FSN; | |||
1166 | } | |||
1167 | ||||
1168 | EncodedStringLiteralNode * | |||
1169 | Demangler::demangleStringLiteral(StringView &MangledName) { | |||
1170 | // This function uses goto, so declare all variables up front. | |||
1171 | OutputStream OS; | |||
1172 | StringView CRC; | |||
1173 | uint64_t StringByteSize; | |||
1174 | bool IsWcharT = false; | |||
1175 | bool IsNegative = false; | |||
1176 | size_t CrcEndPos = 0; | |||
1177 | char *ResultBuffer = nullptr; | |||
1178 | ||||
1179 | EncodedStringLiteralNode *Result = Arena.alloc<EncodedStringLiteralNode>(); | |||
1180 | ||||
1181 | // Prefix indicating the beginning of a string literal | |||
1182 | if (!MangledName.consumeFront("@_")) | |||
1183 | goto StringLiteralError; | |||
1184 | if (MangledName.empty()) | |||
1185 | goto StringLiteralError; | |||
1186 | ||||
1187 | // Char Type (regular or wchar_t) | |||
1188 | switch (MangledName.popFront()) { | |||
1189 | case '1': | |||
1190 | IsWcharT = true; | |||
1191 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
1192 | case '0': | |||
1193 | break; | |||
1194 | default: | |||
1195 | goto StringLiteralError; | |||
1196 | } | |||
1197 | ||||
1198 | // Encoded Length | |||
1199 | std::tie(StringByteSize, IsNegative) = demangleNumber(MangledName); | |||
1200 | if (Error || IsNegative) | |||
1201 | goto StringLiteralError; | |||
1202 | ||||
1203 | // CRC 32 (always 8 characters plus a terminator) | |||
1204 | CrcEndPos = MangledName.find('@'); | |||
1205 | if (CrcEndPos == StringView::npos) | |||
1206 | goto StringLiteralError; | |||
1207 | CRC = MangledName.substr(0, CrcEndPos); | |||
1208 | MangledName = MangledName.dropFront(CrcEndPos + 1); | |||
1209 | if (MangledName.empty()) | |||
1210 | goto StringLiteralError; | |||
1211 | ||||
1212 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) | |||
1213 | // FIXME: Propagate out-of-memory as an error? | |||
1214 | std::terminate(); | |||
1215 | if (IsWcharT) { | |||
1216 | Result->Char = CharKind::Wchar; | |||
1217 | if (StringByteSize > 64) | |||
1218 | Result->IsTruncated = true; | |||
1219 | ||||
1220 | while (!MangledName.consumeFront('@')) { | |||
1221 | assert(StringByteSize >= 2)((StringByteSize >= 2) ? static_cast<void> (0) : __assert_fail ("StringByteSize >= 2", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1221, __PRETTY_FUNCTION__)); | |||
1222 | wchar_t W = demangleWcharLiteral(MangledName); | |||
1223 | if (StringByteSize != 2 || Result->IsTruncated) | |||
1224 | outputEscapedChar(OS, W); | |||
1225 | StringByteSize -= 2; | |||
1226 | if (Error) | |||
1227 | goto StringLiteralError; | |||
1228 | } | |||
1229 | } else { | |||
1230 | // The max byte length is actually 32, but some compilers mangled strings | |||
1231 | // incorrectly, so we have to assume it can go higher. | |||
1232 | constexpr unsigned MaxStringByteLength = 32 * 4; | |||
1233 | uint8_t StringBytes[MaxStringByteLength]; | |||
1234 | ||||
1235 | unsigned BytesDecoded = 0; | |||
1236 | while (!MangledName.consumeFront('@')) { | |||
1237 | assert(StringByteSize >= 1)((StringByteSize >= 1) ? static_cast<void> (0) : __assert_fail ("StringByteSize >= 1", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1237, __PRETTY_FUNCTION__)); | |||
1238 | StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName); | |||
1239 | } | |||
1240 | ||||
1241 | if (StringByteSize > BytesDecoded) | |||
1242 | Result->IsTruncated = true; | |||
1243 | ||||
1244 | unsigned CharBytes = | |||
1245 | guessCharByteSize(StringBytes, BytesDecoded, StringByteSize); | |||
1246 | assert(StringByteSize % CharBytes == 0)((StringByteSize % CharBytes == 0) ? static_cast<void> ( 0) : __assert_fail ("StringByteSize % CharBytes == 0", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1246, __PRETTY_FUNCTION__)); | |||
1247 | switch (CharBytes) { | |||
1248 | case 1: | |||
1249 | Result->Char = CharKind::Char; | |||
1250 | break; | |||
1251 | case 2: | |||
1252 | Result->Char = CharKind::Char16; | |||
1253 | break; | |||
1254 | case 4: | |||
1255 | Result->Char = CharKind::Char32; | |||
1256 | break; | |||
1257 | default: | |||
1258 | LLVM_BUILTIN_UNREACHABLE__builtin_unreachable(); | |||
1259 | } | |||
1260 | const unsigned NumChars = BytesDecoded / CharBytes; | |||
1261 | for (unsigned CharIndex = 0; CharIndex < NumChars; ++CharIndex) { | |||
1262 | unsigned NextChar = | |||
1263 | decodeMultiByteChar(StringBytes, CharIndex, CharBytes); | |||
1264 | if (CharIndex + 1 < NumChars || Result->IsTruncated) | |||
1265 | outputEscapedChar(OS, NextChar); | |||
1266 | } | |||
1267 | } | |||
1268 | ||||
1269 | OS << '\0'; | |||
1270 | ResultBuffer = OS.getBuffer(); | |||
1271 | Result->DecodedString = copyString(ResultBuffer); | |||
1272 | std::free(ResultBuffer); | |||
1273 | return Result; | |||
1274 | ||||
1275 | StringLiteralError: | |||
1276 | Error = true; | |||
1277 | return nullptr; | |||
1278 | } | |||
1279 | ||||
1280 | StringView Demangler::demangleSimpleString(StringView &MangledName, | |||
1281 | bool Memorize) { | |||
1282 | StringView S; | |||
1283 | for (size_t i = 0; i < MangledName.size(); ++i) { | |||
1284 | if (MangledName[i] != '@') | |||
1285 | continue; | |||
1286 | S = MangledName.substr(0, i); | |||
1287 | MangledName = MangledName.dropFront(i + 1); | |||
1288 | ||||
1289 | if (Memorize) | |||
1290 | memorizeString(S); | |||
1291 | return S; | |||
1292 | } | |||
1293 | ||||
1294 | Error = true; | |||
1295 | return {}; | |||
1296 | } | |||
1297 | ||||
1298 | NamedIdentifierNode * | |||
1299 | Demangler::demangleAnonymousNamespaceName(StringView &MangledName) { | |||
1300 | assert(MangledName.startsWith("?A"))((MangledName.startsWith("?A")) ? static_cast<void> (0) : __assert_fail ("MangledName.startsWith(\"?A\")", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1300, __PRETTY_FUNCTION__)); | |||
1301 | MangledName.consumeFront("?A"); | |||
1302 | ||||
1303 | NamedIdentifierNode *Node = Arena.alloc<NamedIdentifierNode>(); | |||
1304 | Node->Name = "`anonymous namespace'"; | |||
1305 | size_t EndPos = MangledName.find('@'); | |||
1306 | if (EndPos == StringView::npos) { | |||
1307 | Error = true; | |||
1308 | return nullptr; | |||
1309 | } | |||
1310 | StringView NamespaceKey = MangledName.substr(0, EndPos); | |||
1311 | memorizeString(NamespaceKey); | |||
1312 | MangledName = MangledName.substr(EndPos + 1); | |||
1313 | return Node; | |||
1314 | } | |||
1315 | ||||
1316 | NamedIdentifierNode * | |||
1317 | Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) { | |||
1318 | assert(startsWithLocalScopePattern(MangledName))((startsWithLocalScopePattern(MangledName)) ? static_cast< void> (0) : __assert_fail ("startsWithLocalScopePattern(MangledName)" , "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1318, __PRETTY_FUNCTION__)); | |||
1319 | ||||
1320 | NamedIdentifierNode *Identifier = Arena.alloc<NamedIdentifierNode>(); | |||
1321 | MangledName.consumeFront('?'); | |||
1322 | auto Number = demangleNumber(MangledName); | |||
1323 | assert(!Number.second)((!Number.second) ? static_cast<void> (0) : __assert_fail ("!Number.second", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1323, __PRETTY_FUNCTION__)); | |||
1324 | ||||
1325 | // One ? to terminate the number | |||
1326 | MangledName.consumeFront('?'); | |||
1327 | ||||
1328 | assert(!Error)((!Error) ? static_cast<void> (0) : __assert_fail ("!Error" , "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1328, __PRETTY_FUNCTION__)); | |||
1329 | Node *Scope = parse(MangledName); | |||
1330 | if (Error) | |||
1331 | return nullptr; | |||
1332 | ||||
1333 | // Render the parent symbol's name into a buffer. | |||
1334 | OutputStream OS; | |||
1335 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) | |||
1336 | // FIXME: Propagate out-of-memory as an error? | |||
1337 | std::terminate(); | |||
1338 | OS << '`'; | |||
1339 | Scope->output(OS, OF_Default); | |||
1340 | OS << '\''; | |||
1341 | OS << "::`" << Number.first << "'"; | |||
1342 | OS << '\0'; | |||
1343 | char *Result = OS.getBuffer(); | |||
1344 | Identifier->Name = copyString(Result); | |||
1345 | std::free(Result); | |||
1346 | return Identifier; | |||
1347 | } | |||
1348 | ||||
1349 | // Parses a type name in the form of A@B@C@@ which represents C::B::A. | |||
1350 | QualifiedNameNode * | |||
1351 | Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) { | |||
1352 | IdentifierNode *Identifier = demangleUnqualifiedTypeName(MangledName, true); | |||
1353 | if (Error) | |||
1354 | return nullptr; | |||
1355 | assert(Identifier)((Identifier) ? static_cast<void> (0) : __assert_fail ( "Identifier", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1355, __PRETTY_FUNCTION__)); | |||
1356 | ||||
1357 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier); | |||
1358 | if (Error) | |||
1359 | return nullptr; | |||
1360 | assert(QN)((QN) ? static_cast<void> (0) : __assert_fail ("QN", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1360, __PRETTY_FUNCTION__)); | |||
1361 | return QN; | |||
1362 | } | |||
1363 | ||||
1364 | // Parses a symbol name in the form of A@B@C@@ which represents C::B::A. | |||
1365 | // Symbol names have slightly different rules regarding what can appear | |||
1366 | // so we separate out the implementations for flexibility. | |||
1367 | QualifiedNameNode * | |||
1368 | Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) { | |||
1369 | // This is the final component of a symbol name (i.e. the leftmost component | |||
1370 | // of a mangled name. Since the only possible template instantiation that | |||
1371 | // can appear in this context is a function template, and since those are | |||
1372 | // not saved for the purposes of name backreferences, only backref simple | |||
1373 | // names. | |||
1374 | IdentifierNode *Identifier = | |||
1375 | demangleUnqualifiedSymbolName(MangledName, NBB_Simple); | |||
1376 | if (Error) | |||
1377 | return nullptr; | |||
1378 | ||||
1379 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier); | |||
1380 | if (Error) | |||
1381 | return nullptr; | |||
1382 | ||||
1383 | if (Identifier->kind() == NodeKind::StructorIdentifier) { | |||
1384 | StructorIdentifierNode *SIN = | |||
1385 | static_cast<StructorIdentifierNode *>(Identifier); | |||
1386 | assert(QN->Components->Count >= 2)((QN->Components->Count >= 2) ? static_cast<void> (0) : __assert_fail ("QN->Components->Count >= 2", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1386, __PRETTY_FUNCTION__)); | |||
1387 | Node *ClassNode = QN->Components->Nodes[QN->Components->Count - 2]; | |||
1388 | SIN->Class = static_cast<IdentifierNode *>(ClassNode); | |||
1389 | } | |||
1390 | assert(QN)((QN) ? static_cast<void> (0) : __assert_fail ("QN", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1390, __PRETTY_FUNCTION__)); | |||
1391 | return QN; | |||
1392 | } | |||
1393 | ||||
1394 | IdentifierNode *Demangler::demangleUnqualifiedTypeName(StringView &MangledName, | |||
1395 | bool Memorize) { | |||
1396 | // An inner-most name can be a back-reference, because a fully-qualified name | |||
1397 | // (e.g. Scope + Inner) can contain other fully qualified names inside of | |||
1398 | // them (for example template parameters), and these nested parameters can | |||
1399 | // refer to previously mangled types. | |||
1400 | if (startsWithDigit(MangledName)) | |||
1401 | return demangleBackRefName(MangledName); | |||
1402 | ||||
1403 | if (MangledName.startsWith("?$")) | |||
1404 | return demangleTemplateInstantiationName(MangledName, NBB_Template); | |||
1405 | ||||
1406 | return demangleSimpleName(MangledName, Memorize); | |||
1407 | } | |||
1408 | ||||
1409 | IdentifierNode * | |||
1410 | Demangler::demangleUnqualifiedSymbolName(StringView &MangledName, | |||
1411 | NameBackrefBehavior NBB) { | |||
1412 | if (startsWithDigit(MangledName)) | |||
1413 | return demangleBackRefName(MangledName); | |||
1414 | if (MangledName.startsWith("?$")) | |||
1415 | return demangleTemplateInstantiationName(MangledName, NBB); | |||
1416 | if (MangledName.startsWith('?')) | |||
1417 | return demangleFunctionIdentifierCode(MangledName); | |||
1418 | return demangleSimpleName(MangledName, (NBB & NBB_Simple) != 0); | |||
1419 | } | |||
1420 | ||||
1421 | IdentifierNode *Demangler::demangleNameScopePiece(StringView &MangledName) { | |||
1422 | if (startsWithDigit(MangledName)) | |||
1423 | return demangleBackRefName(MangledName); | |||
1424 | ||||
1425 | if (MangledName.startsWith("?$")) | |||
1426 | return demangleTemplateInstantiationName(MangledName, NBB_Template); | |||
1427 | ||||
1428 | if (MangledName.startsWith("?A")) | |||
1429 | return demangleAnonymousNamespaceName(MangledName); | |||
1430 | ||||
1431 | if (startsWithLocalScopePattern(MangledName)) | |||
1432 | return demangleLocallyScopedNamePiece(MangledName); | |||
1433 | ||||
1434 | return demangleSimpleName(MangledName, true); | |||
1435 | } | |||
1436 | ||||
1437 | static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, | |||
1438 | size_t Count) { | |||
1439 | NodeArrayNode *N = Arena.alloc<NodeArrayNode>(); | |||
1440 | N->Count = Count; | |||
1441 | N->Nodes = Arena.allocArray<Node *>(Count); | |||
1442 | for (size_t I = 0; I < Count; ++I) { | |||
1443 | N->Nodes[I] = Head->N; | |||
1444 | Head = Head->Next; | |||
1445 | } | |||
1446 | return N; | |||
1447 | } | |||
1448 | ||||
1449 | QualifiedNameNode * | |||
1450 | Demangler::demangleNameScopeChain(StringView &MangledName, | |||
1451 | IdentifierNode *UnqualifiedName) { | |||
1452 | NodeList *Head = Arena.alloc<NodeList>(); | |||
1453 | ||||
1454 | Head->N = UnqualifiedName; | |||
1455 | ||||
1456 | size_t Count = 1; | |||
1457 | while (!MangledName.consumeFront("@")) { | |||
1458 | ++Count; | |||
1459 | NodeList *NewHead = Arena.alloc<NodeList>(); | |||
1460 | NewHead->Next = Head; | |||
1461 | Head = NewHead; | |||
1462 | ||||
1463 | if (MangledName.empty()) { | |||
1464 | Error = true; | |||
1465 | return nullptr; | |||
1466 | } | |||
1467 | ||||
1468 | assert(!Error)((!Error) ? static_cast<void> (0) : __assert_fail ("!Error" , "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1468, __PRETTY_FUNCTION__)); | |||
1469 | IdentifierNode *Elem = demangleNameScopePiece(MangledName); | |||
1470 | if (Error) | |||
1471 | return nullptr; | |||
1472 | ||||
1473 | Head->N = Elem; | |||
1474 | } | |||
1475 | ||||
1476 | QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>(); | |||
1477 | QN->Components = nodeListToNodeArray(Arena, Head, Count); | |||
1478 | return QN; | |||
1479 | } | |||
1480 | ||||
1481 | FuncClass Demangler::demangleFunctionClass(StringView &MangledName) { | |||
1482 | switch (MangledName.popFront()) { | |||
1483 | case '9': | |||
1484 | return FuncClass(FC_ExternC | FC_NoParameterList); | |||
1485 | case 'A': | |||
1486 | return FC_Private; | |||
1487 | case 'B': | |||
1488 | return FuncClass(FC_Private | FC_Far); | |||
1489 | case 'C': | |||
1490 | return FuncClass(FC_Private | FC_Static); | |||
1491 | case 'D': | |||
1492 | return FuncClass(FC_Private | FC_Static); | |||
1493 | case 'E': | |||
1494 | return FuncClass(FC_Private | FC_Virtual); | |||
1495 | case 'F': | |||
1496 | return FuncClass(FC_Private | FC_Virtual); | |||
1497 | case 'G': | |||
1498 | return FuncClass(FC_Private | FC_StaticThisAdjust); | |||
1499 | case 'H': | |||
1500 | return FuncClass(FC_Private | FC_StaticThisAdjust | FC_Far); | |||
1501 | case 'I': | |||
1502 | return FuncClass(FC_Protected); | |||
1503 | case 'J': | |||
1504 | return FuncClass(FC_Protected | FC_Far); | |||
1505 | case 'K': | |||
1506 | return FuncClass(FC_Protected | FC_Static); | |||
1507 | case 'L': | |||
1508 | return FuncClass(FC_Protected | FC_Static | FC_Far); | |||
1509 | case 'M': | |||
1510 | return FuncClass(FC_Protected | FC_Virtual); | |||
1511 | case 'N': | |||
1512 | return FuncClass(FC_Protected | FC_Virtual | FC_Far); | |||
1513 | case 'O': | |||
1514 | return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust); | |||
1515 | case 'P': | |||
1516 | return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust | FC_Far); | |||
1517 | case 'Q': | |||
1518 | return FuncClass(FC_Public); | |||
1519 | case 'R': | |||
1520 | return FuncClass(FC_Public | FC_Far); | |||
1521 | case 'S': | |||
1522 | return FuncClass(FC_Public | FC_Static); | |||
1523 | case 'T': | |||
1524 | return FuncClass(FC_Public | FC_Static | FC_Far); | |||
1525 | case 'U': | |||
1526 | return FuncClass(FC_Public | FC_Virtual); | |||
1527 | case 'V': | |||
1528 | return FuncClass(FC_Public | FC_Virtual | FC_Far); | |||
1529 | case 'W': | |||
1530 | return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust); | |||
1531 | case 'X': | |||
1532 | return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust | FC_Far); | |||
1533 | case 'Y': | |||
1534 | return FuncClass(FC_Global); | |||
1535 | case 'Z': | |||
1536 | return FuncClass(FC_Global | FC_Far); | |||
1537 | case '$': { | |||
1538 | FuncClass VFlag = FC_VirtualThisAdjust; | |||
1539 | if (MangledName.consumeFront('R')) | |||
1540 | VFlag = FuncClass(VFlag | FC_VirtualThisAdjustEx); | |||
1541 | ||||
1542 | switch (MangledName.popFront()) { | |||
1543 | case '0': | |||
1544 | return FuncClass(FC_Private | FC_Virtual | VFlag); | |||
1545 | case '1': | |||
1546 | return FuncClass(FC_Private | FC_Virtual | VFlag | FC_Far); | |||
1547 | case '2': | |||
1548 | return FuncClass(FC_Protected | FC_Virtual | VFlag); | |||
1549 | case '3': | |||
1550 | return FuncClass(FC_Protected | FC_Virtual | VFlag | FC_Far); | |||
1551 | case '4': | |||
1552 | return FuncClass(FC_Public | FC_Virtual | VFlag); | |||
1553 | case '5': | |||
1554 | return FuncClass(FC_Public | FC_Virtual | VFlag | FC_Far); | |||
1555 | } | |||
1556 | } | |||
1557 | } | |||
1558 | ||||
1559 | Error = true; | |||
1560 | return FC_Public; | |||
1561 | } | |||
1562 | ||||
1563 | CallingConv Demangler::demangleCallingConvention(StringView &MangledName) { | |||
1564 | switch (MangledName.popFront()) { | |||
1565 | case 'A': | |||
1566 | case 'B': | |||
1567 | return CallingConv::Cdecl; | |||
1568 | case 'C': | |||
1569 | case 'D': | |||
1570 | return CallingConv::Pascal; | |||
1571 | case 'E': | |||
1572 | case 'F': | |||
1573 | return CallingConv::Thiscall; | |||
1574 | case 'G': | |||
1575 | case 'H': | |||
1576 | return CallingConv::Stdcall; | |||
1577 | case 'I': | |||
1578 | case 'J': | |||
1579 | return CallingConv::Fastcall; | |||
1580 | case 'M': | |||
1581 | case 'N': | |||
1582 | return CallingConv::Clrcall; | |||
1583 | case 'O': | |||
1584 | case 'P': | |||
1585 | return CallingConv::Eabi; | |||
1586 | case 'Q': | |||
1587 | return CallingConv::Vectorcall; | |||
1588 | } | |||
1589 | ||||
1590 | return CallingConv::None; | |||
1591 | } | |||
1592 | ||||
1593 | StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) { | |||
1594 | assert(std::isdigit(MangledName.front()))((std::isdigit(MangledName.front())) ? static_cast<void> (0) : __assert_fail ("std::isdigit(MangledName.front())", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1594, __PRETTY_FUNCTION__)); | |||
1595 | ||||
1596 | switch (MangledName.popFront()) { | |||
1597 | case '0': | |||
1598 | return StorageClass::PrivateStatic; | |||
1599 | case '1': | |||
1600 | return StorageClass::ProtectedStatic; | |||
1601 | case '2': | |||
1602 | return StorageClass::PublicStatic; | |||
1603 | case '3': | |||
1604 | return StorageClass::Global; | |||
1605 | case '4': | |||
1606 | return StorageClass::FunctionLocalStatic; | |||
1607 | } | |||
1608 | Error = true; | |||
1609 | return StorageClass::None; | |||
1610 | } | |||
1611 | ||||
1612 | std::pair<Qualifiers, bool> | |||
1613 | Demangler::demangleQualifiers(StringView &MangledName) { | |||
1614 | ||||
1615 | switch (MangledName.popFront()) { | |||
1616 | // Member qualifiers | |||
1617 | case 'Q': | |||
1618 | return std::make_pair(Q_None, true); | |||
1619 | case 'R': | |||
1620 | return std::make_pair(Q_Const, true); | |||
1621 | case 'S': | |||
1622 | return std::make_pair(Q_Volatile, true); | |||
1623 | case 'T': | |||
1624 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), true); | |||
1625 | // Non-Member qualifiers | |||
1626 | case 'A': | |||
1627 | return std::make_pair(Q_None, false); | |||
1628 | case 'B': | |||
1629 | return std::make_pair(Q_Const, false); | |||
1630 | case 'C': | |||
1631 | return std::make_pair(Q_Volatile, false); | |||
1632 | case 'D': | |||
1633 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), false); | |||
1634 | } | |||
1635 | Error = true; | |||
1636 | return std::make_pair(Q_None, false); | |||
1637 | } | |||
1638 | ||||
1639 | // <variable-type> ::= <type> <cvr-qualifiers> | |||
1640 | // ::= <type> <pointee-cvr-qualifiers> # pointers, references | |||
1641 | TypeNode *Demangler::demangleType(StringView &MangledName, | |||
1642 | QualifierMangleMode QMM) { | |||
1643 | Qualifiers Quals = Q_None; | |||
1644 | bool IsMember = false; | |||
1645 | if (QMM == QualifierMangleMode::Mangle) { | |||
1646 | std::tie(Quals, IsMember) = demangleQualifiers(MangledName); | |||
1647 | } else if (QMM == QualifierMangleMode::Result) { | |||
1648 | if (MangledName.consumeFront('?')) | |||
1649 | std::tie(Quals, IsMember) = demangleQualifiers(MangledName); | |||
1650 | } | |||
1651 | ||||
1652 | TypeNode *Ty = nullptr; | |||
1653 | if (isTagType(MangledName)) | |||
1654 | Ty = demangleClassType(MangledName); | |||
1655 | else if (isPointerType(MangledName)) { | |||
1656 | if (isMemberPointer(MangledName, Error)) | |||
1657 | Ty = demangleMemberPointerType(MangledName); | |||
1658 | else if (!Error) | |||
1659 | Ty = demanglePointerType(MangledName); | |||
1660 | else | |||
1661 | return nullptr; | |||
1662 | } else if (isArrayType(MangledName)) | |||
1663 | Ty = demangleArrayType(MangledName); | |||
1664 | else if (isFunctionType(MangledName)) { | |||
1665 | if (MangledName.consumeFront("$$A8@@")) | |||
1666 | Ty = demangleFunctionType(MangledName, true); | |||
1667 | else { | |||
1668 | assert(MangledName.startsWith("$$A6"))((MangledName.startsWith("$$A6")) ? static_cast<void> ( 0) : __assert_fail ("MangledName.startsWith(\"$$A6\")", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1668, __PRETTY_FUNCTION__)); | |||
1669 | MangledName.consumeFront("$$A6"); | |||
1670 | Ty = demangleFunctionType(MangledName, false); | |||
1671 | } | |||
1672 | } else if (isCustomType(MangledName)) { | |||
1673 | Ty = demangleCustomType(MangledName); | |||
1674 | } else { | |||
1675 | Ty = demanglePrimitiveType(MangledName); | |||
1676 | } | |||
1677 | ||||
1678 | if (!Ty || Error) | |||
1679 | return Ty; | |||
1680 | Ty->Quals = Qualifiers(Ty->Quals | Quals); | |||
1681 | return Ty; | |||
1682 | } | |||
1683 | ||||
1684 | void Demangler::demangleThrowSpecification(StringView &MangledName) { | |||
1685 | if (MangledName.consumeFront('Z')) | |||
1686 | return; | |||
1687 | ||||
1688 | Error = true; | |||
1689 | } | |||
1690 | ||||
1691 | FunctionSignatureNode *Demangler::demangleFunctionType(StringView &MangledName, | |||
1692 | bool HasThisQuals) { | |||
1693 | FunctionSignatureNode *FTy = Arena.alloc<FunctionSignatureNode>(); | |||
1694 | ||||
1695 | if (HasThisQuals) { | |||
1696 | FTy->Quals = demanglePointerExtQualifiers(MangledName); | |||
1697 | FTy->RefQualifier = demangleFunctionRefQualifier(MangledName); | |||
1698 | FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers(MangledName).first); | |||
1699 | } | |||
1700 | ||||
1701 | // Fields that appear on both member and non-member functions. | |||
1702 | FTy->CallConvention = demangleCallingConvention(MangledName); | |||
1703 | ||||
1704 | // <return-type> ::= <type> | |||
1705 | // ::= @ # structors (they have no declared return type) | |||
1706 | bool IsStructor = MangledName.consumeFront('@'); | |||
1707 | if (!IsStructor) | |||
1708 | FTy->ReturnType = demangleType(MangledName, QualifierMangleMode::Result); | |||
1709 | ||||
1710 | FTy->Params = demangleFunctionParameterList(MangledName); | |||
1711 | ||||
1712 | demangleThrowSpecification(MangledName); | |||
1713 | ||||
1714 | return FTy; | |||
1715 | } | |||
1716 | ||||
1717 | FunctionSymbolNode * | |||
1718 | Demangler::demangleFunctionEncoding(StringView &MangledName) { | |||
1719 | FuncClass ExtraFlags = FC_None; | |||
1720 | if (MangledName.consumeFront("$$J0")) | |||
1721 | ExtraFlags = FC_ExternC; | |||
1722 | ||||
1723 | FuncClass FC = demangleFunctionClass(MangledName); | |||
1724 | FC = FuncClass(ExtraFlags | FC); | |||
1725 | ||||
1726 | FunctionSignatureNode *FSN = nullptr; | |||
1727 | ThunkSignatureNode *TTN = nullptr; | |||
1728 | if (FC & FC_StaticThisAdjust) { | |||
1729 | TTN = Arena.alloc<ThunkSignatureNode>(); | |||
1730 | TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName); | |||
1731 | } else if (FC & FC_VirtualThisAdjust) { | |||
1732 | TTN = Arena.alloc<ThunkSignatureNode>(); | |||
1733 | if (FC & FC_VirtualThisAdjustEx) { | |||
1734 | TTN->ThisAdjust.VBPtrOffset = demangleSigned(MangledName); | |||
1735 | TTN->ThisAdjust.VBOffsetOffset = demangleSigned(MangledName); | |||
1736 | } | |||
1737 | TTN->ThisAdjust.VtordispOffset = demangleSigned(MangledName); | |||
1738 | TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName); | |||
1739 | } | |||
1740 | ||||
1741 | if (FC & FC_NoParameterList) { | |||
1742 | // This is an extern "C" function whose full signature hasn't been mangled. | |||
1743 | // This happens when we need to mangle a local symbol inside of an extern | |||
1744 | // "C" function. | |||
1745 | FSN = Arena.alloc<FunctionSignatureNode>(); | |||
1746 | } else { | |||
1747 | bool HasThisQuals = !(FC & (FC_Global | FC_Static)); | |||
1748 | FSN = demangleFunctionType(MangledName, HasThisQuals); | |||
1749 | } | |||
1750 | if (TTN) { | |||
1751 | *static_cast<FunctionSignatureNode *>(TTN) = *FSN; | |||
1752 | FSN = TTN; | |||
1753 | } | |||
1754 | FSN->FunctionClass = FC; | |||
1755 | ||||
1756 | FunctionSymbolNode *Symbol = Arena.alloc<FunctionSymbolNode>(); | |||
1757 | Symbol->Signature = FSN; | |||
1758 | return Symbol; | |||
1759 | } | |||
1760 | ||||
1761 | CustomTypeNode *Demangler::demangleCustomType(StringView &MangledName) { | |||
1762 | assert(MangledName.startsWith('?'))((MangledName.startsWith('?')) ? static_cast<void> (0) : __assert_fail ("MangledName.startsWith('?')", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1762, __PRETTY_FUNCTION__)); | |||
1763 | MangledName.popFront(); | |||
1764 | ||||
1765 | CustomTypeNode *CTN = Arena.alloc<CustomTypeNode>(); | |||
1766 | CTN->Identifier = demangleUnqualifiedTypeName(MangledName, true); | |||
1767 | if (!MangledName.consumeFront('@')) | |||
1768 | Error = true; | |||
1769 | if (Error) | |||
1770 | return nullptr; | |||
1771 | return CTN; | |||
1772 | } | |||
1773 | ||||
1774 | // Reads a primitive type. | |||
1775 | PrimitiveTypeNode *Demangler::demanglePrimitiveType(StringView &MangledName) { | |||
1776 | if (MangledName.consumeFront("$$T")) | |||
1777 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Nullptr); | |||
1778 | ||||
1779 | switch (MangledName.popFront()) { | |||
1780 | case 'X': | |||
1781 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Void); | |||
1782 | case 'D': | |||
1783 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char); | |||
1784 | case 'C': | |||
1785 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Schar); | |||
1786 | case 'E': | |||
1787 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uchar); | |||
1788 | case 'F': | |||
1789 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Short); | |||
1790 | case 'G': | |||
1791 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ushort); | |||
1792 | case 'H': | |||
1793 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Int); | |||
1794 | case 'I': | |||
1795 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint); | |||
1796 | case 'J': | |||
1797 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Long); | |||
1798 | case 'K': | |||
1799 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ulong); | |||
1800 | case 'M': | |||
1801 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Float); | |||
1802 | case 'N': | |||
1803 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Double); | |||
1804 | case 'O': | |||
1805 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ldouble); | |||
1806 | case '_': { | |||
1807 | if (MangledName.empty()) { | |||
1808 | Error = true; | |||
1809 | return nullptr; | |||
1810 | } | |||
1811 | switch (MangledName.popFront()) { | |||
1812 | case 'N': | |||
1813 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Bool); | |||
1814 | case 'J': | |||
1815 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Int64); | |||
1816 | case 'K': | |||
1817 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint64); | |||
1818 | case 'W': | |||
1819 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Wchar); | |||
1820 | case 'S': | |||
1821 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char16); | |||
1822 | case 'U': | |||
1823 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char32); | |||
1824 | } | |||
1825 | break; | |||
1826 | } | |||
1827 | } | |||
1828 | Error = true; | |||
1829 | return nullptr; | |||
1830 | } | |||
1831 | ||||
1832 | TagTypeNode *Demangler::demangleClassType(StringView &MangledName) { | |||
1833 | TagTypeNode *TT = nullptr; | |||
1834 | ||||
1835 | switch (MangledName.popFront()) { | |||
1836 | case 'T': | |||
1837 | TT = Arena.alloc<TagTypeNode>(TagKind::Union); | |||
1838 | break; | |||
1839 | case 'U': | |||
1840 | TT = Arena.alloc<TagTypeNode>(TagKind::Struct); | |||
1841 | break; | |||
1842 | case 'V': | |||
1843 | TT = Arena.alloc<TagTypeNode>(TagKind::Class); | |||
1844 | break; | |||
1845 | case 'W': | |||
1846 | if (MangledName.popFront() != '4') { | |||
1847 | Error = true; | |||
1848 | return nullptr; | |||
1849 | } | |||
1850 | TT = Arena.alloc<TagTypeNode>(TagKind::Enum); | |||
1851 | break; | |||
1852 | default: | |||
1853 | assert(false)((false) ? static_cast<void> (0) : __assert_fail ("false" , "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1853, __PRETTY_FUNCTION__)); | |||
1854 | } | |||
1855 | ||||
1856 | TT->QualifiedName = demangleFullyQualifiedTypeName(MangledName); | |||
1857 | return TT; | |||
1858 | } | |||
1859 | ||||
1860 | // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type> | |||
1861 | // # the E is required for 64-bit non-static pointers | |||
1862 | PointerTypeNode *Demangler::demanglePointerType(StringView &MangledName) { | |||
1863 | PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>(); | |||
1864 | ||||
1865 | std::tie(Pointer->Quals, Pointer->Affinity) = | |||
1866 | demanglePointerCVQualifiers(MangledName); | |||
1867 | ||||
1868 | if (MangledName.consumeFront("6")) { | |||
1869 | Pointer->Pointee = demangleFunctionType(MangledName, false); | |||
1870 | return Pointer; | |||
1871 | } | |||
1872 | ||||
1873 | Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName); | |||
1874 | Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); | |||
1875 | ||||
1876 | Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Mangle); | |||
1877 | return Pointer; | |||
1878 | } | |||
1879 | ||||
1880 | PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) { | |||
1881 | PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>(); | |||
1882 | ||||
1883 | std::tie(Pointer->Quals, Pointer->Affinity) = | |||
1884 | demanglePointerCVQualifiers(MangledName); | |||
1885 | assert(Pointer->Affinity == PointerAffinity::Pointer)((Pointer->Affinity == PointerAffinity::Pointer) ? static_cast <void> (0) : __assert_fail ("Pointer->Affinity == PointerAffinity::Pointer" , "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1885, __PRETTY_FUNCTION__)); | |||
1886 | ||||
1887 | Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName); | |||
1888 | Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); | |||
1889 | ||||
1890 | if (MangledName.consumeFront("8")) { | |||
1891 | Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); | |||
1892 | Pointer->Pointee = demangleFunctionType(MangledName, true); | |||
1893 | } else { | |||
1894 | Qualifiers PointeeQuals = Q_None; | |||
1895 | bool IsMember = false; | |||
1896 | std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName); | |||
1897 | assert(IsMember)((IsMember) ? static_cast<void> (0) : __assert_fail ("IsMember" , "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1897, __PRETTY_FUNCTION__)); | |||
1898 | Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); | |||
1899 | ||||
1900 | Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop); | |||
1901 | Pointer->Pointee->Quals = PointeeQuals; | |||
1902 | } | |||
1903 | ||||
1904 | return Pointer; | |||
1905 | } | |||
1906 | ||||
1907 | Qualifiers Demangler::demanglePointerExtQualifiers(StringView &MangledName) { | |||
1908 | Qualifiers Quals = Q_None; | |||
1909 | if (MangledName.consumeFront('E')) | |||
1910 | Quals = Qualifiers(Quals | Q_Pointer64); | |||
1911 | if (MangledName.consumeFront('I')) | |||
1912 | Quals = Qualifiers(Quals | Q_Restrict); | |||
1913 | if (MangledName.consumeFront('F')) | |||
1914 | Quals = Qualifiers(Quals | Q_Unaligned); | |||
1915 | ||||
1916 | return Quals; | |||
1917 | } | |||
1918 | ||||
1919 | ArrayTypeNode *Demangler::demangleArrayType(StringView &MangledName) { | |||
1920 | assert(MangledName.front() == 'Y')((MangledName.front() == 'Y') ? static_cast<void> (0) : __assert_fail ("MangledName.front() == 'Y'", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 1920, __PRETTY_FUNCTION__)); | |||
1921 | MangledName.popFront(); | |||
1922 | ||||
1923 | uint64_t Rank = 0; | |||
1924 | bool IsNegative = false; | |||
1925 | std::tie(Rank, IsNegative) = demangleNumber(MangledName); | |||
1926 | if (IsNegative || Rank == 0) { | |||
1927 | Error = true; | |||
1928 | return nullptr; | |||
1929 | } | |||
1930 | ||||
1931 | ArrayTypeNode *ATy = Arena.alloc<ArrayTypeNode>(); | |||
1932 | NodeList *Head = Arena.alloc<NodeList>(); | |||
1933 | NodeList *Tail = Head; | |||
1934 | ||||
1935 | for (uint64_t I = 0; I < Rank; ++I) { | |||
1936 | uint64_t D = 0; | |||
1937 | std::tie(D, IsNegative) = demangleNumber(MangledName); | |||
1938 | if (IsNegative) { | |||
1939 | Error = true; | |||
1940 | return nullptr; | |||
1941 | } | |||
1942 | Tail->N = Arena.alloc<IntegerLiteralNode>(D, IsNegative); | |||
1943 | if (I + 1 < Rank) { | |||
1944 | Tail->Next = Arena.alloc<NodeList>(); | |||
1945 | Tail = Tail->Next; | |||
1946 | } | |||
1947 | } | |||
1948 | ATy->Dimensions = nodeListToNodeArray(Arena, Head, Rank); | |||
1949 | ||||
1950 | if (MangledName.consumeFront("$$C")) { | |||
1951 | bool IsMember = false; | |||
1952 | std::tie(ATy->Quals, IsMember) = demangleQualifiers(MangledName); | |||
1953 | if (IsMember) { | |||
1954 | Error = true; | |||
1955 | return nullptr; | |||
1956 | } | |||
1957 | } | |||
1958 | ||||
1959 | ATy->ElementType = demangleType(MangledName, QualifierMangleMode::Drop); | |||
1960 | return ATy; | |||
1961 | } | |||
1962 | ||||
1963 | // Reads a function or a template parameters. | |||
1964 | NodeArrayNode * | |||
1965 | Demangler::demangleFunctionParameterList(StringView &MangledName) { | |||
1966 | // Empty parameter list. | |||
1967 | if (MangledName.consumeFront('X')) | |||
1968 | return {}; | |||
1969 | ||||
1970 | NodeList *Head = Arena.alloc<NodeList>(); | |||
1971 | NodeList **Current = &Head; | |||
1972 | size_t Count = 0; | |||
1973 | while (!Error && !MangledName.startsWith('@') && | |||
1974 | !MangledName.startsWith('Z')) { | |||
1975 | ++Count; | |||
1976 | ||||
1977 | if (startsWithDigit(MangledName)) { | |||
1978 | size_t N = MangledName[0] - '0'; | |||
1979 | if (N >= Backrefs.FunctionParamCount) { | |||
1980 | Error = true; | |||
1981 | return {}; | |||
1982 | } | |||
1983 | MangledName = MangledName.dropFront(); | |||
1984 | ||||
1985 | *Current = Arena.alloc<NodeList>(); | |||
1986 | (*Current)->N = Backrefs.FunctionParams[N]; | |||
1987 | Current = &(*Current)->Next; | |||
1988 | continue; | |||
1989 | } | |||
1990 | ||||
1991 | size_t OldSize = MangledName.size(); | |||
1992 | ||||
1993 | *Current = Arena.alloc<NodeList>(); | |||
1994 | TypeNode *TN = demangleType(MangledName, QualifierMangleMode::Drop); | |||
1995 | if (!TN || Error) | |||
1996 | return nullptr; | |||
1997 | ||||
1998 | (*Current)->N = TN; | |||
1999 | ||||
2000 | size_t CharsConsumed = OldSize - MangledName.size(); | |||
2001 | assert(CharsConsumed != 0)((CharsConsumed != 0) ? static_cast<void> (0) : __assert_fail ("CharsConsumed != 0", "/build/llvm-toolchain-snapshot-8~svn350071/lib/Demangle/MicrosoftDemangle.cpp" , 2001, __PRETTY_FUNCTION__)); | |||
2002 | ||||
2003 | // Single-letter types are ignored for backreferences because memorizing | |||
2004 | // them doesn't save anything. | |||
2005 | if (Backrefs.FunctionParamCount <= 9 && CharsConsumed > 1) | |||
2006 | Backrefs.FunctionParams[Backrefs.FunctionParamCount++] = TN; | |||
2007 | ||||
2008 | Current = &(*Current)->Next; | |||
2009 | } | |||
2010 | ||||
2011 | if (Error) | |||
2012 | return {}; | |||
2013 | ||||
2014 | NodeArrayNode *NA = nodeListToNodeArray(Arena, Head, Count); | |||
2015 | // A non-empty parameter list is terminated by either 'Z' (variadic) parameter | |||
2016 | // list or '@' (non variadic). Careful not to consume "@Z", as in that case | |||
2017 | // the following Z could be a throw specifier. | |||
2018 | if (MangledName.consumeFront('@')) | |||
2019 | return NA; | |||
2020 | ||||
2021 | if (MangledName.consumeFront('Z')) { | |||
2022 | // This is a variadic parameter list. We probably need a variadic node to | |||
2023 | // append to the end. | |||
2024 | return NA; | |||
2025 | } | |||
2026 | ||||
2027 | Error = true; | |||
2028 | return {}; | |||
2029 | } | |||
2030 | ||||
2031 | NodeArrayNode * | |||
2032 | Demangler::demangleTemplateParameterList(StringView &MangledName) { | |||
2033 | NodeList *Head; | |||
| ||||
2034 | NodeList **Current = &Head; | |||
2035 | size_t Count = 0; | |||
2036 | ||||
2037 | while (!Error && !MangledName.startsWith('@')) { | |||
2038 | if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") || | |||
2039 | MangledName.consumeFront("$$$V") || MangledName.consumeFront("$$Z")) { | |||
2040 | // parameter pack separator | |||
2041 | continue; | |||
2042 | } | |||
2043 | ||||
2044 | ++Count; | |||
2045 | ||||
2046 | // Template parameter lists don't participate in back-referencing. | |||
2047 | *Current = Arena.alloc<NodeList>(); | |||
2048 | ||||
2049 | NodeList &TP = **Current; | |||
2050 | ||||
2051 | TemplateParameterReferenceNode *TPRN = nullptr; | |||
2052 | if (MangledName.consumeFront("$$Y")) { | |||
2053 | // Template alias | |||
2054 | TP.N = demangleFullyQualifiedTypeName(MangledName); | |||
2055 | } else if (MangledName.consumeFront("$$B")) { | |||
2056 | // Array | |||
2057 | TP.N = demangleType(MangledName, QualifierMangleMode::Drop); | |||
2058 | } else if (MangledName.consumeFront("$$C")) { | |||
2059 | // Type has qualifiers. | |||
2060 | TP.N = demangleType(MangledName, QualifierMangleMode::Mangle); | |||
2061 | } else if (MangledName.startsWith("$1") || MangledName.startsWith("$H") || | |||
2062 | MangledName.startsWith("$I") || MangledName.startsWith("$J")) { | |||
2063 | // Pointer to member | |||
2064 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); | |||
2065 | TPRN->IsMemberPointer = true; | |||
2066 | ||||
2067 | MangledName = MangledName.dropFront(); | |||
2068 | // 1 - single inheritance <name> | |||
2069 | // H - multiple inheritance <name> <number> | |||
2070 | // I - virtual inheritance <name> <number> <number> <number> | |||
2071 | // J - unspecified inheritance <name> <number> <number> <number> | |||
2072 | char InheritanceSpecifier = MangledName.popFront(); | |||
2073 | SymbolNode *S = nullptr; | |||
2074 | if (MangledName.startsWith('?')) { | |||
2075 | S = parse(MangledName); | |||
2076 | memorizeIdentifier(S->Name->getUnqualifiedIdentifier()); | |||
2077 | } | |||
2078 | ||||
2079 | switch (InheritanceSpecifier) { | |||
2080 | case 'J': | |||
2081 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | |||
2082 | demangleSigned(MangledName); | |||
2083 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
2084 | case 'I': | |||
2085 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | |||
2086 | demangleSigned(MangledName); | |||
2087 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
2088 | case 'H': | |||
2089 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | |||
2090 | demangleSigned(MangledName); | |||
2091 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
2092 | case '1': | |||
2093 | break; | |||
2094 | default: | |||
2095 | Error = true; | |||
2096 | break; | |||
2097 | } | |||
2098 | TPRN->Affinity = PointerAffinity::Pointer; | |||
2099 | TPRN->Symbol = S; | |||
2100 | } else if (MangledName.startsWith("$E?")) { | |||
2101 | MangledName.consumeFront("$E"); | |||
2102 | // Reference to symbol | |||
2103 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); | |||
2104 | TPRN->Symbol = parse(MangledName); | |||
2105 | TPRN->Affinity = PointerAffinity::Reference; | |||
2106 | } else if (MangledName.startsWith("$F") || MangledName.startsWith("$G")) { | |||
2107 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); | |||
2108 | ||||
2109 | // Data member pointer. | |||
2110 | MangledName = MangledName.dropFront(); | |||
2111 | char InheritanceSpecifier = MangledName.popFront(); | |||
2112 | ||||
2113 | switch (InheritanceSpecifier) { | |||
2114 | case 'G': | |||
2115 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | |||
2116 | demangleSigned(MangledName); | |||
2117 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
2118 | case 'F': | |||
2119 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | |||
2120 | demangleSigned(MangledName); | |||
2121 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = | |||
2122 | demangleSigned(MangledName); | |||
2123 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
2124 | case '0': | |||
2125 | break; | |||
2126 | default: | |||
2127 | Error = true; | |||
2128 | break; | |||
2129 | } | |||
2130 | TPRN->IsMemberPointer = true; | |||
2131 | ||||
2132 | } else if (MangledName.consumeFront("$0")) { | |||
2133 | // Integral non-type template parameter | |||
2134 | bool IsNegative = false; | |||
2135 | uint64_t Value = 0; | |||
2136 | std::tie(Value, IsNegative) = demangleNumber(MangledName); | |||
2137 | ||||
2138 | TP.N = Arena.alloc<IntegerLiteralNode>(Value, IsNegative); | |||
2139 | } else { | |||
2140 | TP.N = demangleType(MangledName, QualifierMangleMode::Drop); | |||
2141 | } | |||
2142 | if (Error) | |||
2143 | return nullptr; | |||
2144 | ||||
2145 | Current = &TP.Next; | |||
2146 | } | |||
2147 | ||||
2148 | if (Error) | |||
2149 | return nullptr; | |||
2150 | ||||
2151 | // Template parameter lists cannot be variadic, so it can only be terminated | |||
2152 | // by @. | |||
2153 | if (MangledName.consumeFront('@')) | |||
2154 | return nodeListToNodeArray(Arena, Head, Count); | |||
| ||||
2155 | Error = true; | |||
2156 | return nullptr; | |||
2157 | } | |||
2158 | ||||
2159 | void Demangler::dumpBackReferences() { | |||
2160 | std::printf("%d function parameter backreferences\n", | |||
2161 | (int)Backrefs.FunctionParamCount); | |||
2162 | ||||
2163 | // Create an output stream so we can render each type. | |||
2164 | OutputStream OS; | |||
2165 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) | |||
2166 | std::terminate(); | |||
2167 | for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) { | |||
2168 | OS.setCurrentPosition(0); | |||
2169 | ||||
2170 | TypeNode *T = Backrefs.FunctionParams[I]; | |||
2171 | T->output(OS, OF_Default); | |||
2172 | ||||
2173 | std::printf(" [%d] - %.*s\n", (int)I, (int)OS.getCurrentPosition(), | |||
2174 | OS.getBuffer()); | |||
2175 | } | |||
2176 | std::free(OS.getBuffer()); | |||
2177 | ||||
2178 | if (Backrefs.FunctionParamCount > 0) | |||
2179 | std::printf("\n"); | |||
2180 | std::printf("%d name backreferences\n", (int)Backrefs.NamesCount); | |||
2181 | for (size_t I = 0; I < Backrefs.NamesCount; ++I) { | |||
2182 | std::printf(" [%d] - %.*s\n", (int)I, (int)Backrefs.Names[I]->Name.size(), | |||
2183 | Backrefs.Names[I]->Name.begin()); | |||
2184 | } | |||
2185 | if (Backrefs.NamesCount > 0) | |||
2186 | std::printf("\n"); | |||
2187 | } | |||
2188 | ||||
2189 | char *llvm::microsoftDemangle(const char *MangledName, char *Buf, size_t *N, | |||
2190 | int *Status, MSDemangleFlags Flags) { | |||
2191 | int InternalStatus = demangle_success; | |||
2192 | Demangler D; | |||
2193 | OutputStream S; | |||
2194 | ||||
2195 | StringView Name{MangledName}; | |||
2196 | SymbolNode *AST = D.parse(Name); | |||
2197 | ||||
2198 | if (Flags & MSDF_DumpBackrefs) | |||
2199 | D.dumpBackReferences(); | |||
2200 | ||||
2201 | if (D.Error) | |||
2202 | InternalStatus = demangle_invalid_mangled_name; | |||
2203 | else if (!initializeOutputStream(Buf, N, S, 1024)) | |||
2204 | InternalStatus = demangle_memory_alloc_failure; | |||
2205 | else { | |||
2206 | AST->output(S, OF_Default); | |||
2207 | S += '\0'; | |||
2208 | if (N != nullptr) | |||
2209 | *N = S.getCurrentPosition(); | |||
2210 | Buf = S.getBuffer(); | |||
2211 | } | |||
2212 | ||||
2213 | if (Status) | |||
2214 | *Status = InternalStatus; | |||
2215 | return InternalStatus == demangle_success ? Buf : nullptr; | |||
2216 | } |