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.
outputSpaceIfNecessary(OutputBuffer & OB)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
outputSingleQualifier(OutputBuffer & OB,Qualifiers Q)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
outputQualifierIfPresent(OutputBuffer & OB,Qualifiers Q,Qualifiers Mask,bool NeedSpace)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
outputQualifiers(OutputBuffer & OB,Qualifiers Q,bool SpaceBefore,bool SpaceAfter)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
outputCallingConvention(OutputBuffer & OB,CallingConv CC)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
toString(OutputFlags Flags) const120ba797b6dSZachary Turner std::string Node::toString(OutputFlags Flags) const {
1212e97236aSLuís Ferreira OutputBuffer OB;
122*aabeb5ebSKirill Stoimenov initializeOutputBuffer(nullptr, nullptr, OB, 1024);
1232e97236aSLuís Ferreira this->output(OB, Flags);
1241066e397SNathan Sidwell StringView SV = OB;
1251066e397SNathan Sidwell std::string Owned(SV.begin(), SV.end());
1262e97236aSLuís Ferreira std::free(OB.getBuffer());
127ae209aa9SRaphael Isemann return Owned;
128b472512aSZachary Turner }
129b472512aSZachary Turner
outputPre(OutputBuffer & OB,OutputFlags Flags) const1302e97236aSLuís Ferreira void PrimitiveTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
13103312863SZachary Turner switch (PrimKind) {
13203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void");
13303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool");
13403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char");
13503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char");
13603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");
137a2ca6e78SNico Weber OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t");
13803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t");
13903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t");
14003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short");
14103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short");
14203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int");
14303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int");
14403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long");
14503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long");
14603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64");
14703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64");
14803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t");
14903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float");
15003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double");
15103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double");
15203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");
15303312863SZachary Turner }
1542e97236aSLuís Ferreira outputQualifiers(OB, Quals, true, false);
15503312863SZachary Turner }
15603312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const1572e97236aSLuís Ferreira void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags) const {
1582e97236aSLuís Ferreira output(OB, Flags, ", ");
15938d2edd6SZachary Turner }
16003312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags,StringView Separator) const1612e97236aSLuís Ferreira void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags,
16238d2edd6SZachary Turner StringView Separator) const {
16303312863SZachary Turner if (Count == 0)
16403312863SZachary Turner return;
16503312863SZachary Turner if (Nodes[0])
1662e97236aSLuís Ferreira Nodes[0]->output(OB, Flags);
16703312863SZachary Turner for (size_t I = 1; I < Count; ++I) {
1682e97236aSLuís Ferreira OB << Separator;
1692e97236aSLuís Ferreira Nodes[I]->output(OB, Flags);
17003312863SZachary Turner }
17103312863SZachary Turner }
17203312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const1732e97236aSLuís Ferreira void EncodedStringLiteralNode::output(OutputBuffer &OB,
17438d2edd6SZachary Turner OutputFlags Flags) const {
17503312863SZachary Turner switch (Char) {
17603312863SZachary Turner case CharKind::Wchar:
1772e97236aSLuís Ferreira OB << "L\"";
17803312863SZachary Turner break;
17903312863SZachary Turner case CharKind::Char:
1802e97236aSLuís Ferreira OB << "\"";
18103312863SZachary Turner break;
18203312863SZachary Turner case CharKind::Char16:
1832e97236aSLuís Ferreira OB << "u\"";
18403312863SZachary Turner break;
18503312863SZachary Turner case CharKind::Char32:
1862e97236aSLuís Ferreira OB << "U\"";
18703312863SZachary Turner break;
18803312863SZachary Turner }
1892e97236aSLuís Ferreira OB << DecodedString << "\"";
19003312863SZachary Turner if (IsTruncated)
1912e97236aSLuís Ferreira OB << "...";
19203312863SZachary Turner }
19303312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const1942e97236aSLuís Ferreira void IntegerLiteralNode::output(OutputBuffer &OB, OutputFlags Flags) const {
19503312863SZachary Turner if (IsNegative)
1962e97236aSLuís Ferreira OB << '-';
1972e97236aSLuís Ferreira OB << Value;
19803312863SZachary Turner }
19903312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const2002e97236aSLuís Ferreira void TemplateParameterReferenceNode::output(OutputBuffer &OB,
20138d2edd6SZachary Turner OutputFlags Flags) const {
20203312863SZachary Turner if (ThunkOffsetCount > 0)
2032e97236aSLuís Ferreira OB << "{";
20403312863SZachary Turner else if (Affinity == PointerAffinity::Pointer)
2052e97236aSLuís Ferreira OB << "&";
20603312863SZachary Turner
20703312863SZachary Turner if (Symbol) {
2082e97236aSLuís Ferreira Symbol->output(OB, Flags);
20903312863SZachary Turner if (ThunkOffsetCount > 0)
2102e97236aSLuís Ferreira OB << ", ";
21103312863SZachary Turner }
21203312863SZachary Turner
21303312863SZachary Turner if (ThunkOffsetCount > 0)
2142e97236aSLuís Ferreira OB << ThunkOffsets[0];
21503312863SZachary Turner for (int I = 1; I < ThunkOffsetCount; ++I) {
2162e97236aSLuís Ferreira OB << ", " << ThunkOffsets[I];
21703312863SZachary Turner }
21803312863SZachary Turner if (ThunkOffsetCount > 0)
2192e97236aSLuís Ferreira OB << "}";
22003312863SZachary Turner }
22103312863SZachary Turner
outputTemplateParameters(OutputBuffer & OB,OutputFlags Flags) const2222e97236aSLuís Ferreira void IdentifierNode::outputTemplateParameters(OutputBuffer &OB,
22338d2edd6SZachary Turner OutputFlags Flags) const {
22403312863SZachary Turner if (!TemplateParams)
22503312863SZachary Turner return;
2262e97236aSLuís Ferreira OB << "<";
2272e97236aSLuís Ferreira TemplateParams->output(OB, Flags);
2282e97236aSLuís Ferreira OB << ">";
22903312863SZachary Turner }
23003312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const2312e97236aSLuís Ferreira void DynamicStructorIdentifierNode::output(OutputBuffer &OB,
23238d2edd6SZachary Turner OutputFlags Flags) const {
23303312863SZachary Turner if (IsDestructor)
2342e97236aSLuís Ferreira OB << "`dynamic atexit destructor for ";
23503312863SZachary Turner else
2362e97236aSLuís Ferreira OB << "`dynamic initializer for ";
23703312863SZachary Turner
23832a8a202SZachary Turner if (Variable) {
2392e97236aSLuís Ferreira OB << "`";
2402e97236aSLuís Ferreira Variable->output(OB, Flags);
2412e97236aSLuís Ferreira OB << "''";
24232a8a202SZachary Turner } else {
2432e97236aSLuís Ferreira OB << "'";
2442e97236aSLuís Ferreira Name->output(OB, Flags);
2452e97236aSLuís Ferreira OB << "''";
24603312863SZachary Turner }
24732a8a202SZachary Turner }
24803312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const2492e97236aSLuís Ferreira void NamedIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {
2502e97236aSLuís Ferreira OB << Name;
2512e97236aSLuís Ferreira outputTemplateParameters(OB, Flags);
25203312863SZachary Turner }
25303312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const2542e97236aSLuís Ferreira void IntrinsicFunctionIdentifierNode::output(OutputBuffer &OB,
25538d2edd6SZachary Turner OutputFlags Flags) const {
25603312863SZachary Turner switch (Operator) {
25703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new");
25803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete");
25903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator=");
26003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>");
26103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<");
26203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!");
26303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator==");
26403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!=");
26503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript,
26603312863SZachary Turner "operator[]");
26703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->");
26803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++");
26903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--");
27003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-");
27103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+");
27203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*");
27303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&");
27403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer,
27503312863SZachary Turner "operator->*");
27603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/");
27703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%");
27803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<");
27903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<=");
28003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>");
28103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual,
28203312863SZachary Turner "operator>=");
28303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,");
28403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()");
28503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~");
28603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^");
28703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|");
28803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&");
28903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||");
29003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*=");
29103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+=");
29203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-=");
29303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/=");
29403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%=");
29503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>=");
29603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<=");
29703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual,
29803312863SZachary Turner "operator&=");
29903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual,
30003312863SZachary Turner "operator|=");
30103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual,
30203312863SZachary Turner "operator^=");
30303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'");
30403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor,
30503312863SZachary Turner "`vector deleting dtor'");
30603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure,
30703312863SZachary Turner "`default ctor closure'");
30803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor,
30903312863SZachary Turner "`scalar deleting dtor'");
31003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter,
31103312863SZachary Turner "`vector ctor iterator'");
31203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter,
31303312863SZachary Turner "`vector dtor iterator'");
31403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter,
31503312863SZachary Turner "`vector vbase ctor iterator'");
31603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap,
31703312863SZachary Turner "`virtual displacement map'");
31803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter,
31903312863SZachary Turner "`eh vector ctor iterator'");
32003312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter,
32103312863SZachary Turner "`eh vector dtor iterator'");
32203312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter,
32303312863SZachary Turner "`eh vector vbase ctor iterator'");
32403312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure,
32503312863SZachary Turner "`copy ctor closure'");
32603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure,
32703312863SZachary Turner "`local vftable ctor closure'");
32803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]");
32903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete,
33003312863SZachary Turner "operator delete[]");
33103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter,
33203312863SZachary Turner "`managed vector ctor iterator'");
33303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter,
33403312863SZachary Turner "`managed vector dtor iterator'");
33503312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter,
33603312863SZachary Turner "`EH vector copy ctor iterator'");
33703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter,
33803312863SZachary Turner "`EH vector vbase copy ctor iterator'");
33903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter,
34003312863SZachary Turner "`vector copy ctor iterator'");
34103312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter,
34203312863SZachary Turner "`vector vbase copy constructor iterator'");
34303312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter,
34403312863SZachary Turner "`managed vector vbase copy constructor iterator'");
345e8f21b1aSNico Weber OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait,
346e8f21b1aSNico Weber "operator co_await");
34703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>");
34803312863SZachary Turner case IntrinsicFunctionKind::MaxIntrinsic:
34903312863SZachary Turner case IntrinsicFunctionKind::None:
35003312863SZachary Turner break;
35103312863SZachary Turner }
3522e97236aSLuís Ferreira outputTemplateParameters(OB, Flags);
35303312863SZachary Turner }
35403312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const3552e97236aSLuís Ferreira void LocalStaticGuardIdentifierNode::output(OutputBuffer &OB,
35638d2edd6SZachary Turner OutputFlags Flags) const {
35788ab281bSNico Weber if (IsThread)
3582e97236aSLuís Ferreira OB << "`local static thread guard'";
35988ab281bSNico Weber else
3602e97236aSLuís Ferreira OB << "`local static guard'";
36103312863SZachary Turner if (ScopeIndex > 0)
3622e97236aSLuís Ferreira OB << "{" << ScopeIndex << "}";
36303312863SZachary Turner }
36403312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const3652e97236aSLuís Ferreira void ConversionOperatorIdentifierNode::output(OutputBuffer &OB,
36638d2edd6SZachary Turner OutputFlags Flags) const {
3672e97236aSLuís Ferreira OB << "operator";
3682e97236aSLuís Ferreira outputTemplateParameters(OB, Flags);
3692e97236aSLuís Ferreira OB << " ";
3702e97236aSLuís Ferreira TargetType->output(OB, Flags);
37103312863SZachary Turner }
37203312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const3732e97236aSLuís Ferreira void StructorIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {
37403312863SZachary Turner if (IsDestructor)
3752e97236aSLuís Ferreira OB << "~";
3762e97236aSLuís Ferreira Class->output(OB, Flags);
3772e97236aSLuís Ferreira outputTemplateParameters(OB, Flags);
37803312863SZachary Turner }
37903312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const3802e97236aSLuís Ferreira void LiteralOperatorIdentifierNode::output(OutputBuffer &OB,
38138d2edd6SZachary Turner OutputFlags Flags) const {
3822e97236aSLuís Ferreira OB << "operator \"\"" << Name;
3832e97236aSLuís Ferreira outputTemplateParameters(OB, Flags);
38403312863SZachary Turner }
38503312863SZachary Turner
outputPre(OutputBuffer & OB,OutputFlags Flags) const3862e97236aSLuís Ferreira void FunctionSignatureNode::outputPre(OutputBuffer &OB,
38738d2edd6SZachary Turner OutputFlags Flags) const {
388da92ed83SMartin Storsjo if (!(Flags & OF_NoAccessSpecifier)) {
389a92b4639SNico Weber if (FunctionClass & FC_Public)
3902e97236aSLuís Ferreira OB << "public: ";
391a92b4639SNico Weber if (FunctionClass & FC_Protected)
3922e97236aSLuís Ferreira OB << "protected: ";
393a92b4639SNico Weber if (FunctionClass & FC_Private)
3942e97236aSLuís Ferreira OB << "private: ";
395da92ed83SMartin Storsjo }
396a92b4639SNico Weber
397da92ed83SMartin Storsjo if (!(Flags & OF_NoMemberType)) {
39803312863SZachary Turner if (!(FunctionClass & FC_Global)) {
39903312863SZachary Turner if (FunctionClass & FC_Static)
4002e97236aSLuís Ferreira OB << "static ";
40103312863SZachary Turner }
40203312863SZachary Turner if (FunctionClass & FC_Virtual)
4032e97236aSLuís Ferreira OB << "virtual ";
40403312863SZachary Turner
405a92b4639SNico Weber if (FunctionClass & FC_ExternC)
4062e97236aSLuís Ferreira OB << "extern \"C\" ";
407da92ed83SMartin Storsjo }
408a92b4639SNico Weber
409da92ed83SMartin Storsjo if (!(Flags & OF_NoReturnType) && ReturnType) {
4102e97236aSLuís Ferreira ReturnType->outputPre(OB, Flags);
4112e97236aSLuís Ferreira OB << " ";
41203312863SZachary Turner }
41303312863SZachary Turner
41438d2edd6SZachary Turner if (!(Flags & OF_NoCallingConvention))
4152e97236aSLuís Ferreira outputCallingConvention(OB, CallConvention);
41603312863SZachary Turner }
41703312863SZachary Turner
outputPost(OutputBuffer & OB,OutputFlags Flags) const4182e97236aSLuís Ferreira void FunctionSignatureNode::outputPost(OutputBuffer &OB,
41938d2edd6SZachary Turner OutputFlags Flags) const {
42003312863SZachary Turner if (!(FunctionClass & FC_NoParameterList)) {
4212e97236aSLuís Ferreira OB << "(";
42203312863SZachary Turner if (Params)
4232e97236aSLuís Ferreira Params->output(OB, Flags);
42403312863SZachary Turner else
4252e97236aSLuís Ferreira OB << "void";
4261dce8263SNico Weber
4271dce8263SNico Weber if (IsVariadic) {
4282e97236aSLuís Ferreira if (OB.back() != '(')
4292e97236aSLuís Ferreira OB << ", ";
4302e97236aSLuís Ferreira OB << "...";
4311dce8263SNico Weber }
4322e97236aSLuís Ferreira OB << ")";
43303312863SZachary Turner }
43403312863SZachary Turner
43503312863SZachary Turner if (Quals & Q_Const)
4362e97236aSLuís Ferreira OB << " const";
43703312863SZachary Turner if (Quals & Q_Volatile)
4382e97236aSLuís Ferreira OB << " volatile";
43903312863SZachary Turner if (Quals & Q_Restrict)
4402e97236aSLuís Ferreira OB << " __restrict";
44103312863SZachary Turner if (Quals & Q_Unaligned)
4422e97236aSLuís Ferreira OB << " __unaligned";
44303312863SZachary Turner
4442fe49005SZachary Turner if (IsNoexcept)
4452e97236aSLuís Ferreira OB << " noexcept";
4462fe49005SZachary Turner
44703312863SZachary Turner if (RefQualifier == FunctionRefQualifier::Reference)
4482e97236aSLuís Ferreira OB << " &";
44903312863SZachary Turner else if (RefQualifier == FunctionRefQualifier::RValueReference)
4502e97236aSLuís Ferreira OB << " &&";
45103312863SZachary Turner
452da92ed83SMartin Storsjo if (!(Flags & OF_NoReturnType) && ReturnType)
4532e97236aSLuís Ferreira ReturnType->outputPost(OB, Flags);
45403312863SZachary Turner }
45503312863SZachary Turner
outputPre(OutputBuffer & OB,OutputFlags Flags) const4562e97236aSLuís Ferreira void ThunkSignatureNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
4572e97236aSLuís Ferreira OB << "[thunk]: ";
45803312863SZachary Turner
4592e97236aSLuís Ferreira FunctionSignatureNode::outputPre(OB, Flags);
46003312863SZachary Turner }
46103312863SZachary Turner
outputPost(OutputBuffer & OB,OutputFlags Flags) const4622e97236aSLuís Ferreira void ThunkSignatureNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
46303312863SZachary Turner if (FunctionClass & FC_StaticThisAdjust) {
4642e97236aSLuís Ferreira OB << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
46503312863SZachary Turner } else if (FunctionClass & FC_VirtualThisAdjust) {
46603312863SZachary Turner if (FunctionClass & FC_VirtualThisAdjustEx) {
4672e97236aSLuís Ferreira OB << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
46803312863SZachary Turner << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset
46903312863SZachary Turner << ", " << ThisAdjust.StaticOffset << "}'";
47003312863SZachary Turner } else {
4712e97236aSLuís Ferreira OB << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
47203312863SZachary Turner << ThisAdjust.StaticOffset << "}'";
47303312863SZachary Turner }
47403312863SZachary Turner }
47503312863SZachary Turner
4762e97236aSLuís Ferreira FunctionSignatureNode::outputPost(OB, Flags);
47703312863SZachary Turner }
47803312863SZachary Turner
outputPre(OutputBuffer & OB,OutputFlags Flags) const4792e97236aSLuís Ferreira void PointerTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
48003312863SZachary Turner if (Pointee->kind() == NodeKind::FunctionSignature) {
48103312863SZachary Turner // If this is a pointer to a function, don't output the calling convention.
48203312863SZachary Turner // It needs to go inside the parentheses.
48303312863SZachary Turner const FunctionSignatureNode *Sig =
48403312863SZachary Turner static_cast<const FunctionSignatureNode *>(Pointee);
4852e97236aSLuís Ferreira Sig->outputPre(OB, OF_NoCallingConvention);
48603312863SZachary Turner } else
4872e97236aSLuís Ferreira Pointee->outputPre(OB, Flags);
48803312863SZachary Turner
4892e97236aSLuís Ferreira outputSpaceIfNecessary(OB);
49003312863SZachary Turner
49103312863SZachary Turner if (Quals & Q_Unaligned)
4922e97236aSLuís Ferreira OB << "__unaligned ";
49303312863SZachary Turner
49403312863SZachary Turner if (Pointee->kind() == NodeKind::ArrayType) {
4952e97236aSLuís Ferreira OB << "(";
49603312863SZachary Turner } else if (Pointee->kind() == NodeKind::FunctionSignature) {
4972e97236aSLuís Ferreira OB << "(";
49803312863SZachary Turner const FunctionSignatureNode *Sig =
49903312863SZachary Turner static_cast<const FunctionSignatureNode *>(Pointee);
5002e97236aSLuís Ferreira outputCallingConvention(OB, Sig->CallConvention);
5012e97236aSLuís Ferreira OB << " ";
50203312863SZachary Turner }
50303312863SZachary Turner
50403312863SZachary Turner if (ClassParent) {
5052e97236aSLuís Ferreira ClassParent->output(OB, Flags);
5062e97236aSLuís Ferreira OB << "::";
50703312863SZachary Turner }
50803312863SZachary Turner
50903312863SZachary Turner switch (Affinity) {
51003312863SZachary Turner case PointerAffinity::Pointer:
5112e97236aSLuís Ferreira OB << "*";
51203312863SZachary Turner break;
51303312863SZachary Turner case PointerAffinity::Reference:
5142e97236aSLuís Ferreira OB << "&";
51503312863SZachary Turner break;
51603312863SZachary Turner case PointerAffinity::RValueReference:
5172e97236aSLuís Ferreira OB << "&&";
51803312863SZachary Turner break;
51903312863SZachary Turner default:
52003312863SZachary Turner assert(false);
52103312863SZachary Turner }
5222e97236aSLuís Ferreira outputQualifiers(OB, Quals, false, false);
52303312863SZachary Turner }
52403312863SZachary Turner
outputPost(OutputBuffer & OB,OutputFlags Flags) const5252e97236aSLuís Ferreira void PointerTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
52603312863SZachary Turner if (Pointee->kind() == NodeKind::ArrayType ||
52703312863SZachary Turner Pointee->kind() == NodeKind::FunctionSignature)
5282e97236aSLuís Ferreira OB << ")";
52903312863SZachary Turner
5302e97236aSLuís Ferreira Pointee->outputPost(OB, Flags);
53103312863SZachary Turner }
53203312863SZachary Turner
outputPre(OutputBuffer & OB,OutputFlags Flags) const5332e97236aSLuís Ferreira void TagTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
534ba797b6dSZachary Turner if (!(Flags & OF_NoTagSpecifier)) {
53503312863SZachary Turner switch (Tag) {
53603312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");
53703312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct");
53803312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");
53903312863SZachary Turner OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");
54003312863SZachary Turner }
5412e97236aSLuís Ferreira OB << " ";
542ba797b6dSZachary Turner }
5432e97236aSLuís Ferreira QualifiedName->output(OB, Flags);
5442e97236aSLuís Ferreira outputQualifiers(OB, Quals, true, false);
54503312863SZachary Turner }
54603312863SZachary Turner
outputPost(OutputBuffer & OB,OutputFlags Flags) const5472e97236aSLuís Ferreira void TagTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}
54803312863SZachary Turner
outputPre(OutputBuffer & OB,OutputFlags Flags) const5492e97236aSLuís Ferreira void ArrayTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
5502e97236aSLuís Ferreira ElementType->outputPre(OB, Flags);
5512e97236aSLuís Ferreira outputQualifiers(OB, Quals, true, false);
55203312863SZachary Turner }
55303312863SZachary Turner
outputOneDimension(OutputBuffer & OB,OutputFlags Flags,Node * N) const5542e97236aSLuís Ferreira void ArrayTypeNode::outputOneDimension(OutputBuffer &OB, OutputFlags Flags,
55538d2edd6SZachary Turner Node *N) const {
55603312863SZachary Turner assert(N->kind() == NodeKind::IntegerLiteral);
55703312863SZachary Turner IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);
55803312863SZachary Turner if (ILN->Value != 0)
5592e97236aSLuís Ferreira ILN->output(OB, Flags);
56003312863SZachary Turner }
56103312863SZachary Turner
outputDimensionsImpl(OutputBuffer & OB,OutputFlags Flags) const5622e97236aSLuís Ferreira void ArrayTypeNode::outputDimensionsImpl(OutputBuffer &OB,
56338d2edd6SZachary Turner OutputFlags Flags) const {
56403312863SZachary Turner if (Dimensions->Count == 0)
56503312863SZachary Turner return;
56603312863SZachary Turner
5672e97236aSLuís Ferreira outputOneDimension(OB, Flags, Dimensions->Nodes[0]);
56803312863SZachary Turner for (size_t I = 1; I < Dimensions->Count; ++I) {
5692e97236aSLuís Ferreira OB << "][";
5702e97236aSLuís Ferreira outputOneDimension(OB, Flags, Dimensions->Nodes[I]);
57103312863SZachary Turner }
57203312863SZachary Turner }
57303312863SZachary Turner
outputPost(OutputBuffer & OB,OutputFlags Flags) const5742e97236aSLuís Ferreira void ArrayTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
5752e97236aSLuís Ferreira OB << "[";
5762e97236aSLuís Ferreira outputDimensionsImpl(OB, Flags);
5772e97236aSLuís Ferreira OB << "]";
57803312863SZachary Turner
5792e97236aSLuís Ferreira ElementType->outputPost(OB, Flags);
58003312863SZachary Turner }
58103312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const5822e97236aSLuís Ferreira void SymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
5832e97236aSLuís Ferreira Name->output(OB, Flags);
58403312863SZachary Turner }
58503312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const5862e97236aSLuís Ferreira void FunctionSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
5872e97236aSLuís Ferreira Signature->outputPre(OB, Flags);
5882e97236aSLuís Ferreira outputSpaceIfNecessary(OB);
5892e97236aSLuís Ferreira Name->output(OB, Flags);
5902e97236aSLuís Ferreira Signature->outputPost(OB, Flags);
59103312863SZachary Turner }
59203312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const5932e97236aSLuís Ferreira void VariableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
594da92ed83SMartin Storsjo const char *AccessSpec = nullptr;
595da92ed83SMartin Storsjo bool IsStatic = true;
59603312863SZachary Turner switch (SC) {
59703312863SZachary Turner case StorageClass::PrivateStatic:
598da92ed83SMartin Storsjo AccessSpec = "private";
599a92b4639SNico Weber break;
60003312863SZachary Turner case StorageClass::PublicStatic:
601da92ed83SMartin Storsjo AccessSpec = "public";
602a92b4639SNico Weber break;
60303312863SZachary Turner case StorageClass::ProtectedStatic:
604da92ed83SMartin Storsjo AccessSpec = "protected";
6054dc0b1acSReid Kleckner break;
60603312863SZachary Turner default:
607da92ed83SMartin Storsjo IsStatic = false;
60803312863SZachary Turner break;
60903312863SZachary Turner }
610da92ed83SMartin Storsjo if (!(Flags & OF_NoAccessSpecifier) && AccessSpec)
6112e97236aSLuís Ferreira OB << AccessSpec << ": ";
612da92ed83SMartin Storsjo if (!(Flags & OF_NoMemberType) && IsStatic)
6132e97236aSLuís Ferreira OB << "static ";
61403312863SZachary Turner
615134e1817SLasse Folger if (!(Flags & OF_NoVariableType) && Type) {
6162e97236aSLuís Ferreira Type->outputPre(OB, Flags);
6172e97236aSLuís Ferreira outputSpaceIfNecessary(OB);
61803312863SZachary Turner }
6192e97236aSLuís Ferreira Name->output(OB, Flags);
620134e1817SLasse Folger if (!(Flags & OF_NoVariableType) && Type)
6212e97236aSLuís Ferreira Type->outputPost(OB, Flags);
62203312863SZachary Turner }
62303312863SZachary Turner
outputPre(OutputBuffer & OB,OutputFlags Flags) const6242e97236aSLuís Ferreira void CustomTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
6252e97236aSLuís Ferreira Identifier->output(OB, Flags);
62603312863SZachary Turner }
outputPost(OutputBuffer & OB,OutputFlags Flags) const6272e97236aSLuís Ferreira void CustomTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}
62803312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const6292e97236aSLuís Ferreira void QualifiedNameNode::output(OutputBuffer &OB, OutputFlags Flags) const {
6302e97236aSLuís Ferreira Components->output(OB, Flags, "::");
63138d2edd6SZachary Turner }
63238d2edd6SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const6332e97236aSLuís Ferreira void RttiBaseClassDescriptorNode::output(OutputBuffer &OB,
63438d2edd6SZachary Turner OutputFlags Flags) const {
6352e97236aSLuís Ferreira OB << "`RTTI Base Class Descriptor at (";
6362e97236aSLuís Ferreira OB << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
63738d2edd6SZachary Turner << this->Flags;
6382e97236aSLuís Ferreira OB << ")'";
63903312863SZachary Turner }
64003312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const6412e97236aSLuís Ferreira void LocalStaticGuardVariableNode::output(OutputBuffer &OB,
64238d2edd6SZachary Turner OutputFlags Flags) const {
6432e97236aSLuís Ferreira Name->output(OB, Flags);
64403312863SZachary Turner }
64503312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const6462e97236aSLuís Ferreira void VcallThunkIdentifierNode::output(OutputBuffer &OB,
64738d2edd6SZachary Turner OutputFlags Flags) const {
6482e97236aSLuís Ferreira OB << "`vcall'{" << OffsetInVTable << ", {flat}}";
64903312863SZachary Turner }
65003312863SZachary Turner
output(OutputBuffer & OB,OutputFlags Flags) const6512e97236aSLuís Ferreira void SpecialTableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
6522e97236aSLuís Ferreira outputQualifiers(OB, Quals, false, true);
6532e97236aSLuís Ferreira Name->output(OB, Flags);
65403312863SZachary Turner if (TargetName) {
6552e97236aSLuís Ferreira OB << "{for `";
6562e97236aSLuís Ferreira TargetName->output(OB, Flags);
6572e97236aSLuís Ferreira OB << "'}";
65803312863SZachary Turner }
65903312863SZachary Turner }
660