blob: 2c1e5f44f4227a2132e85f5f8bdd560c52a60fa4 [file] [log] [blame]
Zachary Turner03312862018-08-27 03:48:03 +00001//===- MicrosoftDemangle.cpp ----------------------------------------------===//
2//
Chandler Carruth57b08b02019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Zachary Turner03312862018-08-27 03:48:03 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines a demangler for MSVC-style mangled symbols.
10//
11//===----------------------------------------------------------------------===//
12
Zachary Turner7ba90562018-11-01 15:07:32 +000013#include "llvm/Demangle/MicrosoftDemangleNodes.h"
Erik Pilkington5094e5e2019-01-17 20:37:51 +000014#include "llvm/Demangle/DemangleConfig.h"
Zachary Turner03312862018-08-27 03:48:03 +000015#include "llvm/Demangle/Utility.h"
Chandler Carruthbe4a5492018-08-27 06:52:14 +000016#include <cctype>
Zachary Turner1b9a9382018-12-17 16:42:26 +000017#include <string>
Zachary Turner03312862018-08-27 03:48:03 +000018
19using namespace llvm;
20using namespace ms_demangle;
21
22#define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \
23 case Enum::Value: \
24 OS << Desc; \
25 break;
26
27// Writes a space if the last token does not end with a punctuation.
28static void outputSpaceIfNecessary(OutputStream &OS) {
29 if (OS.empty())
30 return;
31
32 char C = OS.back();
Chandler Carruthbe4a5492018-08-27 06:52:14 +000033 if (std::isalnum(C) || C == '>')
Zachary Turner03312862018-08-27 03:48:03 +000034 OS << " ";
35}
36
37static bool outputSingleQualifier(OutputStream &OS, Qualifiers Q) {
38 switch (Q) {
39 case Q_Const:
40 OS << "const";
41 return true;
42 case Q_Volatile:
43 OS << "volatile";
44 return true;
45 case Q_Restrict:
46 OS << "__restrict";
47 return true;
48 default:
49 break;
50 }
51 return false;
52}
53
54static bool outputQualifierIfPresent(OutputStream &OS, Qualifiers Q,
55 Qualifiers Mask, bool NeedSpace) {
56 if (!(Q & Mask))
57 return NeedSpace;
58
59 if (NeedSpace)
60 OS << " ";
61
62 outputSingleQualifier(OS, Mask);
63 return true;
64}
65
66static void outputQualifiers(OutputStream &OS, Qualifiers Q, bool SpaceBefore,
67 bool SpaceAfter) {
68 if (Q == Q_None)
69 return;
70
71 size_t Pos1 = OS.getCurrentPosition();
72 SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Const, SpaceBefore);
73 SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Volatile, SpaceBefore);
74 SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Restrict, SpaceBefore);
75 size_t Pos2 = OS.getCurrentPosition();
76 if (SpaceAfter && Pos2 > Pos1)
77 OS << " ";
78}
79
80static void outputCallingConvention(OutputStream &OS, CallingConv CC) {
81 outputSpaceIfNecessary(OS);
82
83 switch (CC) {
84 case CallingConv::Cdecl:
85 OS << "__cdecl";
86 break;
87 case CallingConv::Fastcall:
88 OS << "__fastcall";
89 break;
90 case CallingConv::Pascal:
91 OS << "__pascal";
92 break;
93 case CallingConv::Regcall:
94 OS << "__regcall";
95 break;
96 case CallingConv::Stdcall:
97 OS << "__stdcall";
98 break;
99 case CallingConv::Thiscall:
100 OS << "__thiscall";
101 break;
102 case CallingConv::Eabi:
103 OS << "__eabi";
104 break;
105 case CallingConv::Vectorcall:
106 OS << "__vectorcall";
107 break;
108 case CallingConv::Clrcall:
109 OS << "__clrcall";
110 break;
111 default:
112 break;
113 }
114}
115
Zachary Turnerba797b62019-01-02 18:33:12 +0000116std::string Node::toString(OutputFlags Flags) const {
Zachary Turnerb4725122018-12-17 16:14:50 +0000117 OutputStream OS;
118 initializeOutputStream(nullptr, nullptr, OS, 1024);
Zachary Turnerba797b62019-01-02 18:33:12 +0000119 this->output(OS, Flags);
Zachary Turnerb4725122018-12-17 16:14:50 +0000120 OS << '\0';
121 return {OS.getBuffer()};
122}
123
Zachary Turner03312862018-08-27 03:48:03 +0000124void TypeNode::outputQuals(bool SpaceBefore, bool SpaceAfter) const {}
125
Zachary Turner38d2edd2018-08-29 03:59:17 +0000126void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000127 switch (PrimKind) {
128 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void");
129 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool");
130 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char");
131 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char");
132 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");
133 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t");
134 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t");
135 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short");
136 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short");
137 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int");
138 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int");
139 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long");
140 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long");
141 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64");
142 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64");
143 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t");
144 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float");
145 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double");
146 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double");
147 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");
148 }
149 outputQualifiers(OS, Quals, true, false);
150}
151
Zachary Turner38d2edd2018-08-29 03:59:17 +0000152void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags) const {
153 output(OS, Flags, ", ");
154}
Zachary Turner03312862018-08-27 03:48:03 +0000155
Zachary Turner38d2edd2018-08-29 03:59:17 +0000156void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags,
157 StringView Separator) const {
Zachary Turner03312862018-08-27 03:48:03 +0000158 if (Count == 0)
159 return;
160 if (Nodes[0])
Zachary Turner38d2edd2018-08-29 03:59:17 +0000161 Nodes[0]->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000162 for (size_t I = 1; I < Count; ++I) {
163 OS << Separator;
Zachary Turner38d2edd2018-08-29 03:59:17 +0000164 Nodes[I]->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000165 }
166}
167
Zachary Turner38d2edd2018-08-29 03:59:17 +0000168void EncodedStringLiteralNode::output(OutputStream &OS,
169 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000170 switch (Char) {
171 case CharKind::Wchar:
Nico Weberdfc08ba2018-11-09 19:28:50 +0000172 OS << "L\"";
Zachary Turner03312862018-08-27 03:48:03 +0000173 break;
174 case CharKind::Char:
Nico Weberdfc08ba2018-11-09 19:28:50 +0000175 OS << "\"";
Zachary Turner03312862018-08-27 03:48:03 +0000176 break;
177 case CharKind::Char16:
Nico Weberdfc08ba2018-11-09 19:28:50 +0000178 OS << "u\"";
Zachary Turner03312862018-08-27 03:48:03 +0000179 break;
180 case CharKind::Char32:
Nico Weberdfc08ba2018-11-09 19:28:50 +0000181 OS << "U\"";
Zachary Turner03312862018-08-27 03:48:03 +0000182 break;
183 }
184 OS << DecodedString << "\"";
185 if (IsTruncated)
186 OS << "...";
Zachary Turner03312862018-08-27 03:48:03 +0000187}
188
Zachary Turner38d2edd2018-08-29 03:59:17 +0000189void IntegerLiteralNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000190 if (IsNegative)
191 OS << '-';
192 OS << Value;
193}
194
Zachary Turner38d2edd2018-08-29 03:59:17 +0000195void TemplateParameterReferenceNode::output(OutputStream &OS,
196 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000197 if (ThunkOffsetCount > 0)
198 OS << "{";
199 else if (Affinity == PointerAffinity::Pointer)
200 OS << "&";
201
202 if (Symbol) {
Zachary Turner38d2edd2018-08-29 03:59:17 +0000203 Symbol->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000204 if (ThunkOffsetCount > 0)
205 OS << ", ";
206 }
207
208 if (ThunkOffsetCount > 0)
209 OS << ThunkOffsets[0];
210 for (int I = 1; I < ThunkOffsetCount; ++I) {
211 OS << ", " << ThunkOffsets[I];
212 }
213 if (ThunkOffsetCount > 0)
214 OS << "}";
215}
216
Zachary Turner38d2edd2018-08-29 03:59:17 +0000217void IdentifierNode::outputTemplateParameters(OutputStream &OS,
218 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000219 if (!TemplateParams)
220 return;
221 OS << "<";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000222 TemplateParams->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000223 OS << ">";
224}
225
Zachary Turner38d2edd2018-08-29 03:59:17 +0000226void DynamicStructorIdentifierNode::output(OutputStream &OS,
227 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000228 if (IsDestructor)
229 OS << "`dynamic atexit destructor for ";
230 else
231 OS << "`dynamic initializer for ";
232
Zachary Turner32a8a202018-08-29 23:56:09 +0000233 if (Variable) {
234 OS << "`";
235 Variable->output(OS, Flags);
236 OS << "''";
237 } else {
238 OS << "'";
239 Name->output(OS, Flags);
240 OS << "''";
241 }
Zachary Turner03312862018-08-27 03:48:03 +0000242}
243
Zachary Turner38d2edd2018-08-29 03:59:17 +0000244void NamedIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000245 OS << Name;
Zachary Turner38d2edd2018-08-29 03:59:17 +0000246 outputTemplateParameters(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000247}
248
Zachary Turner38d2edd2018-08-29 03:59:17 +0000249void IntrinsicFunctionIdentifierNode::output(OutputStream &OS,
250 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000251 switch (Operator) {
252 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new");
253 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete");
254 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator=");
255 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>");
256 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<");
257 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!");
258 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator==");
259 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!=");
260 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript,
261 "operator[]");
262 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->");
263 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++");
264 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--");
265 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-");
266 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+");
267 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*");
268 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&");
269 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer,
270 "operator->*");
271 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/");
272 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%");
273 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<");
274 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<=");
275 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>");
276 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual,
277 "operator>=");
278 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,");
279 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()");
280 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~");
281 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^");
282 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|");
283 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&");
284 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||");
285 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*=");
286 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+=");
287 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-=");
288 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/=");
289 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%=");
290 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>=");
291 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<=");
292 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual,
293 "operator&=");
294 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual,
295 "operator|=");
296 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual,
297 "operator^=");
298 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'");
299 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor,
300 "`vector deleting dtor'");
301 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure,
302 "`default ctor closure'");
303 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor,
304 "`scalar deleting dtor'");
305 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter,
306 "`vector ctor iterator'");
307 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter,
308 "`vector dtor iterator'");
309 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter,
310 "`vector vbase ctor iterator'");
311 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap,
312 "`virtual displacement map'");
313 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter,
314 "`eh vector ctor iterator'");
315 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter,
316 "`eh vector dtor iterator'");
317 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter,
318 "`eh vector vbase ctor iterator'");
319 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure,
320 "`copy ctor closure'");
321 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure,
322 "`local vftable ctor closure'");
323 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]");
324 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete,
325 "operator delete[]");
326 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter,
327 "`managed vector ctor iterator'");
328 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter,
329 "`managed vector dtor iterator'");
330 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter,
331 "`EH vector copy ctor iterator'");
332 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter,
333 "`EH vector vbase copy ctor iterator'");
334 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter,
335 "`vector copy ctor iterator'");
336 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter,
337 "`vector vbase copy constructor iterator'");
338 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter,
339 "`managed vector vbase copy constructor iterator'");
Nico Webere8f21b12019-04-23 16:20:27 +0000340 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait,
341 "operator co_await");
342 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>");
Zachary Turner03312862018-08-27 03:48:03 +0000343 case IntrinsicFunctionKind::MaxIntrinsic:
344 case IntrinsicFunctionKind::None:
345 break;
346 }
Zachary Turner38d2edd2018-08-29 03:59:17 +0000347 outputTemplateParameters(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000348}
349
Zachary Turner38d2edd2018-08-29 03:59:17 +0000350void LocalStaticGuardIdentifierNode::output(OutputStream &OS,
351 OutputFlags Flags) const {
Nico Weber88ab2812019-05-28 14:54:49 +0000352 if (IsThread)
353 OS << "`local static thread guard'";
354 else
355 OS << "`local static guard'";
Zachary Turner03312862018-08-27 03:48:03 +0000356 if (ScopeIndex > 0)
357 OS << "{" << ScopeIndex << "}";
358}
359
Zachary Turner38d2edd2018-08-29 03:59:17 +0000360void ConversionOperatorIdentifierNode::output(OutputStream &OS,
361 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000362 OS << "operator";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000363 outputTemplateParameters(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000364 OS << " ";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000365 TargetType->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000366}
367
Zachary Turner38d2edd2018-08-29 03:59:17 +0000368void StructorIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000369 if (IsDestructor)
370 OS << "~";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000371 Class->output(OS, Flags);
372 outputTemplateParameters(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000373}
374
Zachary Turner38d2edd2018-08-29 03:59:17 +0000375void LiteralOperatorIdentifierNode::output(OutputStream &OS,
376 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000377 OS << "operator \"\"" << Name;
Zachary Turner38d2edd2018-08-29 03:59:17 +0000378 outputTemplateParameters(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000379}
380
381void FunctionSignatureNode::outputPre(OutputStream &OS,
Zachary Turner38d2edd2018-08-29 03:59:17 +0000382 OutputFlags Flags) const {
Nico Webera92b4632018-11-13 20:18:26 +0000383 if (FunctionClass & FC_Public)
384 OS << "public: ";
385 if (FunctionClass & FC_Protected)
386 OS << "protected: ";
387 if (FunctionClass & FC_Private)
388 OS << "private: ";
389
Zachary Turner03312862018-08-27 03:48:03 +0000390 if (!(FunctionClass & FC_Global)) {
391 if (FunctionClass & FC_Static)
392 OS << "static ";
393 }
Zachary Turner03312862018-08-27 03:48:03 +0000394 if (FunctionClass & FC_Virtual)
395 OS << "virtual ";
396
Nico Webera92b4632018-11-13 20:18:26 +0000397 if (FunctionClass & FC_ExternC)
398 OS << "extern \"C\" ";
399
Zachary Turner03312862018-08-27 03:48:03 +0000400 if (ReturnType) {
Zachary Turner38d2edd2018-08-29 03:59:17 +0000401 ReturnType->outputPre(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000402 OS << " ";
403 }
404
Zachary Turner38d2edd2018-08-29 03:59:17 +0000405 if (!(Flags & OF_NoCallingConvention))
Zachary Turner03312862018-08-27 03:48:03 +0000406 outputCallingConvention(OS, CallConvention);
407}
408
409void FunctionSignatureNode::outputPost(OutputStream &OS,
Zachary Turner38d2edd2018-08-29 03:59:17 +0000410 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000411 if (!(FunctionClass & FC_NoParameterList)) {
412 OS << "(";
413 if (Params)
Zachary Turner38d2edd2018-08-29 03:59:17 +0000414 Params->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000415 else
416 OS << "void";
417 OS << ")";
418 }
419
420 if (Quals & Q_Const)
421 OS << " const";
422 if (Quals & Q_Volatile)
423 OS << " volatile";
424 if (Quals & Q_Restrict)
425 OS << " __restrict";
426 if (Quals & Q_Unaligned)
427 OS << " __unaligned";
428
Zachary Turner2fe49002019-01-08 21:05:51 +0000429 if (IsNoexcept)
430 OS << " noexcept";
431
Zachary Turner03312862018-08-27 03:48:03 +0000432 if (RefQualifier == FunctionRefQualifier::Reference)
433 OS << " &";
434 else if (RefQualifier == FunctionRefQualifier::RValueReference)
435 OS << " &&";
436
437 if (ReturnType)
Zachary Turner38d2edd2018-08-29 03:59:17 +0000438 ReturnType->outputPost(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000439}
440
Zachary Turner38d2edd2018-08-29 03:59:17 +0000441void ThunkSignatureNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000442 OS << "[thunk]: ";
443
444 FunctionSignatureNode::outputPre(OS, Flags);
445}
446
Zachary Turner38d2edd2018-08-29 03:59:17 +0000447void ThunkSignatureNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000448 if (FunctionClass & FC_StaticThisAdjust) {
449 OS << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
450 } else if (FunctionClass & FC_VirtualThisAdjust) {
451 if (FunctionClass & FC_VirtualThisAdjustEx) {
452 OS << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
453 << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset
454 << ", " << ThisAdjust.StaticOffset << "}'";
455 } else {
456 OS << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
457 << ThisAdjust.StaticOffset << "}'";
458 }
459 }
460
461 FunctionSignatureNode::outputPost(OS, Flags);
462}
463
Zachary Turner38d2edd2018-08-29 03:59:17 +0000464void PointerTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000465 if (Pointee->kind() == NodeKind::FunctionSignature) {
466 // If this is a pointer to a function, don't output the calling convention.
467 // It needs to go inside the parentheses.
468 const FunctionSignatureNode *Sig =
469 static_cast<const FunctionSignatureNode *>(Pointee);
Zachary Turner38d2edd2018-08-29 03:59:17 +0000470 Sig->outputPre(OS, OF_NoCallingConvention);
Zachary Turner03312862018-08-27 03:48:03 +0000471 } else
Zachary Turner38d2edd2018-08-29 03:59:17 +0000472 Pointee->outputPre(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000473
474 outputSpaceIfNecessary(OS);
475
476 if (Quals & Q_Unaligned)
477 OS << "__unaligned ";
478
479 if (Pointee->kind() == NodeKind::ArrayType) {
480 OS << "(";
481 } else if (Pointee->kind() == NodeKind::FunctionSignature) {
482 OS << "(";
483 const FunctionSignatureNode *Sig =
484 static_cast<const FunctionSignatureNode *>(Pointee);
485 outputCallingConvention(OS, Sig->CallConvention);
486 OS << " ";
487 }
488
489 if (ClassParent) {
Zachary Turner38d2edd2018-08-29 03:59:17 +0000490 ClassParent->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000491 OS << "::";
492 }
493
494 switch (Affinity) {
495 case PointerAffinity::Pointer:
496 OS << "*";
497 break;
498 case PointerAffinity::Reference:
499 OS << "&";
500 break;
501 case PointerAffinity::RValueReference:
502 OS << "&&";
503 break;
504 default:
505 assert(false);
506 }
507 outputQualifiers(OS, Quals, false, false);
508}
509
Zachary Turner38d2edd2018-08-29 03:59:17 +0000510void PointerTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000511 if (Pointee->kind() == NodeKind::ArrayType ||
512 Pointee->kind() == NodeKind::FunctionSignature)
513 OS << ")";
514
Zachary Turner38d2edd2018-08-29 03:59:17 +0000515 Pointee->outputPost(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000516}
517
Zachary Turner38d2edd2018-08-29 03:59:17 +0000518void TagTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turnerba797b62019-01-02 18:33:12 +0000519 if (!(Flags & OF_NoTagSpecifier)) {
520 switch (Tag) {
521 OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");
522 OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct");
523 OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");
524 OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");
525 }
526 OS << " ";
Zachary Turner03312862018-08-27 03:48:03 +0000527 }
Zachary Turner38d2edd2018-08-29 03:59:17 +0000528 QualifiedName->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000529 outputQualifiers(OS, Quals, true, false);
530}
531
Zachary Turner38d2edd2018-08-29 03:59:17 +0000532void TagTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
Zachary Turner03312862018-08-27 03:48:03 +0000533
Zachary Turner38d2edd2018-08-29 03:59:17 +0000534void ArrayTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
535 ElementType->outputPre(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000536 outputQualifiers(OS, Quals, true, false);
537}
538
Zachary Turner38d2edd2018-08-29 03:59:17 +0000539void ArrayTypeNode::outputOneDimension(OutputStream &OS, OutputFlags Flags,
540 Node *N) const {
Zachary Turner03312862018-08-27 03:48:03 +0000541 assert(N->kind() == NodeKind::IntegerLiteral);
542 IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);
543 if (ILN->Value != 0)
Zachary Turner38d2edd2018-08-29 03:59:17 +0000544 ILN->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000545}
546
Zachary Turner38d2edd2018-08-29 03:59:17 +0000547void ArrayTypeNode::outputDimensionsImpl(OutputStream &OS,
548 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000549 if (Dimensions->Count == 0)
550 return;
551
Zachary Turner38d2edd2018-08-29 03:59:17 +0000552 outputOneDimension(OS, Flags, Dimensions->Nodes[0]);
Zachary Turner03312862018-08-27 03:48:03 +0000553 for (size_t I = 1; I < Dimensions->Count; ++I) {
554 OS << "][";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000555 outputOneDimension(OS, Flags, Dimensions->Nodes[I]);
Zachary Turner03312862018-08-27 03:48:03 +0000556 }
557}
558
Zachary Turner38d2edd2018-08-29 03:59:17 +0000559void ArrayTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000560 OS << "[";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000561 outputDimensionsImpl(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000562 OS << "]";
563
Zachary Turner38d2edd2018-08-29 03:59:17 +0000564 ElementType->outputPost(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000565}
566
Zachary Turner38d2edd2018-08-29 03:59:17 +0000567void SymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
568 Name->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000569}
570
Zachary Turner38d2edd2018-08-29 03:59:17 +0000571void FunctionSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000572 Signature->outputPre(OS, Flags);
573 outputSpaceIfNecessary(OS);
Zachary Turner38d2edd2018-08-29 03:59:17 +0000574 Name->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000575 Signature->outputPost(OS, Flags);
576}
577
Zachary Turner38d2edd2018-08-29 03:59:17 +0000578void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000579 switch (SC) {
580 case StorageClass::PrivateStatic:
Nico Webera92b4632018-11-13 20:18:26 +0000581 OS << "private: static ";
582 break;
Zachary Turner03312862018-08-27 03:48:03 +0000583 case StorageClass::PublicStatic:
Nico Webera92b4632018-11-13 20:18:26 +0000584 OS << "public: static ";
585 break;
Zachary Turner03312862018-08-27 03:48:03 +0000586 case StorageClass::ProtectedStatic:
Nico Webera92b4632018-11-13 20:18:26 +0000587 OS << "protected: static ";
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000588 break;
Zachary Turner03312862018-08-27 03:48:03 +0000589 default:
590 break;
591 }
592
593 if (Type) {
Zachary Turner38d2edd2018-08-29 03:59:17 +0000594 Type->outputPre(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000595 outputSpaceIfNecessary(OS);
596 }
Zachary Turner38d2edd2018-08-29 03:59:17 +0000597 Name->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000598 if (Type)
Zachary Turner38d2edd2018-08-29 03:59:17 +0000599 Type->outputPost(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000600}
601
Zachary Turnerb2fef1a2018-08-29 04:12:44 +0000602void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
603 Identifier->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000604}
Zachary Turnerb2fef1a2018-08-29 04:12:44 +0000605void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
Zachary Turner03312862018-08-27 03:48:03 +0000606
Zachary Turner38d2edd2018-08-29 03:59:17 +0000607void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const {
608 Components->output(OS, Flags, "::");
609}
610
611void RttiBaseClassDescriptorNode::output(OutputStream &OS,
612 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000613 OS << "`RTTI Base Class Descriptor at (";
614 OS << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
Zachary Turner38d2edd2018-08-29 03:59:17 +0000615 << this->Flags;
Zachary Turner03312862018-08-27 03:48:03 +0000616 OS << ")'";
617}
618
Zachary Turner38d2edd2018-08-29 03:59:17 +0000619void LocalStaticGuardVariableNode::output(OutputStream &OS,
620 OutputFlags Flags) const {
621 Name->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000622}
623
Zachary Turner38d2edd2018-08-29 03:59:17 +0000624void VcallThunkIdentifierNode::output(OutputStream &OS,
625 OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000626 OS << "`vcall'{" << OffsetInVTable << ", {flat}}";
627}
628
Zachary Turner38d2edd2018-08-29 03:59:17 +0000629void SpecialTableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner03312862018-08-27 03:48:03 +0000630 outputQualifiers(OS, Quals, false, true);
Zachary Turner38d2edd2018-08-29 03:59:17 +0000631 Name->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000632 if (TargetName) {
633 OS << "{for `";
Zachary Turner38d2edd2018-08-29 03:59:17 +0000634 TargetName->output(OS, Flags);
Zachary Turner03312862018-08-27 03:48:03 +0000635 OS << "'}";
636 }
637 return;
638}