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