1 //===- MicrosoftDemangleNodes.h ---------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the AST nodes used in the MSVC demangler.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLENODES_H
14 #define LLVM_DEMANGLE_MICROSOFTDEMANGLENODES_H
15 
16 #include <array>
17 #include <cstdint>
18 #include <string>
19 #include <string_view>
20 
21 namespace llvm {
22 namespace itanium_demangle {
23 class OutputBuffer;
24 }
25 }
26 
27 using llvm::itanium_demangle::OutputBuffer;
28 
29 namespace llvm {
30 namespace ms_demangle {
31 
32 // Storage classes
33 enum Qualifiers : uint8_t {
34   Q_None = 0,
35   Q_Const = 1 << 0,
36   Q_Volatile = 1 << 1,
37   Q_Far = 1 << 2,
38   Q_Huge = 1 << 3,
39   Q_Unaligned = 1 << 4,
40   Q_Restrict = 1 << 5,
41   Q_Pointer64 = 1 << 6
42 };
43 
44 enum class StorageClass : uint8_t {
45   None,
46   PrivateStatic,
47   ProtectedStatic,
48   PublicStatic,
49   Global,
50   FunctionLocalStatic,
51 };
52 
53 enum class PointerAffinity { None, Pointer, Reference, RValueReference };
54 enum class FunctionRefQualifier { None, Reference, RValueReference };
55 
56 // Calling conventions
57 enum class CallingConv : uint8_t {
58   None,
59   Cdecl,
60   Pascal,
61   Thiscall,
62   Stdcall,
63   Fastcall,
64   Clrcall,
65   Eabi,
66   Vectorcall,
67   Regcall,
68   Swift,      // Clang-only
69   SwiftAsync, // Clang-only
70 };
71 
72 enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef };
73 
74 enum OutputFlags {
75   OF_Default = 0,
76   OF_NoCallingConvention = 1,
77   OF_NoTagSpecifier = 2,
78   OF_NoAccessSpecifier = 4,
79   OF_NoMemberType = 8,
80   OF_NoReturnType = 16,
81   OF_NoVariableType = 32,
82 };
83 
84 // Types
85 enum class PrimitiveKind {
86   Void,
87   Bool,
88   Char,
89   Schar,
90   Uchar,
91   Char8,
92   Char16,
93   Char32,
94   Short,
95   Ushort,
96   Int,
97   Uint,
98   Long,
99   Ulong,
100   Int64,
101   Uint64,
102   Wchar,
103   Float,
104   Double,
105   Ldouble,
106   Nullptr,
107 };
108 
109 enum class CharKind {
110   Char,
111   Char16,
112   Char32,
113   Wchar,
114 };
115 
116 enum class IntrinsicFunctionKind : uint8_t {
117   None,
118   New,                        // ?2 # operator new
119   Delete,                     // ?3 # operator delete
120   Assign,                     // ?4 # operator=
121   RightShift,                 // ?5 # operator>>
122   LeftShift,                  // ?6 # operator<<
123   LogicalNot,                 // ?7 # operator!
124   Equals,                     // ?8 # operator==
125   NotEquals,                  // ?9 # operator!=
126   ArraySubscript,             // ?A # operator[]
127   Pointer,                    // ?C # operator->
128   Dereference,                // ?D # operator*
129   Increment,                  // ?E # operator++
130   Decrement,                  // ?F # operator--
131   Minus,                      // ?G # operator-
132   Plus,                       // ?H # operator+
133   BitwiseAnd,                 // ?I # operator&
134   MemberPointer,              // ?J # operator->*
135   Divide,                     // ?K # operator/
136   Modulus,                    // ?L # operator%
137   LessThan,                   // ?M operator<
138   LessThanEqual,              // ?N operator<=
139   GreaterThan,                // ?O operator>
140   GreaterThanEqual,           // ?P operator>=
141   Comma,                      // ?Q operator,
142   Parens,                     // ?R operator()
143   BitwiseNot,                 // ?S operator~
144   BitwiseXor,                 // ?T operator^
145   BitwiseOr,                  // ?U operator|
146   LogicalAnd,                 // ?V operator&&
147   LogicalOr,                  // ?W operator||
148   TimesEqual,                 // ?X operator*=
149   PlusEqual,                  // ?Y operator+=
150   MinusEqual,                 // ?Z operator-=
151   DivEqual,                   // ?_0 operator/=
152   ModEqual,                   // ?_1 operator%=
153   RshEqual,                   // ?_2 operator>>=
154   LshEqual,                   // ?_3 operator<<=
155   BitwiseAndEqual,            // ?_4 operator&=
156   BitwiseOrEqual,             // ?_5 operator|=
157   BitwiseXorEqual,            // ?_6 operator^=
158   VbaseDtor,                  // ?_D # vbase destructor
159   VecDelDtor,                 // ?_E # vector deleting destructor
160   DefaultCtorClosure,         // ?_F # default constructor closure
161   ScalarDelDtor,              // ?_G # scalar deleting destructor
162   VecCtorIter,                // ?_H # vector constructor iterator
163   VecDtorIter,                // ?_I # vector destructor iterator
164   VecVbaseCtorIter,           // ?_J # vector vbase constructor iterator
165   VdispMap,                   // ?_K # virtual displacement map
166   EHVecCtorIter,              // ?_L # eh vector constructor iterator
167   EHVecDtorIter,              // ?_M # eh vector destructor iterator
168   EHVecVbaseCtorIter,         // ?_N # eh vector vbase constructor iterator
169   CopyCtorClosure,            // ?_O # copy constructor closure
170   LocalVftableCtorClosure,    // ?_T # local vftable constructor closure
171   ArrayNew,                   // ?_U operator new[]
172   ArrayDelete,                // ?_V operator delete[]
173   ManVectorCtorIter,          // ?__A managed vector ctor iterator
174   ManVectorDtorIter,          // ?__B managed vector dtor iterator
175   EHVectorCopyCtorIter,       // ?__C EH vector copy ctor iterator
176   EHVectorVbaseCopyCtorIter,  // ?__D EH vector vbase copy ctor iterator
177   VectorCopyCtorIter,         // ?__G vector copy constructor iterator
178   VectorVbaseCopyCtorIter,    // ?__H vector vbase copy constructor iterator
179   ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy constructor
180   CoAwait,                    // ?__L operator co_await
181   Spaceship,                  // ?__M operator<=>
182   MaxIntrinsic
183 };
184 
185 enum class SpecialIntrinsicKind {
186   None,
187   Vftable,
188   Vbtable,
189   Typeof,
190   VcallThunk,
191   LocalStaticGuard,
192   StringLiteralSymbol,
193   UdtReturning,
194   Unknown,
195   DynamicInitializer,
196   DynamicAtexitDestructor,
197   RttiTypeDescriptor,
198   RttiBaseClassDescriptor,
199   RttiBaseClassArray,
200   RttiClassHierarchyDescriptor,
201   RttiCompleteObjLocator,
202   LocalVftable,
203   LocalStaticThreadGuard,
204 };
205 
206 // Function classes
207 enum FuncClass : uint16_t {
208   FC_None = 0,
209   FC_Public = 1 << 0,
210   FC_Protected = 1 << 1,
211   FC_Private = 1 << 2,
212   FC_Global = 1 << 3,
213   FC_Static = 1 << 4,
214   FC_Virtual = 1 << 5,
215   FC_Far = 1 << 6,
216   FC_ExternC = 1 << 7,
217   FC_NoParameterList = 1 << 8,
218   FC_VirtualThisAdjust = 1 << 9,
219   FC_VirtualThisAdjustEx = 1 << 10,
220   FC_StaticThisAdjust = 1 << 11,
221 };
222 
223 enum class TagKind { Class, Struct, Union, Enum };
224 
225 enum class NodeKind {
226   Unknown,
227   Md5Symbol,
228   PrimitiveType,
229   FunctionSignature,
230   Identifier,
231   NamedIdentifier,
232   VcallThunkIdentifier,
233   LocalStaticGuardIdentifier,
234   IntrinsicFunctionIdentifier,
235   ConversionOperatorIdentifier,
236   DynamicStructorIdentifier,
237   StructorIdentifier,
238   LiteralOperatorIdentifier,
239   ThunkSignature,
240   PointerType,
241   TagType,
242   ArrayType,
243   Custom,
244   IntrinsicType,
245   NodeArray,
246   QualifiedName,
247   TemplateParameterReference,
248   EncodedStringLiteral,
249   IntegerLiteral,
250   RttiBaseClassDescriptor,
251   LocalStaticGuardVariable,
252   FunctionSymbol,
253   VariableSymbol,
254   SpecialTableSymbol
255 };
256 
257 struct Node {
NodeNode258   explicit Node(NodeKind K) : Kind(K) {}
259   virtual ~Node() = default;
260 
kindNode261   NodeKind kind() const { return Kind; }
262 
263   virtual void output(OutputBuffer &OB, OutputFlags Flags) const = 0;
264 
265   std::string toString(OutputFlags Flags = OF_Default) const;
266 
267 private:
268   NodeKind Kind;
269 };
270 
271 struct TypeNode;
272 struct PrimitiveTypeNode;
273 struct FunctionSignatureNode;
274 struct IdentifierNode;
275 struct NamedIdentifierNode;
276 struct VcallThunkIdentifierNode;
277 struct IntrinsicFunctionIdentifierNode;
278 struct LiteralOperatorIdentifierNode;
279 struct ConversionOperatorIdentifierNode;
280 struct StructorIdentifierNode;
281 struct ThunkSignatureNode;
282 struct PointerTypeNode;
283 struct ArrayTypeNode;
284 struct TagTypeNode;
285 struct NodeArrayNode;
286 struct QualifiedNameNode;
287 struct TemplateParameterReferenceNode;
288 struct EncodedStringLiteralNode;
289 struct IntegerLiteralNode;
290 struct RttiBaseClassDescriptorNode;
291 struct LocalStaticGuardVariableNode;
292 struct SymbolNode;
293 struct FunctionSymbolNode;
294 struct VariableSymbolNode;
295 struct SpecialTableSymbolNode;
296 
297 struct TypeNode : public Node {
TypeNodeTypeNode298   explicit TypeNode(NodeKind K) : Node(K) {}
299 
300   virtual void outputPre(OutputBuffer &OB, OutputFlags Flags) const = 0;
301   virtual void outputPost(OutputBuffer &OB, OutputFlags Flags) const = 0;
302 
outputTypeNode303   void output(OutputBuffer &OB, OutputFlags Flags) const override {
304     outputPre(OB, Flags);
305     outputPost(OB, Flags);
306   }
307 
308   Qualifiers Quals = Q_None;
309 };
310 
311 struct PrimitiveTypeNode : public TypeNode {
PrimitiveTypeNodePrimitiveTypeNode312   explicit PrimitiveTypeNode(PrimitiveKind K)
313       : TypeNode(NodeKind::PrimitiveType), PrimKind(K) {}
314 
315   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
outputPostPrimitiveTypeNode316   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override {}
317 
318   PrimitiveKind PrimKind;
319 };
320 
321 struct FunctionSignatureNode : public TypeNode {
FunctionSignatureNodeFunctionSignatureNode322   explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) {}
FunctionSignatureNodeFunctionSignatureNode323   FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) {}
324 
325   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
326   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
327 
328   // Valid if this FunctionTypeNode is the Pointee of a PointerType or
329   // MemberPointerType.
330   PointerAffinity Affinity = PointerAffinity::None;
331 
332   // The function's calling convention.
333   CallingConv CallConvention = CallingConv::None;
334 
335   // Function flags (gloabl, public, etc)
336   FuncClass FunctionClass = FC_Global;
337 
338   FunctionRefQualifier RefQualifier = FunctionRefQualifier::None;
339 
340   // The return type of the function.
341   TypeNode *ReturnType = nullptr;
342 
343   // True if this is a C-style ... varargs function.
344   bool IsVariadic = false;
345 
346   // Function parameters
347   NodeArrayNode *Params = nullptr;
348 
349   // True if the function type is noexcept.
350   bool IsNoexcept = false;
351 };
352 
353 struct IdentifierNode : public Node {
IdentifierNodeIdentifierNode354   explicit IdentifierNode(NodeKind K) : Node(K) {}
355 
356   NodeArrayNode *TemplateParams = nullptr;
357 
358 protected:
359   void outputTemplateParameters(OutputBuffer &OB, OutputFlags Flags) const;
360 };
361 
362 struct VcallThunkIdentifierNode : public IdentifierNode {
VcallThunkIdentifierNodeVcallThunkIdentifierNode363   VcallThunkIdentifierNode() : IdentifierNode(NodeKind::VcallThunkIdentifier) {}
364 
365   void output(OutputBuffer &OB, OutputFlags Flags) const override;
366 
367   uint64_t OffsetInVTable = 0;
368 };
369 
370 struct DynamicStructorIdentifierNode : public IdentifierNode {
DynamicStructorIdentifierNodeDynamicStructorIdentifierNode371   DynamicStructorIdentifierNode()
372       : IdentifierNode(NodeKind::DynamicStructorIdentifier) {}
373 
374   void output(OutputBuffer &OB, OutputFlags Flags) const override;
375 
376   VariableSymbolNode *Variable = nullptr;
377   QualifiedNameNode *Name = nullptr;
378   bool IsDestructor = false;
379 };
380 
381 struct NamedIdentifierNode : public IdentifierNode {
NamedIdentifierNodeNamedIdentifierNode382   NamedIdentifierNode() : IdentifierNode(NodeKind::NamedIdentifier) {}
383 
384   void output(OutputBuffer &OB, OutputFlags Flags) const override;
385 
386   std::string_view Name;
387 };
388 
389 struct IntrinsicFunctionIdentifierNode : public IdentifierNode {
IntrinsicFunctionIdentifierNodeIntrinsicFunctionIdentifierNode390   explicit IntrinsicFunctionIdentifierNode(IntrinsicFunctionKind Operator)
391       : IdentifierNode(NodeKind::IntrinsicFunctionIdentifier),
392         Operator(Operator) {}
393 
394   void output(OutputBuffer &OB, OutputFlags Flags) const override;
395 
396   IntrinsicFunctionKind Operator;
397 };
398 
399 struct LiteralOperatorIdentifierNode : public IdentifierNode {
LiteralOperatorIdentifierNodeLiteralOperatorIdentifierNode400   LiteralOperatorIdentifierNode()
401       : IdentifierNode(NodeKind::LiteralOperatorIdentifier) {}
402 
403   void output(OutputBuffer &OB, OutputFlags Flags) const override;
404 
405   std::string_view Name;
406 };
407 
408 struct LocalStaticGuardIdentifierNode : public IdentifierNode {
LocalStaticGuardIdentifierNodeLocalStaticGuardIdentifierNode409   LocalStaticGuardIdentifierNode()
410       : IdentifierNode(NodeKind::LocalStaticGuardIdentifier) {}
411 
412   void output(OutputBuffer &OB, OutputFlags Flags) const override;
413 
414   bool IsThread = false;
415   uint32_t ScopeIndex = 0;
416 };
417 
418 struct ConversionOperatorIdentifierNode : public IdentifierNode {
ConversionOperatorIdentifierNodeConversionOperatorIdentifierNode419   ConversionOperatorIdentifierNode()
420       : IdentifierNode(NodeKind::ConversionOperatorIdentifier) {}
421 
422   void output(OutputBuffer &OB, OutputFlags Flags) const override;
423 
424   // The type that this operator converts too.
425   TypeNode *TargetType = nullptr;
426 };
427 
428 struct StructorIdentifierNode : public IdentifierNode {
StructorIdentifierNodeStructorIdentifierNode429   StructorIdentifierNode() : IdentifierNode(NodeKind::StructorIdentifier) {}
StructorIdentifierNodeStructorIdentifierNode430   explicit StructorIdentifierNode(bool IsDestructor)
431       : IdentifierNode(NodeKind::StructorIdentifier),
432         IsDestructor(IsDestructor) {}
433 
434   void output(OutputBuffer &OB, OutputFlags Flags) const override;
435 
436   // The name of the class that this is a structor of.
437   IdentifierNode *Class = nullptr;
438   bool IsDestructor = false;
439 };
440 
441 struct ThunkSignatureNode : public FunctionSignatureNode {
ThunkSignatureNodeThunkSignatureNode442   ThunkSignatureNode() : FunctionSignatureNode(NodeKind::ThunkSignature) {}
443 
444   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
445   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
446 
447   struct ThisAdjustor {
448     uint32_t StaticOffset = 0;
449     int32_t VBPtrOffset = 0;
450     int32_t VBOffsetOffset = 0;
451     int32_t VtordispOffset = 0;
452   };
453 
454   ThisAdjustor ThisAdjust;
455 };
456 
457 struct PointerTypeNode : public TypeNode {
PointerTypeNodePointerTypeNode458   PointerTypeNode() : TypeNode(NodeKind::PointerType) {}
459   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
460   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
461 
462   // Is this a pointer, reference, or rvalue-reference?
463   PointerAffinity Affinity = PointerAffinity::None;
464 
465   // If this is a member pointer, this is the class that the member is in.
466   QualifiedNameNode *ClassParent = nullptr;
467 
468   // Represents a type X in "a pointer to X", "a reference to X", or
469   // "rvalue-reference to X"
470   TypeNode *Pointee = nullptr;
471 };
472 
473 struct TagTypeNode : public TypeNode {
TagTypeNodeTagTypeNode474   explicit TagTypeNode(TagKind Tag) : TypeNode(NodeKind::TagType), Tag(Tag) {}
475 
476   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
477   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
478 
479   QualifiedNameNode *QualifiedName = nullptr;
480   TagKind Tag;
481 };
482 
483 struct ArrayTypeNode : public TypeNode {
ArrayTypeNodeArrayTypeNode484   ArrayTypeNode() : TypeNode(NodeKind::ArrayType) {}
485 
486   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
487   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
488 
489   void outputDimensionsImpl(OutputBuffer &OB, OutputFlags Flags) const;
490   void outputOneDimension(OutputBuffer &OB, OutputFlags Flags, Node *N) const;
491 
492   // A list of array dimensions.  e.g. [3,4,5] in `int Foo[3][4][5]`
493   NodeArrayNode *Dimensions = nullptr;
494 
495   // The type of array element.
496   TypeNode *ElementType = nullptr;
497 };
498 
499 struct IntrinsicNode : public TypeNode {
IntrinsicNodeIntrinsicNode500   IntrinsicNode() : TypeNode(NodeKind::IntrinsicType) {}
outputIntrinsicNode501   void output(OutputBuffer &OB, OutputFlags Flags) const override {}
502 };
503 
504 struct CustomTypeNode : public TypeNode {
CustomTypeNodeCustomTypeNode505   CustomTypeNode() : TypeNode(NodeKind::Custom) {}
506 
507   void outputPre(OutputBuffer &OB, OutputFlags Flags) const override;
508   void outputPost(OutputBuffer &OB, OutputFlags Flags) const override;
509 
510   IdentifierNode *Identifier = nullptr;
511 };
512 
513 struct NodeArrayNode : public Node {
NodeArrayNodeNodeArrayNode514   NodeArrayNode() : Node(NodeKind::NodeArray) {}
515 
516   void output(OutputBuffer &OB, OutputFlags Flags) const override;
517 
518   void output(OutputBuffer &OB, OutputFlags Flags,
519               std::string_view Separator) const;
520 
521   Node **Nodes = nullptr;
522   size_t Count = 0;
523 };
524 
525 struct QualifiedNameNode : public Node {
QualifiedNameNodeQualifiedNameNode526   QualifiedNameNode() : Node(NodeKind::QualifiedName) {}
527 
528   void output(OutputBuffer &OB, OutputFlags Flags) const override;
529 
530   NodeArrayNode *Components = nullptr;
531 
getUnqualifiedIdentifierQualifiedNameNode532   IdentifierNode *getUnqualifiedIdentifier() {
533     Node *LastComponent = Components->Nodes[Components->Count - 1];
534     return static_cast<IdentifierNode *>(LastComponent);
535   }
536 };
537 
538 struct TemplateParameterReferenceNode : public Node {
TemplateParameterReferenceNodeTemplateParameterReferenceNode539   TemplateParameterReferenceNode()
540       : Node(NodeKind::TemplateParameterReference) {}
541 
542   void output(OutputBuffer &OB, OutputFlags Flags) const override;
543 
544   SymbolNode *Symbol = nullptr;
545 
546   int ThunkOffsetCount = 0;
547   std::array<int64_t, 3> ThunkOffsets;
548   PointerAffinity Affinity = PointerAffinity::None;
549   bool IsMemberPointer = false;
550 };
551 
552 struct IntegerLiteralNode : public Node {
IntegerLiteralNodeIntegerLiteralNode553   IntegerLiteralNode() : Node(NodeKind::IntegerLiteral) {}
IntegerLiteralNodeIntegerLiteralNode554   IntegerLiteralNode(uint64_t Value, bool IsNegative)
555       : Node(NodeKind::IntegerLiteral), Value(Value), IsNegative(IsNegative) {}
556 
557   void output(OutputBuffer &OB, OutputFlags Flags) const override;
558 
559   uint64_t Value = 0;
560   bool IsNegative = false;
561 };
562 
563 struct RttiBaseClassDescriptorNode : public IdentifierNode {
RttiBaseClassDescriptorNodeRttiBaseClassDescriptorNode564   RttiBaseClassDescriptorNode()
565       : IdentifierNode(NodeKind::RttiBaseClassDescriptor) {}
566 
567   void output(OutputBuffer &OB, OutputFlags Flags) const override;
568 
569   uint32_t NVOffset = 0;
570   int32_t VBPtrOffset = 0;
571   uint32_t VBTableOffset = 0;
572   uint32_t Flags = 0;
573 };
574 
575 struct SymbolNode : public Node {
SymbolNodeSymbolNode576   explicit SymbolNode(NodeKind K) : Node(K) {}
577   void output(OutputBuffer &OB, OutputFlags Flags) const override;
578   QualifiedNameNode *Name = nullptr;
579 };
580 
581 struct SpecialTableSymbolNode : public SymbolNode {
SpecialTableSymbolNodeSpecialTableSymbolNode582   explicit SpecialTableSymbolNode()
583       : SymbolNode(NodeKind::SpecialTableSymbol) {}
584 
585   void output(OutputBuffer &OB, OutputFlags Flags) const override;
586   QualifiedNameNode *TargetName = nullptr;
587   Qualifiers Quals = Qualifiers::Q_None;
588 };
589 
590 struct LocalStaticGuardVariableNode : public SymbolNode {
LocalStaticGuardVariableNodeLocalStaticGuardVariableNode591   LocalStaticGuardVariableNode()
592       : SymbolNode(NodeKind::LocalStaticGuardVariable) {}
593 
594   void output(OutputBuffer &OB, OutputFlags Flags) const override;
595 
596   bool IsVisible = false;
597 };
598 
599 struct EncodedStringLiteralNode : public SymbolNode {
EncodedStringLiteralNodeEncodedStringLiteralNode600   EncodedStringLiteralNode() : SymbolNode(NodeKind::EncodedStringLiteral) {}
601 
602   void output(OutputBuffer &OB, OutputFlags Flags) const override;
603 
604   std::string_view DecodedString;
605   bool IsTruncated = false;
606   CharKind Char = CharKind::Char;
607 };
608 
609 struct VariableSymbolNode : public SymbolNode {
VariableSymbolNodeVariableSymbolNode610   VariableSymbolNode() : SymbolNode(NodeKind::VariableSymbol) {}
611 
612   void output(OutputBuffer &OB, OutputFlags Flags) const override;
613 
614   StorageClass SC = StorageClass::None;
615   TypeNode *Type = nullptr;
616 };
617 
618 struct FunctionSymbolNode : public SymbolNode {
FunctionSymbolNodeFunctionSymbolNode619   FunctionSymbolNode() : SymbolNode(NodeKind::FunctionSymbol) {}
620 
621   void output(OutputBuffer &OB, OutputFlags Flags) const override;
622 
623   FunctionSignatureNode *Signature = nullptr;
624 };
625 
626 } // namespace ms_demangle
627 } // namespace llvm
628 
629 #endif
630