xref: /llvm-project/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp (revision 8280651ad57cb9fb24a404cec2401040c28dec98)
103312863SZachary Turner //===- MicrosoftDemangle.cpp ----------------------------------------------===//
203312863SZachary Turner //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
603312863SZachary Turner //
703312863SZachary Turner //===----------------------------------------------------------------------===//
803312863SZachary Turner //
903312863SZachary Turner // This file defines a demangler for MSVC-style mangled symbols.
1003312863SZachary Turner //
1103312863SZachary Turner //===----------------------------------------------------------------------===//
1203312863SZachary Turner 
137ba90563SZachary Turner #include "llvm/Demangle/MicrosoftDemangleNodes.h"
1403312863SZachary Turner #include "llvm/Demangle/Utility.h"
15be4a5494SChandler Carruth #include <cctype>
161b9a938bSZachary Turner #include <string>
1703312863SZachary Turner 
1803312863SZachary Turner using namespace llvm;
1903312863SZachary Turner using namespace ms_demangle;
2003312863SZachary Turner 
2103312863SZachary Turner #define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc)                             \
2203312863SZachary Turner   case Enum::Value:                                                            \
232e97236aSLuís Ferreira     OB << Desc;                                                                \
2403312863SZachary Turner     break;
2503312863SZachary Turner 
2603312863SZachary Turner // Writes a space if the last token does not end with a punctuation.
272e97236aSLuís Ferreira static void outputSpaceIfNecessary(OutputBuffer &OB) {
282e97236aSLuís Ferreira   if (OB.empty())
2903312863SZachary Turner     return;
3003312863SZachary Turner 
312e97236aSLuís Ferreira   char C = OB.back();
32be4a5494SChandler Carruth   if (std::isalnum(C) || C == '>')
332e97236aSLuís Ferreira     OB << " ";
3403312863SZachary Turner }
3503312863SZachary Turner 
362e97236aSLuís Ferreira static void outputSingleQualifier(OutputBuffer &OB, Qualifiers Q) {
3703312863SZachary Turner   switch (Q) {
3803312863SZachary Turner   case Q_Const:
392e97236aSLuís Ferreira     OB << "const";
40880d21d3SNico Weber     break;
4103312863SZachary Turner   case Q_Volatile:
422e97236aSLuís Ferreira     OB << "volatile";
43880d21d3SNico Weber     break;
4403312863SZachary Turner   case Q_Restrict:
452e97236aSLuís Ferreira     OB << "__restrict";
46880d21d3SNico Weber     break;
4703312863SZachary Turner   default:
4803312863SZachary Turner     break;
4903312863SZachary Turner   }
5003312863SZachary Turner }
5103312863SZachary Turner 
522e97236aSLuís Ferreira static bool outputQualifierIfPresent(OutputBuffer &OB, Qualifiers Q,
5303312863SZachary Turner                                      Qualifiers Mask, bool NeedSpace) {
5403312863SZachary Turner   if (!(Q & Mask))
5503312863SZachary Turner     return NeedSpace;
5603312863SZachary Turner 
5703312863SZachary Turner   if (NeedSpace)
582e97236aSLuís Ferreira     OB << " ";
5903312863SZachary Turner 
602e97236aSLuís Ferreira   outputSingleQualifier(OB, Mask);
6103312863SZachary Turner   return true;
6203312863SZachary Turner }
6303312863SZachary Turner 
642e97236aSLuís Ferreira static void outputQualifiers(OutputBuffer &OB, Qualifiers Q, bool SpaceBefore,
6503312863SZachary Turner                              bool SpaceAfter) {
6603312863SZachary Turner   if (Q == Q_None)
6703312863SZachary Turner     return;
6803312863SZachary Turner 
692e97236aSLuís Ferreira   size_t Pos1 = OB.getCurrentPosition();
702e97236aSLuís Ferreira   SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Const, SpaceBefore);
712e97236aSLuís Ferreira   SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Volatile, SpaceBefore);
722e97236aSLuís Ferreira   SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Restrict, SpaceBefore);
732e97236aSLuís Ferreira   size_t Pos2 = OB.getCurrentPosition();
7403312863SZachary Turner   if (SpaceAfter && Pos2 > Pos1)
752e97236aSLuís Ferreira     OB << " ";
7603312863SZachary Turner }
7703312863SZachary Turner 
782e97236aSLuís Ferreira static void outputCallingConvention(OutputBuffer &OB, CallingConv CC) {
792e97236aSLuís Ferreira   outputSpaceIfNecessary(OB);
8003312863SZachary Turner 
8103312863SZachary Turner   switch (CC) {
8203312863SZachary Turner   case CallingConv::Cdecl:
832e97236aSLuís Ferreira     OB << "__cdecl";
8403312863SZachary Turner     break;
8503312863SZachary Turner   case CallingConv::Fastcall:
862e97236aSLuís Ferreira     OB << "__fastcall";
8703312863SZachary Turner     break;
8803312863SZachary Turner   case CallingConv::Pascal:
892e97236aSLuís Ferreira     OB << "__pascal";
9003312863SZachary Turner     break;
9103312863SZachary Turner   case CallingConv::Regcall:
922e97236aSLuís Ferreira     OB << "__regcall";
9303312863SZachary Turner     break;
9403312863SZachary Turner   case CallingConv::Stdcall:
952e97236aSLuís Ferreira     OB << "__stdcall";
9603312863SZachary Turner     break;
9703312863SZachary Turner   case CallingConv::Thiscall:
982e97236aSLuís Ferreira     OB << "__thiscall";
9903312863SZachary Turner     break;
10003312863SZachary Turner   case CallingConv::Eabi:
1012e97236aSLuís Ferreira     OB << "__eabi";
10203312863SZachary Turner     break;
10303312863SZachary Turner   case CallingConv::Vectorcall:
1042e97236aSLuís Ferreira     OB << "__vectorcall";
10503312863SZachary Turner     break;
10603312863SZachary Turner   case CallingConv::Clrcall:
1072e97236aSLuís Ferreira     OB << "__clrcall";
10803312863SZachary Turner     break;
10944f79296SVarun Gandhi   case CallingConv::Swift:
1102e97236aSLuís Ferreira     OB << "__attribute__((__swiftcall__)) ";
11144f79296SVarun Gandhi     break;
11292dcb1d2SVarun Gandhi   case CallingConv::SwiftAsync:
1132e97236aSLuís Ferreira     OB << "__attribute__((__swiftasynccall__)) ";
11492dcb1d2SVarun Gandhi     break;
11503312863SZachary Turner   default:
11603312863SZachary Turner     break;
11703312863SZachary Turner   }
11803312863SZachary Turner }
11903312863SZachary Turner 
120ba797b6dSZachary Turner std::string Node::toString(OutputFlags Flags) const {
1212e97236aSLuís Ferreira   OutputBuffer OB;
1222e97236aSLuís Ferreira   this->output(OB, Flags);
1237c59e800SNick Desaulniers   std::string_view SV = OB;
1241066e397SNathan Sidwell   std::string Owned(SV.begin(), SV.end());
1252e97236aSLuís Ferreira   std::free(OB.getBuffer());
126ae209aa9SRaphael Isemann   return Owned;
127b472512aSZachary Turner }
128b472512aSZachary Turner 
1292e97236aSLuís Ferreira void PrimitiveTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
13003312863SZachary Turner   switch (PrimKind) {
13103312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void");
13203312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool");
13303312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char");
13403312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char");
13503312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");
136a2ca6e78SNico Weber     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t");
13703312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t");
13803312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t");
13903312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short");
14003312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short");
14103312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int");
14203312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int");
14303312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long");
14403312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long");
14503312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64");
14603312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64");
14703312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t");
14803312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float");
14903312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double");
15003312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double");
15103312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");
152*8280651aSMax Winkler     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Auto, "auto");
153*8280651aSMax Winkler     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, DecltypeAuto, "decltype(auto)");
15403312863SZachary Turner   }
1552e97236aSLuís Ferreira   outputQualifiers(OB, Quals, true, false);
15603312863SZachary Turner }
15703312863SZachary Turner 
1582e97236aSLuís Ferreira void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags) const {
1592e97236aSLuís Ferreira   output(OB, Flags, ", ");
16038d2edd6SZachary Turner }
16103312863SZachary Turner 
1622e97236aSLuís Ferreira void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags,
1637c59e800SNick Desaulniers                            std::string_view Separator) const {
16403312863SZachary Turner   if (Count == 0)
16503312863SZachary Turner     return;
16603312863SZachary Turner   if (Nodes[0])
1672e97236aSLuís Ferreira     Nodes[0]->output(OB, Flags);
16803312863SZachary Turner   for (size_t I = 1; I < Count; ++I) {
1692e97236aSLuís Ferreira     OB << Separator;
1702e97236aSLuís Ferreira     Nodes[I]->output(OB, Flags);
17103312863SZachary Turner   }
17203312863SZachary Turner }
17303312863SZachary Turner 
1742e97236aSLuís Ferreira void EncodedStringLiteralNode::output(OutputBuffer &OB,
17538d2edd6SZachary Turner                                       OutputFlags Flags) const {
17603312863SZachary Turner   switch (Char) {
17703312863SZachary Turner   case CharKind::Wchar:
1782e97236aSLuís Ferreira     OB << "L\"";
17903312863SZachary Turner     break;
18003312863SZachary Turner   case CharKind::Char:
1812e97236aSLuís Ferreira     OB << "\"";
18203312863SZachary Turner     break;
18303312863SZachary Turner   case CharKind::Char16:
1842e97236aSLuís Ferreira     OB << "u\"";
18503312863SZachary Turner     break;
18603312863SZachary Turner   case CharKind::Char32:
1872e97236aSLuís Ferreira     OB << "U\"";
18803312863SZachary Turner     break;
18903312863SZachary Turner   }
1902e97236aSLuís Ferreira   OB << DecodedString << "\"";
19103312863SZachary Turner   if (IsTruncated)
1922e97236aSLuís Ferreira     OB << "...";
19303312863SZachary Turner }
19403312863SZachary Turner 
1952e97236aSLuís Ferreira void IntegerLiteralNode::output(OutputBuffer &OB, OutputFlags Flags) const {
19603312863SZachary Turner   if (IsNegative)
1972e97236aSLuís Ferreira     OB << '-';
1982e97236aSLuís Ferreira   OB << Value;
19903312863SZachary Turner }
20003312863SZachary Turner 
2012e97236aSLuís Ferreira void TemplateParameterReferenceNode::output(OutputBuffer &OB,
20238d2edd6SZachary Turner                                             OutputFlags Flags) const {
20303312863SZachary Turner   if (ThunkOffsetCount > 0)
2042e97236aSLuís Ferreira     OB << "{";
20503312863SZachary Turner   else if (Affinity == PointerAffinity::Pointer)
2062e97236aSLuís Ferreira     OB << "&";
20703312863SZachary Turner 
20803312863SZachary Turner   if (Symbol) {
2092e97236aSLuís Ferreira     Symbol->output(OB, Flags);
21003312863SZachary Turner     if (ThunkOffsetCount > 0)
2112e97236aSLuís Ferreira       OB << ", ";
21203312863SZachary Turner   }
21303312863SZachary Turner 
21403312863SZachary Turner   if (ThunkOffsetCount > 0)
2152e97236aSLuís Ferreira     OB << ThunkOffsets[0];
21603312863SZachary Turner   for (int I = 1; I < ThunkOffsetCount; ++I) {
2172e97236aSLuís Ferreira     OB << ", " << ThunkOffsets[I];
21803312863SZachary Turner   }
21903312863SZachary Turner   if (ThunkOffsetCount > 0)
2202e97236aSLuís Ferreira     OB << "}";
22103312863SZachary Turner }
22203312863SZachary Turner 
2232e97236aSLuís Ferreira void IdentifierNode::outputTemplateParameters(OutputBuffer &OB,
22438d2edd6SZachary Turner                                               OutputFlags Flags) const {
22503312863SZachary Turner   if (!TemplateParams)
22603312863SZachary Turner     return;
2272e97236aSLuís Ferreira   OB << "<";
2282e97236aSLuís Ferreira   TemplateParams->output(OB, Flags);
2292e97236aSLuís Ferreira   OB << ">";
23003312863SZachary Turner }
23103312863SZachary Turner 
2322e97236aSLuís Ferreira void DynamicStructorIdentifierNode::output(OutputBuffer &OB,
23338d2edd6SZachary Turner                                            OutputFlags Flags) const {
23403312863SZachary Turner   if (IsDestructor)
2352e97236aSLuís Ferreira     OB << "`dynamic atexit destructor for ";
23603312863SZachary Turner   else
2372e97236aSLuís Ferreira     OB << "`dynamic initializer for ";
23803312863SZachary Turner 
23932a8a202SZachary Turner   if (Variable) {
2402e97236aSLuís Ferreira     OB << "`";
2412e97236aSLuís Ferreira     Variable->output(OB, Flags);
2422e97236aSLuís Ferreira     OB << "''";
24332a8a202SZachary Turner   } else {
2442e97236aSLuís Ferreira     OB << "'";
2452e97236aSLuís Ferreira     Name->output(OB, Flags);
2462e97236aSLuís Ferreira     OB << "''";
24703312863SZachary Turner   }
24832a8a202SZachary Turner }
24903312863SZachary Turner 
2502e97236aSLuís Ferreira void NamedIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {
2512e97236aSLuís Ferreira   OB << Name;
2522e97236aSLuís Ferreira   outputTemplateParameters(OB, Flags);
25303312863SZachary Turner }
25403312863SZachary Turner 
2552e97236aSLuís Ferreira void IntrinsicFunctionIdentifierNode::output(OutputBuffer &OB,
25638d2edd6SZachary Turner                                              OutputFlags Flags) const {
25703312863SZachary Turner   switch (Operator) {
25803312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new");
25903312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete");
26003312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator=");
26103312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>");
26203312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<");
26303312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!");
26403312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator==");
26503312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!=");
26603312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript,
26703312863SZachary Turner                             "operator[]");
26803312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->");
26903312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++");
27003312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--");
27103312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-");
27203312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+");
27303312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*");
27403312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&");
27503312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer,
27603312863SZachary Turner                             "operator->*");
27703312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/");
27803312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%");
27903312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<");
28003312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<=");
28103312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>");
28203312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual,
28303312863SZachary Turner                             "operator>=");
28403312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,");
28503312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()");
28603312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~");
28703312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^");
28803312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|");
28903312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&");
29003312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||");
29103312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*=");
29203312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+=");
29303312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-=");
29403312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/=");
29503312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%=");
29603312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>=");
29703312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<=");
29803312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual,
29903312863SZachary Turner                             "operator&=");
30003312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual,
30103312863SZachary Turner                             "operator|=");
30203312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual,
30303312863SZachary Turner                             "operator^=");
30403312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'");
30503312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor,
30603312863SZachary Turner                             "`vector deleting dtor'");
30703312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure,
30803312863SZachary Turner                             "`default ctor closure'");
30903312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor,
31003312863SZachary Turner                             "`scalar deleting dtor'");
31103312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter,
31203312863SZachary Turner                             "`vector ctor iterator'");
31303312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter,
31403312863SZachary Turner                             "`vector dtor iterator'");
31503312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter,
31603312863SZachary Turner                             "`vector vbase ctor iterator'");
31703312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap,
31803312863SZachary Turner                             "`virtual displacement map'");
31903312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter,
32003312863SZachary Turner                             "`eh vector ctor iterator'");
32103312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter,
32203312863SZachary Turner                             "`eh vector dtor iterator'");
32303312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter,
32403312863SZachary Turner                             "`eh vector vbase ctor iterator'");
32503312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure,
32603312863SZachary Turner                             "`copy ctor closure'");
32703312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure,
32803312863SZachary Turner                             "`local vftable ctor closure'");
32903312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]");
33003312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete,
33103312863SZachary Turner                             "operator delete[]");
33203312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter,
33303312863SZachary Turner                             "`managed vector ctor iterator'");
33403312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter,
33503312863SZachary Turner                             "`managed vector dtor iterator'");
33603312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter,
33703312863SZachary Turner                             "`EH vector copy ctor iterator'");
33803312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter,
33903312863SZachary Turner                             "`EH vector vbase copy ctor iterator'");
34003312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter,
34103312863SZachary Turner                             "`vector copy ctor iterator'");
34203312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter,
34303312863SZachary Turner                             "`vector vbase copy constructor iterator'");
34403312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter,
34503312863SZachary Turner                             "`managed vector vbase copy constructor iterator'");
346e8f21b1aSNico Weber     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait,
347e8f21b1aSNico Weber                             "operator co_await");
34803312863SZachary Turner     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>");
34903312863SZachary Turner   case IntrinsicFunctionKind::MaxIntrinsic:
35003312863SZachary Turner   case IntrinsicFunctionKind::None:
35103312863SZachary Turner     break;
35203312863SZachary Turner   }
3532e97236aSLuís Ferreira   outputTemplateParameters(OB, Flags);
35403312863SZachary Turner }
35503312863SZachary Turner 
3562e97236aSLuís Ferreira void LocalStaticGuardIdentifierNode::output(OutputBuffer &OB,
35738d2edd6SZachary Turner                                             OutputFlags Flags) const {
35888ab281bSNico Weber   if (IsThread)
3592e97236aSLuís Ferreira     OB << "`local static thread guard'";
36088ab281bSNico Weber   else
3612e97236aSLuís Ferreira     OB << "`local static guard'";
36203312863SZachary Turner   if (ScopeIndex > 0)
3632e97236aSLuís Ferreira     OB << "{" << ScopeIndex << "}";
36403312863SZachary Turner }
36503312863SZachary Turner 
3662e97236aSLuís Ferreira void ConversionOperatorIdentifierNode::output(OutputBuffer &OB,
36738d2edd6SZachary Turner                                               OutputFlags Flags) const {
3682e97236aSLuís Ferreira   OB << "operator";
3692e97236aSLuís Ferreira   outputTemplateParameters(OB, Flags);
3702e97236aSLuís Ferreira   OB << " ";
3712e97236aSLuís Ferreira   TargetType->output(OB, Flags);
37203312863SZachary Turner }
37303312863SZachary Turner 
3742e97236aSLuís Ferreira void StructorIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {
37503312863SZachary Turner   if (IsDestructor)
3762e97236aSLuís Ferreira     OB << "~";
3772e97236aSLuís Ferreira   Class->output(OB, Flags);
3782e97236aSLuís Ferreira   outputTemplateParameters(OB, Flags);
37903312863SZachary Turner }
38003312863SZachary Turner 
3812e97236aSLuís Ferreira void LiteralOperatorIdentifierNode::output(OutputBuffer &OB,
38238d2edd6SZachary Turner                                            OutputFlags Flags) const {
3832e97236aSLuís Ferreira   OB << "operator \"\"" << Name;
3842e97236aSLuís Ferreira   outputTemplateParameters(OB, Flags);
38503312863SZachary Turner }
38603312863SZachary Turner 
3872e97236aSLuís Ferreira void FunctionSignatureNode::outputPre(OutputBuffer &OB,
38838d2edd6SZachary Turner                                       OutputFlags Flags) const {
389da92ed83SMartin Storsjo   if (!(Flags & OF_NoAccessSpecifier)) {
390a92b4639SNico Weber     if (FunctionClass & FC_Public)
3912e97236aSLuís Ferreira       OB << "public: ";
392a92b4639SNico Weber     if (FunctionClass & FC_Protected)
3932e97236aSLuís Ferreira       OB << "protected: ";
394a92b4639SNico Weber     if (FunctionClass & FC_Private)
3952e97236aSLuís Ferreira       OB << "private: ";
396da92ed83SMartin Storsjo   }
397a92b4639SNico Weber 
398da92ed83SMartin Storsjo   if (!(Flags & OF_NoMemberType)) {
39903312863SZachary Turner     if (!(FunctionClass & FC_Global)) {
40003312863SZachary Turner       if (FunctionClass & FC_Static)
4012e97236aSLuís Ferreira         OB << "static ";
40203312863SZachary Turner     }
40303312863SZachary Turner     if (FunctionClass & FC_Virtual)
4042e97236aSLuís Ferreira       OB << "virtual ";
40503312863SZachary Turner 
406a92b4639SNico Weber     if (FunctionClass & FC_ExternC)
4072e97236aSLuís Ferreira       OB << "extern \"C\" ";
408da92ed83SMartin Storsjo   }
409a92b4639SNico Weber 
410da92ed83SMartin Storsjo   if (!(Flags & OF_NoReturnType) && ReturnType) {
4112e97236aSLuís Ferreira     ReturnType->outputPre(OB, Flags);
4122e97236aSLuís Ferreira     OB << " ";
41303312863SZachary Turner   }
41403312863SZachary Turner 
41538d2edd6SZachary Turner   if (!(Flags & OF_NoCallingConvention))
4162e97236aSLuís Ferreira     outputCallingConvention(OB, CallConvention);
41703312863SZachary Turner }
41803312863SZachary Turner 
4192e97236aSLuís Ferreira void FunctionSignatureNode::outputPost(OutputBuffer &OB,
42038d2edd6SZachary Turner                                        OutputFlags Flags) const {
42103312863SZachary Turner   if (!(FunctionClass & FC_NoParameterList)) {
4222e97236aSLuís Ferreira     OB << "(";
42303312863SZachary Turner     if (Params)
4242e97236aSLuís Ferreira       Params->output(OB, Flags);
42503312863SZachary Turner     else
4262e97236aSLuís Ferreira       OB << "void";
4271dce8263SNico Weber 
4281dce8263SNico Weber     if (IsVariadic) {
4292e97236aSLuís Ferreira       if (OB.back() != '(')
4302e97236aSLuís Ferreira         OB << ", ";
4312e97236aSLuís Ferreira       OB << "...";
4321dce8263SNico Weber     }
4332e97236aSLuís Ferreira     OB << ")";
43403312863SZachary Turner   }
43503312863SZachary Turner 
43603312863SZachary Turner   if (Quals & Q_Const)
4372e97236aSLuís Ferreira     OB << " const";
43803312863SZachary Turner   if (Quals & Q_Volatile)
4392e97236aSLuís Ferreira     OB << " volatile";
44003312863SZachary Turner   if (Quals & Q_Restrict)
4412e97236aSLuís Ferreira     OB << " __restrict";
44203312863SZachary Turner   if (Quals & Q_Unaligned)
4432e97236aSLuís Ferreira     OB << " __unaligned";
44403312863SZachary Turner 
4452fe49005SZachary Turner   if (IsNoexcept)
4462e97236aSLuís Ferreira     OB << " noexcept";
4472fe49005SZachary Turner 
44803312863SZachary Turner   if (RefQualifier == FunctionRefQualifier::Reference)
4492e97236aSLuís Ferreira     OB << " &";
45003312863SZachary Turner   else if (RefQualifier == FunctionRefQualifier::RValueReference)
4512e97236aSLuís Ferreira     OB << " &&";
45203312863SZachary Turner 
453da92ed83SMartin Storsjo   if (!(Flags & OF_NoReturnType) && ReturnType)
4542e97236aSLuís Ferreira     ReturnType->outputPost(OB, Flags);
45503312863SZachary Turner }
45603312863SZachary Turner 
4572e97236aSLuís Ferreira void ThunkSignatureNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
4582e97236aSLuís Ferreira   OB << "[thunk]: ";
45903312863SZachary Turner 
4602e97236aSLuís Ferreira   FunctionSignatureNode::outputPre(OB, Flags);
46103312863SZachary Turner }
46203312863SZachary Turner 
4632e97236aSLuís Ferreira void ThunkSignatureNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
46403312863SZachary Turner   if (FunctionClass & FC_StaticThisAdjust) {
4652e97236aSLuís Ferreira     OB << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
46603312863SZachary Turner   } else if (FunctionClass & FC_VirtualThisAdjust) {
46703312863SZachary Turner     if (FunctionClass & FC_VirtualThisAdjustEx) {
4682e97236aSLuís Ferreira       OB << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
46903312863SZachary Turner          << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset
47003312863SZachary Turner          << ", " << ThisAdjust.StaticOffset << "}'";
47103312863SZachary Turner     } else {
4722e97236aSLuís Ferreira       OB << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
47303312863SZachary Turner          << ThisAdjust.StaticOffset << "}'";
47403312863SZachary Turner     }
47503312863SZachary Turner   }
47603312863SZachary Turner 
4772e97236aSLuís Ferreira   FunctionSignatureNode::outputPost(OB, Flags);
47803312863SZachary Turner }
47903312863SZachary Turner 
4802e97236aSLuís Ferreira void PointerTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
48103312863SZachary Turner   if (Pointee->kind() == NodeKind::FunctionSignature) {
48203312863SZachary Turner     // If this is a pointer to a function, don't output the calling convention.
48303312863SZachary Turner     // It needs to go inside the parentheses.
48403312863SZachary Turner     const FunctionSignatureNode *Sig =
48503312863SZachary Turner         static_cast<const FunctionSignatureNode *>(Pointee);
4862e97236aSLuís Ferreira     Sig->outputPre(OB, OF_NoCallingConvention);
48703312863SZachary Turner   } else
4882e97236aSLuís Ferreira     Pointee->outputPre(OB, Flags);
48903312863SZachary Turner 
4902e97236aSLuís Ferreira   outputSpaceIfNecessary(OB);
49103312863SZachary Turner 
49203312863SZachary Turner   if (Quals & Q_Unaligned)
4932e97236aSLuís Ferreira     OB << "__unaligned ";
49403312863SZachary Turner 
49503312863SZachary Turner   if (Pointee->kind() == NodeKind::ArrayType) {
4962e97236aSLuís Ferreira     OB << "(";
49703312863SZachary Turner   } else if (Pointee->kind() == NodeKind::FunctionSignature) {
4982e97236aSLuís Ferreira     OB << "(";
49903312863SZachary Turner     const FunctionSignatureNode *Sig =
50003312863SZachary Turner         static_cast<const FunctionSignatureNode *>(Pointee);
5012e97236aSLuís Ferreira     outputCallingConvention(OB, Sig->CallConvention);
5022e97236aSLuís Ferreira     OB << " ";
50303312863SZachary Turner   }
50403312863SZachary Turner 
50503312863SZachary Turner   if (ClassParent) {
5062e97236aSLuís Ferreira     ClassParent->output(OB, Flags);
5072e97236aSLuís Ferreira     OB << "::";
50803312863SZachary Turner   }
50903312863SZachary Turner 
51003312863SZachary Turner   switch (Affinity) {
51103312863SZachary Turner   case PointerAffinity::Pointer:
5122e97236aSLuís Ferreira     OB << "*";
51303312863SZachary Turner     break;
51403312863SZachary Turner   case PointerAffinity::Reference:
5152e97236aSLuís Ferreira     OB << "&";
51603312863SZachary Turner     break;
51703312863SZachary Turner   case PointerAffinity::RValueReference:
5182e97236aSLuís Ferreira     OB << "&&";
51903312863SZachary Turner     break;
52003312863SZachary Turner   default:
52103312863SZachary Turner     assert(false);
52203312863SZachary Turner   }
5232e97236aSLuís Ferreira   outputQualifiers(OB, Quals, false, false);
52403312863SZachary Turner }
52503312863SZachary Turner 
5262e97236aSLuís Ferreira void PointerTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
52703312863SZachary Turner   if (Pointee->kind() == NodeKind::ArrayType ||
52803312863SZachary Turner       Pointee->kind() == NodeKind::FunctionSignature)
5292e97236aSLuís Ferreira     OB << ")";
53003312863SZachary Turner 
5312e97236aSLuís Ferreira   Pointee->outputPost(OB, Flags);
53203312863SZachary Turner }
53303312863SZachary Turner 
5342e97236aSLuís Ferreira void TagTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
535ba797b6dSZachary Turner   if (!(Flags & OF_NoTagSpecifier)) {
53603312863SZachary Turner     switch (Tag) {
53703312863SZachary Turner       OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");
53803312863SZachary Turner       OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct");
53903312863SZachary Turner       OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");
54003312863SZachary Turner       OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");
54103312863SZachary Turner     }
5422e97236aSLuís Ferreira     OB << " ";
543ba797b6dSZachary Turner   }
5442e97236aSLuís Ferreira   QualifiedName->output(OB, Flags);
5452e97236aSLuís Ferreira   outputQualifiers(OB, Quals, true, false);
54603312863SZachary Turner }
54703312863SZachary Turner 
5482e97236aSLuís Ferreira void TagTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}
54903312863SZachary Turner 
5502e97236aSLuís Ferreira void ArrayTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
5512e97236aSLuís Ferreira   ElementType->outputPre(OB, Flags);
5522e97236aSLuís Ferreira   outputQualifiers(OB, Quals, true, false);
55303312863SZachary Turner }
55403312863SZachary Turner 
5552e97236aSLuís Ferreira void ArrayTypeNode::outputOneDimension(OutputBuffer &OB, OutputFlags Flags,
55638d2edd6SZachary Turner                                        Node *N) const {
55703312863SZachary Turner   assert(N->kind() == NodeKind::IntegerLiteral);
55803312863SZachary Turner   IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);
55903312863SZachary Turner   if (ILN->Value != 0)
5602e97236aSLuís Ferreira     ILN->output(OB, Flags);
56103312863SZachary Turner }
56203312863SZachary Turner 
5632e97236aSLuís Ferreira void ArrayTypeNode::outputDimensionsImpl(OutputBuffer &OB,
56438d2edd6SZachary Turner                                          OutputFlags Flags) const {
56503312863SZachary Turner   if (Dimensions->Count == 0)
56603312863SZachary Turner     return;
56703312863SZachary Turner 
5682e97236aSLuís Ferreira   outputOneDimension(OB, Flags, Dimensions->Nodes[0]);
56903312863SZachary Turner   for (size_t I = 1; I < Dimensions->Count; ++I) {
5702e97236aSLuís Ferreira     OB << "][";
5712e97236aSLuís Ferreira     outputOneDimension(OB, Flags, Dimensions->Nodes[I]);
57203312863SZachary Turner   }
57303312863SZachary Turner }
57403312863SZachary Turner 
5752e97236aSLuís Ferreira void ArrayTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
5762e97236aSLuís Ferreira   OB << "[";
5772e97236aSLuís Ferreira   outputDimensionsImpl(OB, Flags);
5782e97236aSLuís Ferreira   OB << "]";
57903312863SZachary Turner 
5802e97236aSLuís Ferreira   ElementType->outputPost(OB, Flags);
58103312863SZachary Turner }
58203312863SZachary Turner 
5832e97236aSLuís Ferreira void SymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
5842e97236aSLuís Ferreira   Name->output(OB, Flags);
58503312863SZachary Turner }
58603312863SZachary Turner 
5872e97236aSLuís Ferreira void FunctionSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
5882e97236aSLuís Ferreira   Signature->outputPre(OB, Flags);
5892e97236aSLuís Ferreira   outputSpaceIfNecessary(OB);
5902e97236aSLuís Ferreira   Name->output(OB, Flags);
5912e97236aSLuís Ferreira   Signature->outputPost(OB, Flags);
59203312863SZachary Turner }
59303312863SZachary Turner 
5942e97236aSLuís Ferreira void VariableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
595da92ed83SMartin Storsjo   const char *AccessSpec = nullptr;
596da92ed83SMartin Storsjo   bool IsStatic = true;
59703312863SZachary Turner   switch (SC) {
59803312863SZachary Turner   case StorageClass::PrivateStatic:
599da92ed83SMartin Storsjo     AccessSpec = "private";
600a92b4639SNico Weber     break;
60103312863SZachary Turner   case StorageClass::PublicStatic:
602da92ed83SMartin Storsjo     AccessSpec = "public";
603a92b4639SNico Weber     break;
60403312863SZachary Turner   case StorageClass::ProtectedStatic:
605da92ed83SMartin Storsjo     AccessSpec = "protected";
6064dc0b1acSReid Kleckner     break;
60703312863SZachary Turner   default:
608da92ed83SMartin Storsjo     IsStatic = false;
60903312863SZachary Turner     break;
61003312863SZachary Turner   }
611da92ed83SMartin Storsjo   if (!(Flags & OF_NoAccessSpecifier) && AccessSpec)
6122e97236aSLuís Ferreira     OB << AccessSpec << ": ";
613da92ed83SMartin Storsjo   if (!(Flags & OF_NoMemberType) && IsStatic)
6142e97236aSLuís Ferreira     OB << "static ";
61503312863SZachary Turner 
616134e1817SLasse Folger   if (!(Flags & OF_NoVariableType) && Type) {
6172e97236aSLuís Ferreira     Type->outputPre(OB, Flags);
6182e97236aSLuís Ferreira     outputSpaceIfNecessary(OB);
61903312863SZachary Turner   }
6202e97236aSLuís Ferreira   Name->output(OB, Flags);
621134e1817SLasse Folger   if (!(Flags & OF_NoVariableType) && Type)
6222e97236aSLuís Ferreira     Type->outputPost(OB, Flags);
62303312863SZachary Turner }
62403312863SZachary Turner 
6252e97236aSLuís Ferreira void CustomTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
6262e97236aSLuís Ferreira   Identifier->output(OB, Flags);
62703312863SZachary Turner }
6282e97236aSLuís Ferreira void CustomTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}
62903312863SZachary Turner 
6302e97236aSLuís Ferreira void QualifiedNameNode::output(OutputBuffer &OB, OutputFlags Flags) const {
6312e97236aSLuís Ferreira   Components->output(OB, Flags, "::");
63238d2edd6SZachary Turner }
63338d2edd6SZachary Turner 
6342e97236aSLuís Ferreira void RttiBaseClassDescriptorNode::output(OutputBuffer &OB,
63538d2edd6SZachary Turner                                          OutputFlags Flags) const {
6362e97236aSLuís Ferreira   OB << "`RTTI Base Class Descriptor at (";
6372e97236aSLuís Ferreira   OB << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
63838d2edd6SZachary Turner      << this->Flags;
6392e97236aSLuís Ferreira   OB << ")'";
64003312863SZachary Turner }
64103312863SZachary Turner 
6422e97236aSLuís Ferreira void LocalStaticGuardVariableNode::output(OutputBuffer &OB,
64338d2edd6SZachary Turner                                           OutputFlags Flags) const {
6442e97236aSLuís Ferreira   Name->output(OB, Flags);
64503312863SZachary Turner }
64603312863SZachary Turner 
6472e97236aSLuís Ferreira void VcallThunkIdentifierNode::output(OutputBuffer &OB,
64838d2edd6SZachary Turner                                       OutputFlags Flags) const {
6492e97236aSLuís Ferreira   OB << "`vcall'{" << OffsetInVTable << ", {flat}}";
65003312863SZachary Turner }
65103312863SZachary Turner 
6522e97236aSLuís Ferreira void SpecialTableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
6532e97236aSLuís Ferreira   outputQualifiers(OB, Quals, false, true);
6542e97236aSLuís Ferreira   Name->output(OB, Flags);
65503312863SZachary Turner   if (TargetName) {
6562e97236aSLuís Ferreira     OB << "{for `";
6572e97236aSLuís Ferreira     TargetName->output(OB, Flags);
6582e97236aSLuís Ferreira     OB << "'}";
65903312863SZachary Turner   }
66003312863SZachary Turner }
661