xref: /freebsd-src/contrib/llvm-project/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- MicrosoftDemangle.cpp ----------------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file defines a demangler for MSVC-style mangled symbols.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "llvm/Demangle/MicrosoftDemangleNodes.h"
14*0b57cec5SDimitry Andric #include "llvm/Demangle/DemangleConfig.h"
15*0b57cec5SDimitry Andric #include "llvm/Demangle/Utility.h"
16*0b57cec5SDimitry Andric #include <cctype>
17*0b57cec5SDimitry Andric #include <string>
18*0b57cec5SDimitry Andric 
19*0b57cec5SDimitry Andric using namespace llvm;
20*0b57cec5SDimitry Andric using namespace ms_demangle;
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric #define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc)                             \
23*0b57cec5SDimitry Andric   case Enum::Value:                                                            \
24*0b57cec5SDimitry Andric     OS << Desc;                                                                \
25*0b57cec5SDimitry Andric     break;
26*0b57cec5SDimitry Andric 
27*0b57cec5SDimitry Andric // Writes a space if the last token does not end with a punctuation.
28*0b57cec5SDimitry Andric static void outputSpaceIfNecessary(OutputStream &OS) {
29*0b57cec5SDimitry Andric   if (OS.empty())
30*0b57cec5SDimitry Andric     return;
31*0b57cec5SDimitry Andric 
32*0b57cec5SDimitry Andric   char C = OS.back();
33*0b57cec5SDimitry Andric   if (std::isalnum(C) || C == '>')
34*0b57cec5SDimitry Andric     OS << " ";
35*0b57cec5SDimitry Andric }
36*0b57cec5SDimitry Andric 
37*0b57cec5SDimitry Andric static void outputSingleQualifier(OutputStream &OS, Qualifiers Q) {
38*0b57cec5SDimitry Andric   switch (Q) {
39*0b57cec5SDimitry Andric   case Q_Const:
40*0b57cec5SDimitry Andric     OS << "const";
41*0b57cec5SDimitry Andric     break;
42*0b57cec5SDimitry Andric   case Q_Volatile:
43*0b57cec5SDimitry Andric     OS << "volatile";
44*0b57cec5SDimitry Andric     break;
45*0b57cec5SDimitry Andric   case Q_Restrict:
46*0b57cec5SDimitry Andric     OS << "__restrict";
47*0b57cec5SDimitry Andric     break;
48*0b57cec5SDimitry Andric   default:
49*0b57cec5SDimitry Andric     break;
50*0b57cec5SDimitry Andric   }
51*0b57cec5SDimitry Andric }
52*0b57cec5SDimitry Andric 
53*0b57cec5SDimitry Andric static bool outputQualifierIfPresent(OutputStream &OS, Qualifiers Q,
54*0b57cec5SDimitry Andric                                      Qualifiers Mask, bool NeedSpace) {
55*0b57cec5SDimitry Andric   if (!(Q & Mask))
56*0b57cec5SDimitry Andric     return NeedSpace;
57*0b57cec5SDimitry Andric 
58*0b57cec5SDimitry Andric   if (NeedSpace)
59*0b57cec5SDimitry Andric     OS << " ";
60*0b57cec5SDimitry Andric 
61*0b57cec5SDimitry Andric   outputSingleQualifier(OS, Mask);
62*0b57cec5SDimitry Andric   return true;
63*0b57cec5SDimitry Andric }
64*0b57cec5SDimitry Andric 
65*0b57cec5SDimitry Andric static void outputQualifiers(OutputStream &OS, Qualifiers Q, bool SpaceBefore,
66*0b57cec5SDimitry Andric                              bool SpaceAfter) {
67*0b57cec5SDimitry Andric   if (Q == Q_None)
68*0b57cec5SDimitry Andric     return;
69*0b57cec5SDimitry Andric 
70*0b57cec5SDimitry Andric   size_t Pos1 = OS.getCurrentPosition();
71*0b57cec5SDimitry Andric   SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Const, SpaceBefore);
72*0b57cec5SDimitry Andric   SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Volatile, SpaceBefore);
73*0b57cec5SDimitry Andric   SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Restrict, SpaceBefore);
74*0b57cec5SDimitry Andric   size_t Pos2 = OS.getCurrentPosition();
75*0b57cec5SDimitry Andric   if (SpaceAfter && Pos2 > Pos1)
76*0b57cec5SDimitry Andric     OS << " ";
77*0b57cec5SDimitry Andric }
78*0b57cec5SDimitry Andric 
79*0b57cec5SDimitry Andric static void outputCallingConvention(OutputStream &OS, CallingConv CC) {
80*0b57cec5SDimitry Andric   outputSpaceIfNecessary(OS);
81*0b57cec5SDimitry Andric 
82*0b57cec5SDimitry Andric   switch (CC) {
83*0b57cec5SDimitry Andric   case CallingConv::Cdecl:
84*0b57cec5SDimitry Andric     OS << "__cdecl";
85*0b57cec5SDimitry Andric     break;
86*0b57cec5SDimitry Andric   case CallingConv::Fastcall:
87*0b57cec5SDimitry Andric     OS << "__fastcall";
88*0b57cec5SDimitry Andric     break;
89*0b57cec5SDimitry Andric   case CallingConv::Pascal:
90*0b57cec5SDimitry Andric     OS << "__pascal";
91*0b57cec5SDimitry Andric     break;
92*0b57cec5SDimitry Andric   case CallingConv::Regcall:
93*0b57cec5SDimitry Andric     OS << "__regcall";
94*0b57cec5SDimitry Andric     break;
95*0b57cec5SDimitry Andric   case CallingConv::Stdcall:
96*0b57cec5SDimitry Andric     OS << "__stdcall";
97*0b57cec5SDimitry Andric     break;
98*0b57cec5SDimitry Andric   case CallingConv::Thiscall:
99*0b57cec5SDimitry Andric     OS << "__thiscall";
100*0b57cec5SDimitry Andric     break;
101*0b57cec5SDimitry Andric   case CallingConv::Eabi:
102*0b57cec5SDimitry Andric     OS << "__eabi";
103*0b57cec5SDimitry Andric     break;
104*0b57cec5SDimitry Andric   case CallingConv::Vectorcall:
105*0b57cec5SDimitry Andric     OS << "__vectorcall";
106*0b57cec5SDimitry Andric     break;
107*0b57cec5SDimitry Andric   case CallingConv::Clrcall:
108*0b57cec5SDimitry Andric     OS << "__clrcall";
109*0b57cec5SDimitry Andric     break;
110*0b57cec5SDimitry Andric   default:
111*0b57cec5SDimitry Andric     break;
112*0b57cec5SDimitry Andric   }
113*0b57cec5SDimitry Andric }
114*0b57cec5SDimitry Andric 
115*0b57cec5SDimitry Andric std::string Node::toString(OutputFlags Flags) const {
116*0b57cec5SDimitry Andric   OutputStream OS;
117*0b57cec5SDimitry Andric   initializeOutputStream(nullptr, nullptr, OS, 1024);
118*0b57cec5SDimitry Andric   this->output(OS, Flags);
119*0b57cec5SDimitry Andric   OS << '\0';
120*0b57cec5SDimitry Andric   return {OS.getBuffer()};
121*0b57cec5SDimitry Andric }
122*0b57cec5SDimitry Andric 
123*0b57cec5SDimitry Andric void TypeNode::outputQuals(bool SpaceBefore, bool SpaceAfter) const {}
124*0b57cec5SDimitry Andric 
125*0b57cec5SDimitry Andric void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
126*0b57cec5SDimitry Andric   switch (PrimKind) {
127*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void");
128*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool");
129*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char");
130*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char");
131*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");
132*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t");
133*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t");
134*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t");
135*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short");
136*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short");
137*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int");
138*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int");
139*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long");
140*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long");
141*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64");
142*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64");
143*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t");
144*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float");
145*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double");
146*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double");
147*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");
148*0b57cec5SDimitry Andric   }
149*0b57cec5SDimitry Andric   outputQualifiers(OS, Quals, true, false);
150*0b57cec5SDimitry Andric }
151*0b57cec5SDimitry Andric 
152*0b57cec5SDimitry Andric void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags) const {
153*0b57cec5SDimitry Andric   output(OS, Flags, ", ");
154*0b57cec5SDimitry Andric }
155*0b57cec5SDimitry Andric 
156*0b57cec5SDimitry Andric void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags,
157*0b57cec5SDimitry Andric                            StringView Separator) const {
158*0b57cec5SDimitry Andric   if (Count == 0)
159*0b57cec5SDimitry Andric     return;
160*0b57cec5SDimitry Andric   if (Nodes[0])
161*0b57cec5SDimitry Andric     Nodes[0]->output(OS, Flags);
162*0b57cec5SDimitry Andric   for (size_t I = 1; I < Count; ++I) {
163*0b57cec5SDimitry Andric     OS << Separator;
164*0b57cec5SDimitry Andric     Nodes[I]->output(OS, Flags);
165*0b57cec5SDimitry Andric   }
166*0b57cec5SDimitry Andric }
167*0b57cec5SDimitry Andric 
168*0b57cec5SDimitry Andric void EncodedStringLiteralNode::output(OutputStream &OS,
169*0b57cec5SDimitry Andric                                       OutputFlags Flags) const {
170*0b57cec5SDimitry Andric   switch (Char) {
171*0b57cec5SDimitry Andric   case CharKind::Wchar:
172*0b57cec5SDimitry Andric     OS << "L\"";
173*0b57cec5SDimitry Andric     break;
174*0b57cec5SDimitry Andric   case CharKind::Char:
175*0b57cec5SDimitry Andric     OS << "\"";
176*0b57cec5SDimitry Andric     break;
177*0b57cec5SDimitry Andric   case CharKind::Char16:
178*0b57cec5SDimitry Andric     OS << "u\"";
179*0b57cec5SDimitry Andric     break;
180*0b57cec5SDimitry Andric   case CharKind::Char32:
181*0b57cec5SDimitry Andric     OS << "U\"";
182*0b57cec5SDimitry Andric     break;
183*0b57cec5SDimitry Andric   }
184*0b57cec5SDimitry Andric   OS << DecodedString << "\"";
185*0b57cec5SDimitry Andric   if (IsTruncated)
186*0b57cec5SDimitry Andric     OS << "...";
187*0b57cec5SDimitry Andric }
188*0b57cec5SDimitry Andric 
189*0b57cec5SDimitry Andric void IntegerLiteralNode::output(OutputStream &OS, OutputFlags Flags) const {
190*0b57cec5SDimitry Andric   if (IsNegative)
191*0b57cec5SDimitry Andric     OS << '-';
192*0b57cec5SDimitry Andric   OS << Value;
193*0b57cec5SDimitry Andric }
194*0b57cec5SDimitry Andric 
195*0b57cec5SDimitry Andric void TemplateParameterReferenceNode::output(OutputStream &OS,
196*0b57cec5SDimitry Andric                                             OutputFlags Flags) const {
197*0b57cec5SDimitry Andric   if (ThunkOffsetCount > 0)
198*0b57cec5SDimitry Andric     OS << "{";
199*0b57cec5SDimitry Andric   else if (Affinity == PointerAffinity::Pointer)
200*0b57cec5SDimitry Andric     OS << "&";
201*0b57cec5SDimitry Andric 
202*0b57cec5SDimitry Andric   if (Symbol) {
203*0b57cec5SDimitry Andric     Symbol->output(OS, Flags);
204*0b57cec5SDimitry Andric     if (ThunkOffsetCount > 0)
205*0b57cec5SDimitry Andric       OS << ", ";
206*0b57cec5SDimitry Andric   }
207*0b57cec5SDimitry Andric 
208*0b57cec5SDimitry Andric   if (ThunkOffsetCount > 0)
209*0b57cec5SDimitry Andric     OS << ThunkOffsets[0];
210*0b57cec5SDimitry Andric   for (int I = 1; I < ThunkOffsetCount; ++I) {
211*0b57cec5SDimitry Andric     OS << ", " << ThunkOffsets[I];
212*0b57cec5SDimitry Andric   }
213*0b57cec5SDimitry Andric   if (ThunkOffsetCount > 0)
214*0b57cec5SDimitry Andric     OS << "}";
215*0b57cec5SDimitry Andric }
216*0b57cec5SDimitry Andric 
217*0b57cec5SDimitry Andric void IdentifierNode::outputTemplateParameters(OutputStream &OS,
218*0b57cec5SDimitry Andric                                               OutputFlags Flags) const {
219*0b57cec5SDimitry Andric   if (!TemplateParams)
220*0b57cec5SDimitry Andric     return;
221*0b57cec5SDimitry Andric   OS << "<";
222*0b57cec5SDimitry Andric   TemplateParams->output(OS, Flags);
223*0b57cec5SDimitry Andric   OS << ">";
224*0b57cec5SDimitry Andric }
225*0b57cec5SDimitry Andric 
226*0b57cec5SDimitry Andric void DynamicStructorIdentifierNode::output(OutputStream &OS,
227*0b57cec5SDimitry Andric                                            OutputFlags Flags) const {
228*0b57cec5SDimitry Andric   if (IsDestructor)
229*0b57cec5SDimitry Andric     OS << "`dynamic atexit destructor for ";
230*0b57cec5SDimitry Andric   else
231*0b57cec5SDimitry Andric     OS << "`dynamic initializer for ";
232*0b57cec5SDimitry Andric 
233*0b57cec5SDimitry Andric   if (Variable) {
234*0b57cec5SDimitry Andric     OS << "`";
235*0b57cec5SDimitry Andric     Variable->output(OS, Flags);
236*0b57cec5SDimitry Andric     OS << "''";
237*0b57cec5SDimitry Andric   } else {
238*0b57cec5SDimitry Andric     OS << "'";
239*0b57cec5SDimitry Andric     Name->output(OS, Flags);
240*0b57cec5SDimitry Andric     OS << "''";
241*0b57cec5SDimitry Andric   }
242*0b57cec5SDimitry Andric }
243*0b57cec5SDimitry Andric 
244*0b57cec5SDimitry Andric void NamedIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
245*0b57cec5SDimitry Andric   OS << Name;
246*0b57cec5SDimitry Andric   outputTemplateParameters(OS, Flags);
247*0b57cec5SDimitry Andric }
248*0b57cec5SDimitry Andric 
249*0b57cec5SDimitry Andric void IntrinsicFunctionIdentifierNode::output(OutputStream &OS,
250*0b57cec5SDimitry Andric                                              OutputFlags Flags) const {
251*0b57cec5SDimitry Andric   switch (Operator) {
252*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new");
253*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete");
254*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator=");
255*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>");
256*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<");
257*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!");
258*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator==");
259*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!=");
260*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript,
261*0b57cec5SDimitry Andric                             "operator[]");
262*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->");
263*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++");
264*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--");
265*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-");
266*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+");
267*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*");
268*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&");
269*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer,
270*0b57cec5SDimitry Andric                             "operator->*");
271*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/");
272*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%");
273*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<");
274*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<=");
275*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>");
276*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual,
277*0b57cec5SDimitry Andric                             "operator>=");
278*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,");
279*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()");
280*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~");
281*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^");
282*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|");
283*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&");
284*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||");
285*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*=");
286*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+=");
287*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-=");
288*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/=");
289*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%=");
290*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>=");
291*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<=");
292*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual,
293*0b57cec5SDimitry Andric                             "operator&=");
294*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual,
295*0b57cec5SDimitry Andric                             "operator|=");
296*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual,
297*0b57cec5SDimitry Andric                             "operator^=");
298*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'");
299*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor,
300*0b57cec5SDimitry Andric                             "`vector deleting dtor'");
301*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure,
302*0b57cec5SDimitry Andric                             "`default ctor closure'");
303*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor,
304*0b57cec5SDimitry Andric                             "`scalar deleting dtor'");
305*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter,
306*0b57cec5SDimitry Andric                             "`vector ctor iterator'");
307*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter,
308*0b57cec5SDimitry Andric                             "`vector dtor iterator'");
309*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter,
310*0b57cec5SDimitry Andric                             "`vector vbase ctor iterator'");
311*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap,
312*0b57cec5SDimitry Andric                             "`virtual displacement map'");
313*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter,
314*0b57cec5SDimitry Andric                             "`eh vector ctor iterator'");
315*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter,
316*0b57cec5SDimitry Andric                             "`eh vector dtor iterator'");
317*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter,
318*0b57cec5SDimitry Andric                             "`eh vector vbase ctor iterator'");
319*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure,
320*0b57cec5SDimitry Andric                             "`copy ctor closure'");
321*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure,
322*0b57cec5SDimitry Andric                             "`local vftable ctor closure'");
323*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]");
324*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete,
325*0b57cec5SDimitry Andric                             "operator delete[]");
326*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter,
327*0b57cec5SDimitry Andric                             "`managed vector ctor iterator'");
328*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter,
329*0b57cec5SDimitry Andric                             "`managed vector dtor iterator'");
330*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter,
331*0b57cec5SDimitry Andric                             "`EH vector copy ctor iterator'");
332*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter,
333*0b57cec5SDimitry Andric                             "`EH vector vbase copy ctor iterator'");
334*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter,
335*0b57cec5SDimitry Andric                             "`vector copy ctor iterator'");
336*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter,
337*0b57cec5SDimitry Andric                             "`vector vbase copy constructor iterator'");
338*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter,
339*0b57cec5SDimitry Andric                             "`managed vector vbase copy constructor iterator'");
340*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait,
341*0b57cec5SDimitry Andric                             "operator co_await");
342*0b57cec5SDimitry Andric     OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>");
343*0b57cec5SDimitry Andric   case IntrinsicFunctionKind::MaxIntrinsic:
344*0b57cec5SDimitry Andric   case IntrinsicFunctionKind::None:
345*0b57cec5SDimitry Andric     break;
346*0b57cec5SDimitry Andric   }
347*0b57cec5SDimitry Andric   outputTemplateParameters(OS, Flags);
348*0b57cec5SDimitry Andric }
349*0b57cec5SDimitry Andric 
350*0b57cec5SDimitry Andric void LocalStaticGuardIdentifierNode::output(OutputStream &OS,
351*0b57cec5SDimitry Andric                                             OutputFlags Flags) const {
352*0b57cec5SDimitry Andric   if (IsThread)
353*0b57cec5SDimitry Andric     OS << "`local static thread guard'";
354*0b57cec5SDimitry Andric   else
355*0b57cec5SDimitry Andric     OS << "`local static guard'";
356*0b57cec5SDimitry Andric   if (ScopeIndex > 0)
357*0b57cec5SDimitry Andric     OS << "{" << ScopeIndex << "}";
358*0b57cec5SDimitry Andric }
359*0b57cec5SDimitry Andric 
360*0b57cec5SDimitry Andric void ConversionOperatorIdentifierNode::output(OutputStream &OS,
361*0b57cec5SDimitry Andric                                               OutputFlags Flags) const {
362*0b57cec5SDimitry Andric   OS << "operator";
363*0b57cec5SDimitry Andric   outputTemplateParameters(OS, Flags);
364*0b57cec5SDimitry Andric   OS << " ";
365*0b57cec5SDimitry Andric   TargetType->output(OS, Flags);
366*0b57cec5SDimitry Andric }
367*0b57cec5SDimitry Andric 
368*0b57cec5SDimitry Andric void StructorIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
369*0b57cec5SDimitry Andric   if (IsDestructor)
370*0b57cec5SDimitry Andric     OS << "~";
371*0b57cec5SDimitry Andric   Class->output(OS, Flags);
372*0b57cec5SDimitry Andric   outputTemplateParameters(OS, Flags);
373*0b57cec5SDimitry Andric }
374*0b57cec5SDimitry Andric 
375*0b57cec5SDimitry Andric void LiteralOperatorIdentifierNode::output(OutputStream &OS,
376*0b57cec5SDimitry Andric                                            OutputFlags Flags) const {
377*0b57cec5SDimitry Andric   OS << "operator \"\"" << Name;
378*0b57cec5SDimitry Andric   outputTemplateParameters(OS, Flags);
379*0b57cec5SDimitry Andric }
380*0b57cec5SDimitry Andric 
381*0b57cec5SDimitry Andric void FunctionSignatureNode::outputPre(OutputStream &OS,
382*0b57cec5SDimitry Andric                                       OutputFlags Flags) const {
383*0b57cec5SDimitry Andric   if (FunctionClass & FC_Public)
384*0b57cec5SDimitry Andric     OS << "public: ";
385*0b57cec5SDimitry Andric   if (FunctionClass & FC_Protected)
386*0b57cec5SDimitry Andric     OS << "protected: ";
387*0b57cec5SDimitry Andric   if (FunctionClass & FC_Private)
388*0b57cec5SDimitry Andric     OS << "private: ";
389*0b57cec5SDimitry Andric 
390*0b57cec5SDimitry Andric   if (!(FunctionClass & FC_Global)) {
391*0b57cec5SDimitry Andric     if (FunctionClass & FC_Static)
392*0b57cec5SDimitry Andric       OS << "static ";
393*0b57cec5SDimitry Andric   }
394*0b57cec5SDimitry Andric   if (FunctionClass & FC_Virtual)
395*0b57cec5SDimitry Andric     OS << "virtual ";
396*0b57cec5SDimitry Andric 
397*0b57cec5SDimitry Andric   if (FunctionClass & FC_ExternC)
398*0b57cec5SDimitry Andric     OS << "extern \"C\" ";
399*0b57cec5SDimitry Andric 
400*0b57cec5SDimitry Andric   if (ReturnType) {
401*0b57cec5SDimitry Andric     ReturnType->outputPre(OS, Flags);
402*0b57cec5SDimitry Andric     OS << " ";
403*0b57cec5SDimitry Andric   }
404*0b57cec5SDimitry Andric 
405*0b57cec5SDimitry Andric   if (!(Flags & OF_NoCallingConvention))
406*0b57cec5SDimitry Andric     outputCallingConvention(OS, CallConvention);
407*0b57cec5SDimitry Andric }
408*0b57cec5SDimitry Andric 
409*0b57cec5SDimitry Andric void FunctionSignatureNode::outputPost(OutputStream &OS,
410*0b57cec5SDimitry Andric                                        OutputFlags Flags) const {
411*0b57cec5SDimitry Andric   if (!(FunctionClass & FC_NoParameterList)) {
412*0b57cec5SDimitry Andric     OS << "(";
413*0b57cec5SDimitry Andric     if (Params)
414*0b57cec5SDimitry Andric       Params->output(OS, Flags);
415*0b57cec5SDimitry Andric     else
416*0b57cec5SDimitry Andric       OS << "void";
417*0b57cec5SDimitry Andric 
418*0b57cec5SDimitry Andric     if (IsVariadic) {
419*0b57cec5SDimitry Andric       if (OS.back() != '(')
420*0b57cec5SDimitry Andric         OS << ", ";
421*0b57cec5SDimitry Andric       OS << "...";
422*0b57cec5SDimitry Andric     }
423*0b57cec5SDimitry Andric     OS << ")";
424*0b57cec5SDimitry Andric   }
425*0b57cec5SDimitry Andric 
426*0b57cec5SDimitry Andric   if (Quals & Q_Const)
427*0b57cec5SDimitry Andric     OS << " const";
428*0b57cec5SDimitry Andric   if (Quals & Q_Volatile)
429*0b57cec5SDimitry Andric     OS << " volatile";
430*0b57cec5SDimitry Andric   if (Quals & Q_Restrict)
431*0b57cec5SDimitry Andric     OS << " __restrict";
432*0b57cec5SDimitry Andric   if (Quals & Q_Unaligned)
433*0b57cec5SDimitry Andric     OS << " __unaligned";
434*0b57cec5SDimitry Andric 
435*0b57cec5SDimitry Andric   if (IsNoexcept)
436*0b57cec5SDimitry Andric     OS << " noexcept";
437*0b57cec5SDimitry Andric 
438*0b57cec5SDimitry Andric   if (RefQualifier == FunctionRefQualifier::Reference)
439*0b57cec5SDimitry Andric     OS << " &";
440*0b57cec5SDimitry Andric   else if (RefQualifier == FunctionRefQualifier::RValueReference)
441*0b57cec5SDimitry Andric     OS << " &&";
442*0b57cec5SDimitry Andric 
443*0b57cec5SDimitry Andric   if (ReturnType)
444*0b57cec5SDimitry Andric     ReturnType->outputPost(OS, Flags);
445*0b57cec5SDimitry Andric }
446*0b57cec5SDimitry Andric 
447*0b57cec5SDimitry Andric void ThunkSignatureNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
448*0b57cec5SDimitry Andric   OS << "[thunk]: ";
449*0b57cec5SDimitry Andric 
450*0b57cec5SDimitry Andric   FunctionSignatureNode::outputPre(OS, Flags);
451*0b57cec5SDimitry Andric }
452*0b57cec5SDimitry Andric 
453*0b57cec5SDimitry Andric void ThunkSignatureNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
454*0b57cec5SDimitry Andric   if (FunctionClass & FC_StaticThisAdjust) {
455*0b57cec5SDimitry Andric     OS << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
456*0b57cec5SDimitry Andric   } else if (FunctionClass & FC_VirtualThisAdjust) {
457*0b57cec5SDimitry Andric     if (FunctionClass & FC_VirtualThisAdjustEx) {
458*0b57cec5SDimitry Andric       OS << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
459*0b57cec5SDimitry Andric          << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset
460*0b57cec5SDimitry Andric          << ", " << ThisAdjust.StaticOffset << "}'";
461*0b57cec5SDimitry Andric     } else {
462*0b57cec5SDimitry Andric       OS << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
463*0b57cec5SDimitry Andric          << ThisAdjust.StaticOffset << "}'";
464*0b57cec5SDimitry Andric     }
465*0b57cec5SDimitry Andric   }
466*0b57cec5SDimitry Andric 
467*0b57cec5SDimitry Andric   FunctionSignatureNode::outputPost(OS, Flags);
468*0b57cec5SDimitry Andric }
469*0b57cec5SDimitry Andric 
470*0b57cec5SDimitry Andric void PointerTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
471*0b57cec5SDimitry Andric   if (Pointee->kind() == NodeKind::FunctionSignature) {
472*0b57cec5SDimitry Andric     // If this is a pointer to a function, don't output the calling convention.
473*0b57cec5SDimitry Andric     // It needs to go inside the parentheses.
474*0b57cec5SDimitry Andric     const FunctionSignatureNode *Sig =
475*0b57cec5SDimitry Andric         static_cast<const FunctionSignatureNode *>(Pointee);
476*0b57cec5SDimitry Andric     Sig->outputPre(OS, OF_NoCallingConvention);
477*0b57cec5SDimitry Andric   } else
478*0b57cec5SDimitry Andric     Pointee->outputPre(OS, Flags);
479*0b57cec5SDimitry Andric 
480*0b57cec5SDimitry Andric   outputSpaceIfNecessary(OS);
481*0b57cec5SDimitry Andric 
482*0b57cec5SDimitry Andric   if (Quals & Q_Unaligned)
483*0b57cec5SDimitry Andric     OS << "__unaligned ";
484*0b57cec5SDimitry Andric 
485*0b57cec5SDimitry Andric   if (Pointee->kind() == NodeKind::ArrayType) {
486*0b57cec5SDimitry Andric     OS << "(";
487*0b57cec5SDimitry Andric   } else if (Pointee->kind() == NodeKind::FunctionSignature) {
488*0b57cec5SDimitry Andric     OS << "(";
489*0b57cec5SDimitry Andric     const FunctionSignatureNode *Sig =
490*0b57cec5SDimitry Andric         static_cast<const FunctionSignatureNode *>(Pointee);
491*0b57cec5SDimitry Andric     outputCallingConvention(OS, Sig->CallConvention);
492*0b57cec5SDimitry Andric     OS << " ";
493*0b57cec5SDimitry Andric   }
494*0b57cec5SDimitry Andric 
495*0b57cec5SDimitry Andric   if (ClassParent) {
496*0b57cec5SDimitry Andric     ClassParent->output(OS, Flags);
497*0b57cec5SDimitry Andric     OS << "::";
498*0b57cec5SDimitry Andric   }
499*0b57cec5SDimitry Andric 
500*0b57cec5SDimitry Andric   switch (Affinity) {
501*0b57cec5SDimitry Andric   case PointerAffinity::Pointer:
502*0b57cec5SDimitry Andric     OS << "*";
503*0b57cec5SDimitry Andric     break;
504*0b57cec5SDimitry Andric   case PointerAffinity::Reference:
505*0b57cec5SDimitry Andric     OS << "&";
506*0b57cec5SDimitry Andric     break;
507*0b57cec5SDimitry Andric   case PointerAffinity::RValueReference:
508*0b57cec5SDimitry Andric     OS << "&&";
509*0b57cec5SDimitry Andric     break;
510*0b57cec5SDimitry Andric   default:
511*0b57cec5SDimitry Andric     assert(false);
512*0b57cec5SDimitry Andric   }
513*0b57cec5SDimitry Andric   outputQualifiers(OS, Quals, false, false);
514*0b57cec5SDimitry Andric }
515*0b57cec5SDimitry Andric 
516*0b57cec5SDimitry Andric void PointerTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
517*0b57cec5SDimitry Andric   if (Pointee->kind() == NodeKind::ArrayType ||
518*0b57cec5SDimitry Andric       Pointee->kind() == NodeKind::FunctionSignature)
519*0b57cec5SDimitry Andric     OS << ")";
520*0b57cec5SDimitry Andric 
521*0b57cec5SDimitry Andric   Pointee->outputPost(OS, Flags);
522*0b57cec5SDimitry Andric }
523*0b57cec5SDimitry Andric 
524*0b57cec5SDimitry Andric void TagTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
525*0b57cec5SDimitry Andric   if (!(Flags & OF_NoTagSpecifier)) {
526*0b57cec5SDimitry Andric     switch (Tag) {
527*0b57cec5SDimitry Andric       OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");
528*0b57cec5SDimitry Andric       OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct");
529*0b57cec5SDimitry Andric       OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");
530*0b57cec5SDimitry Andric       OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");
531*0b57cec5SDimitry Andric     }
532*0b57cec5SDimitry Andric     OS << " ";
533*0b57cec5SDimitry Andric   }
534*0b57cec5SDimitry Andric   QualifiedName->output(OS, Flags);
535*0b57cec5SDimitry Andric   outputQualifiers(OS, Quals, true, false);
536*0b57cec5SDimitry Andric }
537*0b57cec5SDimitry Andric 
538*0b57cec5SDimitry Andric void TagTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
539*0b57cec5SDimitry Andric 
540*0b57cec5SDimitry Andric void ArrayTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
541*0b57cec5SDimitry Andric   ElementType->outputPre(OS, Flags);
542*0b57cec5SDimitry Andric   outputQualifiers(OS, Quals, true, false);
543*0b57cec5SDimitry Andric }
544*0b57cec5SDimitry Andric 
545*0b57cec5SDimitry Andric void ArrayTypeNode::outputOneDimension(OutputStream &OS, OutputFlags Flags,
546*0b57cec5SDimitry Andric                                        Node *N) const {
547*0b57cec5SDimitry Andric   assert(N->kind() == NodeKind::IntegerLiteral);
548*0b57cec5SDimitry Andric   IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);
549*0b57cec5SDimitry Andric   if (ILN->Value != 0)
550*0b57cec5SDimitry Andric     ILN->output(OS, Flags);
551*0b57cec5SDimitry Andric }
552*0b57cec5SDimitry Andric 
553*0b57cec5SDimitry Andric void ArrayTypeNode::outputDimensionsImpl(OutputStream &OS,
554*0b57cec5SDimitry Andric                                          OutputFlags Flags) const {
555*0b57cec5SDimitry Andric   if (Dimensions->Count == 0)
556*0b57cec5SDimitry Andric     return;
557*0b57cec5SDimitry Andric 
558*0b57cec5SDimitry Andric   outputOneDimension(OS, Flags, Dimensions->Nodes[0]);
559*0b57cec5SDimitry Andric   for (size_t I = 1; I < Dimensions->Count; ++I) {
560*0b57cec5SDimitry Andric     OS << "][";
561*0b57cec5SDimitry Andric     outputOneDimension(OS, Flags, Dimensions->Nodes[I]);
562*0b57cec5SDimitry Andric   }
563*0b57cec5SDimitry Andric }
564*0b57cec5SDimitry Andric 
565*0b57cec5SDimitry Andric void ArrayTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
566*0b57cec5SDimitry Andric   OS << "[";
567*0b57cec5SDimitry Andric   outputDimensionsImpl(OS, Flags);
568*0b57cec5SDimitry Andric   OS << "]";
569*0b57cec5SDimitry Andric 
570*0b57cec5SDimitry Andric   ElementType->outputPost(OS, Flags);
571*0b57cec5SDimitry Andric }
572*0b57cec5SDimitry Andric 
573*0b57cec5SDimitry Andric void SymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
574*0b57cec5SDimitry Andric   Name->output(OS, Flags);
575*0b57cec5SDimitry Andric }
576*0b57cec5SDimitry Andric 
577*0b57cec5SDimitry Andric void FunctionSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
578*0b57cec5SDimitry Andric   Signature->outputPre(OS, Flags);
579*0b57cec5SDimitry Andric   outputSpaceIfNecessary(OS);
580*0b57cec5SDimitry Andric   Name->output(OS, Flags);
581*0b57cec5SDimitry Andric   Signature->outputPost(OS, Flags);
582*0b57cec5SDimitry Andric }
583*0b57cec5SDimitry Andric 
584*0b57cec5SDimitry Andric void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
585*0b57cec5SDimitry Andric   switch (SC) {
586*0b57cec5SDimitry Andric   case StorageClass::PrivateStatic:
587*0b57cec5SDimitry Andric     OS << "private: static ";
588*0b57cec5SDimitry Andric     break;
589*0b57cec5SDimitry Andric   case StorageClass::PublicStatic:
590*0b57cec5SDimitry Andric     OS << "public: static ";
591*0b57cec5SDimitry Andric     break;
592*0b57cec5SDimitry Andric   case StorageClass::ProtectedStatic:
593*0b57cec5SDimitry Andric     OS << "protected: static ";
594*0b57cec5SDimitry Andric     break;
595*0b57cec5SDimitry Andric   default:
596*0b57cec5SDimitry Andric     break;
597*0b57cec5SDimitry Andric   }
598*0b57cec5SDimitry Andric 
599*0b57cec5SDimitry Andric   if (Type) {
600*0b57cec5SDimitry Andric     Type->outputPre(OS, Flags);
601*0b57cec5SDimitry Andric     outputSpaceIfNecessary(OS);
602*0b57cec5SDimitry Andric   }
603*0b57cec5SDimitry Andric   Name->output(OS, Flags);
604*0b57cec5SDimitry Andric   if (Type)
605*0b57cec5SDimitry Andric     Type->outputPost(OS, Flags);
606*0b57cec5SDimitry Andric }
607*0b57cec5SDimitry Andric 
608*0b57cec5SDimitry Andric void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
609*0b57cec5SDimitry Andric   Identifier->output(OS, Flags);
610*0b57cec5SDimitry Andric }
611*0b57cec5SDimitry Andric void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
612*0b57cec5SDimitry Andric 
613*0b57cec5SDimitry Andric void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const {
614*0b57cec5SDimitry Andric   Components->output(OS, Flags, "::");
615*0b57cec5SDimitry Andric }
616*0b57cec5SDimitry Andric 
617*0b57cec5SDimitry Andric void RttiBaseClassDescriptorNode::output(OutputStream &OS,
618*0b57cec5SDimitry Andric                                          OutputFlags Flags) const {
619*0b57cec5SDimitry Andric   OS << "`RTTI Base Class Descriptor at (";
620*0b57cec5SDimitry Andric   OS << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
621*0b57cec5SDimitry Andric      << this->Flags;
622*0b57cec5SDimitry Andric   OS << ")'";
623*0b57cec5SDimitry Andric }
624*0b57cec5SDimitry Andric 
625*0b57cec5SDimitry Andric void LocalStaticGuardVariableNode::output(OutputStream &OS,
626*0b57cec5SDimitry Andric                                           OutputFlags Flags) const {
627*0b57cec5SDimitry Andric   Name->output(OS, Flags);
628*0b57cec5SDimitry Andric }
629*0b57cec5SDimitry Andric 
630*0b57cec5SDimitry Andric void VcallThunkIdentifierNode::output(OutputStream &OS,
631*0b57cec5SDimitry Andric                                       OutputFlags Flags) const {
632*0b57cec5SDimitry Andric   OS << "`vcall'{" << OffsetInVTable << ", {flat}}";
633*0b57cec5SDimitry Andric }
634*0b57cec5SDimitry Andric 
635*0b57cec5SDimitry Andric void SpecialTableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
636*0b57cec5SDimitry Andric   outputQualifiers(OS, Quals, false, true);
637*0b57cec5SDimitry Andric   Name->output(OS, Flags);
638*0b57cec5SDimitry Andric   if (TargetName) {
639*0b57cec5SDimitry Andric     OS << "{for `";
640*0b57cec5SDimitry Andric     TargetName->output(OS, Flags);
641*0b57cec5SDimitry Andric     OS << "'}";
642*0b57cec5SDimitry Andric   }
643*0b57cec5SDimitry Andric   return;
644*0b57cec5SDimitry Andric }
645