//===- MicrosoftDemangleNodes.h ---------------------------------*- C++ -*-===// // // 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 the AST nodes used in the MSVC demangler. // //===----------------------------------------------------------------------===// #ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLENODES_H #define LLVM_DEMANGLE_MICROSOFTDEMANGLENODES_H #include "StringView.h" #include #include #include namespace llvm { namespace itanium_demangle { class OutputBuffer; } } // namespace llvm using llvm::itanium_demangle::OutputBuffer; using llvm::itanium_demangle::StringView; namespace llvm { namespace ms_demangle { // Storage classes enum Qualifiers : uint8_t { Q_None = 0, Q_Const = 1 << 0, Q_Volatile = 1 << 1, Q_Far = 1 << 2, Q_Huge = 1 << 3, Q_Unaligned = 1 << 4, Q_Restrict = 1 << 5, Q_Pointer64 = 1 << 6 }; class StorageClass { public: enum StorageClassValue : uint8_t { None, PrivateStatic, ProtectedStatic, PublicStatic, Global, FunctionLocalStatic, }; StringView* pos = nullptr; StorageClass() = default; constexpr StorageClass(StorageClassValue type) : type(type) { } operator StorageClass() const { return type; } void set(StorageClassValue type) { this->type = type; } constexpr bool operator==(StorageClass type) const { return this->type == type.type; } constexpr bool operator!=(StorageClass type) const { return this->type != type.type; } constexpr bool operator==(StorageClassValue type) const { return this->type == type; } constexpr bool operator!=(StorageClassValue type) const { return this->type != type; } inline std::string toEnumString() { std::string ret; ret += std::to_string((int)this->type); if (this->type == None) ret += "\t| None"; if (this->type == PrivateStatic) ret += "\t| PrivateStatic"; if (this->type == ProtectedStatic) ret += "\t| ProtectedStatic"; if (this->type == PublicStatic) ret += "\t| PublicStatic"; if (this->type == Global) ret += "\t| StaGlobaltic"; if (this->type == FunctionLocalStatic) ret += "\t| FunctionLocalStatic"; return ret; } inline void fromMangledName(StringView& MangledName) { switch (MangledName.popFront()) { case '0': this->type = PrivateStatic; case '1': this->type = ProtectedStatic; case '2': this->type = PublicStatic; case '3': this->type = Global; case '4': this->type = FunctionLocalStatic; } DEMANGLE_UNREACHABLE; } inline char toChar() const { switch (this->type) { case PrivateStatic: return '0'; case ProtectedStatic: return '1'; case PublicStatic: return '2'; case Global: return '3'; case FunctionLocalStatic: return '4'; } DEMANGLE_UNREACHABLE; } private: StorageClassValue type; }; enum class PointerAffinity { None, Pointer, Reference, RValueReference }; enum class FunctionRefQualifier { None, Reference, RValueReference }; // Calling conventions enum class CallingConv : uint8_t { None, Cdecl, Pascal, Thiscall, Stdcall, Fastcall, Clrcall, Eabi, Vectorcall, Regcall, Swift, // Clang-only SwiftAsync, // Clang-only }; enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef }; enum OutputFlags { OF_Default = 0, OF_NoCallingConvention = 1, OF_NoTagSpecifier = 2, OF_NoAccessSpecifier = 4, OF_NoMemberType = 8, OF_NoReturnType = 16, OF_NoVariableType = 32, }; // Types enum class PrimitiveKind { Void, Bool, Char, Schar, Uchar, Char8, Char16, Char32, Short, Ushort, Int, Uint, Long, Ulong, Int64, Uint64, Wchar, Float, Double, Ldouble, Nullptr, }; enum class CharKind { Char, Char16, Char32, Wchar, }; enum class IntrinsicFunctionKind : uint8_t { None, New, // ?2 # operator new Delete, // ?3 # operator delete Assign, // ?4 # operator= RightShift, // ?5 # operator>> LeftShift, // ?6 # operator<< LogicalNot, // ?7 # operator! Equals, // ?8 # operator== NotEquals, // ?9 # operator!= ArraySubscript, // ?A # operator[] Pointer, // ?C # operator-> Dereference, // ?D # operator* Increment, // ?E # operator++ Decrement, // ?F # operator-- Minus, // ?G # operator- Plus, // ?H # operator+ BitwiseAnd, // ?I # operator& MemberPointer, // ?J # operator->* Divide, // ?K # operator/ Modulus, // ?L # operator% LessThan, // ?M operator< LessThanEqual, // ?N operator<= GreaterThan, // ?O operator> GreaterThanEqual, // ?P operator>= Comma, // ?Q operator, Parens, // ?R operator() BitwiseNot, // ?S operator~ BitwiseXor, // ?T operator^ BitwiseOr, // ?U operator| LogicalAnd, // ?V operator&& LogicalOr, // ?W operator|| TimesEqual, // ?X operator*= PlusEqual, // ?Y operator+= MinusEqual, // ?Z operator-= DivEqual, // ?_0 operator/= ModEqual, // ?_1 operator%= RshEqual, // ?_2 operator>>= LshEqual, // ?_3 operator<<= BitwiseAndEqual, // ?_4 operator&= BitwiseOrEqual, // ?_5 operator|= BitwiseXorEqual, // ?_6 operator^= VbaseDtor, // ?_D # vbase destructor VecDelDtor, // ?_E # vector deleting destructor DefaultCtorClosure, // ?_F # default constructor closure ScalarDelDtor, // ?_G # scalar deleting destructor VecCtorIter, // ?_H # vector constructor iterator VecDtorIter, // ?_I # vector destructor iterator VecVbaseCtorIter, // ?_J # vector vbase constructor iterator VdispMap, // ?_K # virtual displacement map EHVecCtorIter, // ?_L # eh vector constructor iterator EHVecDtorIter, // ?_M # eh vector destructor iterator EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator CopyCtorClosure, // ?_O # copy constructor closure LocalVftableCtorClosure, // ?_T # local vftable constructor closure ArrayNew, // ?_U operator new[] ArrayDelete, // ?_V operator delete[] ManVectorCtorIter, // ?__A managed vector ctor iterator ManVectorDtorIter, // ?__B managed vector dtor iterator EHVectorCopyCtorIter, // ?__C EH vector copy ctor iterator EHVectorVbaseCopyCtorIter, // ?__D EH vector vbase copy ctor iterator VectorCopyCtorIter, // ?__G vector copy constructor iterator VectorVbaseCopyCtorIter, // ?__H vector vbase copy constructor iterator ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy constructor CoAwait, // ?__L operator co_await Spaceship, // ?__M operator<=> MaxIntrinsic }; enum class SpecialIntrinsicKind { None, Vftable, Vbtable, Typeof, VcallThunk, LocalStaticGuard, StringLiteralSymbol, UdtReturning, Unknown, DynamicInitializer, DynamicAtexitDestructor, RttiTypeDescriptor, RttiBaseClassDescriptor, RttiBaseClassArray, RttiClassHierarchyDescriptor, RttiCompleteObjLocator, LocalVftable, LocalStaticThreadGuard, }; // Function classes enum FuncClass : uint16_t { FC_None = 0, FC_Public = 1 << 0, FC_Protected = 1 << 1, FC_Private = 1 << 2, FC_Global = 1 << 3, FC_Static = 1 << 4, FC_Virtual = 1 << 5, FC_Far = 1 << 6, FC_ExternC = 1 << 7, FC_NoParameterList = 1 << 8, FC_VirtualThisAdjust = 1 << 9, FC_VirtualThisAdjustEx = 1 << 10, FC_StaticThisAdjust = 1 << 11, }; class FuncClassType { public: StringView* pos = nullptr; FuncClassType() = default; constexpr FuncClassType(FuncClass type) : type(type) { } operator FuncClass() const { return type; } void set(FuncClassType type) { this->type = type; } constexpr bool operator==(FuncClassType type) const { return this->type == type.type; } constexpr bool operator!=(FuncClassType type) const { return this->type != type.type; } constexpr bool operator==(FuncClass type) const { return this->type == type; } constexpr bool operator!=(FuncClass type) const { return this->type != type; } inline bool has(FuncClass type) const { return (this->type & type) == type; } inline void remove(FuncClass type) { this->type = static_cast(this->type & ~type); } inline void add(FuncClass type) { this->type = static_cast(this->type | type); } inline std::string toEnumString() { std::string ret; ret += std::to_string((int)this->type); if (this->type & FC_Public) ret += "\t| Public"; if (this->type & FC_Protected) ret += "\t| Protected"; if (this->type & FC_Private) ret += "\t| Private"; if (this->type & FC_Global) ret += "\t| Global"; if (this->type & FC_Static) ret += "\t| Static"; if (this->type & FC_Virtual) ret += "\t| Virtual"; if (this->type & FC_ExternC) ret += "\t| ExternC"; if (this->type & FC_NoParameterList) ret += "\t| NoParameterList"; if (this->type & FC_VirtualThisAdjust) ret += "\t| VirtualThisAdjust"; if (this->type & FC_VirtualThisAdjustEx) ret += "\t| VirtualThisAdjustEx"; if (this->type & FC_StaticThisAdjust) ret += "\t| StaticThisAdjust"; if (this->type & FC_Far) ret += "\t| Far"; return ret; } inline void fromMangledName(StringView& MangledName) { switch (MangledName.popFront()) { case '9': this->set(FuncClass(FC_ExternC | FC_NoParameterList)); return; case 'A': this->set(FC_Private); return; case 'B': this->set(FuncClass(FC_Private | FC_Far)); return; case 'C': this->set(FuncClass(FC_Private | FC_Static)); return; case 'D': this->set(FuncClass(FC_Private | FC_Static | FC_Far)); return; case 'E': this->set(FuncClass(FC_Private | FC_Virtual)); return; case 'F': this->set(FuncClass(FC_Private | FC_Virtual | FC_Far)); return; case 'G': this->set(FuncClass(FC_Private | FC_StaticThisAdjust)); return; case 'H': this->set(FuncClass(FC_Private | FC_StaticThisAdjust | FC_Far)); return; case 'I': this->set(FuncClass(FC_Protected)); return; case 'J': this->set(FuncClass(FC_Protected | FC_Far)); return; case 'K': this->set(FuncClass(FC_Protected | FC_Static)); return; case 'L': this->set(FuncClass(FC_Protected | FC_Static | FC_Far)); return; case 'M': this->set(FuncClass(FC_Protected | FC_Virtual)); return; case 'N': this->set(FuncClass(FC_Protected | FC_Virtual | FC_Far)); return; case 'O': this->set(FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust)); return; case 'P': this->set(FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust | FC_Far)); return; case 'Q': this->set(FuncClass(FC_Public)); return; case 'R': this->set(FuncClass(FC_Public | FC_Far)); return; case 'S': this->set(FuncClass(FC_Public | FC_Static)); return; case 'T': this->set(FuncClass(FC_Public | FC_Static | FC_Far)); return; case 'U': this->set(FuncClass(FC_Public | FC_Virtual)); return; case 'V': this->set(FuncClass(FC_Public | FC_Virtual | FC_Far)); return; case 'W': this->set(FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust)); return; case 'X': this->set(FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust | FC_Far)); return; case 'Y': this->set(FuncClass(FC_Global)); return; case 'Z': this->set(FuncClass(FC_Global | FC_Far)); return; case '$': { FuncClass VFlag = FC_VirtualThisAdjust; if (MangledName.consumeFront('R')) VFlag = FuncClass(VFlag | FC_VirtualThisAdjustEx); if (MangledName.empty()) break; switch (MangledName.popFront()) { case '0': this->set(FuncClass(FC_Private | FC_Virtual | VFlag)); return; case '1': this->set(FuncClass(FC_Private | FC_Virtual | VFlag | FC_Far)); return; case '2': this->set(FuncClass(FC_Protected | FC_Virtual | VFlag)); return; case '3': this->set(FuncClass(FC_Protected | FC_Virtual | VFlag | FC_Far)); return; case '4': this->set(FuncClass(FC_Public | FC_Virtual | VFlag)); return; case '5': this->set(FuncClass(FC_Public | FC_Virtual | VFlag | FC_Far)); return; } } } } inline std::string toString() const { switch (this->type) { case FC_ExternC | FC_NoParameterList: return "9"; case FC_Private: return "A"; case FC_Private | FC_Far: return "B"; case FC_Private | FC_Static: return "C"; case FC_Private | FC_Static | FC_Far: return "D"; case FC_Private | FC_Virtual: return "E"; case FC_Private | FC_Virtual | FC_Far: return "F"; case FC_Private | FC_StaticThisAdjust: return "G"; case FC_Private | FC_StaticThisAdjust | FC_Far: return "H"; case FC_Protected: return "I"; case FC_Protected | FC_Far: return "J"; case FC_Protected | FC_Static: return "K"; case FC_Protected | FC_Static | FC_Far: return "L"; case FC_Protected | FC_Virtual: return "M"; case FC_Protected | FC_Virtual | FC_Far: return "N"; case FC_Protected | FC_Virtual | FC_StaticThisAdjust: return "O"; case FC_Protected | FC_Virtual | FC_StaticThisAdjust | FC_Far: return "P"; case FC_Public: return "Q"; case FC_Public | FC_Far: return "R"; case FC_Public | FC_Static: return "S"; case FC_Public | FC_Static | FC_Far: return "T"; case FC_Public | FC_Virtual: return "U"; case FC_Public | FC_Virtual | FC_Far: return "V"; case FC_Public | FC_Virtual | FC_StaticThisAdjust: return "W"; case FC_Public | FC_Virtual | FC_StaticThisAdjust | FC_Far: return "X"; case FC_Global: return "Y"; case FC_Global | FC_Far: return "Z"; default: if (this->type & FC_VirtualThisAdjust) { std::string result; result += '$'; if (this->type & FC_VirtualThisAdjustEx) result += 'R'; switch (this->type & ~(FC_VirtualThisAdjust | FC_VirtualThisAdjustEx)) { case FC_Private | FC_Virtual: result += '0'; break; case FC_Private | FC_Virtual | FC_Far: result += '1'; break; case FC_Protected | FC_Virtual: result += '2'; break; case FC_Protected | FC_Virtual | FC_Far: result += '3'; break; case FC_Public | FC_Virtual: result += '4'; break; case FC_Public | FC_Virtual | FC_Far: result += '5'; break; } return result; } } return ""; } private: FuncClass type; }; enum class TagKind { Class, Struct, Union, Enum }; enum class NodeKind { Unknown, Md5Symbol, PrimitiveType, FunctionSignature, Identifier, NamedIdentifier, VcallThunkIdentifier, LocalStaticGuardIdentifier, IntrinsicFunctionIdentifier, ConversionOperatorIdentifier, DynamicStructorIdentifier, StructorIdentifier, LiteralOperatorIdentifier, ThunkSignature, PointerType, TagType, ArrayType, Custom, IntrinsicType, NodeArray, QualifiedName, TemplateParameterReference, EncodedStringLiteral, IntegerLiteral, RttiBaseClassDescriptor, LocalStaticGuardVariable, FunctionSymbol, VariableSymbol, SpecialTableSymbol }; struct Node { explicit Node(NodeKind K) : Kind(K) { } virtual ~Node() = default; NodeKind kind() const { return Kind; } virtual void output(OutputBuffer& OB, OutputFlags Flags) const = 0; std::string toString(OutputFlags Flags = OF_Default) const; private: NodeKind Kind; }; struct TypeNode; struct PrimitiveTypeNode; struct FunctionSignatureNode; struct IdentifierNode; struct NamedIdentifierNode; struct VcallThunkIdentifierNode; struct IntrinsicFunctionIdentifierNode; struct LiteralOperatorIdentifierNode; struct ConversionOperatorIdentifierNode; struct StructorIdentifierNode; struct ThunkSignatureNode; struct PointerTypeNode; struct ArrayTypeNode; struct TagTypeNode; struct NodeArrayNode; struct QualifiedNameNode; struct TemplateParameterReferenceNode; struct EncodedStringLiteralNode; struct IntegerLiteralNode; struct RttiBaseClassDescriptorNode; struct LocalStaticGuardVariableNode; struct SymbolNode; struct FunctionSymbolNode; struct VariableSymbolNode; struct SpecialTableSymbolNode; struct TypeNode : public Node { explicit TypeNode(NodeKind K) : Node(K) { } virtual void outputPre(OutputBuffer& OB, OutputFlags Flags) const = 0; virtual void outputPost(OutputBuffer& OB, OutputFlags Flags) const = 0; void output(OutputBuffer& OB, OutputFlags Flags) const override { outputPre(OB, Flags); outputPost(OB, Flags); } Qualifiers Quals = Q_None; }; struct PrimitiveTypeNode : public TypeNode { explicit PrimitiveTypeNode(PrimitiveKind K) : TypeNode(NodeKind::PrimitiveType) , PrimKind(K) { } void outputPre(OutputBuffer& OB, OutputFlags Flags) const override; void outputPost(OutputBuffer& OB, OutputFlags Flags) const override { } PrimitiveKind PrimKind; }; struct FunctionSignatureNode : public TypeNode { explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) { } FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) { } void outputPre(OutputBuffer& OB, OutputFlags Flags) const override; void outputPost(OutputBuffer& OB, OutputFlags Flags) const override; // Valid if this FunctionTypeNode is the Pointee of a PointerType or // MemberPointerType. PointerAffinity Affinity = PointerAffinity::None; // The function's calling convention. CallingConv CallConvention = CallingConv::None; // Function flags (gloabl, public, etc) FuncClassType FunctionClass = FC_Global; FunctionRefQualifier RefQualifier = FunctionRefQualifier::None; // The return type of the function. TypeNode* ReturnType = nullptr; // True if this is a C-style ... varargs function. bool IsVariadic = false; // Function parameters NodeArrayNode* Params = nullptr; // True if the function type is noexcept. bool IsNoexcept = false; }; struct IdentifierNode : public Node { explicit IdentifierNode(NodeKind K) : Node(K) { } NodeArrayNode* TemplateParams = nullptr; protected: void outputTemplateParameters(OutputBuffer& OB, OutputFlags Flags) const; }; struct VcallThunkIdentifierNode : public IdentifierNode { VcallThunkIdentifierNode() : IdentifierNode(NodeKind::VcallThunkIdentifier) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; uint64_t OffsetInVTable = 0; }; struct DynamicStructorIdentifierNode : public IdentifierNode { DynamicStructorIdentifierNode() : IdentifierNode(NodeKind::DynamicStructorIdentifier) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; VariableSymbolNode* Variable = nullptr; QualifiedNameNode* Name = nullptr; bool IsDestructor = false; }; struct NamedIdentifierNode : public IdentifierNode { NamedIdentifierNode() : IdentifierNode(NodeKind::NamedIdentifier) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; StringView Name; }; struct IntrinsicFunctionIdentifierNode : public IdentifierNode { explicit IntrinsicFunctionIdentifierNode(IntrinsicFunctionKind Operator) : IdentifierNode(NodeKind::IntrinsicFunctionIdentifier) , Operator(Operator) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; IntrinsicFunctionKind Operator; }; struct LiteralOperatorIdentifierNode : public IdentifierNode { LiteralOperatorIdentifierNode() : IdentifierNode(NodeKind::LiteralOperatorIdentifier) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; StringView Name; }; struct LocalStaticGuardIdentifierNode : public IdentifierNode { LocalStaticGuardIdentifierNode() : IdentifierNode(NodeKind::LocalStaticGuardIdentifier) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; bool IsThread = false; uint32_t ScopeIndex = 0; }; struct ConversionOperatorIdentifierNode : public IdentifierNode { ConversionOperatorIdentifierNode() : IdentifierNode(NodeKind::ConversionOperatorIdentifier) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; // The type that this operator converts too. TypeNode* TargetType = nullptr; }; struct StructorIdentifierNode : public IdentifierNode { StructorIdentifierNode() : IdentifierNode(NodeKind::StructorIdentifier) { } explicit StructorIdentifierNode(bool IsDestructor) : IdentifierNode(NodeKind::StructorIdentifier) , IsDestructor(IsDestructor) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; // The name of the class that this is a structor of. IdentifierNode* Class = nullptr; bool IsDestructor = false; }; struct ThunkSignatureNode : public FunctionSignatureNode { ThunkSignatureNode() : FunctionSignatureNode(NodeKind::ThunkSignature) { } void outputPre(OutputBuffer& OB, OutputFlags Flags) const override; void outputPost(OutputBuffer& OB, OutputFlags Flags) const override; struct ThisAdjustor { uint32_t StaticOffset = 0; int32_t VBPtrOffset = 0; int32_t VBOffsetOffset = 0; int32_t VtordispOffset = 0; }; ThisAdjustor ThisAdjust; }; struct PointerTypeNode : public TypeNode { PointerTypeNode() : TypeNode(NodeKind::PointerType) { } void outputPre(OutputBuffer& OB, OutputFlags Flags) const override; void outputPost(OutputBuffer& OB, OutputFlags Flags) const override; // Is this a pointer, reference, or rvalue-reference? PointerAffinity Affinity = PointerAffinity::None; // If this is a member pointer, this is the class that the member is in. QualifiedNameNode* ClassParent = nullptr; // Represents a type X in "a pointer to X", "a reference to X", or // "rvalue-reference to X" TypeNode* Pointee = nullptr; }; struct TagTypeNode : public TypeNode { explicit TagTypeNode(TagKind Tag) : TypeNode(NodeKind::TagType) , Tag(Tag) { } void outputPre(OutputBuffer& OB, OutputFlags Flags) const override; void outputPost(OutputBuffer& OB, OutputFlags Flags) const override; QualifiedNameNode* QualifiedName = nullptr; TagKind Tag; }; struct ArrayTypeNode : public TypeNode { ArrayTypeNode() : TypeNode(NodeKind::ArrayType) { } void outputPre(OutputBuffer& OB, OutputFlags Flags) const override; void outputPost(OutputBuffer& OB, OutputFlags Flags) const override; void outputDimensionsImpl(OutputBuffer& OB, OutputFlags Flags) const; void outputOneDimension(OutputBuffer& OB, OutputFlags Flags, Node* N) const; // A list of array dimensions. e.g. [3,4,5] in `int Foo[3][4][5]` NodeArrayNode* Dimensions = nullptr; // The type of array element. TypeNode* ElementType = nullptr; }; struct IntrinsicNode : public TypeNode { IntrinsicNode() : TypeNode(NodeKind::IntrinsicType) { } void output(OutputBuffer& OB, OutputFlags Flags) const override { } }; struct CustomTypeNode : public TypeNode { CustomTypeNode() : TypeNode(NodeKind::Custom) { } void outputPre(OutputBuffer& OB, OutputFlags Flags) const override; void outputPost(OutputBuffer& OB, OutputFlags Flags) const override; IdentifierNode* Identifier = nullptr; }; struct NodeArrayNode : public Node { NodeArrayNode() : Node(NodeKind::NodeArray) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; void output(OutputBuffer& OB, OutputFlags Flags, StringView Separator) const; Node** Nodes = nullptr; size_t Count = 0; }; struct QualifiedNameNode : public Node { QualifiedNameNode() : Node(NodeKind::QualifiedName) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; NodeArrayNode* Components = nullptr; IdentifierNode* getUnqualifiedIdentifier() { Node* LastComponent = Components->Nodes[Components->Count - 1]; return static_cast(LastComponent); } }; struct TemplateParameterReferenceNode : public Node { TemplateParameterReferenceNode() : Node(NodeKind::TemplateParameterReference) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; SymbolNode* Symbol = nullptr; int ThunkOffsetCount = 0; std::array ThunkOffsets; PointerAffinity Affinity = PointerAffinity::None; bool IsMemberPointer = false; }; struct IntegerLiteralNode : public Node { IntegerLiteralNode() : Node(NodeKind::IntegerLiteral) { } IntegerLiteralNode(uint64_t Value, bool IsNegative) : Node(NodeKind::IntegerLiteral) , Value(Value) , IsNegative(IsNegative) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; uint64_t Value = 0; bool IsNegative = false; }; struct RttiBaseClassDescriptorNode : public IdentifierNode { RttiBaseClassDescriptorNode() : IdentifierNode(NodeKind::RttiBaseClassDescriptor) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; uint32_t NVOffset = 0; int32_t VBPtrOffset = 0; uint32_t VBTableOffset = 0; uint32_t Flags = 0; }; struct SymbolNode : public Node { explicit SymbolNode(NodeKind K) : Node(K) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; QualifiedNameNode* Name = nullptr; }; struct SpecialTableSymbolNode : public SymbolNode { explicit SpecialTableSymbolNode() : SymbolNode(NodeKind::SpecialTableSymbol) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; QualifiedNameNode* TargetName = nullptr; Qualifiers Quals = Qualifiers::Q_None; }; struct LocalStaticGuardVariableNode : public SymbolNode { LocalStaticGuardVariableNode() : SymbolNode(NodeKind::LocalStaticGuardVariable) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; bool IsVisible = false; }; struct EncodedStringLiteralNode : public SymbolNode { EncodedStringLiteralNode() : SymbolNode(NodeKind::EncodedStringLiteral) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; StringView DecodedString; bool IsTruncated = false; CharKind Char = CharKind::Char; }; struct VariableSymbolNode : public SymbolNode { VariableSymbolNode() : SymbolNode(NodeKind::VariableSymbol) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; StorageClass SC = StorageClass::None; TypeNode* Type = nullptr; }; struct FunctionSymbolNode : public SymbolNode { FunctionSymbolNode() : SymbolNode(NodeKind::FunctionSymbol) { } void output(OutputBuffer& OB, OutputFlags Flags) const override; FunctionSignatureNode* Signature = nullptr; }; } // namespace ms_demangle } // namespace llvm #endif