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; 1100b57cec5SDimitry Andric default: 1110b57cec5SDimitry Andric break; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric std::string Node::toString(OutputFlags Flags) const { 1160b57cec5SDimitry Andric OutputStream OS; 1170b57cec5SDimitry Andric initializeOutputStream(nullptr, nullptr, OS, 1024); 1180b57cec5SDimitry Andric this->output(OS, Flags); 1190b57cec5SDimitry Andric OS << '\0'; 1200b57cec5SDimitry Andric return {OS.getBuffer()}; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 1240b57cec5SDimitry Andric switch (PrimKind) { 1250b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void"); 1260b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool"); 1270b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char"); 1280b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char"); 1290b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char"); 1300b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t"); 1310b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t"); 1320b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t"); 1330b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short"); 1340b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short"); 1350b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int"); 1360b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int"); 1370b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long"); 1380b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long"); 1390b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64"); 1400b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64"); 1410b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t"); 1420b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float"); 1430b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double"); 1440b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double"); 1450b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t"); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric outputQualifiers(OS, Quals, true, false); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags) const { 1510b57cec5SDimitry Andric output(OS, Flags, ", "); 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags, 1550b57cec5SDimitry Andric StringView Separator) const { 1560b57cec5SDimitry Andric if (Count == 0) 1570b57cec5SDimitry Andric return; 1580b57cec5SDimitry Andric if (Nodes[0]) 1590b57cec5SDimitry Andric Nodes[0]->output(OS, Flags); 1600b57cec5SDimitry Andric for (size_t I = 1; I < Count; ++I) { 1610b57cec5SDimitry Andric OS << Separator; 1620b57cec5SDimitry Andric Nodes[I]->output(OS, Flags); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric void EncodedStringLiteralNode::output(OutputStream &OS, 1670b57cec5SDimitry Andric OutputFlags Flags) const { 1680b57cec5SDimitry Andric switch (Char) { 1690b57cec5SDimitry Andric case CharKind::Wchar: 1700b57cec5SDimitry Andric OS << "L\""; 1710b57cec5SDimitry Andric break; 1720b57cec5SDimitry Andric case CharKind::Char: 1730b57cec5SDimitry Andric OS << "\""; 1740b57cec5SDimitry Andric break; 1750b57cec5SDimitry Andric case CharKind::Char16: 1760b57cec5SDimitry Andric OS << "u\""; 1770b57cec5SDimitry Andric break; 1780b57cec5SDimitry Andric case CharKind::Char32: 1790b57cec5SDimitry Andric OS << "U\""; 1800b57cec5SDimitry Andric break; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric OS << DecodedString << "\""; 1830b57cec5SDimitry Andric if (IsTruncated) 1840b57cec5SDimitry Andric OS << "..."; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric void IntegerLiteralNode::output(OutputStream &OS, OutputFlags Flags) const { 1880b57cec5SDimitry Andric if (IsNegative) 1890b57cec5SDimitry Andric OS << '-'; 1900b57cec5SDimitry Andric OS << Value; 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric void TemplateParameterReferenceNode::output(OutputStream &OS, 1940b57cec5SDimitry Andric OutputFlags Flags) const { 1950b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 1960b57cec5SDimitry Andric OS << "{"; 1970b57cec5SDimitry Andric else if (Affinity == PointerAffinity::Pointer) 1980b57cec5SDimitry Andric OS << "&"; 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric if (Symbol) { 2010b57cec5SDimitry Andric Symbol->output(OS, Flags); 2020b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 2030b57cec5SDimitry Andric OS << ", "; 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 2070b57cec5SDimitry Andric OS << ThunkOffsets[0]; 2080b57cec5SDimitry Andric for (int I = 1; I < ThunkOffsetCount; ++I) { 2090b57cec5SDimitry Andric OS << ", " << ThunkOffsets[I]; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric if (ThunkOffsetCount > 0) 2120b57cec5SDimitry Andric OS << "}"; 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric void IdentifierNode::outputTemplateParameters(OutputStream &OS, 2160b57cec5SDimitry Andric OutputFlags Flags) const { 2170b57cec5SDimitry Andric if (!TemplateParams) 2180b57cec5SDimitry Andric return; 2190b57cec5SDimitry Andric OS << "<"; 2200b57cec5SDimitry Andric TemplateParams->output(OS, Flags); 2210b57cec5SDimitry Andric OS << ">"; 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric void DynamicStructorIdentifierNode::output(OutputStream &OS, 2250b57cec5SDimitry Andric OutputFlags Flags) const { 2260b57cec5SDimitry Andric if (IsDestructor) 2270b57cec5SDimitry Andric OS << "`dynamic atexit destructor for "; 2280b57cec5SDimitry Andric else 2290b57cec5SDimitry Andric OS << "`dynamic initializer for "; 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric if (Variable) { 2320b57cec5SDimitry Andric OS << "`"; 2330b57cec5SDimitry Andric Variable->output(OS, Flags); 2340b57cec5SDimitry Andric OS << "''"; 2350b57cec5SDimitry Andric } else { 2360b57cec5SDimitry Andric OS << "'"; 2370b57cec5SDimitry Andric Name->output(OS, Flags); 2380b57cec5SDimitry Andric OS << "''"; 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric void NamedIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const { 2430b57cec5SDimitry Andric OS << Name; 2440b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric void IntrinsicFunctionIdentifierNode::output(OutputStream &OS, 2480b57cec5SDimitry Andric OutputFlags Flags) const { 2490b57cec5SDimitry Andric switch (Operator) { 2500b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new"); 2510b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete"); 2520b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator="); 2530b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>"); 2540b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<"); 2550b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!"); 2560b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator=="); 2570b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!="); 2580b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript, 2590b57cec5SDimitry Andric "operator[]"); 2600b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->"); 2610b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++"); 2620b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--"); 2630b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-"); 2640b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+"); 2650b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*"); 2660b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&"); 2670b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer, 2680b57cec5SDimitry Andric "operator->*"); 2690b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/"); 2700b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%"); 2710b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<"); 2720b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<="); 2730b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>"); 2740b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual, 2750b57cec5SDimitry Andric "operator>="); 2760b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,"); 2770b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()"); 2780b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~"); 2790b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^"); 2800b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|"); 2810b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&"); 2820b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||"); 2830b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*="); 2840b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+="); 2850b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-="); 2860b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/="); 2870b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%="); 2880b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>="); 2890b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<="); 2900b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual, 2910b57cec5SDimitry Andric "operator&="); 2920b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual, 2930b57cec5SDimitry Andric "operator|="); 2940b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual, 2950b57cec5SDimitry Andric "operator^="); 2960b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'"); 2970b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor, 2980b57cec5SDimitry Andric "`vector deleting dtor'"); 2990b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure, 3000b57cec5SDimitry Andric "`default ctor closure'"); 3010b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor, 3020b57cec5SDimitry Andric "`scalar deleting dtor'"); 3030b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter, 3040b57cec5SDimitry Andric "`vector ctor iterator'"); 3050b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter, 3060b57cec5SDimitry Andric "`vector dtor iterator'"); 3070b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter, 3080b57cec5SDimitry Andric "`vector vbase ctor iterator'"); 3090b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap, 3100b57cec5SDimitry Andric "`virtual displacement map'"); 3110b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter, 3120b57cec5SDimitry Andric "`eh vector ctor iterator'"); 3130b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter, 3140b57cec5SDimitry Andric "`eh vector dtor iterator'"); 3150b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter, 3160b57cec5SDimitry Andric "`eh vector vbase ctor iterator'"); 3170b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure, 3180b57cec5SDimitry Andric "`copy ctor closure'"); 3190b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure, 3200b57cec5SDimitry Andric "`local vftable ctor closure'"); 3210b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]"); 3220b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete, 3230b57cec5SDimitry Andric "operator delete[]"); 3240b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter, 3250b57cec5SDimitry Andric "`managed vector ctor iterator'"); 3260b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter, 3270b57cec5SDimitry Andric "`managed vector dtor iterator'"); 3280b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter, 3290b57cec5SDimitry Andric "`EH vector copy ctor iterator'"); 3300b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter, 3310b57cec5SDimitry Andric "`EH vector vbase copy ctor iterator'"); 3320b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter, 3330b57cec5SDimitry Andric "`vector copy ctor iterator'"); 3340b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter, 3350b57cec5SDimitry Andric "`vector vbase copy constructor iterator'"); 3360b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter, 3370b57cec5SDimitry Andric "`managed vector vbase copy constructor iterator'"); 3380b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait, 3390b57cec5SDimitry Andric "operator co_await"); 3400b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>"); 3410b57cec5SDimitry Andric case IntrinsicFunctionKind::MaxIntrinsic: 3420b57cec5SDimitry Andric case IntrinsicFunctionKind::None: 3430b57cec5SDimitry Andric break; 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric void LocalStaticGuardIdentifierNode::output(OutputStream &OS, 3490b57cec5SDimitry Andric OutputFlags Flags) const { 3500b57cec5SDimitry Andric if (IsThread) 3510b57cec5SDimitry Andric OS << "`local static thread guard'"; 3520b57cec5SDimitry Andric else 3530b57cec5SDimitry Andric OS << "`local static guard'"; 3540b57cec5SDimitry Andric if (ScopeIndex > 0) 3550b57cec5SDimitry Andric OS << "{" << ScopeIndex << "}"; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric void ConversionOperatorIdentifierNode::output(OutputStream &OS, 3590b57cec5SDimitry Andric OutputFlags Flags) const { 3600b57cec5SDimitry Andric OS << "operator"; 3610b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 3620b57cec5SDimitry Andric OS << " "; 3630b57cec5SDimitry Andric TargetType->output(OS, Flags); 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric void StructorIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const { 3670b57cec5SDimitry Andric if (IsDestructor) 3680b57cec5SDimitry Andric OS << "~"; 3690b57cec5SDimitry Andric Class->output(OS, Flags); 3700b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric void LiteralOperatorIdentifierNode::output(OutputStream &OS, 3740b57cec5SDimitry Andric OutputFlags Flags) const { 3750b57cec5SDimitry Andric OS << "operator \"\"" << Name; 3760b57cec5SDimitry Andric outputTemplateParameters(OS, Flags); 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric void FunctionSignatureNode::outputPre(OutputStream &OS, 3800b57cec5SDimitry Andric OutputFlags Flags) const { 381*8bcb0991SDimitry Andric if (!(Flags & OF_NoAccessSpecifier)) { 3820b57cec5SDimitry Andric if (FunctionClass & FC_Public) 3830b57cec5SDimitry Andric OS << "public: "; 3840b57cec5SDimitry Andric if (FunctionClass & FC_Protected) 3850b57cec5SDimitry Andric OS << "protected: "; 3860b57cec5SDimitry Andric if (FunctionClass & FC_Private) 3870b57cec5SDimitry Andric OS << "private: "; 388*8bcb0991SDimitry Andric } 3890b57cec5SDimitry Andric 390*8bcb0991SDimitry Andric if (!(Flags & OF_NoMemberType)) { 3910b57cec5SDimitry Andric if (!(FunctionClass & FC_Global)) { 3920b57cec5SDimitry Andric if (FunctionClass & FC_Static) 3930b57cec5SDimitry Andric OS << "static "; 3940b57cec5SDimitry Andric } 3950b57cec5SDimitry Andric if (FunctionClass & FC_Virtual) 3960b57cec5SDimitry Andric OS << "virtual "; 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric if (FunctionClass & FC_ExternC) 3990b57cec5SDimitry Andric OS << "extern \"C\" "; 400*8bcb0991SDimitry Andric } 4010b57cec5SDimitry Andric 402*8bcb0991SDimitry Andric if (!(Flags & OF_NoReturnType) && ReturnType) { 4030b57cec5SDimitry Andric ReturnType->outputPre(OS, Flags); 4040b57cec5SDimitry Andric OS << " "; 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric if (!(Flags & OF_NoCallingConvention)) 4080b57cec5SDimitry Andric outputCallingConvention(OS, CallConvention); 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric void FunctionSignatureNode::outputPost(OutputStream &OS, 4120b57cec5SDimitry Andric OutputFlags Flags) const { 4130b57cec5SDimitry Andric if (!(FunctionClass & FC_NoParameterList)) { 4140b57cec5SDimitry Andric OS << "("; 4150b57cec5SDimitry Andric if (Params) 4160b57cec5SDimitry Andric Params->output(OS, Flags); 4170b57cec5SDimitry Andric else 4180b57cec5SDimitry Andric OS << "void"; 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric if (IsVariadic) { 4210b57cec5SDimitry Andric if (OS.back() != '(') 4220b57cec5SDimitry Andric OS << ", "; 4230b57cec5SDimitry Andric OS << "..."; 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric OS << ")"; 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric if (Quals & Q_Const) 4290b57cec5SDimitry Andric OS << " const"; 4300b57cec5SDimitry Andric if (Quals & Q_Volatile) 4310b57cec5SDimitry Andric OS << " volatile"; 4320b57cec5SDimitry Andric if (Quals & Q_Restrict) 4330b57cec5SDimitry Andric OS << " __restrict"; 4340b57cec5SDimitry Andric if (Quals & Q_Unaligned) 4350b57cec5SDimitry Andric OS << " __unaligned"; 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric if (IsNoexcept) 4380b57cec5SDimitry Andric OS << " noexcept"; 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric if (RefQualifier == FunctionRefQualifier::Reference) 4410b57cec5SDimitry Andric OS << " &"; 4420b57cec5SDimitry Andric else if (RefQualifier == FunctionRefQualifier::RValueReference) 4430b57cec5SDimitry Andric OS << " &&"; 4440b57cec5SDimitry Andric 445*8bcb0991SDimitry Andric if (!(Flags & OF_NoReturnType) && ReturnType) 4460b57cec5SDimitry Andric ReturnType->outputPost(OS, Flags); 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric void ThunkSignatureNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 4500b57cec5SDimitry Andric OS << "[thunk]: "; 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric FunctionSignatureNode::outputPre(OS, Flags); 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric void ThunkSignatureNode::outputPost(OutputStream &OS, OutputFlags Flags) const { 4560b57cec5SDimitry Andric if (FunctionClass & FC_StaticThisAdjust) { 4570b57cec5SDimitry Andric OS << "`adjustor{" << ThisAdjust.StaticOffset << "}'"; 4580b57cec5SDimitry Andric } else if (FunctionClass & FC_VirtualThisAdjust) { 4590b57cec5SDimitry Andric if (FunctionClass & FC_VirtualThisAdjustEx) { 4600b57cec5SDimitry Andric OS << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", " 4610b57cec5SDimitry Andric << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset 4620b57cec5SDimitry Andric << ", " << ThisAdjust.StaticOffset << "}'"; 4630b57cec5SDimitry Andric } else { 4640b57cec5SDimitry Andric OS << "`vtordisp{" << ThisAdjust.VtordispOffset << ", " 4650b57cec5SDimitry Andric << ThisAdjust.StaticOffset << "}'"; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric FunctionSignatureNode::outputPost(OS, Flags); 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric void PointerTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 4730b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::FunctionSignature) { 4740b57cec5SDimitry Andric // If this is a pointer to a function, don't output the calling convention. 4750b57cec5SDimitry Andric // It needs to go inside the parentheses. 4760b57cec5SDimitry Andric const FunctionSignatureNode *Sig = 4770b57cec5SDimitry Andric static_cast<const FunctionSignatureNode *>(Pointee); 4780b57cec5SDimitry Andric Sig->outputPre(OS, OF_NoCallingConvention); 4790b57cec5SDimitry Andric } else 4800b57cec5SDimitry Andric Pointee->outputPre(OS, Flags); 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric outputSpaceIfNecessary(OS); 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric if (Quals & Q_Unaligned) 4850b57cec5SDimitry Andric OS << "__unaligned "; 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::ArrayType) { 4880b57cec5SDimitry Andric OS << "("; 4890b57cec5SDimitry Andric } else if (Pointee->kind() == NodeKind::FunctionSignature) { 4900b57cec5SDimitry Andric OS << "("; 4910b57cec5SDimitry Andric const FunctionSignatureNode *Sig = 4920b57cec5SDimitry Andric static_cast<const FunctionSignatureNode *>(Pointee); 4930b57cec5SDimitry Andric outputCallingConvention(OS, Sig->CallConvention); 4940b57cec5SDimitry Andric OS << " "; 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric if (ClassParent) { 4980b57cec5SDimitry Andric ClassParent->output(OS, Flags); 4990b57cec5SDimitry Andric OS << "::"; 5000b57cec5SDimitry Andric } 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric switch (Affinity) { 5030b57cec5SDimitry Andric case PointerAffinity::Pointer: 5040b57cec5SDimitry Andric OS << "*"; 5050b57cec5SDimitry Andric break; 5060b57cec5SDimitry Andric case PointerAffinity::Reference: 5070b57cec5SDimitry Andric OS << "&"; 5080b57cec5SDimitry Andric break; 5090b57cec5SDimitry Andric case PointerAffinity::RValueReference: 5100b57cec5SDimitry Andric OS << "&&"; 5110b57cec5SDimitry Andric break; 5120b57cec5SDimitry Andric default: 5130b57cec5SDimitry Andric assert(false); 5140b57cec5SDimitry Andric } 5150b57cec5SDimitry Andric outputQualifiers(OS, Quals, false, false); 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric void PointerTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const { 5190b57cec5SDimitry Andric if (Pointee->kind() == NodeKind::ArrayType || 5200b57cec5SDimitry Andric Pointee->kind() == NodeKind::FunctionSignature) 5210b57cec5SDimitry Andric OS << ")"; 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric Pointee->outputPost(OS, Flags); 5240b57cec5SDimitry Andric } 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric void TagTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 5270b57cec5SDimitry Andric if (!(Flags & OF_NoTagSpecifier)) { 5280b57cec5SDimitry Andric switch (Tag) { 5290b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class"); 5300b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct"); 5310b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union"); 5320b57cec5SDimitry Andric OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum"); 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric OS << " "; 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric QualifiedName->output(OS, Flags); 5370b57cec5SDimitry Andric outputQualifiers(OS, Quals, true, false); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric void TagTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {} 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric void ArrayTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 5430b57cec5SDimitry Andric ElementType->outputPre(OS, Flags); 5440b57cec5SDimitry Andric outputQualifiers(OS, Quals, true, false); 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric void ArrayTypeNode::outputOneDimension(OutputStream &OS, OutputFlags Flags, 5480b57cec5SDimitry Andric Node *N) const { 5490b57cec5SDimitry Andric assert(N->kind() == NodeKind::IntegerLiteral); 5500b57cec5SDimitry Andric IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N); 5510b57cec5SDimitry Andric if (ILN->Value != 0) 5520b57cec5SDimitry Andric ILN->output(OS, Flags); 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric void ArrayTypeNode::outputDimensionsImpl(OutputStream &OS, 5560b57cec5SDimitry Andric OutputFlags Flags) const { 5570b57cec5SDimitry Andric if (Dimensions->Count == 0) 5580b57cec5SDimitry Andric return; 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric outputOneDimension(OS, Flags, Dimensions->Nodes[0]); 5610b57cec5SDimitry Andric for (size_t I = 1; I < Dimensions->Count; ++I) { 5620b57cec5SDimitry Andric OS << "]["; 5630b57cec5SDimitry Andric outputOneDimension(OS, Flags, Dimensions->Nodes[I]); 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric void ArrayTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const { 5680b57cec5SDimitry Andric OS << "["; 5690b57cec5SDimitry Andric outputDimensionsImpl(OS, Flags); 5700b57cec5SDimitry Andric OS << "]"; 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric ElementType->outputPost(OS, Flags); 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric void SymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 5760b57cec5SDimitry Andric Name->output(OS, Flags); 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric void FunctionSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 5800b57cec5SDimitry Andric Signature->outputPre(OS, Flags); 5810b57cec5SDimitry Andric outputSpaceIfNecessary(OS); 5820b57cec5SDimitry Andric Name->output(OS, Flags); 5830b57cec5SDimitry Andric Signature->outputPost(OS, Flags); 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 587*8bcb0991SDimitry Andric const char *AccessSpec = nullptr; 588*8bcb0991SDimitry Andric bool IsStatic = true; 5890b57cec5SDimitry Andric switch (SC) { 5900b57cec5SDimitry Andric case StorageClass::PrivateStatic: 591*8bcb0991SDimitry Andric AccessSpec = "private"; 5920b57cec5SDimitry Andric break; 5930b57cec5SDimitry Andric case StorageClass::PublicStatic: 594*8bcb0991SDimitry Andric AccessSpec = "public"; 5950b57cec5SDimitry Andric break; 5960b57cec5SDimitry Andric case StorageClass::ProtectedStatic: 597*8bcb0991SDimitry Andric AccessSpec = "protected"; 5980b57cec5SDimitry Andric break; 5990b57cec5SDimitry Andric default: 600*8bcb0991SDimitry Andric IsStatic = false; 6010b57cec5SDimitry Andric break; 6020b57cec5SDimitry Andric } 603*8bcb0991SDimitry Andric if (!(Flags & OF_NoAccessSpecifier) && AccessSpec) 604*8bcb0991SDimitry Andric OS << AccessSpec << ": "; 605*8bcb0991SDimitry Andric if (!(Flags & OF_NoMemberType) && IsStatic) 606*8bcb0991SDimitry Andric OS << "static "; 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric if (Type) { 6090b57cec5SDimitry Andric Type->outputPre(OS, Flags); 6100b57cec5SDimitry Andric outputSpaceIfNecessary(OS); 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric Name->output(OS, Flags); 6130b57cec5SDimitry Andric if (Type) 6140b57cec5SDimitry Andric Type->outputPost(OS, Flags); 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { 6180b57cec5SDimitry Andric Identifier->output(OS, Flags); 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {} 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const { 6230b57cec5SDimitry Andric Components->output(OS, Flags, "::"); 6240b57cec5SDimitry Andric } 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric void RttiBaseClassDescriptorNode::output(OutputStream &OS, 6270b57cec5SDimitry Andric OutputFlags Flags) const { 6280b57cec5SDimitry Andric OS << "`RTTI Base Class Descriptor at ("; 6290b57cec5SDimitry Andric OS << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", " 6300b57cec5SDimitry Andric << this->Flags; 6310b57cec5SDimitry Andric OS << ")'"; 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric void LocalStaticGuardVariableNode::output(OutputStream &OS, 6350b57cec5SDimitry Andric OutputFlags Flags) const { 6360b57cec5SDimitry Andric Name->output(OS, Flags); 6370b57cec5SDimitry Andric } 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric void VcallThunkIdentifierNode::output(OutputStream &OS, 6400b57cec5SDimitry Andric OutputFlags Flags) const { 6410b57cec5SDimitry Andric OS << "`vcall'{" << OffsetInVTable << ", {flat}}"; 6420b57cec5SDimitry Andric } 6430b57cec5SDimitry Andric 6440b57cec5SDimitry Andric void SpecialTableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { 6450b57cec5SDimitry Andric outputQualifiers(OS, Quals, false, true); 6460b57cec5SDimitry Andric Name->output(OS, Flags); 6470b57cec5SDimitry Andric if (TargetName) { 6480b57cec5SDimitry Andric OS << "{for `"; 6490b57cec5SDimitry Andric TargetName->output(OS, Flags); 6500b57cec5SDimitry Andric OS << "'}"; 6510b57cec5SDimitry Andric } 6520b57cec5SDimitry Andric return; 6530b57cec5SDimitry Andric } 654