Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Demangle/MicrosoftDemangleNodes.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
//===----------------------------------------------------------------------===//
12
13
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
14
#include "llvm/Demangle/Utility.h"
15
#include <cctype>
16
#include <string>
17
18
using namespace llvm;
19
using namespace ms_demangle;
20
21
#define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \
22
case Enum::Value: \
23
OB << Desc; \
24
break;
25
26
// Writes a space if the last token does not end with a punctuation.
27
static void outputSpaceIfNecessary(OutputBuffer &OB) {
28
if (OB.empty())
29
return;
30
31
char C = OB.back();
32
if (std::isalnum(C) || C == '>')
33
OB << " ";
34
}
35
36
static void outputSingleQualifier(OutputBuffer &OB, Qualifiers Q) {
37
switch (Q) {
38
case Q_Const:
39
OB << "const";
40
break;
41
case Q_Volatile:
42
OB << "volatile";
43
break;
44
case Q_Restrict:
45
OB << "__restrict";
46
break;
47
default:
48
break;
49
}
50
}
51
52
static bool outputQualifierIfPresent(OutputBuffer &OB, Qualifiers Q,
53
Qualifiers Mask, bool NeedSpace) {
54
if (!(Q & Mask))
55
return NeedSpace;
56
57
if (NeedSpace)
58
OB << " ";
59
60
outputSingleQualifier(OB, Mask);
61
return true;
62
}
63
64
static void outputQualifiers(OutputBuffer &OB, Qualifiers Q, bool SpaceBefore,
65
bool SpaceAfter) {
66
if (Q == Q_None)
67
return;
68
69
size_t Pos1 = OB.getCurrentPosition();
70
SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Const, SpaceBefore);
71
SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Volatile, SpaceBefore);
72
SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Restrict, SpaceBefore);
73
size_t Pos2 = OB.getCurrentPosition();
74
if (SpaceAfter && Pos2 > Pos1)
75
OB << " ";
76
}
77
78
static void outputCallingConvention(OutputBuffer &OB, CallingConv CC) {
79
outputSpaceIfNecessary(OB);
80
81
switch (CC) {
82
case CallingConv::Cdecl:
83
OB << "__cdecl";
84
break;
85
case CallingConv::Fastcall:
86
OB << "__fastcall";
87
break;
88
case CallingConv::Pascal:
89
OB << "__pascal";
90
break;
91
case CallingConv::Regcall:
92
OB << "__regcall";
93
break;
94
case CallingConv::Stdcall:
95
OB << "__stdcall";
96
break;
97
case CallingConv::Thiscall:
98
OB << "__thiscall";
99
break;
100
case CallingConv::Eabi:
101
OB << "__eabi";
102
break;
103
case CallingConv::Vectorcall:
104
OB << "__vectorcall";
105
break;
106
case CallingConv::Clrcall:
107
OB << "__clrcall";
108
break;
109
case CallingConv::Swift:
110
OB << "__attribute__((__swiftcall__)) ";
111
break;
112
case CallingConv::SwiftAsync:
113
OB << "__attribute__((__swiftasynccall__)) ";
114
break;
115
default:
116
break;
117
}
118
}
119
120
std::string Node::toString(OutputFlags Flags) const {
121
OutputBuffer OB;
122
this->output(OB, Flags);
123
std::string_view SV = OB;
124
std::string Owned(SV.begin(), SV.end());
125
std::free(OB.getBuffer());
126
return Owned;
127
}
128
129
void PrimitiveTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
130
switch (PrimKind) {
131
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void");
132
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool");
133
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char");
134
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char");
135
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");
136
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t");
137
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t");
138
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t");
139
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short");
140
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short");
141
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int");
142
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int");
143
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long");
144
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long");
145
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64");
146
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64");
147
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t");
148
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float");
149
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double");
150
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double");
151
OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");
152
}
153
outputQualifiers(OB, Quals, true, false);
154
}
155
156
void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags) const {
157
output(OB, Flags, ", ");
158
}
159
160
void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags,
161
std::string_view Separator) const {
162
if (Count == 0)
163
return;
164
if (Nodes[0])
165
Nodes[0]->output(OB, Flags);
166
for (size_t I = 1; I < Count; ++I) {
167
OB << Separator;
168
Nodes[I]->output(OB, Flags);
169
}
170
}
171
172
void EncodedStringLiteralNode::output(OutputBuffer &OB,
173
OutputFlags Flags) const {
174
switch (Char) {
175
case CharKind::Wchar:
176
OB << "L\"";
177
break;
178
case CharKind::Char:
179
OB << "\"";
180
break;
181
case CharKind::Char16:
182
OB << "u\"";
183
break;
184
case CharKind::Char32:
185
OB << "U\"";
186
break;
187
}
188
OB << DecodedString << "\"";
189
if (IsTruncated)
190
OB << "...";
191
}
192
193
void IntegerLiteralNode::output(OutputBuffer &OB, OutputFlags Flags) const {
194
if (IsNegative)
195
OB << '-';
196
OB << Value;
197
}
198
199
void TemplateParameterReferenceNode::output(OutputBuffer &OB,
200
OutputFlags Flags) const {
201
if (ThunkOffsetCount > 0)
202
OB << "{";
203
else if (Affinity == PointerAffinity::Pointer)
204
OB << "&";
205
206
if (Symbol) {
207
Symbol->output(OB, Flags);
208
if (ThunkOffsetCount > 0)
209
OB << ", ";
210
}
211
212
if (ThunkOffsetCount > 0)
213
OB << ThunkOffsets[0];
214
for (int I = 1; I < ThunkOffsetCount; ++I) {
215
OB << ", " << ThunkOffsets[I];
216
}
217
if (ThunkOffsetCount > 0)
218
OB << "}";
219
}
220
221
void IdentifierNode::outputTemplateParameters(OutputBuffer &OB,
222
OutputFlags Flags) const {
223
if (!TemplateParams)
224
return;
225
OB << "<";
226
TemplateParams->output(OB, Flags);
227
OB << ">";
228
}
229
230
void DynamicStructorIdentifierNode::output(OutputBuffer &OB,
231
OutputFlags Flags) const {
232
if (IsDestructor)
233
OB << "`dynamic atexit destructor for ";
234
else
235
OB << "`dynamic initializer for ";
236
237
if (Variable) {
238
OB << "`";
239
Variable->output(OB, Flags);
240
OB << "''";
241
} else {
242
OB << "'";
243
Name->output(OB, Flags);
244
OB << "''";
245
}
246
}
247
248
void NamedIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {
249
OB << Name;
250
outputTemplateParameters(OB, Flags);
251
}
252
253
void IntrinsicFunctionIdentifierNode::output(OutputBuffer &OB,
254
OutputFlags Flags) const {
255
switch (Operator) {
256
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new");
257
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete");
258
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator=");
259
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>");
260
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<");
261
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!");
262
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator==");
263
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!=");
264
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript,
265
"operator[]");
266
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->");
267
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++");
268
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--");
269
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-");
270
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+");
271
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*");
272
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&");
273
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer,
274
"operator->*");
275
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/");
276
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%");
277
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<");
278
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<=");
279
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>");
280
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual,
281
"operator>=");
282
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,");
283
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()");
284
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~");
285
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^");
286
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|");
287
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&");
288
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||");
289
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*=");
290
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+=");
291
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-=");
292
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/=");
293
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%=");
294
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>=");
295
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<=");
296
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual,
297
"operator&=");
298
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual,
299
"operator|=");
300
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual,
301
"operator^=");
302
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'");
303
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor,
304
"`vector deleting dtor'");
305
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure,
306
"`default ctor closure'");
307
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor,
308
"`scalar deleting dtor'");
309
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter,
310
"`vector ctor iterator'");
311
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter,
312
"`vector dtor iterator'");
313
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter,
314
"`vector vbase ctor iterator'");
315
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap,
316
"`virtual displacement map'");
317
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter,
318
"`eh vector ctor iterator'");
319
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter,
320
"`eh vector dtor iterator'");
321
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter,
322
"`eh vector vbase ctor iterator'");
323
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure,
324
"`copy ctor closure'");
325
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure,
326
"`local vftable ctor closure'");
327
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]");
328
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete,
329
"operator delete[]");
330
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter,
331
"`managed vector ctor iterator'");
332
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter,
333
"`managed vector dtor iterator'");
334
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter,
335
"`EH vector copy ctor iterator'");
336
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter,
337
"`EH vector vbase copy ctor iterator'");
338
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter,
339
"`vector copy ctor iterator'");
340
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter,
341
"`vector vbase copy constructor iterator'");
342
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter,
343
"`managed vector vbase copy constructor iterator'");
344
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait,
345
"operator co_await");
346
OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>");
347
case IntrinsicFunctionKind::MaxIntrinsic:
348
case IntrinsicFunctionKind::None:
349
break;
350
}
351
outputTemplateParameters(OB, Flags);
352
}
353
354
void LocalStaticGuardIdentifierNode::output(OutputBuffer &OB,
355
OutputFlags Flags) const {
356
if (IsThread)
357
OB << "`local static thread guard'";
358
else
359
OB << "`local static guard'";
360
if (ScopeIndex > 0)
361
OB << "{" << ScopeIndex << "}";
362
}
363
364
void ConversionOperatorIdentifierNode::output(OutputBuffer &OB,
365
OutputFlags Flags) const {
366
OB << "operator";
367
outputTemplateParameters(OB, Flags);
368
OB << " ";
369
TargetType->output(OB, Flags);
370
}
371
372
void StructorIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {
373
if (IsDestructor)
374
OB << "~";
375
Class->output(OB, Flags);
376
outputTemplateParameters(OB, Flags);
377
}
378
379
void LiteralOperatorIdentifierNode::output(OutputBuffer &OB,
380
OutputFlags Flags) const {
381
OB << "operator \"\"" << Name;
382
outputTemplateParameters(OB, Flags);
383
}
384
385
void FunctionSignatureNode::outputPre(OutputBuffer &OB,
386
OutputFlags Flags) const {
387
if (!(Flags & OF_NoAccessSpecifier)) {
388
if (FunctionClass & FC_Public)
389
OB << "public: ";
390
if (FunctionClass & FC_Protected)
391
OB << "protected: ";
392
if (FunctionClass & FC_Private)
393
OB << "private: ";
394
}
395
396
if (!(Flags & OF_NoMemberType)) {
397
if (!(FunctionClass & FC_Global)) {
398
if (FunctionClass & FC_Static)
399
OB << "static ";
400
}
401
if (FunctionClass & FC_Virtual)
402
OB << "virtual ";
403
404
if (FunctionClass & FC_ExternC)
405
OB << "extern \"C\" ";
406
}
407
408
if (!(Flags & OF_NoReturnType) && ReturnType) {
409
ReturnType->outputPre(OB, Flags);
410
OB << " ";
411
}
412
413
if (!(Flags & OF_NoCallingConvention))
414
outputCallingConvention(OB, CallConvention);
415
}
416
417
void FunctionSignatureNode::outputPost(OutputBuffer &OB,
418
OutputFlags Flags) const {
419
if (!(FunctionClass & FC_NoParameterList)) {
420
OB << "(";
421
if (Params)
422
Params->output(OB, Flags);
423
else
424
OB << "void";
425
426
if (IsVariadic) {
427
if (OB.back() != '(')
428
OB << ", ";
429
OB << "...";
430
}
431
OB << ")";
432
}
433
434
if (Quals & Q_Const)
435
OB << " const";
436
if (Quals & Q_Volatile)
437
OB << " volatile";
438
if (Quals & Q_Restrict)
439
OB << " __restrict";
440
if (Quals & Q_Unaligned)
441
OB << " __unaligned";
442
443
if (IsNoexcept)
444
OB << " noexcept";
445
446
if (RefQualifier == FunctionRefQualifier::Reference)
447
OB << " &";
448
else if (RefQualifier == FunctionRefQualifier::RValueReference)
449
OB << " &&";
450
451
if (!(Flags & OF_NoReturnType) && ReturnType)
452
ReturnType->outputPost(OB, Flags);
453
}
454
455
void ThunkSignatureNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
456
OB << "[thunk]: ";
457
458
FunctionSignatureNode::outputPre(OB, Flags);
459
}
460
461
void ThunkSignatureNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
462
if (FunctionClass & FC_StaticThisAdjust) {
463
OB << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
464
} else if (FunctionClass & FC_VirtualThisAdjust) {
465
if (FunctionClass & FC_VirtualThisAdjustEx) {
466
OB << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
467
<< ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset
468
<< ", " << ThisAdjust.StaticOffset << "}'";
469
} else {
470
OB << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
471
<< ThisAdjust.StaticOffset << "}'";
472
}
473
}
474
475
FunctionSignatureNode::outputPost(OB, Flags);
476
}
477
478
void PointerTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
479
if (Pointee->kind() == NodeKind::FunctionSignature) {
480
// If this is a pointer to a function, don't output the calling convention.
481
// It needs to go inside the parentheses.
482
const FunctionSignatureNode *Sig =
483
static_cast<const FunctionSignatureNode *>(Pointee);
484
Sig->outputPre(OB, OF_NoCallingConvention);
485
} else
486
Pointee->outputPre(OB, Flags);
487
488
outputSpaceIfNecessary(OB);
489
490
if (Quals & Q_Unaligned)
491
OB << "__unaligned ";
492
493
if (Pointee->kind() == NodeKind::ArrayType) {
494
OB << "(";
495
} else if (Pointee->kind() == NodeKind::FunctionSignature) {
496
OB << "(";
497
const FunctionSignatureNode *Sig =
498
static_cast<const FunctionSignatureNode *>(Pointee);
499
outputCallingConvention(OB, Sig->CallConvention);
500
OB << " ";
501
}
502
503
if (ClassParent) {
504
ClassParent->output(OB, Flags);
505
OB << "::";
506
}
507
508
switch (Affinity) {
509
case PointerAffinity::Pointer:
510
OB << "*";
511
break;
512
case PointerAffinity::Reference:
513
OB << "&";
514
break;
515
case PointerAffinity::RValueReference:
516
OB << "&&";
517
break;
518
default:
519
assert(false);
520
}
521
outputQualifiers(OB, Quals, false, false);
522
}
523
524
void PointerTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
525
if (Pointee->kind() == NodeKind::ArrayType ||
526
Pointee->kind() == NodeKind::FunctionSignature)
527
OB << ")";
528
529
Pointee->outputPost(OB, Flags);
530
}
531
532
void TagTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
533
if (!(Flags & OF_NoTagSpecifier)) {
534
switch (Tag) {
535
OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");
536
OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct");
537
OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");
538
OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");
539
}
540
OB << " ";
541
}
542
QualifiedName->output(OB, Flags);
543
outputQualifiers(OB, Quals, true, false);
544
}
545
546
void TagTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}
547
548
void ArrayTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
549
ElementType->outputPre(OB, Flags);
550
outputQualifiers(OB, Quals, true, false);
551
}
552
553
void ArrayTypeNode::outputOneDimension(OutputBuffer &OB, OutputFlags Flags,
554
Node *N) const {
555
assert(N->kind() == NodeKind::IntegerLiteral);
556
IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);
557
if (ILN->Value != 0)
558
ILN->output(OB, Flags);
559
}
560
561
void ArrayTypeNode::outputDimensionsImpl(OutputBuffer &OB,
562
OutputFlags Flags) const {
563
if (Dimensions->Count == 0)
564
return;
565
566
outputOneDimension(OB, Flags, Dimensions->Nodes[0]);
567
for (size_t I = 1; I < Dimensions->Count; ++I) {
568
OB << "][";
569
outputOneDimension(OB, Flags, Dimensions->Nodes[I]);
570
}
571
}
572
573
void ArrayTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
574
OB << "[";
575
outputDimensionsImpl(OB, Flags);
576
OB << "]";
577
578
ElementType->outputPost(OB, Flags);
579
}
580
581
void SymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
582
Name->output(OB, Flags);
583
}
584
585
void FunctionSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
586
Signature->outputPre(OB, Flags);
587
outputSpaceIfNecessary(OB);
588
Name->output(OB, Flags);
589
Signature->outputPost(OB, Flags);
590
}
591
592
void VariableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
593
const char *AccessSpec = nullptr;
594
bool IsStatic = true;
595
switch (SC) {
596
case StorageClass::PrivateStatic:
597
AccessSpec = "private";
598
break;
599
case StorageClass::PublicStatic:
600
AccessSpec = "public";
601
break;
602
case StorageClass::ProtectedStatic:
603
AccessSpec = "protected";
604
break;
605
default:
606
IsStatic = false;
607
break;
608
}
609
if (!(Flags & OF_NoAccessSpecifier) && AccessSpec)
610
OB << AccessSpec << ": ";
611
if (!(Flags & OF_NoMemberType) && IsStatic)
612
OB << "static ";
613
614
if (!(Flags & OF_NoVariableType) && Type) {
615
Type->outputPre(OB, Flags);
616
outputSpaceIfNecessary(OB);
617
}
618
Name->output(OB, Flags);
619
if (!(Flags & OF_NoVariableType) && Type)
620
Type->outputPost(OB, Flags);
621
}
622
623
void CustomTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
624
Identifier->output(OB, Flags);
625
}
626
void CustomTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}
627
628
void QualifiedNameNode::output(OutputBuffer &OB, OutputFlags Flags) const {
629
Components->output(OB, Flags, "::");
630
}
631
632
void RttiBaseClassDescriptorNode::output(OutputBuffer &OB,
633
OutputFlags Flags) const {
634
OB << "`RTTI Base Class Descriptor at (";
635
OB << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
636
<< this->Flags;
637
OB << ")'";
638
}
639
640
void LocalStaticGuardVariableNode::output(OutputBuffer &OB,
641
OutputFlags Flags) const {
642
Name->output(OB, Flags);
643
}
644
645
void VcallThunkIdentifierNode::output(OutputBuffer &OB,
646
OutputFlags Flags) const {
647
OB << "`vcall'{" << OffsetInVTable << ", {flat}}";
648
}
649
650
void SpecialTableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
651
outputQualifiers(OB, Quals, false, true);
652
Name->output(OB, Flags);
653
if (TargetName) {
654
OB << "{for `";
655
TargetName->output(OB, Flags);
656
OB << "'}";
657
}
658
}
659
660