1 //===- MicrosoftDemangle.cpp ----------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
20 using namespace ms_demangle
;
22 #define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \
27 // Writes a space if the last token does not end with a punctuation.
28 static void outputSpaceIfNecessary(OutputStream
&OS
) {
33 if (std::isalnum(C
) || C
== '>')
37 static void outputSingleQualifier(OutputStream
&OS
, Qualifiers Q
) {
53 static bool outputQualifierIfPresent(OutputStream
&OS
, Qualifiers Q
,
54 Qualifiers Mask
, bool NeedSpace
) {
61 outputSingleQualifier(OS
, Mask
);
65 static void outputQualifiers(OutputStream
&OS
, Qualifiers Q
, bool SpaceBefore
,
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
)
79 static void outputCallingConvention(OutputStream
&OS
, CallingConv CC
) {
80 outputSpaceIfNecessary(OS
);
83 case CallingConv::Cdecl
:
86 case CallingConv::Fastcall
:
89 case CallingConv::Pascal
:
92 case CallingConv::Regcall
:
95 case CallingConv::Stdcall
:
98 case CallingConv::Thiscall
:
101 case CallingConv::Eabi
:
104 case CallingConv::Vectorcall
:
105 OS
<< "__vectorcall";
107 case CallingConv::Clrcall
:
110 case CallingConv::Swift
:
111 OS
<< "__attribute__((__swiftcall__)) ";
113 case CallingConv::SwiftAsync
:
114 OS
<< "__attribute__((__swiftasynccall__)) ";
121 std::string
Node::toString(OutputFlags Flags
) const {
123 initializeOutputStream(nullptr, nullptr, OS
, 1024);
124 this->output(OS
, Flags
);
126 std::string
Owned(OS
.getBuffer());
127 std::free(OS
.getBuffer());
131 void PrimitiveTypeNode::outputPre(OutputStream
&OS
, OutputFlags Flags
) const {
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 {
167 Nodes
[0]->output(OS
, Flags
);
168 for (size_t I
= 1; I
< Count
; ++I
) {
170 Nodes
[I
]->output(OS
, Flags
);
174 void EncodedStringLiteralNode::output(OutputStream
&OS
,
175 OutputFlags Flags
) const {
177 case CharKind::Wchar
:
183 case CharKind::Char16
:
186 case CharKind::Char32
:
190 OS
<< DecodedString
<< "\"";
195 void IntegerLiteralNode::output(OutputStream
&OS
, OutputFlags Flags
) const {
201 void TemplateParameterReferenceNode::output(OutputStream
&OS
,
202 OutputFlags Flags
) const {
203 if (ThunkOffsetCount
> 0)
205 else if (Affinity
== PointerAffinity::Pointer
)
209 Symbol
->output(OS
, Flags
);
210 if (ThunkOffsetCount
> 0)
214 if (ThunkOffsetCount
> 0)
215 OS
<< ThunkOffsets
[0];
216 for (int I
= 1; I
< ThunkOffsetCount
; ++I
) {
217 OS
<< ", " << ThunkOffsets
[I
];
219 if (ThunkOffsetCount
> 0)
223 void IdentifierNode::outputTemplateParameters(OutputStream
&OS
,
224 OutputFlags Flags
) const {
228 TemplateParams
->output(OS
, Flags
);
232 void DynamicStructorIdentifierNode::output(OutputStream
&OS
,
233 OutputFlags Flags
) const {
235 OS
<< "`dynamic atexit destructor for ";
237 OS
<< "`dynamic initializer for ";
241 Variable
->output(OS
, Flags
);
245 Name
->output(OS
, Flags
);
250 void NamedIdentifierNode::output(OutputStream
&OS
, OutputFlags Flags
) const {
252 outputTemplateParameters(OS
, Flags
);
255 void IntrinsicFunctionIdentifierNode::output(OutputStream
&OS
,
256 OutputFlags Flags
) const {
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
,
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
,
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
,
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
,
300 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, BitwiseOrEqual
,
302 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, BitwiseXorEqual
,
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
:
353 outputTemplateParameters(OS
, Flags
);
356 void LocalStaticGuardIdentifierNode::output(OutputStream
&OS
,
357 OutputFlags Flags
) const {
359 OS
<< "`local static thread guard'";
361 OS
<< "`local static guard'";
363 OS
<< "{" << ScopeIndex
<< "}";
366 void ConversionOperatorIdentifierNode::output(OutputStream
&OS
,
367 OutputFlags Flags
) const {
369 outputTemplateParameters(OS
, Flags
);
371 TargetType
->output(OS
, Flags
);
374 void StructorIdentifierNode::output(OutputStream
&OS
, OutputFlags Flags
) const {
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
)
392 if (FunctionClass
& FC_Protected
)
394 if (FunctionClass
& FC_Private
)
398 if (!(Flags
& OF_NoMemberType
)) {
399 if (!(FunctionClass
& FC_Global
)) {
400 if (FunctionClass
& FC_Static
)
403 if (FunctionClass
& FC_Virtual
)
406 if (FunctionClass
& FC_ExternC
)
407 OS
<< "extern \"C\" ";
410 if (!(Flags
& OF_NoReturnType
) && ReturnType
) {
411 ReturnType
->outputPre(OS
, Flags
);
415 if (!(Flags
& OF_NoCallingConvention
))
416 outputCallingConvention(OS
, CallConvention
);
419 void FunctionSignatureNode::outputPost(OutputStream
&OS
,
420 OutputFlags Flags
) const {
421 if (!(FunctionClass
& FC_NoParameterList
)) {
424 Params
->output(OS
, Flags
);
429 if (OS
.back() != '(')
438 if (Quals
& Q_Volatile
)
440 if (Quals
& Q_Restrict
)
442 if (Quals
& Q_Unaligned
)
443 OS
<< " __unaligned";
448 if (RefQualifier
== FunctionRefQualifier::Reference
)
450 else if (RefQualifier
== FunctionRefQualifier::RValueReference
)
453 if (!(Flags
& OF_NoReturnType
) && ReturnType
)
454 ReturnType
->outputPost(OS
, Flags
);
457 void ThunkSignatureNode::outputPre(OutputStream
&OS
, OutputFlags Flags
) const {
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
<< "}'";
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
);
488 Pointee
->outputPre(OS
, Flags
);
490 outputSpaceIfNecessary(OS
);
492 if (Quals
& Q_Unaligned
)
493 OS
<< "__unaligned ";
495 if (Pointee
->kind() == NodeKind::ArrayType
) {
497 } else if (Pointee
->kind() == NodeKind::FunctionSignature
) {
499 const FunctionSignatureNode
*Sig
=
500 static_cast<const FunctionSignatureNode
*>(Pointee
);
501 outputCallingConvention(OS
, Sig
->CallConvention
);
506 ClassParent
->output(OS
, Flags
);
511 case PointerAffinity::Pointer
:
514 case PointerAffinity::Reference
:
517 case PointerAffinity::RValueReference
:
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
)
531 Pointee
->outputPost(OS
, Flags
);
534 void TagTypeNode::outputPre(OutputStream
&OS
, OutputFlags Flags
) const {
535 if (!(Flags
& OF_NoTagSpecifier
)) {
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");
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
,
557 assert(N
->kind() == NodeKind::IntegerLiteral
);
558 IntegerLiteralNode
*ILN
= static_cast<IntegerLiteralNode
*>(N
);
560 ILN
->output(OS
, Flags
);
563 void ArrayTypeNode::outputDimensionsImpl(OutputStream
&OS
,
564 OutputFlags Flags
) const {
565 if (Dimensions
->Count
== 0)
568 outputOneDimension(OS
, Flags
, Dimensions
->Nodes
[0]);
569 for (size_t I
= 1; I
< Dimensions
->Count
; ++I
) {
571 outputOneDimension(OS
, Flags
, Dimensions
->Nodes
[I
]);
575 void ArrayTypeNode::outputPost(OutputStream
&OS
, OutputFlags Flags
) const {
577 outputDimensionsImpl(OS
, Flags
);
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;
598 case StorageClass::PrivateStatic
:
599 AccessSpec
= "private";
601 case StorageClass::PublicStatic
:
602 AccessSpec
= "public";
604 case StorageClass::ProtectedStatic
:
605 AccessSpec
= "protected";
611 if (!(Flags
& OF_NoAccessSpecifier
) && AccessSpec
)
612 OS
<< AccessSpec
<< ": ";
613 if (!(Flags
& OF_NoMemberType
) && IsStatic
)
617 Type
->outputPre(OS
, Flags
);
618 outputSpaceIfNecessary(OS
);
620 Name
->output(OS
, Flags
);
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
<< ", "
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
);
657 TargetName
->output(OS
, Flags
);