Bug Summary

File:llvm/include/llvm/Demangle/MicrosoftDemangle.h
Warning:line 88, column 12
4096 bytes is possibly not enough for array allocation which requires 16 bytes. Current overhead requires the size of 4080 bytes

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name MicrosoftDemangle.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/lib/Demangle -resource-dir /usr/lib/llvm-13/lib/clang/13.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/lib/Demangle -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/include -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-13/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/lib/Demangle -fdebug-prefix-map=/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c=. -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-07-26-235520-9401-1 -x c++ /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp

/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Demangle/MicrosoftDemangle.cpp

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

/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/Demangle/MicrosoftDemangle.h

1//===------------------------- MicrosoftDemangle.h --------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
10#define LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
11
12#include "llvm/Demangle/DemangleConfig.h"
13#include "llvm/Demangle/MicrosoftDemangleNodes.h"
14#include "llvm/Demangle/StringView.h"
15#include "llvm/Demangle/Utility.h"
16
17#include <utility>
18
19namespace llvm {
20namespace ms_demangle {
21// This memory allocator is extremely fast, but it doesn't call dtors
22// for allocated objects. That means you can't use STL containers
23// (such as std::vector) with this allocator. But it pays off --
24// the demangler is 3x faster with this allocator compared to one with
25// STL containers.
26constexpr size_t AllocUnit = 4096;
27
28class ArenaAllocator {
29 struct AllocatorNode {
30 uint8_t *Buf = nullptr;
31 size_t Used = 0;
32 size_t Capacity = 0;
33 AllocatorNode *Next = nullptr;
34 };
35
36 void addNode(size_t Capacity) {
37 AllocatorNode *NewHead = new AllocatorNode;
38 NewHead->Buf = new uint8_t[Capacity];
27
Value assigned to field 'Buf'
39 NewHead->Next = Head;
40 NewHead->Capacity = Capacity;
41 Head = NewHead;
42 NewHead->Used = 0;
43 }
44
45public:
46 ArenaAllocator() { addNode(AllocUnit); }
47
48 ~ArenaAllocator() {
49 while (Head) {
50 assert(Head->Buf)(static_cast <bool> (Head->Buf) ? void (0) : __assert_fail
("Head->Buf", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/Demangle/MicrosoftDemangle.h"
, 50, __extension__ __PRETTY_FUNCTION__))
;
51 delete[] Head->Buf;
52 AllocatorNode *Next = Head->Next;
53 delete Head;
54 Head = Next;
55 }
56 }
57
58 char *allocUnalignedBuffer(size_t Size) {
59 assert(Head && Head->Buf)(static_cast <bool> (Head && Head->Buf) ? void
(0) : __assert_fail ("Head && Head->Buf", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/Demangle/MicrosoftDemangle.h"
, 59, __extension__ __PRETTY_FUNCTION__))
;
60
61 uint8_t *P = Head->Buf + Head->Used;
62
63 Head->Used += Size;
64 if (Head->Used <= Head->Capacity)
65 return reinterpret_cast<char *>(P);
66
67 addNode(std::max(AllocUnit, Size));
68 Head->Used = Size;
69 return reinterpret_cast<char *>(Head->Buf);
70 }
71
72 template <typename T, typename... Args> T *allocArray(size_t Count) {
73 size_t Size = Count * sizeof(T);
74 assert(Head && Head->Buf)(static_cast <bool> (Head && Head->Buf) ? void
(0) : __assert_fail ("Head && Head->Buf", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/Demangle/MicrosoftDemangle.h"
, 74, __extension__ __PRETTY_FUNCTION__))
;
23
'?' condition is true
75
76 size_t P = (size_t)Head->Buf + Head->Used;
77 uintptr_t AlignedP =
78 (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
79 uint8_t *PP = (uint8_t *)AlignedP;
80 size_t Adjustment = AlignedP - P;
81
82 Head->Used += Size + Adjustment;
83 if (Head->Used <= Head->Capacity)
24
Assuming field 'Used' is > field 'Capacity'
25
Taking false branch
84 return new (PP) T[Count]();
85
86 addNode(std::max(AllocUnit, Size));
26
Calling 'ArenaAllocator::addNode'
28
Returning from 'ArenaAllocator::addNode'
87 Head->Used = Size;
88 return new (Head->Buf) T[Count]();
29
4096 bytes is possibly not enough for array allocation which requires 16 bytes. Current overhead requires the size of 4080 bytes
89 }
90
91 template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) {
92 constexpr size_t Size = sizeof(T);
93 assert(Head && Head->Buf)(static_cast <bool> (Head && Head->Buf) ? void
(0) : __assert_fail ("Head && Head->Buf", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/Demangle/MicrosoftDemangle.h"
, 93, __extension__ __PRETTY_FUNCTION__))
;
94
95 size_t P = (size_t)Head->Buf + Head->Used;
96 uintptr_t AlignedP =
97 (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
98 uint8_t *PP = (uint8_t *)AlignedP;
99 size_t Adjustment = AlignedP - P;
100
101 Head->Used += Size + Adjustment;
102 if (Head->Used <= Head->Capacity)
103 return new (PP) T(std::forward<Args>(ConstructorArgs)...);
104
105 static_assert(Size < AllocUnit, "");
106 addNode(AllocUnit);
107 Head->Used = Size;
108 return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...);
109 }
110
111private:
112 AllocatorNode *Head = nullptr;
113};
114
115struct BackrefContext {
116 static constexpr size_t Max = 10;
117
118 TypeNode *FunctionParams[Max];
119 size_t FunctionParamCount = 0;
120
121 // The first 10 BackReferences in a mangled name can be back-referenced by
122 // special name @[0-9]. This is a storage for the first 10 BackReferences.
123 NamedIdentifierNode *Names[Max];
124 size_t NamesCount = 0;
125};
126
127enum class QualifierMangleMode { Drop, Mangle, Result };
128
129enum NameBackrefBehavior : uint8_t {
130 NBB_None = 0, // don't save any names as backrefs.
131 NBB_Template = 1 << 0, // save template instanations.
132 NBB_Simple = 1 << 1, // save simple names.
133};
134
135enum class FunctionIdentifierCodeGroup { Basic, Under, DoubleUnder };
136
137// Demangler class takes the main role in demangling symbols.
138// It has a set of functions to parse mangled symbols into Type instances.
139// It also has a set of functions to convert Type instances to strings.
140class Demangler {
141public:
142 Demangler() = default;
143 virtual ~Demangler() = default;
144
145 // You are supposed to call parse() first and then check if error is true. If
146 // it is false, call output() to write the formatted name to the given stream.
147 SymbolNode *parse(StringView &MangledName);
148
149 TagTypeNode *parseTagUniqueName(StringView &MangledName);
150
151 // True if an error occurred.
152 bool Error = false;
153
154 void dumpBackReferences();
155
156private:
157 SymbolNode *demangleEncodedSymbol(StringView &MangledName,
158 QualifiedNameNode *QN);
159 SymbolNode *demangleDeclarator(StringView &MangledName);
160 SymbolNode *demangleMD5Name(StringView &MangledName);
161 SymbolNode *demangleTypeinfoName(StringView &MangledName);
162
163 VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,
164 StorageClass SC);
165 FunctionSymbolNode *demangleFunctionEncoding(StringView &MangledName);
166
167 Qualifiers demanglePointerExtQualifiers(StringView &MangledName);
168
169 // Parser functions. This is a recursive-descent parser.
170 TypeNode *demangleType(StringView &MangledName, QualifierMangleMode QMM);
171 PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName);
172 CustomTypeNode *demangleCustomType(StringView &MangledName);
173 TagTypeNode *demangleClassType(StringView &MangledName);
174 PointerTypeNode *demanglePointerType(StringView &MangledName);
175 PointerTypeNode *demangleMemberPointerType(StringView &MangledName);
176 FunctionSignatureNode *demangleFunctionType(StringView &MangledName,
177 bool HasThisQuals);
178
179 ArrayTypeNode *demangleArrayType(StringView &MangledName);
180
181 NodeArrayNode *demangleFunctionParameterList(StringView &MangledName,
182 bool &IsVariadic);
183 NodeArrayNode *demangleTemplateParameterList(StringView &MangledName);
184
185 std::pair<uint64_t, bool> demangleNumber(StringView &MangledName);
186 uint64_t demangleUnsigned(StringView &MangledName);
187 int64_t demangleSigned(StringView &MangledName);
188
189 void memorizeString(StringView s);
190 void memorizeIdentifier(IdentifierNode *Identifier);
191
192 /// Allocate a copy of \p Borrowed into memory that we own.
193 StringView copyString(StringView Borrowed);
194
195 QualifiedNameNode *demangleFullyQualifiedTypeName(StringView &MangledName);
196 QualifiedNameNode *demangleFullyQualifiedSymbolName(StringView &MangledName);
197
198 IdentifierNode *demangleUnqualifiedTypeName(StringView &MangledName,
199 bool Memorize);
200 IdentifierNode *demangleUnqualifiedSymbolName(StringView &MangledName,
201 NameBackrefBehavior NBB);
202
203 QualifiedNameNode *demangleNameScopeChain(StringView &MangledName,
204 IdentifierNode *UnqualifiedName);
205 IdentifierNode *demangleNameScopePiece(StringView &MangledName);
206
207 NamedIdentifierNode *demangleBackRefName(StringView &MangledName);
208 IdentifierNode *demangleTemplateInstantiationName(StringView &MangledName,
209 NameBackrefBehavior NBB);
210 IntrinsicFunctionKind
211 translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group);
212 IdentifierNode *demangleFunctionIdentifierCode(StringView &MangledName);
213 IdentifierNode *
214 demangleFunctionIdentifierCode(StringView &MangledName,
215 FunctionIdentifierCodeGroup Group);
216 StructorIdentifierNode *demangleStructorIdentifier(StringView &MangledName,
217 bool IsDestructor);
218 ConversionOperatorIdentifierNode *
219 demangleConversionOperatorIdentifier(StringView &MangledName);
220 LiteralOperatorIdentifierNode *
221 demangleLiteralOperatorIdentifier(StringView &MangledName);
222
223 SymbolNode *demangleSpecialIntrinsic(StringView &MangledName);
224 SpecialTableSymbolNode *
225 demangleSpecialTableSymbolNode(StringView &MangledName,
226 SpecialIntrinsicKind SIK);
227 LocalStaticGuardVariableNode *
228 demangleLocalStaticGuard(StringView &MangledName, bool IsThread);
229 VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
230 StringView &MangledName,
231 StringView VariableName);
232 VariableSymbolNode *
233 demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
234 StringView &MangledName);
235 FunctionSymbolNode *demangleInitFiniStub(StringView &MangledName,
236 bool IsDestructor);
237
238 NamedIdentifierNode *demangleSimpleName(StringView &MangledName,
239 bool Memorize);
240 NamedIdentifierNode *demangleAnonymousNamespaceName(StringView &MangledName);
241 NamedIdentifierNode *demangleLocallyScopedNamePiece(StringView &MangledName);
242 EncodedStringLiteralNode *demangleStringLiteral(StringView &MangledName);
243 FunctionSymbolNode *demangleVcallThunkNode(StringView &MangledName);
244
245 StringView demangleSimpleString(StringView &MangledName, bool Memorize);
246
247 FuncClass demangleFunctionClass(StringView &MangledName);
248 CallingConv demangleCallingConvention(StringView &MangledName);
249 StorageClass demangleVariableStorageClass(StringView &MangledName);
250 bool demangleThrowSpecification(StringView &MangledName);
251 wchar_t demangleWcharLiteral(StringView &MangledName);
252 uint8_t demangleCharLiteral(StringView &MangledName);
253
254 std::pair<Qualifiers, bool> demangleQualifiers(StringView &MangledName);
255
256 // Memory allocator.
257 ArenaAllocator Arena;
258
259 // A single type uses one global back-ref table for all function params.
260 // This means back-refs can even go "into" other types. Examples:
261 //
262 // // Second int* is a back-ref to first.
263 // void foo(int *, int*);
264 //
265 // // Second int* is not a back-ref to first (first is not a function param).
266 // int* foo(int*);
267 //
268 // // Second int* is a back-ref to first (ALL function types share the same
269 // // back-ref map.
270 // using F = void(*)(int*);
271 // F G(int *);
272 BackrefContext Backrefs;
273};
274
275} // namespace ms_demangle
276} // namespace llvm
277
278#endif // LLVM_DEMANGLE_MICROSOFTDEMANGLE_H