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_SUPPORT_MICROSOFTDEMANGLENODES_H 14 #define LLVM_SUPPORT_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 }; 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 }; 82 83 // Types 84 enum class PrimitiveKind { 85 Void, 86 Bool, 87 Char, 88 Schar, 89 Uchar, 90 Char8, 91 Char16, 92 Char32, 93 Short, 94 Ushort, 95 Int, 96 Uint, 97 Long, 98 Ulong, 99 Int64, 100 Uint64, 101 Wchar, 102 Float, 103 Double, 104 Ldouble, 105 Nullptr, 106 }; 107 108 enum class CharKind { 109 Char, 110 Char16, 111 Char32, 112 Wchar, 113 }; 114 115 enum class IntrinsicFunctionKind : uint8_t { 116 None, 117 New, // ?2 # operator new 118 Delete, // ?3 # operator delete 119 Assign, // ?4 # operator= 120 RightShift, // ?5 # operator>> 121 LeftShift, // ?6 # operator<< 122 LogicalNot, // ?7 # operator! 123 Equals, // ?8 # operator== 124 NotEquals, // ?9 # operator!= 125 ArraySubscript, // ?A # operator[] 126 Pointer, // ?C # operator-> 127 Dereference, // ?D # operator* 128 Increment, // ?E # operator++ 129 Decrement, // ?F # operator-- 130 Minus, // ?G # operator- 131 Plus, // ?H # operator+ 132 BitwiseAnd, // ?I # operator& 133 MemberPointer, // ?J # operator->* 134 Divide, // ?K # operator/ 135 Modulus, // ?L # operator% 136 LessThan, // ?M operator< 137 LessThanEqual, // ?N operator<= 138 GreaterThan, // ?O operator> 139 GreaterThanEqual, // ?P operator>= 140 Comma, // ?Q operator, 141 Parens, // ?R operator() 142 BitwiseNot, // ?S operator~ 143 BitwiseXor, // ?T operator^ 144 BitwiseOr, // ?U operator| 145 LogicalAnd, // ?V operator&& 146 LogicalOr, // ?W operator|| 147 TimesEqual, // ?X operator*= 148 PlusEqual, // ?Y operator+= 149 MinusEqual, // ?Z operator-= 150 DivEqual, // ?_0 operator/= 151 ModEqual, // ?_1 operator%= 152 RshEqual, // ?_2 operator>>= 153 LshEqual, // ?_3 operator<<= 154 BitwiseAndEqual, // ?_4 operator&= 155 BitwiseOrEqual, // ?_5 operator|= 156 BitwiseXorEqual, // ?_6 operator^= 157 VbaseDtor, // ?_D # vbase destructor 158 VecDelDtor, // ?_E # vector deleting destructor 159 DefaultCtorClosure, // ?_F # default constructor closure 160 ScalarDelDtor, // ?_G # scalar deleting destructor 161 VecCtorIter, // ?_H # vector constructor iterator 162 VecDtorIter, // ?_I # vector destructor iterator 163 VecVbaseCtorIter, // ?_J # vector vbase constructor iterator 164 VdispMap, // ?_K # virtual displacement map 165 EHVecCtorIter, // ?_L # eh vector constructor iterator 166 EHVecDtorIter, // ?_M # eh vector destructor iterator 167 EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator 168 CopyCtorClosure, // ?_O # copy constructor closure 169 LocalVftableCtorClosure, // ?_T # local vftable constructor closure 170 ArrayNew, // ?_U operator new[] 171 ArrayDelete, // ?_V operator delete[] 172 ManVectorCtorIter, // ?__A managed vector ctor iterator 173 ManVectorDtorIter, // ?__B managed vector dtor iterator 174 EHVectorCopyCtorIter, // ?__C EH vector copy ctor iterator 175 EHVectorVbaseCopyCtorIter, // ?__D EH vector vbase copy ctor iterator 176 VectorCopyCtorIter, // ?__G vector copy constructor iterator 177 VectorVbaseCopyCtorIter, // ?__H vector vbase copy constructor iterator 178 ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy constructor 179 CoAwait, // ?__L operator co_await 180 Spaceship, // ?__M operator<=> 181 MaxIntrinsic 182 }; 183 184 enum class SpecialIntrinsicKind { 185 None, 186 Vftable, 187 Vbtable, 188 Typeof, 189 VcallThunk, 190 LocalStaticGuard, 191 StringLiteralSymbol, 192 UdtReturning, 193 Unknown, 194 DynamicInitializer, 195 DynamicAtexitDestructor, 196 RttiTypeDescriptor, 197 RttiBaseClassDescriptor, 198 RttiBaseClassArray, 199 RttiClassHierarchyDescriptor, 200 RttiCompleteObjLocator, 201 LocalVftable, 202 LocalStaticThreadGuard, 203 }; 204 205 // Function classes 206 enum FuncClass : uint16_t { 207 FC_None = 0, 208 FC_Public = 1 << 0, 209 FC_Protected = 1 << 1, 210 FC_Private = 1 << 2, 211 FC_Global = 1 << 3, 212 FC_Static = 1 << 4, 213 FC_Virtual = 1 << 5, 214 FC_Far = 1 << 6, 215 FC_ExternC = 1 << 7, 216 FC_NoParameterList = 1 << 8, 217 FC_VirtualThisAdjust = 1 << 9, 218 FC_VirtualThisAdjustEx = 1 << 10, 219 FC_StaticThisAdjust = 1 << 11, 220 }; 221 222 enum class TagKind { Class, Struct, Union, Enum }; 223 224 enum class NodeKind { 225 Unknown, 226 Md5Symbol, 227 PrimitiveType, 228 FunctionSignature, 229 Identifier, 230 NamedIdentifier, 231 VcallThunkIdentifier, 232 LocalStaticGuardIdentifier, 233 IntrinsicFunctionIdentifier, 234 ConversionOperatorIdentifier, 235 DynamicStructorIdentifier, 236 StructorIdentifier, 237 LiteralOperatorIdentifier, 238 ThunkSignature, 239 PointerType, 240 TagType, 241 ArrayType, 242 Custom, 243 IntrinsicType, 244 NodeArray, 245 QualifiedName, 246 TemplateParameterReference, 247 EncodedStringLiteral, 248 IntegerLiteral, 249 RttiBaseClassDescriptor, 250 LocalStaticGuardVariable, 251 FunctionSymbol, 252 VariableSymbol, 253 SpecialTableSymbol 254 }; 255 256 struct Node { NodeNode257 explicit Node(NodeKind K) : Kind(K) {} 258 virtual ~Node() = default; 259 kindNode260 NodeKind kind() const { return Kind; } 261 262 virtual void output(OutputStream &OS, OutputFlags Flags) const = 0; 263 264 std::string toString(OutputFlags Flags = OF_Default) const; 265 266 private: 267 NodeKind Kind; 268 }; 269 270 struct TypeNode; 271 struct PrimitiveTypeNode; 272 struct FunctionSignatureNode; 273 struct IdentifierNode; 274 struct NamedIdentifierNode; 275 struct VcallThunkIdentifierNode; 276 struct IntrinsicFunctionIdentifierNode; 277 struct LiteralOperatorIdentifierNode; 278 struct ConversionOperatorIdentifierNode; 279 struct StructorIdentifierNode; 280 struct ThunkSignatureNode; 281 struct PointerTypeNode; 282 struct ArrayTypeNode; 283 struct CustomNode; 284 struct TagTypeNode; 285 struct IntrinsicTypeNode; 286 struct NodeArrayNode; 287 struct QualifiedNameNode; 288 struct TemplateParameterReferenceNode; 289 struct EncodedStringLiteralNode; 290 struct IntegerLiteralNode; 291 struct RttiBaseClassDescriptorNode; 292 struct LocalStaticGuardVariableNode; 293 struct SymbolNode; 294 struct FunctionSymbolNode; 295 struct VariableSymbolNode; 296 struct SpecialTableSymbolNode; 297 298 struct TypeNode : public Node { TypeNodeTypeNode299 explicit TypeNode(NodeKind K) : Node(K) {} 300 301 virtual void outputPre(OutputStream &OS, OutputFlags Flags) const = 0; 302 virtual void outputPost(OutputStream &OS, OutputFlags Flags) const = 0; 303 outputTypeNode304 void output(OutputStream &OS, OutputFlags Flags) const override { 305 outputPre(OS, Flags); 306 outputPost(OS, Flags); 307 } 308 309 Qualifiers Quals = Q_None; 310 }; 311 312 struct PrimitiveTypeNode : public TypeNode { PrimitiveTypeNodePrimitiveTypeNode313 explicit PrimitiveTypeNode(PrimitiveKind K) 314 : TypeNode(NodeKind::PrimitiveType), PrimKind(K) {} 315 316 void outputPre(OutputStream &OS, OutputFlags Flags) const; outputPostPrimitiveTypeNode317 void outputPost(OutputStream &OS, OutputFlags Flags) const {} 318 319 PrimitiveKind PrimKind; 320 }; 321 322 struct FunctionSignatureNode : public TypeNode { FunctionSignatureNodeFunctionSignatureNode323 explicit FunctionSignatureNode(NodeKind K) : TypeNode(K) {} FunctionSignatureNodeFunctionSignatureNode324 FunctionSignatureNode() : TypeNode(NodeKind::FunctionSignature) {} 325 326 void outputPre(OutputStream &OS, OutputFlags Flags) const override; 327 void outputPost(OutputStream &OS, OutputFlags Flags) const override; 328 329 // Valid if this FunctionTypeNode is the Pointee of a PointerType or 330 // MemberPointerType. 331 PointerAffinity Affinity = PointerAffinity::None; 332 333 // The function's calling convention. 334 CallingConv CallConvention = CallingConv::None; 335 336 // Function flags (gloabl, public, etc) 337 FuncClass FunctionClass = FC_Global; 338 339 FunctionRefQualifier RefQualifier = FunctionRefQualifier::None; 340 341 // The return type of the function. 342 TypeNode *ReturnType = nullptr; 343 344 // True if this is a C-style ... varargs function. 345 bool IsVariadic = false; 346 347 // Function parameters 348 NodeArrayNode *Params = nullptr; 349 350 // True if the function type is noexcept. 351 bool IsNoexcept = false; 352 }; 353 354 struct IdentifierNode : public Node { IdentifierNodeIdentifierNode355 explicit IdentifierNode(NodeKind K) : Node(K) {} 356 357 NodeArrayNode *TemplateParams = nullptr; 358 359 protected: 360 void outputTemplateParameters(OutputStream &OS, OutputFlags Flags) const; 361 }; 362 363 struct VcallThunkIdentifierNode : public IdentifierNode { VcallThunkIdentifierNodeVcallThunkIdentifierNode364 VcallThunkIdentifierNode() : IdentifierNode(NodeKind::VcallThunkIdentifier) {} 365 366 void output(OutputStream &OS, OutputFlags Flags) const override; 367 368 uint64_t OffsetInVTable = 0; 369 }; 370 371 struct DynamicStructorIdentifierNode : public IdentifierNode { DynamicStructorIdentifierNodeDynamicStructorIdentifierNode372 DynamicStructorIdentifierNode() 373 : IdentifierNode(NodeKind::DynamicStructorIdentifier) {} 374 375 void output(OutputStream &OS, OutputFlags Flags) const override; 376 377 VariableSymbolNode *Variable = nullptr; 378 QualifiedNameNode *Name = nullptr; 379 bool IsDestructor = false; 380 }; 381 382 struct NamedIdentifierNode : public IdentifierNode { NamedIdentifierNodeNamedIdentifierNode383 NamedIdentifierNode() : IdentifierNode(NodeKind::NamedIdentifier) {} 384 385 void output(OutputStream &OS, OutputFlags Flags) const override; 386 387 StringView Name; 388 }; 389 390 struct IntrinsicFunctionIdentifierNode : public IdentifierNode { IntrinsicFunctionIdentifierNodeIntrinsicFunctionIdentifierNode391 explicit IntrinsicFunctionIdentifierNode(IntrinsicFunctionKind Operator) 392 : IdentifierNode(NodeKind::IntrinsicFunctionIdentifier), 393 Operator(Operator) {} 394 395 void output(OutputStream &OS, OutputFlags Flags) const override; 396 397 IntrinsicFunctionKind Operator; 398 }; 399 400 struct LiteralOperatorIdentifierNode : public IdentifierNode { LiteralOperatorIdentifierNodeLiteralOperatorIdentifierNode401 LiteralOperatorIdentifierNode() 402 : IdentifierNode(NodeKind::LiteralOperatorIdentifier) {} 403 404 void output(OutputStream &OS, OutputFlags Flags) const override; 405 406 StringView Name; 407 }; 408 409 struct LocalStaticGuardIdentifierNode : public IdentifierNode { LocalStaticGuardIdentifierNodeLocalStaticGuardIdentifierNode410 LocalStaticGuardIdentifierNode() 411 : IdentifierNode(NodeKind::LocalStaticGuardIdentifier) {} 412 413 void output(OutputStream &OS, OutputFlags Flags) const override; 414 415 bool IsThread = false; 416 uint32_t ScopeIndex = 0; 417 }; 418 419 struct ConversionOperatorIdentifierNode : public IdentifierNode { ConversionOperatorIdentifierNodeConversionOperatorIdentifierNode420 ConversionOperatorIdentifierNode() 421 : IdentifierNode(NodeKind::ConversionOperatorIdentifier) {} 422 423 void output(OutputStream &OS, OutputFlags Flags) const override; 424 425 // The type that this operator converts too. 426 TypeNode *TargetType = nullptr; 427 }; 428 429 struct StructorIdentifierNode : public IdentifierNode { StructorIdentifierNodeStructorIdentifierNode430 StructorIdentifierNode() : IdentifierNode(NodeKind::StructorIdentifier) {} StructorIdentifierNodeStructorIdentifierNode431 explicit StructorIdentifierNode(bool IsDestructor) 432 : IdentifierNode(NodeKind::StructorIdentifier), 433 IsDestructor(IsDestructor) {} 434 435 void output(OutputStream &OS, OutputFlags Flags) const override; 436 437 // The name of the class that this is a structor of. 438 IdentifierNode *Class = nullptr; 439 bool IsDestructor = false; 440 }; 441 442 struct ThunkSignatureNode : public FunctionSignatureNode { ThunkSignatureNodeThunkSignatureNode443 ThunkSignatureNode() : FunctionSignatureNode(NodeKind::ThunkSignature) {} 444 445 void outputPre(OutputStream &OS, OutputFlags Flags) const override; 446 void outputPost(OutputStream &OS, OutputFlags Flags) const override; 447 448 struct ThisAdjustor { 449 uint32_t StaticOffset = 0; 450 int32_t VBPtrOffset = 0; 451 int32_t VBOffsetOffset = 0; 452 int32_t VtordispOffset = 0; 453 }; 454 455 ThisAdjustor ThisAdjust; 456 }; 457 458 struct PointerTypeNode : public TypeNode { PointerTypeNodePointerTypeNode459 PointerTypeNode() : TypeNode(NodeKind::PointerType) {} 460 void outputPre(OutputStream &OS, OutputFlags Flags) const override; 461 void outputPost(OutputStream &OS, OutputFlags Flags) const override; 462 463 // Is this a pointer, reference, or rvalue-reference? 464 PointerAffinity Affinity = PointerAffinity::None; 465 466 // If this is a member pointer, this is the class that the member is in. 467 QualifiedNameNode *ClassParent = nullptr; 468 469 // Represents a type X in "a pointer to X", "a reference to X", or 470 // "rvalue-reference to X" 471 TypeNode *Pointee = nullptr; 472 }; 473 474 struct TagTypeNode : public TypeNode { TagTypeNodeTagTypeNode475 explicit TagTypeNode(TagKind Tag) : TypeNode(NodeKind::TagType), Tag(Tag) {} 476 477 void outputPre(OutputStream &OS, OutputFlags Flags) const; 478 void outputPost(OutputStream &OS, OutputFlags Flags) const; 479 480 QualifiedNameNode *QualifiedName = nullptr; 481 TagKind Tag; 482 }; 483 484 struct ArrayTypeNode : public TypeNode { ArrayTypeNodeArrayTypeNode485 ArrayTypeNode() : TypeNode(NodeKind::ArrayType) {} 486 487 void outputPre(OutputStream &OS, OutputFlags Flags) const; 488 void outputPost(OutputStream &OS, OutputFlags Flags) const; 489 490 void outputDimensionsImpl(OutputStream &OS, OutputFlags Flags) const; 491 void outputOneDimension(OutputStream &OS, OutputFlags Flags, Node *N) const; 492 493 // A list of array dimensions. e.g. [3,4,5] in `int Foo[3][4][5]` 494 NodeArrayNode *Dimensions = nullptr; 495 496 // The type of array element. 497 TypeNode *ElementType = nullptr; 498 }; 499 500 struct IntrinsicNode : public TypeNode { IntrinsicNodeIntrinsicNode501 IntrinsicNode() : TypeNode(NodeKind::IntrinsicType) {} outputIntrinsicNode502 void output(OutputStream &OS, OutputFlags Flags) const override {} 503 }; 504 505 struct CustomTypeNode : public TypeNode { CustomTypeNodeCustomTypeNode506 CustomTypeNode() : TypeNode(NodeKind::Custom) {} 507 508 void outputPre(OutputStream &OS, OutputFlags Flags) const override; 509 void outputPost(OutputStream &OS, OutputFlags Flags) const override; 510 511 IdentifierNode *Identifier = nullptr; 512 }; 513 514 struct NodeArrayNode : public Node { NodeArrayNodeNodeArrayNode515 NodeArrayNode() : Node(NodeKind::NodeArray) {} 516 517 void output(OutputStream &OS, OutputFlags Flags) const override; 518 519 void output(OutputStream &OS, OutputFlags Flags, StringView 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(OutputStream &OS, 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(OutputStream &OS, 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(OutputStream &OS, 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(OutputStream &OS, 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(OutputStream &OS, 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(OutputStream &OS, 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(OutputStream &OS, 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(OutputStream &OS, OutputFlags Flags) const override; 603 604 StringView 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(OutputStream &OS, 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(OutputStream &OS, OutputFlags Flags) const override; 622 623 FunctionSignatureNode *Signature = nullptr; 624 }; 625 626 } // namespace ms_demangle 627 } // namespace llvm 628 629 #endif 630