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/Utility.h" 150b57cec5SDimitry Andric #include <cctype> 160b57cec5SDimitry Andric #include <string> 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric using namespace llvm; 190b57cec5SDimitry Andric using namespace ms_demangle; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric #define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \ 220b57cec5SDimitry Andric case Enum::Value: \ 23349cc55cSDimitry Andric OB << Desc; \ 240b57cec5SDimitry Andric break; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric // Writes a space if the last token does not end with a punctuation. 27349cc55cSDimitry Andric static void outputSpaceIfNecessary(OutputBuffer &OB) { 28349cc55cSDimitry Andric if (OB.empty()) 290b57cec5SDimitry Andric return; 300b57cec5SDimitry Andric 31349cc55cSDimitry Andric char C = OB.back(); 320b57cec5SDimitry Andric if (std::isalnum(C) || C == '>') 33349cc55cSDimitry Andric OB << " "; 340b57cec5SDimitry Andric } 350b57cec5SDimitry Andric 36349cc55cSDimitry Andric static void outputSingleQualifier(OutputBuffer &OB, Qualifiers Q) { 370b57cec5SDimitry Andric switch (Q) { 380b57cec5SDimitry Andric case Q_Const: 39349cc55cSDimitry Andric OB << "const"; 400b57cec5SDimitry Andric break; 410b57cec5SDimitry Andric case Q_Volatile: 42349cc55cSDimitry Andric OB << "volatile"; 430b57cec5SDimitry Andric break; 440b57cec5SDimitry Andric case Q_Restrict: 45349cc55cSDimitry Andric OB << "__restrict"; 460b57cec5SDimitry Andric break; 470b57cec5SDimitry Andric default: 480b57cec5SDimitry Andric break; 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 52349cc55cSDimitry Andric static bool outputQualifierIfPresent(OutputBuffer &OB, Qualifiers Q, 530b57cec5SDimitry Andric Qualifiers Mask, bool NeedSpace) { 540b57cec5SDimitry Andric if (!(Q & Mask)) 550b57cec5SDimitry Andric return NeedSpace; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric if (NeedSpace) 58349cc55cSDimitry Andric OB << " "; 590b57cec5SDimitry Andric 60349cc55cSDimitry Andric outputSingleQualifier(OB, Mask); 610b57cec5SDimitry Andric return true; 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 64349cc55cSDimitry Andric static void outputQualifiers(OutputBuffer &OB, Qualifiers Q, bool SpaceBefore, 650b57cec5SDimitry Andric bool SpaceAfter) { 660b57cec5SDimitry Andric if (Q == Q_None) 670b57cec5SDimitry Andric return; 680b57cec5SDimitry Andric 69349cc55cSDimitry Andric size_t Pos1 = OB.getCurrentPosition(); 70349cc55cSDimitry Andric SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Const, SpaceBefore); 71349cc55cSDimitry Andric SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Volatile, SpaceBefore); 72349cc55cSDimitry Andric SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Restrict, SpaceBefore); 73349cc55cSDimitry Andric size_t Pos2 = OB.getCurrentPosition(); 740b57cec5SDimitry Andric if (SpaceAfter && Pos2 > Pos1) 75349cc55cSDimitry Andric OB << " "; 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 78349cc55cSDimitry Andric static void outputCallingConvention(OutputBuffer &OB, CallingConv CC) { 79349cc55cSDimitry Andric outputSpaceIfNecessary(OB); 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric switch (CC) { 820b57cec5SDimitry Andric case CallingConv::Cdecl: 83349cc55cSDimitry Andric OB << "__cdecl"; 840b57cec5SDimitry Andric break; 850b57cec5SDimitry Andric case CallingConv::Fastcall: 86349cc55cSDimitry Andric OB << "__fastcall"; 870b57cec5SDimitry Andric break; 880b57cec5SDimitry Andric case CallingConv::Pascal: 89349cc55cSDimitry Andric OB << "__pascal"; 900b57cec5SDimitry Andric break; 910b57cec5SDimitry Andric case CallingConv::Regcall: 92349cc55cSDimitry Andric OB << "__regcall"; 930b57cec5SDimitry Andric break; 940b57cec5SDimitry Andric case CallingConv::Stdcall: 95349cc55cSDimitry Andric OB << "__stdcall"; 960b57cec5SDimitry Andric break; 970b57cec5SDimitry Andric case CallingConv::Thiscall: 98349cc55cSDimitry Andric OB << "__thiscall"; 990b57cec5SDimitry Andric break; 1000b57cec5SDimitry Andric case CallingConv::Eabi: 101349cc55cSDimitry Andric OB << "__eabi"; 1020b57cec5SDimitry Andric break; 1030b57cec5SDimitry Andric case CallingConv::Vectorcall: 104349cc55cSDimitry Andric OB << "__vectorcall"; 1050b57cec5SDimitry Andric break; 1060b57cec5SDimitry Andric case CallingConv::Clrcall: 107349cc55cSDimitry Andric OB << "__clrcall"; 1080b57cec5SDimitry Andric break; 109fe6060f1SDimitry Andric case CallingConv::Swift: 110349cc55cSDimitry Andric OB << "__attribute__((__swiftcall__)) "; 111fe6060f1SDimitry Andric break; 112fe6060f1SDimitry Andric case CallingConv::SwiftAsync: 113349cc55cSDimitry Andric OB << "__attribute__((__swiftasynccall__)) "; 114fe6060f1SDimitry Andric break; 1150b57cec5SDimitry Andric default: 1160b57cec5SDimitry Andric break; 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric std::string Node::toString(OutputFlags Flags) const { 121349cc55cSDimitry Andric OutputBuffer OB; 122349cc55cSDimitry Andric initializeOutputBuffer(nullptr, nullptr, OB, 1024); 123349cc55cSDimitry Andric this->output(OB, Flags); 124*81ad6265SDimitry Andric StringView SV = OB; 125*81ad6265SDimitry Andric std::string Owned(SV.begin(), SV.end()); 126349cc55cSDimitry Andric std::free(OB.getBuffer()); 127fe6060f1SDimitry Andric return Owned; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 130349cc55cSDimitry Andric void PrimitiveTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 1310b57cec5SDimitry Andric switch (PrimKind) { 1320b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void"); 1330b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool"); 1340b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char"); 1350b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char"); 1360b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char"); 1370b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t"); 1380b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t"); 1390b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t"); 1400b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short"); 1410b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short"); 1420b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int"); 1430b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int"); 1440b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long"); 1450b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long"); 1460b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64"); 1470b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64"); 1480b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t"); 1490b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float"); 1500b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double"); 1510b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double"); 1520b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t"); 1530b57cec5SDimitry Andric } 154349cc55cSDimitry Andric outputQualifiers(OB, Quals, true, false); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 157349cc55cSDimitry Andric void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags) const { 158349cc55cSDimitry Andric output(OB, Flags, ", "); 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 161349cc55cSDimitry Andric void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags, 1620b57cec5SDimitry Andric StringView Separator) const { 1630b57cec5SDimitry Andric if (Count == 0) 1640b57cec5SDimitry Andric return; 1650b57cec5SDimitry Andric if (Nodes[0]) 166349cc55cSDimitry Andric Nodes[0]->output(OB, Flags); 1670b57cec5SDimitry Andric for (size_t I = 1; I < Count; ++I) { 168349cc55cSDimitry Andric OB << Separator; 169349cc55cSDimitry Andric Nodes[I]->output(OB, Flags); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric 173349cc55cSDimitry Andric void EncodedStringLiteralNode::output(OutputBuffer &OB, 1740b57cec5SDimitry Andric OutputFlags Flags) const { 1750b57cec5SDimitry Andric switch (Char) { 1760b57cec5SDimitry Andric case CharKind::Wchar: 177349cc55cSDimitry Andric OB << "L\""; 1780b57cec5SDimitry Andric break; 1790b57cec5SDimitry Andric case CharKind::Char: 180349cc55cSDimitry Andric OB << "\""; 1810b57cec5SDimitry Andric break; 1820b57cec5SDimitry Andric case CharKind::Char16: 183349cc55cSDimitry Andric OB << "u\""; 1840b57cec5SDimitry Andric break; 1850b57cec5SDimitry Andric case CharKind::Char32: 186349cc55cSDimitry Andric OB << "U\""; 1870b57cec5SDimitry Andric break; 1880b57cec5SDimitry Andric } 189349cc55cSDimitry Andric OB << DecodedString << "\""; 1900b57cec5SDimitry Andric if (IsTruncated) 191349cc55cSDimitry Andric OB << "..."; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 194349cc55cSDimitry Andric void IntegerLiteralNode::output(OutputBuffer &OB, OutputFlags Flags) const { 1950b57cec5SDimitry Andric if (IsNegative) 196349cc55cSDimitry Andric OB << '-'; 197349cc55cSDimitry Andric OB << Value; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 200349cc55cSDimitry Andric void TemplateParameterReferenceNode::output(OutputBuffer &OB, 2010b57cec5SDimitry Andric OutputFlags Flags) const { 2020b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 203349cc55cSDimitry Andric OB << "{"; 2040b57cec5SDimitry Andric else if (Affinity == PointerAffinity::Pointer) 205349cc55cSDimitry Andric OB << "&"; 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric if (Symbol) { 208349cc55cSDimitry Andric Symbol->output(OB, Flags); 2090b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 210349cc55cSDimitry Andric OB << ", "; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 214349cc55cSDimitry Andric OB << ThunkOffsets[0]; 2150b57cec5SDimitry Andric for (int I = 1; I < ThunkOffsetCount; ++I) { 216349cc55cSDimitry Andric OB << ", " << ThunkOffsets[I]; 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 219349cc55cSDimitry Andric OB << "}"; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 222349cc55cSDimitry Andric void IdentifierNode::outputTemplateParameters(OutputBuffer &OB, 2230b57cec5SDimitry Andric OutputFlags Flags) const { 2240b57cec5SDimitry Andric if (!TemplateParams) 2250b57cec5SDimitry Andric return; 226349cc55cSDimitry Andric OB << "<"; 227349cc55cSDimitry Andric TemplateParams->output(OB, Flags); 228349cc55cSDimitry Andric OB << ">"; 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric 231349cc55cSDimitry Andric void DynamicStructorIdentifierNode::output(OutputBuffer &OB, 2320b57cec5SDimitry Andric OutputFlags Flags) const { 2330b57cec5SDimitry Andric if (IsDestructor) 234349cc55cSDimitry Andric OB << "`dynamic atexit destructor for "; 2350b57cec5SDimitry Andric else 236349cc55cSDimitry Andric OB << "`dynamic initializer for "; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric if (Variable) { 239349cc55cSDimitry Andric OB << "`"; 240349cc55cSDimitry Andric Variable->output(OB, Flags); 241349cc55cSDimitry Andric OB << "''"; 2420b57cec5SDimitry Andric } else { 243349cc55cSDimitry Andric OB << "'"; 244349cc55cSDimitry Andric Name->output(OB, Flags); 245349cc55cSDimitry Andric OB << "''"; 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 249349cc55cSDimitry Andric void NamedIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const { 250349cc55cSDimitry Andric OB << Name; 251349cc55cSDimitry Andric outputTemplateParameters(OB, Flags); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 254349cc55cSDimitry Andric void IntrinsicFunctionIdentifierNode::output(OutputBuffer &OB, 2550b57cec5SDimitry Andric OutputFlags Flags) const { 2560b57cec5SDimitry Andric switch (Operator) { 2570b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new"); 2580b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete"); 2590b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator="); 2600b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>"); 2610b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<"); 2620b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!"); 2630b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator=="); 2640b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!="); 2650b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript, 2660b57cec5SDimitry Andric "operator[]"); 2670b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->"); 2680b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++"); 2690b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--"); 2700b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-"); 2710b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+"); 2720b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*"); 2730b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&"); 2740b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer, 2750b57cec5SDimitry Andric "operator->*"); 2760b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/"); 2770b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%"); 2780b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<"); 2790b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<="); 2800b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>"); 2810b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual, 2820b57cec5SDimitry Andric "operator>="); 2830b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,"); 2840b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()"); 2850b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~"); 2860b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^"); 2870b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|"); 2880b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&"); 2890b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||"); 2900b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*="); 2910b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+="); 2920b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-="); 2930b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/="); 2940b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%="); 2950b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>="); 2960b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<="); 2970b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual, 2980b57cec5SDimitry Andric "operator&="); 2990b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual, 3000b57cec5SDimitry Andric "operator|="); 3010b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual, 3020b57cec5SDimitry Andric "operator^="); 3030b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'"); 3040b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor, 3050b57cec5SDimitry Andric "`vector deleting dtor'"); 3060b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure, 3070b57cec5SDimitry Andric "`default ctor closure'"); 3080b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor, 3090b57cec5SDimitry Andric "`scalar deleting dtor'"); 3100b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter, 3110b57cec5SDimitry Andric "`vector ctor iterator'"); 3120b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter, 3130b57cec5SDimitry Andric "`vector dtor iterator'"); 3140b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter, 3150b57cec5SDimitry Andric "`vector vbase ctor iterator'"); 3160b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap, 3170b57cec5SDimitry Andric "`virtual displacement map'"); 3180b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter, 3190b57cec5SDimitry Andric "`eh vector ctor iterator'"); 3200b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter, 3210b57cec5SDimitry Andric "`eh vector dtor iterator'"); 3220b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter, 3230b57cec5SDimitry Andric "`eh vector vbase ctor iterator'"); 3240b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure, 3250b57cec5SDimitry Andric "`copy ctor closure'"); 3260b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure, 3270b57cec5SDimitry Andric "`local vftable ctor closure'"); 3280b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]"); 3290b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete, 3300b57cec5SDimitry Andric "operator delete[]"); 3310b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter, 3320b57cec5SDimitry Andric "`managed vector ctor iterator'"); 3330b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter, 3340b57cec5SDimitry Andric "`managed vector dtor iterator'"); 3350b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter, 3360b57cec5SDimitry Andric "`EH vector copy ctor iterator'"); 3370b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter, 3380b57cec5SDimitry Andric "`EH vector vbase copy ctor iterator'"); 3390b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter, 3400b57cec5SDimitry Andric "`vector copy ctor iterator'"); 3410b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter, 3420b57cec5SDimitry Andric "`vector vbase copy constructor iterator'"); 3430b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter, 3440b57cec5SDimitry Andric "`managed vector vbase copy constructor iterator'"); 3450b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait, 3460b57cec5SDimitry Andric "operator co_await"); 3470b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>"); 3480b57cec5SDimitry Andric case IntrinsicFunctionKind::MaxIntrinsic: 3490b57cec5SDimitry Andric case IntrinsicFunctionKind::None: 3500b57cec5SDimitry Andric break; 3510b57cec5SDimitry Andric } 352349cc55cSDimitry Andric outputTemplateParameters(OB, Flags); 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric 355349cc55cSDimitry Andric void LocalStaticGuardIdentifierNode::output(OutputBuffer &OB, 3560b57cec5SDimitry Andric OutputFlags Flags) const { 3570b57cec5SDimitry Andric if (IsThread) 358349cc55cSDimitry Andric OB << "`local static thread guard'"; 3590b57cec5SDimitry Andric else 360349cc55cSDimitry Andric OB << "`local static guard'"; 3610b57cec5SDimitry Andric if (ScopeIndex > 0) 362349cc55cSDimitry Andric OB << "{" << ScopeIndex << "}"; 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 365349cc55cSDimitry Andric void ConversionOperatorIdentifierNode::output(OutputBuffer &OB, 3660b57cec5SDimitry Andric OutputFlags Flags) const { 367349cc55cSDimitry Andric OB << "operator"; 368349cc55cSDimitry Andric outputTemplateParameters(OB, Flags); 369349cc55cSDimitry Andric OB << " "; 370349cc55cSDimitry Andric TargetType->output(OB, Flags); 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric 373349cc55cSDimitry Andric void StructorIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const { 3740b57cec5SDimitry Andric if (IsDestructor) 375349cc55cSDimitry Andric OB << "~"; 376349cc55cSDimitry Andric Class->output(OB, Flags); 377349cc55cSDimitry Andric outputTemplateParameters(OB, Flags); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 380349cc55cSDimitry Andric void LiteralOperatorIdentifierNode::output(OutputBuffer &OB, 3810b57cec5SDimitry Andric OutputFlags Flags) const { 382349cc55cSDimitry Andric OB << "operator \"\"" << Name; 383349cc55cSDimitry Andric outputTemplateParameters(OB, Flags); 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric 386349cc55cSDimitry Andric void FunctionSignatureNode::outputPre(OutputBuffer &OB, 3870b57cec5SDimitry Andric OutputFlags Flags) const { 3888bcb0991SDimitry Andric if (!(Flags & OF_NoAccessSpecifier)) { 3890b57cec5SDimitry Andric if (FunctionClass & FC_Public) 390349cc55cSDimitry Andric OB << "public: "; 3910b57cec5SDimitry Andric if (FunctionClass & FC_Protected) 392349cc55cSDimitry Andric OB << "protected: "; 3930b57cec5SDimitry Andric if (FunctionClass & FC_Private) 394349cc55cSDimitry Andric OB << "private: "; 3958bcb0991SDimitry Andric } 3960b57cec5SDimitry Andric 3978bcb0991SDimitry Andric if (!(Flags & OF_NoMemberType)) { 3980b57cec5SDimitry Andric if (!(FunctionClass & FC_Global)) { 3990b57cec5SDimitry Andric if (FunctionClass & FC_Static) 400349cc55cSDimitry Andric OB << "static "; 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric if (FunctionClass & FC_Virtual) 403349cc55cSDimitry Andric OB << "virtual "; 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric if (FunctionClass & FC_ExternC) 406349cc55cSDimitry Andric OB << "extern \"C\" "; 4078bcb0991SDimitry Andric } 4080b57cec5SDimitry Andric 4098bcb0991SDimitry Andric if (!(Flags & OF_NoReturnType) && ReturnType) { 410349cc55cSDimitry Andric ReturnType->outputPre(OB, Flags); 411349cc55cSDimitry Andric OB << " "; 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric if (!(Flags & OF_NoCallingConvention)) 415349cc55cSDimitry Andric outputCallingConvention(OB, CallConvention); 4160b57cec5SDimitry Andric } 4170b57cec5SDimitry Andric 418349cc55cSDimitry Andric void FunctionSignatureNode::outputPost(OutputBuffer &OB, 4190b57cec5SDimitry Andric OutputFlags Flags) const { 4200b57cec5SDimitry Andric if (!(FunctionClass & FC_NoParameterList)) { 421349cc55cSDimitry Andric OB << "("; 4220b57cec5SDimitry Andric if (Params) 423349cc55cSDimitry Andric Params->output(OB, Flags); 4240b57cec5SDimitry Andric else 425349cc55cSDimitry Andric OB << "void"; 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric if (IsVariadic) { 428349cc55cSDimitry Andric if (OB.back() != '(') 429349cc55cSDimitry Andric OB << ", "; 430349cc55cSDimitry Andric OB << "..."; 4310b57cec5SDimitry Andric } 432349cc55cSDimitry Andric OB << ")"; 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric if (Quals & Q_Const) 436349cc55cSDimitry Andric OB << " const"; 4370b57cec5SDimitry Andric if (Quals & Q_Volatile) 438349cc55cSDimitry Andric OB << " volatile"; 4390b57cec5SDimitry Andric if (Quals & Q_Restrict) 440349cc55cSDimitry Andric OB << " __restrict"; 4410b57cec5SDimitry Andric if (Quals & Q_Unaligned) 442349cc55cSDimitry Andric OB << " __unaligned"; 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric if (IsNoexcept) 445349cc55cSDimitry Andric OB << " noexcept"; 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric if (RefQualifier == FunctionRefQualifier::Reference) 448349cc55cSDimitry Andric OB << " &"; 4490b57cec5SDimitry Andric else if (RefQualifier == FunctionRefQualifier::RValueReference) 450349cc55cSDimitry Andric OB << " &&"; 4510b57cec5SDimitry Andric 4528bcb0991SDimitry Andric if (!(Flags & OF_NoReturnType) && ReturnType) 453349cc55cSDimitry Andric ReturnType->outputPost(OB, Flags); 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric 456349cc55cSDimitry Andric void ThunkSignatureNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 457349cc55cSDimitry Andric OB << "[thunk]: "; 4580b57cec5SDimitry Andric 459349cc55cSDimitry Andric FunctionSignatureNode::outputPre(OB, Flags); 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric 462349cc55cSDimitry Andric void ThunkSignatureNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const { 4630b57cec5SDimitry Andric if (FunctionClass & FC_StaticThisAdjust) { 464349cc55cSDimitry Andric OB << "`adjustor{" << ThisAdjust.StaticOffset << "}'"; 4650b57cec5SDimitry Andric } else if (FunctionClass & FC_VirtualThisAdjust) { 4660b57cec5SDimitry Andric if (FunctionClass & FC_VirtualThisAdjustEx) { 467349cc55cSDimitry Andric OB << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", " 4680b57cec5SDimitry Andric << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset 4690b57cec5SDimitry Andric << ", " << ThisAdjust.StaticOffset << "}'"; 4700b57cec5SDimitry Andric } else { 471349cc55cSDimitry Andric OB << "`vtordisp{" << ThisAdjust.VtordispOffset << ", " 4720b57cec5SDimitry Andric << ThisAdjust.StaticOffset << "}'"; 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 476349cc55cSDimitry Andric FunctionSignatureNode::outputPost(OB, Flags); 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric 479349cc55cSDimitry Andric void PointerTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 4800b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::FunctionSignature) { 4810b57cec5SDimitry Andric // If this is a pointer to a function, don't output the calling convention. 4820b57cec5SDimitry Andric // It needs to go inside the parentheses. 4830b57cec5SDimitry Andric const FunctionSignatureNode *Sig = 4840b57cec5SDimitry Andric static_cast<const FunctionSignatureNode *>(Pointee); 485349cc55cSDimitry Andric Sig->outputPre(OB, OF_NoCallingConvention); 4860b57cec5SDimitry Andric } else 487349cc55cSDimitry Andric Pointee->outputPre(OB, Flags); 4880b57cec5SDimitry Andric 489349cc55cSDimitry Andric outputSpaceIfNecessary(OB); 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric if (Quals & Q_Unaligned) 492349cc55cSDimitry Andric OB << "__unaligned "; 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::ArrayType) { 495349cc55cSDimitry Andric OB << "("; 4960b57cec5SDimitry Andric } else if (Pointee->kind() == NodeKind::FunctionSignature) { 497349cc55cSDimitry Andric OB << "("; 4980b57cec5SDimitry Andric const FunctionSignatureNode *Sig = 4990b57cec5SDimitry Andric static_cast<const FunctionSignatureNode *>(Pointee); 500349cc55cSDimitry Andric outputCallingConvention(OB, Sig->CallConvention); 501349cc55cSDimitry Andric OB << " "; 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric if (ClassParent) { 505349cc55cSDimitry Andric ClassParent->output(OB, Flags); 506349cc55cSDimitry Andric OB << "::"; 5070b57cec5SDimitry Andric } 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric switch (Affinity) { 5100b57cec5SDimitry Andric case PointerAffinity::Pointer: 511349cc55cSDimitry Andric OB << "*"; 5120b57cec5SDimitry Andric break; 5130b57cec5SDimitry Andric case PointerAffinity::Reference: 514349cc55cSDimitry Andric OB << "&"; 5150b57cec5SDimitry Andric break; 5160b57cec5SDimitry Andric case PointerAffinity::RValueReference: 517349cc55cSDimitry Andric OB << "&&"; 5180b57cec5SDimitry Andric break; 5190b57cec5SDimitry Andric default: 5200b57cec5SDimitry Andric assert(false); 5210b57cec5SDimitry Andric } 522349cc55cSDimitry Andric outputQualifiers(OB, Quals, false, false); 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric 525349cc55cSDimitry Andric void PointerTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const { 5260b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::ArrayType || 5270b57cec5SDimitry Andric Pointee->kind() == NodeKind::FunctionSignature) 528349cc55cSDimitry Andric OB << ")"; 5290b57cec5SDimitry Andric 530349cc55cSDimitry Andric Pointee->outputPost(OB, Flags); 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric 533349cc55cSDimitry Andric void TagTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 5340b57cec5SDimitry Andric if (!(Flags & OF_NoTagSpecifier)) { 5350b57cec5SDimitry Andric switch (Tag) { 5360b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class"); 5370b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct"); 5380b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union"); 5390b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum"); 5400b57cec5SDimitry Andric } 541349cc55cSDimitry Andric OB << " "; 5420b57cec5SDimitry Andric } 543349cc55cSDimitry Andric QualifiedName->output(OB, Flags); 544349cc55cSDimitry Andric outputQualifiers(OB, Quals, true, false); 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 547349cc55cSDimitry Andric void TagTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {} 5480b57cec5SDimitry Andric 549349cc55cSDimitry Andric void ArrayTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 550349cc55cSDimitry Andric ElementType->outputPre(OB, Flags); 551349cc55cSDimitry Andric outputQualifiers(OB, Quals, true, false); 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric 554349cc55cSDimitry Andric void ArrayTypeNode::outputOneDimension(OutputBuffer &OB, OutputFlags Flags, 5550b57cec5SDimitry Andric Node *N) const { 5560b57cec5SDimitry Andric assert(N->kind() == NodeKind::IntegerLiteral); 5570b57cec5SDimitry Andric IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N); 5580b57cec5SDimitry Andric if (ILN->Value != 0) 559349cc55cSDimitry Andric ILN->output(OB, Flags); 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 562349cc55cSDimitry Andric void ArrayTypeNode::outputDimensionsImpl(OutputBuffer &OB, 5630b57cec5SDimitry Andric OutputFlags Flags) const { 5640b57cec5SDimitry Andric if (Dimensions->Count == 0) 5650b57cec5SDimitry Andric return; 5660b57cec5SDimitry Andric 567349cc55cSDimitry Andric outputOneDimension(OB, Flags, Dimensions->Nodes[0]); 5680b57cec5SDimitry Andric for (size_t I = 1; I < Dimensions->Count; ++I) { 569349cc55cSDimitry Andric OB << "]["; 570349cc55cSDimitry Andric outputOneDimension(OB, Flags, Dimensions->Nodes[I]); 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 574349cc55cSDimitry Andric void ArrayTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const { 575349cc55cSDimitry Andric OB << "["; 576349cc55cSDimitry Andric outputDimensionsImpl(OB, Flags); 577349cc55cSDimitry Andric OB << "]"; 5780b57cec5SDimitry Andric 579349cc55cSDimitry Andric ElementType->outputPost(OB, Flags); 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric 582349cc55cSDimitry Andric void SymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { 583349cc55cSDimitry Andric Name->output(OB, Flags); 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric 586349cc55cSDimitry Andric void FunctionSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { 587349cc55cSDimitry Andric Signature->outputPre(OB, Flags); 588349cc55cSDimitry Andric outputSpaceIfNecessary(OB); 589349cc55cSDimitry Andric Name->output(OB, Flags); 590349cc55cSDimitry Andric Signature->outputPost(OB, Flags); 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 593349cc55cSDimitry Andric void VariableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { 5948bcb0991SDimitry Andric const char *AccessSpec = nullptr; 5958bcb0991SDimitry Andric bool IsStatic = true; 5960b57cec5SDimitry Andric switch (SC) { 5970b57cec5SDimitry Andric case StorageClass::PrivateStatic: 5988bcb0991SDimitry Andric AccessSpec = "private"; 5990b57cec5SDimitry Andric break; 6000b57cec5SDimitry Andric case StorageClass::PublicStatic: 6018bcb0991SDimitry Andric AccessSpec = "public"; 6020b57cec5SDimitry Andric break; 6030b57cec5SDimitry Andric case StorageClass::ProtectedStatic: 6048bcb0991SDimitry Andric AccessSpec = "protected"; 6050b57cec5SDimitry Andric break; 6060b57cec5SDimitry Andric default: 6078bcb0991SDimitry Andric IsStatic = false; 6080b57cec5SDimitry Andric break; 6090b57cec5SDimitry Andric } 6108bcb0991SDimitry Andric if (!(Flags & OF_NoAccessSpecifier) && AccessSpec) 611349cc55cSDimitry Andric OB << AccessSpec << ": "; 6128bcb0991SDimitry Andric if (!(Flags & OF_NoMemberType) && IsStatic) 613349cc55cSDimitry Andric OB << "static "; 6140b57cec5SDimitry Andric 615349cc55cSDimitry Andric if (!(Flags & OF_NoVariableType) && Type) { 616349cc55cSDimitry Andric Type->outputPre(OB, Flags); 617349cc55cSDimitry Andric outputSpaceIfNecessary(OB); 6180b57cec5SDimitry Andric } 619349cc55cSDimitry Andric Name->output(OB, Flags); 620349cc55cSDimitry Andric if (!(Flags & OF_NoVariableType) && Type) 621349cc55cSDimitry Andric Type->outputPost(OB, Flags); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric 624349cc55cSDimitry Andric void CustomTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const { 625349cc55cSDimitry Andric Identifier->output(OB, Flags); 6260b57cec5SDimitry Andric } 627349cc55cSDimitry Andric void CustomTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {} 6280b57cec5SDimitry Andric 629349cc55cSDimitry Andric void QualifiedNameNode::output(OutputBuffer &OB, OutputFlags Flags) const { 630349cc55cSDimitry Andric Components->output(OB, Flags, "::"); 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric 633349cc55cSDimitry Andric void RttiBaseClassDescriptorNode::output(OutputBuffer &OB, 6340b57cec5SDimitry Andric OutputFlags Flags) const { 635349cc55cSDimitry Andric OB << "`RTTI Base Class Descriptor at ("; 636349cc55cSDimitry Andric OB << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", " 6370b57cec5SDimitry Andric << this->Flags; 638349cc55cSDimitry Andric OB << ")'"; 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric 641349cc55cSDimitry Andric void LocalStaticGuardVariableNode::output(OutputBuffer &OB, 6420b57cec5SDimitry Andric OutputFlags Flags) const { 643349cc55cSDimitry Andric Name->output(OB, Flags); 6440b57cec5SDimitry Andric } 6450b57cec5SDimitry Andric 646349cc55cSDimitry Andric void VcallThunkIdentifierNode::output(OutputBuffer &OB, 6470b57cec5SDimitry Andric OutputFlags Flags) const { 648349cc55cSDimitry Andric OB << "`vcall'{" << OffsetInVTable << ", {flat}}"; 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric 651349cc55cSDimitry Andric void SpecialTableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { 652349cc55cSDimitry Andric outputQualifiers(OB, Quals, false, true); 653349cc55cSDimitry Andric Name->output(OB, Flags); 6540b57cec5SDimitry Andric if (TargetName) { 655349cc55cSDimitry Andric OB << "{for `"; 656349cc55cSDimitry Andric TargetName->output(OB, Flags); 657349cc55cSDimitry Andric OB << "'}"; 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric } 660