10b57cec5SDimitry Andric //===- MicrosoftDemangle.cpp ----------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines a demangler for MSVC-style mangled symbols. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/Demangle/MicrosoftDemangleNodes.h" 140b57cec5SDimitry Andric #include "llvm/Demangle/DemangleConfig.h" 150b57cec5SDimitry Andric #include "llvm/Demangle/Utility.h" 160b57cec5SDimitry Andric #include <cctype> 170b57cec5SDimitry Andric #include <string> 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric using namespace llvm; 200b57cec5SDimitry Andric using namespace ms_demangle; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric #define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \ 230b57cec5SDimitry Andric case Enum::Value: \ 240b57cec5SDimitry Andric OS << Desc; \ 250b57cec5SDimitry Andric break; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric // Writes a space if the last token does not end with a punctuation. 280b57cec5SDimitry Andric static void outputSpaceIfNecessary(OutputStream &OS) { 290b57cec5SDimitry Andric if (OS.empty()) 300b57cec5SDimitry Andric return; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric char C = OS.back(); 330b57cec5SDimitry Andric if (std::isalnum(C) || C == '>') 340b57cec5SDimitry Andric OS << " "; 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric static void outputSingleQualifier(OutputStream &OS, Qualifiers Q) { 380b57cec5SDimitry Andric switch (Q) { 390b57cec5SDimitry Andric case Q_Const: 400b57cec5SDimitry Andric OS << "const"; 410b57cec5SDimitry Andric break; 420b57cec5SDimitry Andric case Q_Volatile: 430b57cec5SDimitry Andric OS << "volatile"; 440b57cec5SDimitry Andric break; 450b57cec5SDimitry Andric case Q_Restrict: 460b57cec5SDimitry Andric OS << "__restrict"; 470b57cec5SDimitry Andric break; 480b57cec5SDimitry Andric default: 490b57cec5SDimitry Andric break; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric static bool outputQualifierIfPresent(OutputStream &OS, Qualifiers Q, 540b57cec5SDimitry Andric Qualifiers Mask, bool NeedSpace) { 550b57cec5SDimitry Andric if (!(Q & Mask)) 560b57cec5SDimitry Andric return NeedSpace; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric if (NeedSpace) 590b57cec5SDimitry Andric OS << " "; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric outputSingleQualifier(OS, Mask); 620b57cec5SDimitry Andric return true; 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric static void outputQualifiers(OutputStream &OS, Qualifiers Q, bool SpaceBefore, 660b57cec5SDimitry Andric bool SpaceAfter) { 670b57cec5SDimitry Andric if (Q == Q_None) 680b57cec5SDimitry Andric return; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric size_t Pos1 = OS.getCurrentPosition(); 710b57cec5SDimitry Andric SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Const, SpaceBefore); 720b57cec5SDimitry Andric SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Volatile, SpaceBefore); 730b57cec5SDimitry Andric SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Restrict, SpaceBefore); 740b57cec5SDimitry Andric size_t Pos2 = OS.getCurrentPosition(); 750b57cec5SDimitry Andric if (SpaceAfter && Pos2 > Pos1) 760b57cec5SDimitry Andric OS << " "; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric static void outputCallingConvention(OutputStream &OS, CallingConv CC) { 800b57cec5SDimitry Andric outputSpaceIfNecessary(OS); 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric switch (CC) { 830b57cec5SDimitry Andric case CallingConv::Cdecl: 840b57cec5SDimitry Andric OS << "__cdecl"; 850b57cec5SDimitry Andric break; 860b57cec5SDimitry Andric case CallingConv::Fastcall: 870b57cec5SDimitry Andric OS << "__fastcall"; 880b57cec5SDimitry Andric break; 890b57cec5SDimitry Andric case CallingConv::Pascal: 900b57cec5SDimitry Andric OS << "__pascal"; 910b57cec5SDimitry Andric break; 920b57cec5SDimitry Andric case CallingConv::Regcall: 930b57cec5SDimitry Andric OS << "__regcall"; 940b57cec5SDimitry Andric break; 950b57cec5SDimitry Andric case CallingConv::Stdcall: 960b57cec5SDimitry Andric OS << "__stdcall"; 970b57cec5SDimitry Andric break; 980b57cec5SDimitry Andric case CallingConv::Thiscall: 990b57cec5SDimitry Andric OS << "__thiscall"; 1000b57cec5SDimitry Andric break; 1010b57cec5SDimitry Andric case CallingConv::Eabi: 1020b57cec5SDimitry Andric OS << "__eabi"; 1030b57cec5SDimitry Andric break; 1040b57cec5SDimitry Andric case CallingConv::Vectorcall: 1050b57cec5SDimitry Andric OS << "__vectorcall"; 1060b57cec5SDimitry Andric break; 1070b57cec5SDimitry Andric case CallingConv::Clrcall: 1080b57cec5SDimitry Andric OS << "__clrcall"; 1090b57cec5SDimitry Andric break; 110*fe6060f1SDimitry Andric case CallingConv::Swift: 111*fe6060f1SDimitry Andric OS << "__attribute__((__swiftcall__)) "; 112*fe6060f1SDimitry Andric break; 113*fe6060f1SDimitry Andric case CallingConv::SwiftAsync: 114*fe6060f1SDimitry Andric OS << "__attribute__((__swiftasynccall__)) "; 115*fe6060f1SDimitry Andric break; 1160b57cec5SDimitry Andric default: 1170b57cec5SDimitry Andric break; 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric std::string Node::toString(OutputFlags Flags) const { 1220b57cec5SDimitry Andric OutputStream OS; 1230b57cec5SDimitry Andric initializeOutputStream(nullptr, nullptr, OS, 1024); 1240b57cec5SDimitry Andric this->output(OS, Flags); 1250b57cec5SDimitry Andric OS << '\0'; 126*fe6060f1SDimitry Andric std::string Owned(OS.getBuffer()); 127*fe6060f1SDimitry Andric std::free(OS.getBuffer()); 128*fe6060f1SDimitry Andric return Owned; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 1320b57cec5SDimitry Andric switch (PrimKind) { 1330b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void"); 1340b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool"); 1350b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char"); 1360b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char"); 1370b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char"); 1380b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t"); 1390b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t"); 1400b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t"); 1410b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short"); 1420b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short"); 1430b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int"); 1440b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int"); 1450b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long"); 1460b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long"); 1470b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64"); 1480b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64"); 1490b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t"); 1500b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float"); 1510b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double"); 1520b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double"); 1530b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t"); 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric outputQualifiers(OS, Quals, true, false); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags) const { 1590b57cec5SDimitry Andric output(OS, Flags, ", "); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags, 1630b57cec5SDimitry Andric StringView Separator) const { 1640b57cec5SDimitry Andric if (Count == 0) 1650b57cec5SDimitry Andric return; 1660b57cec5SDimitry Andric if (Nodes[0]) 1670b57cec5SDimitry Andric Nodes[0]->output(OS, Flags); 1680b57cec5SDimitry Andric for (size_t I = 1; I < Count; ++I) { 1690b57cec5SDimitry Andric OS << Separator; 1700b57cec5SDimitry Andric Nodes[I]->output(OS, Flags); 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric void EncodedStringLiteralNode::output(OutputStream &OS, 1750b57cec5SDimitry Andric OutputFlags Flags) const { 1760b57cec5SDimitry Andric switch (Char) { 1770b57cec5SDimitry Andric case CharKind::Wchar: 1780b57cec5SDimitry Andric OS << "L\""; 1790b57cec5SDimitry Andric break; 1800b57cec5SDimitry Andric case CharKind::Char: 1810b57cec5SDimitry Andric OS << "\""; 1820b57cec5SDimitry Andric break; 1830b57cec5SDimitry Andric case CharKind::Char16: 1840b57cec5SDimitry Andric OS << "u\""; 1850b57cec5SDimitry Andric break; 1860b57cec5SDimitry Andric case CharKind::Char32: 1870b57cec5SDimitry Andric OS << "U\""; 1880b57cec5SDimitry Andric break; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric OS << DecodedString << "\""; 1910b57cec5SDimitry Andric if (IsTruncated) 1920b57cec5SDimitry Andric OS << "..."; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric void IntegerLiteralNode::output(OutputStream &OS, OutputFlags Flags) const { 1960b57cec5SDimitry Andric if (IsNegative) 1970b57cec5SDimitry Andric OS << '-'; 1980b57cec5SDimitry Andric OS << Value; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric void TemplateParameterReferenceNode::output(OutputStream &OS, 2020b57cec5SDimitry Andric OutputFlags Flags) const { 2030b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 2040b57cec5SDimitry Andric OS << "{"; 2050b57cec5SDimitry Andric else if (Affinity == PointerAffinity::Pointer) 2060b57cec5SDimitry Andric OS << "&"; 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric if (Symbol) { 2090b57cec5SDimitry Andric Symbol->output(OS, Flags); 2100b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 2110b57cec5SDimitry Andric OS << ", "; 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 2150b57cec5SDimitry Andric OS << ThunkOffsets[0]; 2160b57cec5SDimitry Andric for (int I = 1; I < ThunkOffsetCount; ++I) { 2170b57cec5SDimitry Andric OS << ", " << ThunkOffsets[I]; 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 2200b57cec5SDimitry Andric OS << "}"; 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric void IdentifierNode::outputTemplateParameters(OutputStream &OS, 2240b57cec5SDimitry Andric OutputFlags Flags) const { 2250b57cec5SDimitry Andric if (!TemplateParams) 2260b57cec5SDimitry Andric return; 2270b57cec5SDimitry Andric OS << "<"; 2280b57cec5SDimitry Andric TemplateParams->output(OS, Flags); 2290b57cec5SDimitry Andric OS << ">"; 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric void DynamicStructorIdentifierNode::output(OutputStream &OS, 2330b57cec5SDimitry Andric OutputFlags Flags) const { 2340b57cec5SDimitry Andric if (IsDestructor) 2350b57cec5SDimitry Andric OS << "`dynamic atexit destructor for "; 2360b57cec5SDimitry Andric else 2370b57cec5SDimitry Andric OS << "`dynamic initializer for "; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric if (Variable) { 2400b57cec5SDimitry Andric OS << "`"; 2410b57cec5SDimitry Andric Variable->output(OS, Flags); 2420b57cec5SDimitry Andric OS << "''"; 2430b57cec5SDimitry Andric } else { 2440b57cec5SDimitry Andric OS << "'"; 2450b57cec5SDimitry Andric Name->output(OS, Flags); 2460b57cec5SDimitry Andric OS << "''"; 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric void NamedIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const { 2510b57cec5SDimitry Andric OS << Name; 2520b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric void IntrinsicFunctionIdentifierNode::output(OutputStream &OS, 2560b57cec5SDimitry Andric OutputFlags Flags) const { 2570b57cec5SDimitry Andric switch (Operator) { 2580b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new"); 2590b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete"); 2600b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator="); 2610b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>"); 2620b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<"); 2630b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!"); 2640b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator=="); 2650b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!="); 2660b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript, 2670b57cec5SDimitry Andric "operator[]"); 2680b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->"); 2690b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++"); 2700b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--"); 2710b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-"); 2720b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+"); 2730b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*"); 2740b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&"); 2750b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer, 2760b57cec5SDimitry Andric "operator->*"); 2770b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/"); 2780b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%"); 2790b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<"); 2800b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<="); 2810b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>"); 2820b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual, 2830b57cec5SDimitry Andric "operator>="); 2840b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,"); 2850b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()"); 2860b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~"); 2870b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^"); 2880b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|"); 2890b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&"); 2900b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||"); 2910b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*="); 2920b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+="); 2930b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-="); 2940b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/="); 2950b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%="); 2960b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>="); 2970b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<="); 2980b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual, 2990b57cec5SDimitry Andric "operator&="); 3000b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual, 3010b57cec5SDimitry Andric "operator|="); 3020b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual, 3030b57cec5SDimitry Andric "operator^="); 3040b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'"); 3050b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor, 3060b57cec5SDimitry Andric "`vector deleting dtor'"); 3070b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure, 3080b57cec5SDimitry Andric "`default ctor closure'"); 3090b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor, 3100b57cec5SDimitry Andric "`scalar deleting dtor'"); 3110b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter, 3120b57cec5SDimitry Andric "`vector ctor iterator'"); 3130b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter, 3140b57cec5SDimitry Andric "`vector dtor iterator'"); 3150b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter, 3160b57cec5SDimitry Andric "`vector vbase ctor iterator'"); 3170b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap, 3180b57cec5SDimitry Andric "`virtual displacement map'"); 3190b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter, 3200b57cec5SDimitry Andric "`eh vector ctor iterator'"); 3210b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter, 3220b57cec5SDimitry Andric "`eh vector dtor iterator'"); 3230b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter, 3240b57cec5SDimitry Andric "`eh vector vbase ctor iterator'"); 3250b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure, 3260b57cec5SDimitry Andric "`copy ctor closure'"); 3270b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure, 3280b57cec5SDimitry Andric "`local vftable ctor closure'"); 3290b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]"); 3300b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete, 3310b57cec5SDimitry Andric "operator delete[]"); 3320b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter, 3330b57cec5SDimitry Andric "`managed vector ctor iterator'"); 3340b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter, 3350b57cec5SDimitry Andric "`managed vector dtor iterator'"); 3360b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter, 3370b57cec5SDimitry Andric "`EH vector copy ctor iterator'"); 3380b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter, 3390b57cec5SDimitry Andric "`EH vector vbase copy ctor iterator'"); 3400b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter, 3410b57cec5SDimitry Andric "`vector copy ctor iterator'"); 3420b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter, 3430b57cec5SDimitry Andric "`vector vbase copy constructor iterator'"); 3440b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter, 3450b57cec5SDimitry Andric "`managed vector vbase copy constructor iterator'"); 3460b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait, 3470b57cec5SDimitry Andric "operator co_await"); 3480b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>"); 3490b57cec5SDimitry Andric case IntrinsicFunctionKind::MaxIntrinsic: 3500b57cec5SDimitry Andric case IntrinsicFunctionKind::None: 3510b57cec5SDimitry Andric break; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric void LocalStaticGuardIdentifierNode::output(OutputStream &OS, 3570b57cec5SDimitry Andric OutputFlags Flags) const { 3580b57cec5SDimitry Andric if (IsThread) 3590b57cec5SDimitry Andric OS << "`local static thread guard'"; 3600b57cec5SDimitry Andric else 3610b57cec5SDimitry Andric OS << "`local static guard'"; 3620b57cec5SDimitry Andric if (ScopeIndex > 0) 3630b57cec5SDimitry Andric OS << "{" << ScopeIndex << "}"; 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric void ConversionOperatorIdentifierNode::output(OutputStream &OS, 3670b57cec5SDimitry Andric OutputFlags Flags) const { 3680b57cec5SDimitry Andric OS << "operator"; 3690b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 3700b57cec5SDimitry Andric OS << " "; 3710b57cec5SDimitry Andric TargetType->output(OS, Flags); 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric void StructorIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const { 3750b57cec5SDimitry Andric if (IsDestructor) 3760b57cec5SDimitry Andric OS << "~"; 3770b57cec5SDimitry Andric Class->output(OS, Flags); 3780b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric void LiteralOperatorIdentifierNode::output(OutputStream &OS, 3820b57cec5SDimitry Andric OutputFlags Flags) const { 3830b57cec5SDimitry Andric OS << "operator \"\"" << Name; 3840b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric void FunctionSignatureNode::outputPre(OutputStream &OS, 3880b57cec5SDimitry Andric OutputFlags Flags) const { 3898bcb0991SDimitry Andric if (!(Flags & OF_NoAccessSpecifier)) { 3900b57cec5SDimitry Andric if (FunctionClass & FC_Public) 3910b57cec5SDimitry Andric OS << "public: "; 3920b57cec5SDimitry Andric if (FunctionClass & FC_Protected) 3930b57cec5SDimitry Andric OS << "protected: "; 3940b57cec5SDimitry Andric if (FunctionClass & FC_Private) 3950b57cec5SDimitry Andric OS << "private: "; 3968bcb0991SDimitry Andric } 3970b57cec5SDimitry Andric 3988bcb0991SDimitry Andric if (!(Flags & OF_NoMemberType)) { 3990b57cec5SDimitry Andric if (!(FunctionClass & FC_Global)) { 4000b57cec5SDimitry Andric if (FunctionClass & FC_Static) 4010b57cec5SDimitry Andric OS << "static "; 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric if (FunctionClass & FC_Virtual) 4040b57cec5SDimitry Andric OS << "virtual "; 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric if (FunctionClass & FC_ExternC) 4070b57cec5SDimitry Andric OS << "extern \"C\" "; 4088bcb0991SDimitry Andric } 4090b57cec5SDimitry Andric 4108bcb0991SDimitry Andric if (!(Flags & OF_NoReturnType) && ReturnType) { 4110b57cec5SDimitry Andric ReturnType->outputPre(OS, Flags); 4120b57cec5SDimitry Andric OS << " "; 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric if (!(Flags & OF_NoCallingConvention)) 4160b57cec5SDimitry Andric outputCallingConvention(OS, CallConvention); 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric void FunctionSignatureNode::outputPost(OutputStream &OS, 4200b57cec5SDimitry Andric OutputFlags Flags) const { 4210b57cec5SDimitry Andric if (!(FunctionClass & FC_NoParameterList)) { 4220b57cec5SDimitry Andric OS << "("; 4230b57cec5SDimitry Andric if (Params) 4240b57cec5SDimitry Andric Params->output(OS, Flags); 4250b57cec5SDimitry Andric else 4260b57cec5SDimitry Andric OS << "void"; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric if (IsVariadic) { 4290b57cec5SDimitry Andric if (OS.back() != '(') 4300b57cec5SDimitry Andric OS << ", "; 4310b57cec5SDimitry Andric OS << "..."; 4320b57cec5SDimitry Andric } 4330b57cec5SDimitry Andric OS << ")"; 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric if (Quals & Q_Const) 4370b57cec5SDimitry Andric OS << " const"; 4380b57cec5SDimitry Andric if (Quals & Q_Volatile) 4390b57cec5SDimitry Andric OS << " volatile"; 4400b57cec5SDimitry Andric if (Quals & Q_Restrict) 4410b57cec5SDimitry Andric OS << " __restrict"; 4420b57cec5SDimitry Andric if (Quals & Q_Unaligned) 4430b57cec5SDimitry Andric OS << " __unaligned"; 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric if (IsNoexcept) 4460b57cec5SDimitry Andric OS << " noexcept"; 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric if (RefQualifier == FunctionRefQualifier::Reference) 4490b57cec5SDimitry Andric OS << " &"; 4500b57cec5SDimitry Andric else if (RefQualifier == FunctionRefQualifier::RValueReference) 4510b57cec5SDimitry Andric OS << " &&"; 4520b57cec5SDimitry Andric 4538bcb0991SDimitry Andric if (!(Flags & OF_NoReturnType) && ReturnType) 4540b57cec5SDimitry Andric ReturnType->outputPost(OS, Flags); 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric void ThunkSignatureNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 4580b57cec5SDimitry Andric OS << "[thunk]: "; 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric FunctionSignatureNode::outputPre(OS, Flags); 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric void ThunkSignatureNode::outputPost(OutputStream &OS, OutputFlags Flags) const { 4640b57cec5SDimitry Andric if (FunctionClass & FC_StaticThisAdjust) { 4650b57cec5SDimitry Andric OS << "`adjustor{" << ThisAdjust.StaticOffset << "}'"; 4660b57cec5SDimitry Andric } else if (FunctionClass & FC_VirtualThisAdjust) { 4670b57cec5SDimitry Andric if (FunctionClass & FC_VirtualThisAdjustEx) { 4680b57cec5SDimitry Andric OS << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", " 4690b57cec5SDimitry Andric << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset 4700b57cec5SDimitry Andric << ", " << ThisAdjust.StaticOffset << "}'"; 4710b57cec5SDimitry Andric } else { 4720b57cec5SDimitry Andric OS << "`vtordisp{" << ThisAdjust.VtordispOffset << ", " 4730b57cec5SDimitry Andric << ThisAdjust.StaticOffset << "}'"; 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric FunctionSignatureNode::outputPost(OS, Flags); 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric void PointerTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 4810b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::FunctionSignature) { 4820b57cec5SDimitry Andric // If this is a pointer to a function, don't output the calling convention. 4830b57cec5SDimitry Andric // It needs to go inside the parentheses. 4840b57cec5SDimitry Andric const FunctionSignatureNode *Sig = 4850b57cec5SDimitry Andric static_cast<const FunctionSignatureNode *>(Pointee); 4860b57cec5SDimitry Andric Sig->outputPre(OS, OF_NoCallingConvention); 4870b57cec5SDimitry Andric } else 4880b57cec5SDimitry Andric Pointee->outputPre(OS, Flags); 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric outputSpaceIfNecessary(OS); 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric if (Quals & Q_Unaligned) 4930b57cec5SDimitry Andric OS << "__unaligned "; 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::ArrayType) { 4960b57cec5SDimitry Andric OS << "("; 4970b57cec5SDimitry Andric } else if (Pointee->kind() == NodeKind::FunctionSignature) { 4980b57cec5SDimitry Andric OS << "("; 4990b57cec5SDimitry Andric const FunctionSignatureNode *Sig = 5000b57cec5SDimitry Andric static_cast<const FunctionSignatureNode *>(Pointee); 5010b57cec5SDimitry Andric outputCallingConvention(OS, Sig->CallConvention); 5020b57cec5SDimitry Andric OS << " "; 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric if (ClassParent) { 5060b57cec5SDimitry Andric ClassParent->output(OS, Flags); 5070b57cec5SDimitry Andric OS << "::"; 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric switch (Affinity) { 5110b57cec5SDimitry Andric case PointerAffinity::Pointer: 5120b57cec5SDimitry Andric OS << "*"; 5130b57cec5SDimitry Andric break; 5140b57cec5SDimitry Andric case PointerAffinity::Reference: 5150b57cec5SDimitry Andric OS << "&"; 5160b57cec5SDimitry Andric break; 5170b57cec5SDimitry Andric case PointerAffinity::RValueReference: 5180b57cec5SDimitry Andric OS << "&&"; 5190b57cec5SDimitry Andric break; 5200b57cec5SDimitry Andric default: 5210b57cec5SDimitry Andric assert(false); 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric outputQualifiers(OS, Quals, false, false); 5240b57cec5SDimitry Andric } 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric void PointerTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const { 5270b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::ArrayType || 5280b57cec5SDimitry Andric Pointee->kind() == NodeKind::FunctionSignature) 5290b57cec5SDimitry Andric OS << ")"; 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric Pointee->outputPost(OS, Flags); 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric void TagTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 5350b57cec5SDimitry Andric if (!(Flags & OF_NoTagSpecifier)) { 5360b57cec5SDimitry Andric switch (Tag) { 5370b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class"); 5380b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct"); 5390b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union"); 5400b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum"); 5410b57cec5SDimitry Andric } 5420b57cec5SDimitry Andric OS << " "; 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric QualifiedName->output(OS, Flags); 5450b57cec5SDimitry Andric outputQualifiers(OS, Quals, true, false); 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric void TagTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {} 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric void ArrayTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 5510b57cec5SDimitry Andric ElementType->outputPre(OS, Flags); 5520b57cec5SDimitry Andric outputQualifiers(OS, Quals, true, false); 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric void ArrayTypeNode::outputOneDimension(OutputStream &OS, OutputFlags Flags, 5560b57cec5SDimitry Andric Node *N) const { 5570b57cec5SDimitry Andric assert(N->kind() == NodeKind::IntegerLiteral); 5580b57cec5SDimitry Andric IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N); 5590b57cec5SDimitry Andric if (ILN->Value != 0) 5600b57cec5SDimitry Andric ILN->output(OS, Flags); 5610b57cec5SDimitry Andric } 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric void ArrayTypeNode::outputDimensionsImpl(OutputStream &OS, 5640b57cec5SDimitry Andric OutputFlags Flags) const { 5650b57cec5SDimitry Andric if (Dimensions->Count == 0) 5660b57cec5SDimitry Andric return; 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric outputOneDimension(OS, Flags, Dimensions->Nodes[0]); 5690b57cec5SDimitry Andric for (size_t I = 1; I < Dimensions->Count; ++I) { 5700b57cec5SDimitry Andric OS << "]["; 5710b57cec5SDimitry Andric outputOneDimension(OS, Flags, Dimensions->Nodes[I]); 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric void ArrayTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const { 5760b57cec5SDimitry Andric OS << "["; 5770b57cec5SDimitry Andric outputDimensionsImpl(OS, Flags); 5780b57cec5SDimitry Andric OS << "]"; 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric ElementType->outputPost(OS, Flags); 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric void SymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 5840b57cec5SDimitry Andric Name->output(OS, Flags); 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric void FunctionSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 5880b57cec5SDimitry Andric Signature->outputPre(OS, Flags); 5890b57cec5SDimitry Andric outputSpaceIfNecessary(OS); 5900b57cec5SDimitry Andric Name->output(OS, Flags); 5910b57cec5SDimitry Andric Signature->outputPost(OS, Flags); 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 5958bcb0991SDimitry Andric const char *AccessSpec = nullptr; 5968bcb0991SDimitry Andric bool IsStatic = true; 5970b57cec5SDimitry Andric switch (SC) { 5980b57cec5SDimitry Andric case StorageClass::PrivateStatic: 5998bcb0991SDimitry Andric AccessSpec = "private"; 6000b57cec5SDimitry Andric break; 6010b57cec5SDimitry Andric case StorageClass::PublicStatic: 6028bcb0991SDimitry Andric AccessSpec = "public"; 6030b57cec5SDimitry Andric break; 6040b57cec5SDimitry Andric case StorageClass::ProtectedStatic: 6058bcb0991SDimitry Andric AccessSpec = "protected"; 6060b57cec5SDimitry Andric break; 6070b57cec5SDimitry Andric default: 6088bcb0991SDimitry Andric IsStatic = false; 6090b57cec5SDimitry Andric break; 6100b57cec5SDimitry Andric } 6118bcb0991SDimitry Andric if (!(Flags & OF_NoAccessSpecifier) && AccessSpec) 6128bcb0991SDimitry Andric OS << AccessSpec << ": "; 6138bcb0991SDimitry Andric if (!(Flags & OF_NoMemberType) && IsStatic) 6148bcb0991SDimitry Andric OS << "static "; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric if (Type) { 6170b57cec5SDimitry Andric Type->outputPre(OS, Flags); 6180b57cec5SDimitry Andric outputSpaceIfNecessary(OS); 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric Name->output(OS, Flags); 6210b57cec5SDimitry Andric if (Type) 6220b57cec5SDimitry Andric Type->outputPost(OS, Flags); 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 6260b57cec5SDimitry Andric Identifier->output(OS, Flags); 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {} 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const { 6310b57cec5SDimitry Andric Components->output(OS, Flags, "::"); 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric void RttiBaseClassDescriptorNode::output(OutputStream &OS, 6350b57cec5SDimitry Andric OutputFlags Flags) const { 6360b57cec5SDimitry Andric OS << "`RTTI Base Class Descriptor at ("; 6370b57cec5SDimitry Andric OS << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", " 6380b57cec5SDimitry Andric << this->Flags; 6390b57cec5SDimitry Andric OS << ")'"; 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric void LocalStaticGuardVariableNode::output(OutputStream &OS, 6430b57cec5SDimitry Andric OutputFlags Flags) const { 6440b57cec5SDimitry Andric Name->output(OS, Flags); 6450b57cec5SDimitry Andric } 6460b57cec5SDimitry Andric 6470b57cec5SDimitry Andric void VcallThunkIdentifierNode::output(OutputStream &OS, 6480b57cec5SDimitry Andric OutputFlags Flags) const { 6490b57cec5SDimitry Andric OS << "`vcall'{" << OffsetInVTable << ", {flat}}"; 6500b57cec5SDimitry Andric } 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric void SpecialTableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 6530b57cec5SDimitry Andric outputQualifiers(OS, Quals, false, true); 6540b57cec5SDimitry Andric Name->output(OS, Flags); 6550b57cec5SDimitry Andric if (TargetName) { 6560b57cec5SDimitry Andric OS << "{for `"; 6570b57cec5SDimitry Andric TargetName->output(OS, Flags); 6580b57cec5SDimitry Andric OS << "'}"; 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric } 661