diff options
Diffstat (limited to 'demangle/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp')
-rw-r--r-- | demangle/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp | 658 |
1 files changed, 658 insertions, 0 deletions
diff --git a/demangle/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/demangle/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp new file mode 100644 index 00000000..975649f2 --- /dev/null +++ b/demangle/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp @@ -0,0 +1,658 @@ +//===- MicrosoftDemangle.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines a demangler for MSVC-style mangled symbols. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Demangle/MicrosoftDemangleNodes.h" +#include "llvm/Demangle/Utility.h" +#include <cctype> +#include <string> + +using namespace llvm; +using namespace ms_demangle; + +#define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \ + case Enum::Value: \ + OB << Desc; \ + break; + +// Writes a space if the last token does not end with a punctuation. +static void outputSpaceIfNecessary(OutputBuffer &OB) { + if (OB.empty()) + return; + + char C = OB.back(); + if (std::isalnum(C) || C == '>') + OB << " "; +} + +static void outputSingleQualifier(OutputBuffer &OB, Qualifiers Q) { + switch (Q) { + case Q_Const: + OB << "const"; + break; + case Q_Volatile: + OB << "volatile"; + break; + case Q_Restrict: + OB << "__restrict"; + break; + default: + break; + } +} + +static bool outputQualifierIfPresent(OutputBuffer &OB, Qualifiers Q, + Qualifiers Mask, bool NeedSpace) { + if (!(Q & Mask)) + return NeedSpace; + + if (NeedSpace) + OB << " "; + + outputSingleQualifier(OB, Mask); + return true; +} + +static void outputQualifiers(OutputBuffer &OB, Qualifiers Q, bool SpaceBefore, + bool SpaceAfter) { + if (Q == Q_None) + return; + + size_t Pos1 = OB.getCurrentPosition(); + SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Const, SpaceBefore); + SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Volatile, SpaceBefore); + SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Restrict, SpaceBefore); + size_t Pos2 = OB.getCurrentPosition(); + if (SpaceAfter && Pos2 > Pos1) + OB << " "; +} + +static void outputCallingConvention(OutputBuffer &OB, CallingConv CC) { + outputSpaceIfNecessary(OB); + + switch (CC) { + case CallingConv::Cdecl: + OB << "__cdecl"; + break; + case CallingConv::Fastcall: + OB << "__fastcall"; + break; + case CallingConv::Pascal: + OB << "__pascal"; + break; + case CallingConv::Regcall: + OB << "__regcall"; + break; + case CallingConv::Stdcall: + OB << "__stdcall"; + break; + case CallingConv::Thiscall: + OB << "__thiscall"; + break; + case CallingConv::Eabi: + OB << "__eabi"; + break; + case CallingConv::Vectorcall: + OB << "__vectorcall"; + break; + case CallingConv::Clrcall: + OB << "__clrcall"; + break; + case CallingConv::Swift: + OB << "__attribute__((__swiftcall__)) "; + break; + case CallingConv::SwiftAsync: + OB << "__attribute__((__swiftasynccall__)) "; + break; + default: + break; + } +} + +std::string Node::toString(OutputFlags Flags) const { + OutputBuffer OB; + this->output(OB, Flags); + StringView SV = OB; + std::string Owned(SV.begin(), SV.end()); + std::free(OB.getBuffer()); + return Owned; +} + +void PrimitiveTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { + switch (PrimKind) { + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double"); + OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t"); + } + outputQualifiers(OB, Quals, true, false); +} + +void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags) const { + output(OB, Flags, ", "); +} + +void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags, + StringView Separator) const { + if (Count == 0) + return; + if (Nodes[0]) + Nodes[0]->output(OB, Flags); + for (size_t I = 1; I < Count; ++I) { + OB << Separator; + Nodes[I]->output(OB, Flags); + } +} + +void EncodedStringLiteralNode::output(OutputBuffer &OB, + OutputFlags Flags) const { + switch (Char) { + case CharKind::Wchar: + OB << "L\""; + break; + case CharKind::Char: + OB << "\""; + break; + case CharKind::Char16: + OB << "u\""; + break; + case CharKind::Char32: + OB << "U\""; + break; + } + OB << DecodedString << "\""; + if (IsTruncated) + OB << "..."; +} + +void IntegerLiteralNode::output(OutputBuffer &OB, OutputFlags Flags) const { + if (IsNegative) + OB << '-'; + OB << Value; +} + +void TemplateParameterReferenceNode::output(OutputBuffer &OB, + OutputFlags Flags) const { + if (ThunkOffsetCount > 0) + OB << "{"; + else if (Affinity == PointerAffinity::Pointer) + OB << "&"; + + if (Symbol) { + Symbol->output(OB, Flags); + if (ThunkOffsetCount > 0) + OB << ", "; + } + + if (ThunkOffsetCount > 0) + OB << ThunkOffsets[0]; + for (int I = 1; I < ThunkOffsetCount; ++I) { + OB << ", " << ThunkOffsets[I]; + } + if (ThunkOffsetCount > 0) + OB << "}"; +} + +void IdentifierNode::outputTemplateParameters(OutputBuffer &OB, + OutputFlags Flags) const { + if (!TemplateParams) + return; + OB << "<"; + TemplateParams->output(OB, Flags); + OB << ">"; +} + +void DynamicStructorIdentifierNode::output(OutputBuffer &OB, + OutputFlags Flags) const { + if (IsDestructor) + OB << "`dynamic atexit destructor for "; + else + OB << "`dynamic initializer for "; + + if (Variable) { + OB << "`"; + Variable->output(OB, Flags); + OB << "''"; + } else { + OB << "'"; + Name->output(OB, Flags); + OB << "''"; + } +} + +void NamedIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const { + OB << Name; + outputTemplateParameters(OB, Flags); +} + +void IntrinsicFunctionIdentifierNode::output(OutputBuffer &OB, + OutputFlags Flags) const { + switch (Operator) { + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator=="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript, + "operator[]"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer, + "operator->*"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual, + "operator>="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual, + "operator&="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual, + "operator|="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual, + "operator^="); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor, + "`vector deleting dtor'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure, + "`default ctor closure'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor, + "`scalar deleting dtor'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter, + "`vector ctor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter, + "`vector dtor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter, + "`vector vbase ctor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap, + "`virtual displacement map'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter, + "`eh vector ctor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter, + "`eh vector dtor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter, + "`eh vector vbase ctor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure, + "`copy ctor closure'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure, + "`local vftable ctor closure'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete, + "operator delete[]"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter, + "`managed vector ctor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter, + "`managed vector dtor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter, + "`EH vector copy ctor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter, + "`EH vector vbase copy ctor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter, + "`vector copy ctor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter, + "`vector vbase copy constructor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter, + "`managed vector vbase copy constructor iterator'"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait, + "operator co_await"); + OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>"); + case IntrinsicFunctionKind::MaxIntrinsic: + case IntrinsicFunctionKind::None: + break; + } + outputTemplateParameters(OB, Flags); +} + +void LocalStaticGuardIdentifierNode::output(OutputBuffer &OB, + OutputFlags Flags) const { + if (IsThread) + OB << "`local static thread guard'"; + else + OB << "`local static guard'"; + if (ScopeIndex > 0) + OB << "{" << ScopeIndex << "}"; +} + +void ConversionOperatorIdentifierNode::output(OutputBuffer &OB, + OutputFlags Flags) const { + OB << "operator"; + outputTemplateParameters(OB, Flags); + OB << " "; + TargetType->output(OB, Flags); +} + +void StructorIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const { + if (IsDestructor) + OB << "~"; + Class->output(OB, Flags); + outputTemplateParameters(OB, Flags); +} + +void LiteralOperatorIdentifierNode::output(OutputBuffer &OB, + OutputFlags Flags) const { + OB << "operator \"\"" << Name; + outputTemplateParameters(OB, Flags); +} + +void FunctionSignatureNode::outputPre(OutputBuffer &OB, + OutputFlags Flags) const { + if (!(Flags & OF_NoAccessSpecifier)) { + if (FunctionClass & FC_Public) + OB << "public: "; + if (FunctionClass & FC_Protected) + OB << "protected: "; + if (FunctionClass & FC_Private) + OB << "private: "; + } + + if (!(Flags & OF_NoMemberType)) { + if (!(FunctionClass & FC_Global)) { + if (FunctionClass & FC_Static) + OB << "static "; + } + if (FunctionClass & FC_Virtual) + OB << "virtual "; + + if (FunctionClass & FC_ExternC) + OB << "extern \"C\" "; + } + + if (!(Flags & OF_NoReturnType) && ReturnType) { + ReturnType->outputPre(OB, Flags); + OB << " "; + } + + if (!(Flags & OF_NoCallingConvention)) + outputCallingConvention(OB, CallConvention); +} + +void FunctionSignatureNode::outputPost(OutputBuffer &OB, + OutputFlags Flags) const { + if (!(FunctionClass & FC_NoParameterList)) { + OB << "("; + if (Params) + Params->output(OB, Flags); + else + OB << "void"; + + if (IsVariadic) { + if (OB.back() != '(') + OB << ", "; + OB << "..."; + } + OB << ")"; + } + + if (Quals & Q_Const) + OB << " const"; + if (Quals & Q_Volatile) + OB << " volatile"; + if (Quals & Q_Restrict) + OB << " __restrict"; + if (Quals & Q_Unaligned) + OB << " __unaligned"; + + if (IsNoexcept) + OB << " noexcept"; + + if (RefQualifier == FunctionRefQualifier::Reference) + OB << " &"; + else if (RefQualifier == FunctionRefQualifier::RValueReference) + OB << " &&"; + + if (!(Flags & OF_NoReturnType) && ReturnType) + ReturnType->outputPost(OB, Flags); +} + +void ThunkSignatureNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { + OB << "[thunk]: "; + + FunctionSignatureNode::outputPre(OB, Flags); +} + +void ThunkSignatureNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const { + if (FunctionClass & FC_StaticThisAdjust) { + OB << "`adjustor{" << ThisAdjust.StaticOffset << "}'"; + } else if (FunctionClass & FC_VirtualThisAdjust) { + if (FunctionClass & FC_VirtualThisAdjustEx) { + OB << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", " + << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset + << ", " << ThisAdjust.StaticOffset << "}'"; + } else { + OB << "`vtordisp{" << ThisAdjust.VtordispOffset << ", " + << ThisAdjust.StaticOffset << "}'"; + } + } + + FunctionSignatureNode::outputPost(OB, Flags); +} + +void PointerTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { + if (Pointee->kind() == NodeKind::FunctionSignature) { + // If this is a pointer to a function, don't output the calling convention. + // It needs to go inside the parentheses. + const FunctionSignatureNode *Sig = + static_cast<const FunctionSignatureNode *>(Pointee); + Sig->outputPre(OB, OF_NoCallingConvention); + } else + Pointee->outputPre(OB, Flags); + + outputSpaceIfNecessary(OB); + + if (Quals & Q_Unaligned) + OB << "__unaligned "; + + if (Pointee->kind() == NodeKind::ArrayType) { + OB << "("; + } else if (Pointee->kind() == NodeKind::FunctionSignature) { + OB << "("; + const FunctionSignatureNode *Sig = + static_cast<const FunctionSignatureNode *>(Pointee); + outputCallingConvention(OB, Sig->CallConvention); + OB << " "; + } + + if (ClassParent) { + ClassParent->output(OB, Flags); + OB << "::"; + } + + switch (Affinity) { + case PointerAffinity::Pointer: + OB << "*"; + break; + case PointerAffinity::Reference: + OB << "&"; + break; + case PointerAffinity::RValueReference: + OB << "&&"; + break; + default: + assert(false); + } + outputQualifiers(OB, Quals, false, false); +} + +void PointerTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const { + if (Pointee->kind() == NodeKind::ArrayType || + Pointee->kind() == NodeKind::FunctionSignature) + OB << ")"; + + Pointee->outputPost(OB, Flags); +} + +void TagTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { + if (!(Flags & OF_NoTagSpecifier)) { + switch (Tag) { + OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class"); + OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct"); + OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union"); + OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum"); + } + OB << " "; + } + QualifiedName->output(OB, Flags); + outputQualifiers(OB, Quals, true, false); +} + +void TagTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {} + +void ArrayTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { + ElementType->outputPre(OB, Flags); + outputQualifiers(OB, Quals, true, false); +} + +void ArrayTypeNode::outputOneDimension(OutputBuffer &OB, OutputFlags Flags, + Node *N) const { + assert(N->kind() == NodeKind::IntegerLiteral); + IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N); + if (ILN->Value != 0) + ILN->output(OB, Flags); +} + +void ArrayTypeNode::outputDimensionsImpl(OutputBuffer &OB, + OutputFlags Flags) const { + if (Dimensions->Count == 0) + return; + + outputOneDimension(OB, Flags, Dimensions->Nodes[0]); + for (size_t I = 1; I < Dimensions->Count; ++I) { + OB << "]["; + outputOneDimension(OB, Flags, Dimensions->Nodes[I]); + } +} + +void ArrayTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const { + OB << "["; + outputDimensionsImpl(OB, Flags); + OB << "]"; + + ElementType->outputPost(OB, Flags); +} + +void SymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { + Name->output(OB, Flags); +} + +void FunctionSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { + Signature->outputPre(OB, Flags); + outputSpaceIfNecessary(OB); + Name->output(OB, Flags); + Signature->outputPost(OB, Flags); +} + +void VariableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { + const char *AccessSpec = nullptr; + bool IsStatic = true; + switch (SC) { + case StorageClass::PrivateStatic: + AccessSpec = "private"; + break; + case StorageClass::PublicStatic: + AccessSpec = "public"; + break; + case StorageClass::ProtectedStatic: + AccessSpec = "protected"; + break; + default: + IsStatic = false; + break; + } + if (!(Flags & OF_NoAccessSpecifier) && AccessSpec) + OB << AccessSpec << ": "; + if (!(Flags & OF_NoMemberType) && IsStatic) + OB << "static "; + + if (!(Flags & OF_NoVariableType) && Type) { + Type->outputPre(OB, Flags); + outputSpaceIfNecessary(OB); + } + Name->output(OB, Flags); + if (!(Flags & OF_NoVariableType) && Type) + Type->outputPost(OB, Flags); +} + +void CustomTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { + Identifier->output(OB, Flags); +} +void CustomTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {} + +void QualifiedNameNode::output(OutputBuffer &OB, OutputFlags Flags) const { + Components->output(OB, Flags, "::"); +} + +void RttiBaseClassDescriptorNode::output(OutputBuffer &OB, + OutputFlags Flags) const { + OB << "`RTTI Base Class Descriptor at ("; + OB << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", " + << this->Flags; + OB << ")'"; +} + +void LocalStaticGuardVariableNode::output(OutputBuffer &OB, + OutputFlags Flags) const { + Name->output(OB, Flags); +} + +void VcallThunkIdentifierNode::output(OutputBuffer &OB, + OutputFlags Flags) const { + OB << "`vcall'{" << OffsetInVTable << ", {flat}}"; +} + +void SpecialTableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { + outputQualifiers(OB, Quals, false, true); + Name->output(OB, Flags); + if (TargetName) { + OB << "{for `"; + TargetName->output(OB, Flags); + OB << "'}"; + } +} |