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