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