Path: blob/main/contrib/llvm-project/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
35232 views
//===- MicrosoftDemangle.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines a demangler for MSVC-style mangled symbols.9//10//===----------------------------------------------------------------------===//1112#include "llvm/Demangle/MicrosoftDemangleNodes.h"13#include "llvm/Demangle/Utility.h"14#include <cctype>15#include <string>1617using namespace llvm;18using namespace ms_demangle;1920#define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \21case Enum::Value: \22OB << Desc; \23break;2425// Writes a space if the last token does not end with a punctuation.26static void outputSpaceIfNecessary(OutputBuffer &OB) {27if (OB.empty())28return;2930char C = OB.back();31if (std::isalnum(C) || C == '>')32OB << " ";33}3435static void outputSingleQualifier(OutputBuffer &OB, Qualifiers Q) {36switch (Q) {37case Q_Const:38OB << "const";39break;40case Q_Volatile:41OB << "volatile";42break;43case Q_Restrict:44OB << "__restrict";45break;46default:47break;48}49}5051static bool outputQualifierIfPresent(OutputBuffer &OB, Qualifiers Q,52Qualifiers Mask, bool NeedSpace) {53if (!(Q & Mask))54return NeedSpace;5556if (NeedSpace)57OB << " ";5859outputSingleQualifier(OB, Mask);60return true;61}6263static void outputQualifiers(OutputBuffer &OB, Qualifiers Q, bool SpaceBefore,64bool SpaceAfter) {65if (Q == Q_None)66return;6768size_t Pos1 = OB.getCurrentPosition();69SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Const, SpaceBefore);70SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Volatile, SpaceBefore);71SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Restrict, SpaceBefore);72size_t Pos2 = OB.getCurrentPosition();73if (SpaceAfter && Pos2 > Pos1)74OB << " ";75}7677static void outputCallingConvention(OutputBuffer &OB, CallingConv CC) {78outputSpaceIfNecessary(OB);7980switch (CC) {81case CallingConv::Cdecl:82OB << "__cdecl";83break;84case CallingConv::Fastcall:85OB << "__fastcall";86break;87case CallingConv::Pascal:88OB << "__pascal";89break;90case CallingConv::Regcall:91OB << "__regcall";92break;93case CallingConv::Stdcall:94OB << "__stdcall";95break;96case CallingConv::Thiscall:97OB << "__thiscall";98break;99case CallingConv::Eabi:100OB << "__eabi";101break;102case CallingConv::Vectorcall:103OB << "__vectorcall";104break;105case CallingConv::Clrcall:106OB << "__clrcall";107break;108case CallingConv::Swift:109OB << "__attribute__((__swiftcall__)) ";110break;111case CallingConv::SwiftAsync:112OB << "__attribute__((__swiftasynccall__)) ";113break;114default:115break;116}117}118119std::string Node::toString(OutputFlags Flags) const {120OutputBuffer OB;121this->output(OB, Flags);122std::string_view SV = OB;123std::string Owned(SV.begin(), SV.end());124std::free(OB.getBuffer());125return Owned;126}127128void PrimitiveTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {129switch (PrimKind) {130OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void");131OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool");132OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char");133OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char");134OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");135OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t");136OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t");137OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t");138OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short");139OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short");140OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int");141OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int");142OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long");143OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long");144OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64");145OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64");146OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t");147OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float");148OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double");149OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double");150OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");151}152outputQualifiers(OB, Quals, true, false);153}154155void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags) const {156output(OB, Flags, ", ");157}158159void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags,160std::string_view Separator) const {161if (Count == 0)162return;163if (Nodes[0])164Nodes[0]->output(OB, Flags);165for (size_t I = 1; I < Count; ++I) {166OB << Separator;167Nodes[I]->output(OB, Flags);168}169}170171void EncodedStringLiteralNode::output(OutputBuffer &OB,172OutputFlags Flags) const {173switch (Char) {174case CharKind::Wchar:175OB << "L\"";176break;177case CharKind::Char:178OB << "\"";179break;180case CharKind::Char16:181OB << "u\"";182break;183case CharKind::Char32:184OB << "U\"";185break;186}187OB << DecodedString << "\"";188if (IsTruncated)189OB << "...";190}191192void IntegerLiteralNode::output(OutputBuffer &OB, OutputFlags Flags) const {193if (IsNegative)194OB << '-';195OB << Value;196}197198void TemplateParameterReferenceNode::output(OutputBuffer &OB,199OutputFlags Flags) const {200if (ThunkOffsetCount > 0)201OB << "{";202else if (Affinity == PointerAffinity::Pointer)203OB << "&";204205if (Symbol) {206Symbol->output(OB, Flags);207if (ThunkOffsetCount > 0)208OB << ", ";209}210211if (ThunkOffsetCount > 0)212OB << ThunkOffsets[0];213for (int I = 1; I < ThunkOffsetCount; ++I) {214OB << ", " << ThunkOffsets[I];215}216if (ThunkOffsetCount > 0)217OB << "}";218}219220void IdentifierNode::outputTemplateParameters(OutputBuffer &OB,221OutputFlags Flags) const {222if (!TemplateParams)223return;224OB << "<";225TemplateParams->output(OB, Flags);226OB << ">";227}228229void DynamicStructorIdentifierNode::output(OutputBuffer &OB,230OutputFlags Flags) const {231if (IsDestructor)232OB << "`dynamic atexit destructor for ";233else234OB << "`dynamic initializer for ";235236if (Variable) {237OB << "`";238Variable->output(OB, Flags);239OB << "''";240} else {241OB << "'";242Name->output(OB, Flags);243OB << "''";244}245}246247void NamedIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {248OB << Name;249outputTemplateParameters(OB, Flags);250}251252void IntrinsicFunctionIdentifierNode::output(OutputBuffer &OB,253OutputFlags Flags) const {254switch (Operator) {255OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new");256OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete");257OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator=");258OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>");259OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<");260OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!");261OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator==");262OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!=");263OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript,264"operator[]");265OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->");266OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++");267OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--");268OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-");269OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+");270OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*");271OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&");272OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer,273"operator->*");274OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/");275OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%");276OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<");277OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<=");278OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>");279OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual,280"operator>=");281OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,");282OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()");283OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~");284OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^");285OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|");286OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&");287OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||");288OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*=");289OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+=");290OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-=");291OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/=");292OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%=");293OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>=");294OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<=");295OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual,296"operator&=");297OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual,298"operator|=");299OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual,300"operator^=");301OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'");302OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor,303"`vector deleting dtor'");304OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure,305"`default ctor closure'");306OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor,307"`scalar deleting dtor'");308OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter,309"`vector ctor iterator'");310OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter,311"`vector dtor iterator'");312OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter,313"`vector vbase ctor iterator'");314OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap,315"`virtual displacement map'");316OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter,317"`eh vector ctor iterator'");318OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter,319"`eh vector dtor iterator'");320OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter,321"`eh vector vbase ctor iterator'");322OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure,323"`copy ctor closure'");324OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure,325"`local vftable ctor closure'");326OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]");327OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete,328"operator delete[]");329OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter,330"`managed vector ctor iterator'");331OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter,332"`managed vector dtor iterator'");333OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter,334"`EH vector copy ctor iterator'");335OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter,336"`EH vector vbase copy ctor iterator'");337OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter,338"`vector copy ctor iterator'");339OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter,340"`vector vbase copy constructor iterator'");341OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter,342"`managed vector vbase copy constructor iterator'");343OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait,344"operator co_await");345OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>");346case IntrinsicFunctionKind::MaxIntrinsic:347case IntrinsicFunctionKind::None:348break;349}350outputTemplateParameters(OB, Flags);351}352353void LocalStaticGuardIdentifierNode::output(OutputBuffer &OB,354OutputFlags Flags) const {355if (IsThread)356OB << "`local static thread guard'";357else358OB << "`local static guard'";359if (ScopeIndex > 0)360OB << "{" << ScopeIndex << "}";361}362363void ConversionOperatorIdentifierNode::output(OutputBuffer &OB,364OutputFlags Flags) const {365OB << "operator";366outputTemplateParameters(OB, Flags);367OB << " ";368TargetType->output(OB, Flags);369}370371void StructorIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {372if (IsDestructor)373OB << "~";374Class->output(OB, Flags);375outputTemplateParameters(OB, Flags);376}377378void LiteralOperatorIdentifierNode::output(OutputBuffer &OB,379OutputFlags Flags) const {380OB << "operator \"\"" << Name;381outputTemplateParameters(OB, Flags);382}383384void FunctionSignatureNode::outputPre(OutputBuffer &OB,385OutputFlags Flags) const {386if (!(Flags & OF_NoAccessSpecifier)) {387if (FunctionClass & FC_Public)388OB << "public: ";389if (FunctionClass & FC_Protected)390OB << "protected: ";391if (FunctionClass & FC_Private)392OB << "private: ";393}394395if (!(Flags & OF_NoMemberType)) {396if (!(FunctionClass & FC_Global)) {397if (FunctionClass & FC_Static)398OB << "static ";399}400if (FunctionClass & FC_Virtual)401OB << "virtual ";402403if (FunctionClass & FC_ExternC)404OB << "extern \"C\" ";405}406407if (!(Flags & OF_NoReturnType) && ReturnType) {408ReturnType->outputPre(OB, Flags);409OB << " ";410}411412if (!(Flags & OF_NoCallingConvention))413outputCallingConvention(OB, CallConvention);414}415416void FunctionSignatureNode::outputPost(OutputBuffer &OB,417OutputFlags Flags) const {418if (!(FunctionClass & FC_NoParameterList)) {419OB << "(";420if (Params)421Params->output(OB, Flags);422else423OB << "void";424425if (IsVariadic) {426if (OB.back() != '(')427OB << ", ";428OB << "...";429}430OB << ")";431}432433if (Quals & Q_Const)434OB << " const";435if (Quals & Q_Volatile)436OB << " volatile";437if (Quals & Q_Restrict)438OB << " __restrict";439if (Quals & Q_Unaligned)440OB << " __unaligned";441442if (IsNoexcept)443OB << " noexcept";444445if (RefQualifier == FunctionRefQualifier::Reference)446OB << " &";447else if (RefQualifier == FunctionRefQualifier::RValueReference)448OB << " &&";449450if (!(Flags & OF_NoReturnType) && ReturnType)451ReturnType->outputPost(OB, Flags);452}453454void ThunkSignatureNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {455OB << "[thunk]: ";456457FunctionSignatureNode::outputPre(OB, Flags);458}459460void ThunkSignatureNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {461if (FunctionClass & FC_StaticThisAdjust) {462OB << "`adjustor{" << ThisAdjust.StaticOffset << "}'";463} else if (FunctionClass & FC_VirtualThisAdjust) {464if (FunctionClass & FC_VirtualThisAdjustEx) {465OB << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "466<< ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset467<< ", " << ThisAdjust.StaticOffset << "}'";468} else {469OB << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "470<< ThisAdjust.StaticOffset << "}'";471}472}473474FunctionSignatureNode::outputPost(OB, Flags);475}476477void PointerTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {478if (Pointee->kind() == NodeKind::FunctionSignature) {479// If this is a pointer to a function, don't output the calling convention.480// It needs to go inside the parentheses.481const FunctionSignatureNode *Sig =482static_cast<const FunctionSignatureNode *>(Pointee);483Sig->outputPre(OB, OF_NoCallingConvention);484} else485Pointee->outputPre(OB, Flags);486487outputSpaceIfNecessary(OB);488489if (Quals & Q_Unaligned)490OB << "__unaligned ";491492if (Pointee->kind() == NodeKind::ArrayType) {493OB << "(";494} else if (Pointee->kind() == NodeKind::FunctionSignature) {495OB << "(";496const FunctionSignatureNode *Sig =497static_cast<const FunctionSignatureNode *>(Pointee);498outputCallingConvention(OB, Sig->CallConvention);499OB << " ";500}501502if (ClassParent) {503ClassParent->output(OB, Flags);504OB << "::";505}506507switch (Affinity) {508case PointerAffinity::Pointer:509OB << "*";510break;511case PointerAffinity::Reference:512OB << "&";513break;514case PointerAffinity::RValueReference:515OB << "&&";516break;517default:518assert(false);519}520outputQualifiers(OB, Quals, false, false);521}522523void PointerTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {524if (Pointee->kind() == NodeKind::ArrayType ||525Pointee->kind() == NodeKind::FunctionSignature)526OB << ")";527528Pointee->outputPost(OB, Flags);529}530531void TagTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {532if (!(Flags & OF_NoTagSpecifier)) {533switch (Tag) {534OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");535OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct");536OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");537OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");538}539OB << " ";540}541QualifiedName->output(OB, Flags);542outputQualifiers(OB, Quals, true, false);543}544545void TagTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}546547void ArrayTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {548ElementType->outputPre(OB, Flags);549outputQualifiers(OB, Quals, true, false);550}551552void ArrayTypeNode::outputOneDimension(OutputBuffer &OB, OutputFlags Flags,553Node *N) const {554assert(N->kind() == NodeKind::IntegerLiteral);555IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);556if (ILN->Value != 0)557ILN->output(OB, Flags);558}559560void ArrayTypeNode::outputDimensionsImpl(OutputBuffer &OB,561OutputFlags Flags) const {562if (Dimensions->Count == 0)563return;564565outputOneDimension(OB, Flags, Dimensions->Nodes[0]);566for (size_t I = 1; I < Dimensions->Count; ++I) {567OB << "][";568outputOneDimension(OB, Flags, Dimensions->Nodes[I]);569}570}571572void ArrayTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {573OB << "[";574outputDimensionsImpl(OB, Flags);575OB << "]";576577ElementType->outputPost(OB, Flags);578}579580void SymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {581Name->output(OB, Flags);582}583584void FunctionSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {585Signature->outputPre(OB, Flags);586outputSpaceIfNecessary(OB);587Name->output(OB, Flags);588Signature->outputPost(OB, Flags);589}590591void VariableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {592const char *AccessSpec = nullptr;593bool IsStatic = true;594switch (SC) {595case StorageClass::PrivateStatic:596AccessSpec = "private";597break;598case StorageClass::PublicStatic:599AccessSpec = "public";600break;601case StorageClass::ProtectedStatic:602AccessSpec = "protected";603break;604default:605IsStatic = false;606break;607}608if (!(Flags & OF_NoAccessSpecifier) && AccessSpec)609OB << AccessSpec << ": ";610if (!(Flags & OF_NoMemberType) && IsStatic)611OB << "static ";612613if (!(Flags & OF_NoVariableType) && Type) {614Type->outputPre(OB, Flags);615outputSpaceIfNecessary(OB);616}617Name->output(OB, Flags);618if (!(Flags & OF_NoVariableType) && Type)619Type->outputPost(OB, Flags);620}621622void CustomTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {623Identifier->output(OB, Flags);624}625void CustomTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}626627void QualifiedNameNode::output(OutputBuffer &OB, OutputFlags Flags) const {628Components->output(OB, Flags, "::");629}630631void RttiBaseClassDescriptorNode::output(OutputBuffer &OB,632OutputFlags Flags) const {633OB << "`RTTI Base Class Descriptor at (";634OB << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "635<< this->Flags;636OB << ")'";637}638639void LocalStaticGuardVariableNode::output(OutputBuffer &OB,640OutputFlags Flags) const {641Name->output(OB, Flags);642}643644void VcallThunkIdentifierNode::output(OutputBuffer &OB,645OutputFlags Flags) const {646OB << "`vcall'{" << OffsetInVTable << ", {flat}}";647}648649void SpecialTableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {650outputQualifiers(OB, Quals, false, true);651Name->output(OB, Flags);652if (TargetName) {653OB << "{for `";654TargetName->output(OB, Flags);655OB << "'}";656}657}658659660