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/Utility.h"
19 using namespace ms_demangle
;
21 #define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \
26 // Writes a space if the last token does not end with a punctuation.
27 static void outputSpaceIfNecessary(OutputBuffer
&OB
) {
32 if (std::isalnum(C
) || C
== '>')
36 static void outputSingleQualifier(OutputBuffer
&OB
, Qualifiers Q
) {
52 static bool outputQualifierIfPresent(OutputBuffer
&OB
, Qualifiers Q
,
53 Qualifiers Mask
, bool NeedSpace
) {
60 outputSingleQualifier(OB
, Mask
);
64 static void outputQualifiers(OutputBuffer
&OB
, Qualifiers Q
, bool SpaceBefore
,
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
)
78 static void outputCallingConvention(OutputBuffer
&OB
, CallingConv CC
) {
79 outputSpaceIfNecessary(OB
);
82 case CallingConv::Cdecl
:
85 case CallingConv::Fastcall
:
88 case CallingConv::Pascal
:
91 case CallingConv::Regcall
:
94 case CallingConv::Stdcall
:
97 case CallingConv::Thiscall
:
100 case CallingConv::Eabi
:
103 case CallingConv::Vectorcall
:
104 OB
<< "__vectorcall";
106 case CallingConv::Clrcall
:
109 case CallingConv::Swift
:
110 OB
<< "__attribute__((__swiftcall__)) ";
112 case CallingConv::SwiftAsync
:
113 OB
<< "__attribute__((__swiftasynccall__)) ";
120 std::string
Node::toString(OutputFlags Flags
) const {
122 initializeOutputBuffer(nullptr, nullptr, OB
, 1024);
123 this->output(OB
, Flags
);
125 std::string
Owned(SV
.begin(), SV
.end());
126 std::free(OB
.getBuffer());
130 void PrimitiveTypeNode::outputPre(OutputBuffer
&OB
, OutputFlags Flags
) const {
132 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Void
, "void");
133 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Bool
, "bool");
134 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Char
, "char");
135 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Schar
, "signed char");
136 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Uchar
, "unsigned char");
137 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Char8
, "char8_t");
138 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Char16
, "char16_t");
139 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Char32
, "char32_t");
140 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Short
, "short");
141 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Ushort
, "unsigned short");
142 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Int
, "int");
143 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Uint
, "unsigned int");
144 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Long
, "long");
145 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Ulong
, "unsigned long");
146 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Int64
, "__int64");
147 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Uint64
, "unsigned __int64");
148 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Wchar
, "wchar_t");
149 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Float
, "float");
150 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Double
, "double");
151 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Ldouble
, "long double");
152 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind
, Nullptr
, "std::nullptr_t");
154 outputQualifiers(OB
, Quals
, true, false);
157 void NodeArrayNode::output(OutputBuffer
&OB
, OutputFlags Flags
) const {
158 output(OB
, Flags
, ", ");
161 void NodeArrayNode::output(OutputBuffer
&OB
, OutputFlags Flags
,
162 StringView Separator
) const {
166 Nodes
[0]->output(OB
, Flags
);
167 for (size_t I
= 1; I
< Count
; ++I
) {
169 Nodes
[I
]->output(OB
, Flags
);
173 void EncodedStringLiteralNode::output(OutputBuffer
&OB
,
174 OutputFlags Flags
) const {
176 case CharKind::Wchar
:
182 case CharKind::Char16
:
185 case CharKind::Char32
:
189 OB
<< DecodedString
<< "\"";
194 void IntegerLiteralNode::output(OutputBuffer
&OB
, OutputFlags Flags
) const {
200 void TemplateParameterReferenceNode::output(OutputBuffer
&OB
,
201 OutputFlags Flags
) const {
202 if (ThunkOffsetCount
> 0)
204 else if (Affinity
== PointerAffinity::Pointer
)
208 Symbol
->output(OB
, Flags
);
209 if (ThunkOffsetCount
> 0)
213 if (ThunkOffsetCount
> 0)
214 OB
<< ThunkOffsets
[0];
215 for (int I
= 1; I
< ThunkOffsetCount
; ++I
) {
216 OB
<< ", " << ThunkOffsets
[I
];
218 if (ThunkOffsetCount
> 0)
222 void IdentifierNode::outputTemplateParameters(OutputBuffer
&OB
,
223 OutputFlags Flags
) const {
227 TemplateParams
->output(OB
, Flags
);
231 void DynamicStructorIdentifierNode::output(OutputBuffer
&OB
,
232 OutputFlags Flags
) const {
234 OB
<< "`dynamic atexit destructor for ";
236 OB
<< "`dynamic initializer for ";
240 Variable
->output(OB
, Flags
);
244 Name
->output(OB
, Flags
);
249 void NamedIdentifierNode::output(OutputBuffer
&OB
, OutputFlags Flags
) const {
251 outputTemplateParameters(OB
, Flags
);
254 void IntrinsicFunctionIdentifierNode::output(OutputBuffer
&OB
,
255 OutputFlags Flags
) const {
257 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, New
, "operator new");
258 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Delete
, "operator delete");
259 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Assign
, "operator=");
260 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, RightShift
, "operator>>");
261 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, LeftShift
, "operator<<");
262 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, LogicalNot
, "operator!");
263 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Equals
, "operator==");
264 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, NotEquals
, "operator!=");
265 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, ArraySubscript
,
267 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Pointer
, "operator->");
268 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Increment
, "operator++");
269 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Decrement
, "operator--");
270 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Minus
, "operator-");
271 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Plus
, "operator+");
272 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Dereference
, "operator*");
273 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, BitwiseAnd
, "operator&");
274 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, MemberPointer
,
276 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Divide
, "operator/");
277 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Modulus
, "operator%");
278 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, LessThan
, "operator<");
279 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, LessThanEqual
, "operator<=");
280 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, GreaterThan
, "operator>");
281 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, GreaterThanEqual
,
283 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Comma
, "operator,");
284 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Parens
, "operator()");
285 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, BitwiseNot
, "operator~");
286 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, BitwiseXor
, "operator^");
287 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, BitwiseOr
, "operator|");
288 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, LogicalAnd
, "operator&&");
289 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, LogicalOr
, "operator||");
290 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, TimesEqual
, "operator*=");
291 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, PlusEqual
, "operator+=");
292 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, MinusEqual
, "operator-=");
293 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, DivEqual
, "operator/=");
294 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, ModEqual
, "operator%=");
295 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, RshEqual
, "operator>>=");
296 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, LshEqual
, "operator<<=");
297 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, BitwiseAndEqual
,
299 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, BitwiseOrEqual
,
301 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, BitwiseXorEqual
,
303 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, VbaseDtor
, "`vbase dtor'");
304 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, VecDelDtor
,
305 "`vector deleting dtor'");
306 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, DefaultCtorClosure
,
307 "`default ctor closure'");
308 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, ScalarDelDtor
,
309 "`scalar deleting dtor'");
310 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, VecCtorIter
,
311 "`vector ctor iterator'");
312 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, VecDtorIter
,
313 "`vector dtor iterator'");
314 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, VecVbaseCtorIter
,
315 "`vector vbase ctor iterator'");
316 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, VdispMap
,
317 "`virtual displacement map'");
318 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, EHVecCtorIter
,
319 "`eh vector ctor iterator'");
320 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, EHVecDtorIter
,
321 "`eh vector dtor iterator'");
322 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, EHVecVbaseCtorIter
,
323 "`eh vector vbase ctor iterator'");
324 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, CopyCtorClosure
,
325 "`copy ctor closure'");
326 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, LocalVftableCtorClosure
,
327 "`local vftable ctor closure'");
328 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, ArrayNew
, "operator new[]");
329 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, ArrayDelete
,
330 "operator delete[]");
331 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, ManVectorCtorIter
,
332 "`managed vector ctor iterator'");
333 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, ManVectorDtorIter
,
334 "`managed vector dtor iterator'");
335 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, EHVectorCopyCtorIter
,
336 "`EH vector copy ctor iterator'");
337 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, EHVectorVbaseCopyCtorIter
,
338 "`EH vector vbase copy ctor iterator'");
339 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, VectorCopyCtorIter
,
340 "`vector copy ctor iterator'");
341 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, VectorVbaseCopyCtorIter
,
342 "`vector vbase copy constructor iterator'");
343 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, ManVectorVbaseCopyCtorIter
,
344 "`managed vector vbase copy constructor iterator'");
345 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, CoAwait
,
346 "operator co_await");
347 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind
, Spaceship
, "operator<=>");
348 case IntrinsicFunctionKind::MaxIntrinsic
:
349 case IntrinsicFunctionKind::None
:
352 outputTemplateParameters(OB
, Flags
);
355 void LocalStaticGuardIdentifierNode::output(OutputBuffer
&OB
,
356 OutputFlags Flags
) const {
358 OB
<< "`local static thread guard'";
360 OB
<< "`local static guard'";
362 OB
<< "{" << ScopeIndex
<< "}";
365 void ConversionOperatorIdentifierNode::output(OutputBuffer
&OB
,
366 OutputFlags Flags
) const {
368 outputTemplateParameters(OB
, Flags
);
370 TargetType
->output(OB
, Flags
);
373 void StructorIdentifierNode::output(OutputBuffer
&OB
, OutputFlags Flags
) const {
376 Class
->output(OB
, Flags
);
377 outputTemplateParameters(OB
, Flags
);
380 void LiteralOperatorIdentifierNode::output(OutputBuffer
&OB
,
381 OutputFlags Flags
) const {
382 OB
<< "operator \"\"" << Name
;
383 outputTemplateParameters(OB
, Flags
);
386 void FunctionSignatureNode::outputPre(OutputBuffer
&OB
,
387 OutputFlags Flags
) const {
388 if (!(Flags
& OF_NoAccessSpecifier
)) {
389 if (FunctionClass
& FC_Public
)
391 if (FunctionClass
& FC_Protected
)
393 if (FunctionClass
& FC_Private
)
397 if (!(Flags
& OF_NoMemberType
)) {
398 if (!(FunctionClass
& FC_Global
)) {
399 if (FunctionClass
& FC_Static
)
402 if (FunctionClass
& FC_Virtual
)
405 if (FunctionClass
& FC_ExternC
)
406 OB
<< "extern \"C\" ";
409 if (!(Flags
& OF_NoReturnType
) && ReturnType
) {
410 ReturnType
->outputPre(OB
, Flags
);
414 if (!(Flags
& OF_NoCallingConvention
))
415 outputCallingConvention(OB
, CallConvention
);
418 void FunctionSignatureNode::outputPost(OutputBuffer
&OB
,
419 OutputFlags Flags
) const {
420 if (!(FunctionClass
& FC_NoParameterList
)) {
423 Params
->output(OB
, Flags
);
428 if (OB
.back() != '(')
437 if (Quals
& Q_Volatile
)
439 if (Quals
& Q_Restrict
)
441 if (Quals
& Q_Unaligned
)
442 OB
<< " __unaligned";
447 if (RefQualifier
== FunctionRefQualifier::Reference
)
449 else if (RefQualifier
== FunctionRefQualifier::RValueReference
)
452 if (!(Flags
& OF_NoReturnType
) && ReturnType
)
453 ReturnType
->outputPost(OB
, Flags
);
456 void ThunkSignatureNode::outputPre(OutputBuffer
&OB
, OutputFlags Flags
) const {
459 FunctionSignatureNode::outputPre(OB
, Flags
);
462 void ThunkSignatureNode::outputPost(OutputBuffer
&OB
, OutputFlags Flags
) const {
463 if (FunctionClass
& FC_StaticThisAdjust
) {
464 OB
<< "`adjustor{" << ThisAdjust
.StaticOffset
<< "}'";
465 } else if (FunctionClass
& FC_VirtualThisAdjust
) {
466 if (FunctionClass
& FC_VirtualThisAdjustEx
) {
467 OB
<< "`vtordispex{" << ThisAdjust
.VBPtrOffset
<< ", "
468 << ThisAdjust
.VBOffsetOffset
<< ", " << ThisAdjust
.VtordispOffset
469 << ", " << ThisAdjust
.StaticOffset
<< "}'";
471 OB
<< "`vtordisp{" << ThisAdjust
.VtordispOffset
<< ", "
472 << ThisAdjust
.StaticOffset
<< "}'";
476 FunctionSignatureNode::outputPost(OB
, Flags
);
479 void PointerTypeNode::outputPre(OutputBuffer
&OB
, OutputFlags Flags
) const {
480 if (Pointee
->kind() == NodeKind::FunctionSignature
) {
481 // If this is a pointer to a function, don't output the calling convention.
482 // It needs to go inside the parentheses.
483 const FunctionSignatureNode
*Sig
=
484 static_cast<const FunctionSignatureNode
*>(Pointee
);
485 Sig
->outputPre(OB
, OF_NoCallingConvention
);
487 Pointee
->outputPre(OB
, Flags
);
489 outputSpaceIfNecessary(OB
);
491 if (Quals
& Q_Unaligned
)
492 OB
<< "__unaligned ";
494 if (Pointee
->kind() == NodeKind::ArrayType
) {
496 } else if (Pointee
->kind() == NodeKind::FunctionSignature
) {
498 const FunctionSignatureNode
*Sig
=
499 static_cast<const FunctionSignatureNode
*>(Pointee
);
500 outputCallingConvention(OB
, Sig
->CallConvention
);
505 ClassParent
->output(OB
, Flags
);
510 case PointerAffinity::Pointer
:
513 case PointerAffinity::Reference
:
516 case PointerAffinity::RValueReference
:
522 outputQualifiers(OB
, Quals
, false, false);
525 void PointerTypeNode::outputPost(OutputBuffer
&OB
, OutputFlags Flags
) const {
526 if (Pointee
->kind() == NodeKind::ArrayType
||
527 Pointee
->kind() == NodeKind::FunctionSignature
)
530 Pointee
->outputPost(OB
, Flags
);
533 void TagTypeNode::outputPre(OutputBuffer
&OB
, OutputFlags Flags
) const {
534 if (!(Flags
& OF_NoTagSpecifier
)) {
536 OUTPUT_ENUM_CLASS_VALUE(TagKind
, Class
, "class");
537 OUTPUT_ENUM_CLASS_VALUE(TagKind
, Struct
, "struct");
538 OUTPUT_ENUM_CLASS_VALUE(TagKind
, Union
, "union");
539 OUTPUT_ENUM_CLASS_VALUE(TagKind
, Enum
, "enum");
543 QualifiedName
->output(OB
, Flags
);
544 outputQualifiers(OB
, Quals
, true, false);
547 void TagTypeNode::outputPost(OutputBuffer
&OB
, OutputFlags Flags
) const {}
549 void ArrayTypeNode::outputPre(OutputBuffer
&OB
, OutputFlags Flags
) const {
550 ElementType
->outputPre(OB
, Flags
);
551 outputQualifiers(OB
, Quals
, true, false);
554 void ArrayTypeNode::outputOneDimension(OutputBuffer
&OB
, OutputFlags Flags
,
556 assert(N
->kind() == NodeKind::IntegerLiteral
);
557 IntegerLiteralNode
*ILN
= static_cast<IntegerLiteralNode
*>(N
);
559 ILN
->output(OB
, Flags
);
562 void ArrayTypeNode::outputDimensionsImpl(OutputBuffer
&OB
,
563 OutputFlags Flags
) const {
564 if (Dimensions
->Count
== 0)
567 outputOneDimension(OB
, Flags
, Dimensions
->Nodes
[0]);
568 for (size_t I
= 1; I
< Dimensions
->Count
; ++I
) {
570 outputOneDimension(OB
, Flags
, Dimensions
->Nodes
[I
]);
574 void ArrayTypeNode::outputPost(OutputBuffer
&OB
, OutputFlags Flags
) const {
576 outputDimensionsImpl(OB
, Flags
);
579 ElementType
->outputPost(OB
, Flags
);
582 void SymbolNode::output(OutputBuffer
&OB
, OutputFlags Flags
) const {
583 Name
->output(OB
, Flags
);
586 void FunctionSymbolNode::output(OutputBuffer
&OB
, OutputFlags Flags
) const {
587 Signature
->outputPre(OB
, Flags
);
588 outputSpaceIfNecessary(OB
);
589 Name
->output(OB
, Flags
);
590 Signature
->outputPost(OB
, Flags
);
593 void VariableSymbolNode::output(OutputBuffer
&OB
, OutputFlags Flags
) const {
594 const char *AccessSpec
= nullptr;
595 bool IsStatic
= true;
597 case StorageClass::PrivateStatic
:
598 AccessSpec
= "private";
600 case StorageClass::PublicStatic
:
601 AccessSpec
= "public";
603 case StorageClass::ProtectedStatic
:
604 AccessSpec
= "protected";
610 if (!(Flags
& OF_NoAccessSpecifier
) && AccessSpec
)
611 OB
<< AccessSpec
<< ": ";
612 if (!(Flags
& OF_NoMemberType
) && IsStatic
)
615 if (!(Flags
& OF_NoVariableType
) && Type
) {
616 Type
->outputPre(OB
, Flags
);
617 outputSpaceIfNecessary(OB
);
619 Name
->output(OB
, Flags
);
620 if (!(Flags
& OF_NoVariableType
) && Type
)
621 Type
->outputPost(OB
, Flags
);
624 void CustomTypeNode::outputPre(OutputBuffer
&OB
, OutputFlags Flags
) const {
625 Identifier
->output(OB
, Flags
);
627 void CustomTypeNode::outputPost(OutputBuffer
&OB
, OutputFlags Flags
) const {}
629 void QualifiedNameNode::output(OutputBuffer
&OB
, OutputFlags Flags
) const {
630 Components
->output(OB
, Flags
, "::");
633 void RttiBaseClassDescriptorNode::output(OutputBuffer
&OB
,
634 OutputFlags Flags
) const {
635 OB
<< "`RTTI Base Class Descriptor at (";
636 OB
<< NVOffset
<< ", " << VBPtrOffset
<< ", " << VBTableOffset
<< ", "
641 void LocalStaticGuardVariableNode::output(OutputBuffer
&OB
,
642 OutputFlags Flags
) const {
643 Name
->output(OB
, Flags
);
646 void VcallThunkIdentifierNode::output(OutputBuffer
&OB
,
647 OutputFlags Flags
) const {
648 OB
<< "`vcall'{" << OffsetInVTable
<< ", {flat}}";
651 void SpecialTableSymbolNode::output(OutputBuffer
&OB
, OutputFlags Flags
) const {
652 outputQualifiers(OB
, Quals
, false, true);
653 Name
->output(OB
, Flags
);
656 TargetName
->output(OB
, Flags
);