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