blob: 622f8e75e35136fdf9529b0701876759f1fcd12d [file] [log] [blame]
Zachary Turner6e3e8a72018-08-27 03:48:03 +00001//===- MicrosoftDemangle.cpp ----------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a demangler for MSVC-style mangled symbols.
11//
12//===----------------------------------------------------------------------===//
13
Zachary Turnerc35d5db2018-11-01 15:07:32 +000014#include "llvm/Demangle/MicrosoftDemangleNodes.h"
Zachary Turner6e3e8a72018-08-27 03:48:03 +000015#include "llvm/Demangle/Compiler.h"
16#include "llvm/Demangle/Utility.h"
Chandler Carruthb19b37f2018-08-27 06:52:14 +000017#include <cctype>
Zachary Turner785589d2018-12-17 16:42:26 +000018#include <string>
Zachary Turner6e3e8a72018-08-27 03:48:03 +000019
20using namespace llvm;
21using namespace ms_demangle;
22
23#define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc) \
24 case Enum::Value: \
25 OS << Desc; \
26 break;
27
28// Writes a space if the last token does not end with a punctuation.
29static void outputSpaceIfNecessary(OutputStream &OS) {
30 if (OS.empty())
31 return;
32
33 char C = OS.back();
Chandler Carruthb19b37f2018-08-27 06:52:14 +000034 if (std::isalnum(C) || C == '>')
Zachary Turner6e3e8a72018-08-27 03:48:03 +000035 OS << " ";
36}
37
38static bool outputSingleQualifier(OutputStream &OS, Qualifiers Q) {
39 switch (Q) {
40 case Q_Const:
41 OS << "const";
42 return true;
43 case Q_Volatile:
44 OS << "volatile";
45 return true;
46 case Q_Restrict:
47 OS << "__restrict";
48 return true;
49 default:
50 break;
51 }
52 return false;
53}
54
55static bool outputQualifierIfPresent(OutputStream &OS, Qualifiers Q,
56 Qualifiers Mask, bool NeedSpace) {
57 if (!(Q & Mask))
58 return NeedSpace;
59
60 if (NeedSpace)
61 OS << " ";
62
63 outputSingleQualifier(OS, Mask);
64 return true;
65}
66
67static void outputQualifiers(OutputStream &OS, Qualifiers Q, bool SpaceBefore,
68 bool SpaceAfter) {
69 if (Q == Q_None)
70 return;
71
72 size_t Pos1 = OS.getCurrentPosition();
73 SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Const, SpaceBefore);
74 SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Volatile, SpaceBefore);
75 SpaceBefore = outputQualifierIfPresent(OS, Q, Q_Restrict, SpaceBefore);
76 size_t Pos2 = OS.getCurrentPosition();
77 if (SpaceAfter && Pos2 > Pos1)
78 OS << " ";
79}
80
81static void outputCallingConvention(OutputStream &OS, CallingConv CC) {
82 outputSpaceIfNecessary(OS);
83
84 switch (CC) {
85 case CallingConv::Cdecl:
86 OS << "__cdecl";
87 break;
88 case CallingConv::Fastcall:
89 OS << "__fastcall";
90 break;
91 case CallingConv::Pascal:
92 OS << "__pascal";
93 break;
94 case CallingConv::Regcall:
95 OS << "__regcall";
96 break;
97 case CallingConv::Stdcall:
98 OS << "__stdcall";
99 break;
100 case CallingConv::Thiscall:
101 OS << "__thiscall";
102 break;
103 case CallingConv::Eabi:
104 OS << "__eabi";
105 break;
106 case CallingConv::Vectorcall:
107 OS << "__vectorcall";
108 break;
109 case CallingConv::Clrcall:
110 OS << "__clrcall";
111 break;
112 default:
113 break;
114 }
115}
116
Zachary Turnered72a642019-01-02 18:33:12 +0000117std::string Node::toString(OutputFlags Flags) const {
Zachary Turner18f6a2a2018-12-17 16:14:50 +0000118 OutputStream OS;
119 initializeOutputStream(nullptr, nullptr, OS, 1024);
Zachary Turnered72a642019-01-02 18:33:12 +0000120 this->output(OS, Flags);
Zachary Turner18f6a2a2018-12-17 16:14:50 +0000121 OS << '\0';
122 return {OS.getBuffer()};
123}
124
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000125void TypeNode::outputQuals(bool SpaceBefore, bool SpaceAfter) const {}
126
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000127void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000128 switch (PrimKind) {
129 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void");
130 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool");
131 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char");
132 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char");
133 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");
134 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t");
135 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t");
136 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short");
137 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short");
138 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int");
139 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int");
140 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long");
141 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long");
142 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64");
143 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64");
144 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t");
145 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float");
146 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double");
147 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double");
148 OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");
149 }
150 outputQualifiers(OS, Quals, true, false);
151}
152
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000153void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags) const {
154 output(OS, Flags, ", ");
155}
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000156
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000157void NodeArrayNode::output(OutputStream &OS, OutputFlags Flags,
158 StringView Separator) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000159 if (Count == 0)
160 return;
161 if (Nodes[0])
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000162 Nodes[0]->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000163 for (size_t I = 1; I < Count; ++I) {
164 OS << Separator;
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000165 Nodes[I]->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000166 }
167}
168
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000169void EncodedStringLiteralNode::output(OutputStream &OS,
170 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000171 switch (Char) {
172 case CharKind::Wchar:
Nico Weber86c04a02018-11-09 19:28:50 +0000173 OS << "L\"";
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000174 break;
175 case CharKind::Char:
Nico Weber86c04a02018-11-09 19:28:50 +0000176 OS << "\"";
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000177 break;
178 case CharKind::Char16:
Nico Weber86c04a02018-11-09 19:28:50 +0000179 OS << "u\"";
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000180 break;
181 case CharKind::Char32:
Nico Weber86c04a02018-11-09 19:28:50 +0000182 OS << "U\"";
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000183 break;
184 }
185 OS << DecodedString << "\"";
186 if (IsTruncated)
187 OS << "...";
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000188}
189
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000190void IntegerLiteralNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000191 if (IsNegative)
192 OS << '-';
193 OS << Value;
194}
195
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000196void TemplateParameterReferenceNode::output(OutputStream &OS,
197 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000198 if (ThunkOffsetCount > 0)
199 OS << "{";
200 else if (Affinity == PointerAffinity::Pointer)
201 OS << "&";
202
203 if (Symbol) {
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000204 Symbol->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000205 if (ThunkOffsetCount > 0)
206 OS << ", ";
207 }
208
209 if (ThunkOffsetCount > 0)
210 OS << ThunkOffsets[0];
211 for (int I = 1; I < ThunkOffsetCount; ++I) {
212 OS << ", " << ThunkOffsets[I];
213 }
214 if (ThunkOffsetCount > 0)
215 OS << "}";
216}
217
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000218void IdentifierNode::outputTemplateParameters(OutputStream &OS,
219 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000220 if (!TemplateParams)
221 return;
222 OS << "<";
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000223 TemplateParams->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000224 OS << ">";
225}
226
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000227void DynamicStructorIdentifierNode::output(OutputStream &OS,
228 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000229 if (IsDestructor)
230 OS << "`dynamic atexit destructor for ";
231 else
232 OS << "`dynamic initializer for ";
233
Zachary Turner6568fb52018-08-29 23:56:09 +0000234 if (Variable) {
235 OS << "`";
236 Variable->output(OS, Flags);
237 OS << "''";
238 } else {
239 OS << "'";
240 Name->output(OS, Flags);
241 OS << "''";
242 }
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000243}
244
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000245void NamedIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000246 OS << Name;
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000247 outputTemplateParameters(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000248}
249
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000250void IntrinsicFunctionIdentifierNode::output(OutputStream &OS,
251 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000252 switch (Operator) {
253 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new");
254 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete");
255 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator=");
256 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>");
257 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<");
258 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!");
259 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator==");
260 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!=");
261 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript,
262 "operator[]");
263 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->");
264 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++");
265 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--");
266 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-");
267 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+");
268 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*");
269 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&");
270 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer,
271 "operator->*");
272 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/");
273 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%");
274 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<");
275 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<=");
276 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>");
277 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual,
278 "operator>=");
279 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,");
280 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()");
281 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~");
282 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^");
283 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|");
284 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&");
285 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||");
286 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*=");
287 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+=");
288 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-=");
289 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/=");
290 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%=");
291 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>=");
292 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<=");
293 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual,
294 "operator&=");
295 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual,
296 "operator|=");
297 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual,
298 "operator^=");
299 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'");
300 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor,
301 "`vector deleting dtor'");
302 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure,
303 "`default ctor closure'");
304 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor,
305 "`scalar deleting dtor'");
306 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter,
307 "`vector ctor iterator'");
308 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter,
309 "`vector dtor iterator'");
310 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter,
311 "`vector vbase ctor iterator'");
312 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap,
313 "`virtual displacement map'");
314 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter,
315 "`eh vector ctor iterator'");
316 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter,
317 "`eh vector dtor iterator'");
318 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter,
319 "`eh vector vbase ctor iterator'");
320 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure,
321 "`copy ctor closure'");
322 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure,
323 "`local vftable ctor closure'");
324 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]");
325 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete,
326 "operator delete[]");
327 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter,
328 "`managed vector ctor iterator'");
329 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter,
330 "`managed vector dtor iterator'");
331 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter,
332 "`EH vector copy ctor iterator'");
333 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter,
334 "`EH vector vbase copy ctor iterator'");
335 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter,
336 "`vector copy ctor iterator'");
337 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter,
338 "`vector vbase copy constructor iterator'");
339 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter,
340 "`managed vector vbase copy constructor iterator'");
341 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait, "co_await");
342 OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator <=>");
343 case IntrinsicFunctionKind::MaxIntrinsic:
344 case IntrinsicFunctionKind::None:
345 break;
346 }
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000347 outputTemplateParameters(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000348}
349
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000350void LocalStaticGuardIdentifierNode::output(OutputStream &OS,
351 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000352 OS << "`local static guard'";
353 if (ScopeIndex > 0)
354 OS << "{" << ScopeIndex << "}";
355}
356
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000357void ConversionOperatorIdentifierNode::output(OutputStream &OS,
358 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000359 OS << "operator";
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000360 outputTemplateParameters(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000361 OS << " ";
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000362 TargetType->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000363}
364
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000365void StructorIdentifierNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000366 if (IsDestructor)
367 OS << "~";
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000368 Class->output(OS, Flags);
369 outputTemplateParameters(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000370}
371
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000372void LiteralOperatorIdentifierNode::output(OutputStream &OS,
373 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000374 OS << "operator \"\"" << Name;
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000375 outputTemplateParameters(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000376}
377
378void FunctionSignatureNode::outputPre(OutputStream &OS,
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000379 OutputFlags Flags) const {
Nico Weber65bbcca2018-11-13 20:18:26 +0000380 if (FunctionClass & FC_Public)
381 OS << "public: ";
382 if (FunctionClass & FC_Protected)
383 OS << "protected: ";
384 if (FunctionClass & FC_Private)
385 OS << "private: ";
386
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000387 if (!(FunctionClass & FC_Global)) {
388 if (FunctionClass & FC_Static)
389 OS << "static ";
390 }
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000391 if (FunctionClass & FC_Virtual)
392 OS << "virtual ";
393
Nico Weber65bbcca2018-11-13 20:18:26 +0000394 if (FunctionClass & FC_ExternC)
395 OS << "extern \"C\" ";
396
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000397 if (ReturnType) {
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000398 ReturnType->outputPre(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000399 OS << " ";
400 }
401
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000402 if (!(Flags & OF_NoCallingConvention))
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000403 outputCallingConvention(OS, CallConvention);
404}
405
406void FunctionSignatureNode::outputPost(OutputStream &OS,
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000407 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000408 if (!(FunctionClass & FC_NoParameterList)) {
409 OS << "(";
410 if (Params)
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000411 Params->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000412 else
413 OS << "void";
414 OS << ")";
415 }
416
417 if (Quals & Q_Const)
418 OS << " const";
419 if (Quals & Q_Volatile)
420 OS << " volatile";
421 if (Quals & Q_Restrict)
422 OS << " __restrict";
423 if (Quals & Q_Unaligned)
424 OS << " __unaligned";
425
Zachary Turnerf4448ba2019-01-08 21:05:51 +0000426 if (IsNoexcept)
427 OS << " noexcept";
428
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000429 if (RefQualifier == FunctionRefQualifier::Reference)
430 OS << " &";
431 else if (RefQualifier == FunctionRefQualifier::RValueReference)
432 OS << " &&";
433
434 if (ReturnType)
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000435 ReturnType->outputPost(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000436}
437
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000438void ThunkSignatureNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000439 OS << "[thunk]: ";
440
441 FunctionSignatureNode::outputPre(OS, Flags);
442}
443
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000444void ThunkSignatureNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000445 if (FunctionClass & FC_StaticThisAdjust) {
446 OS << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
447 } else if (FunctionClass & FC_VirtualThisAdjust) {
448 if (FunctionClass & FC_VirtualThisAdjustEx) {
449 OS << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
450 << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset
451 << ", " << ThisAdjust.StaticOffset << "}'";
452 } else {
453 OS << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
454 << ThisAdjust.StaticOffset << "}'";
455 }
456 }
457
458 FunctionSignatureNode::outputPost(OS, Flags);
459}
460
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000461void PointerTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000462 if (Pointee->kind() == NodeKind::FunctionSignature) {
463 // If this is a pointer to a function, don't output the calling convention.
464 // It needs to go inside the parentheses.
465 const FunctionSignatureNode *Sig =
466 static_cast<const FunctionSignatureNode *>(Pointee);
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000467 Sig->outputPre(OS, OF_NoCallingConvention);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000468 } else
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000469 Pointee->outputPre(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000470
471 outputSpaceIfNecessary(OS);
472
473 if (Quals & Q_Unaligned)
474 OS << "__unaligned ";
475
476 if (Pointee->kind() == NodeKind::ArrayType) {
477 OS << "(";
478 } else if (Pointee->kind() == NodeKind::FunctionSignature) {
479 OS << "(";
480 const FunctionSignatureNode *Sig =
481 static_cast<const FunctionSignatureNode *>(Pointee);
482 outputCallingConvention(OS, Sig->CallConvention);
483 OS << " ";
484 }
485
486 if (ClassParent) {
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000487 ClassParent->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000488 OS << "::";
489 }
490
491 switch (Affinity) {
492 case PointerAffinity::Pointer:
493 OS << "*";
494 break;
495 case PointerAffinity::Reference:
496 OS << "&";
497 break;
498 case PointerAffinity::RValueReference:
499 OS << "&&";
500 break;
501 default:
502 assert(false);
503 }
504 outputQualifiers(OS, Quals, false, false);
505}
506
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000507void PointerTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000508 if (Pointee->kind() == NodeKind::ArrayType ||
509 Pointee->kind() == NodeKind::FunctionSignature)
510 OS << ")";
511
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000512 Pointee->outputPost(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000513}
514
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000515void TagTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
Zachary Turnered72a642019-01-02 18:33:12 +0000516 if (!(Flags & OF_NoTagSpecifier)) {
517 switch (Tag) {
518 OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");
519 OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct");
520 OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");
521 OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");
522 }
523 OS << " ";
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000524 }
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000525 QualifiedName->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000526 outputQualifiers(OS, Quals, true, false);
527}
528
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000529void TagTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000530
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000531void ArrayTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
532 ElementType->outputPre(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000533 outputQualifiers(OS, Quals, true, false);
534}
535
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000536void ArrayTypeNode::outputOneDimension(OutputStream &OS, OutputFlags Flags,
537 Node *N) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000538 assert(N->kind() == NodeKind::IntegerLiteral);
539 IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);
540 if (ILN->Value != 0)
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000541 ILN->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000542}
543
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000544void ArrayTypeNode::outputDimensionsImpl(OutputStream &OS,
545 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000546 if (Dimensions->Count == 0)
547 return;
548
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000549 outputOneDimension(OS, Flags, Dimensions->Nodes[0]);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000550 for (size_t I = 1; I < Dimensions->Count; ++I) {
551 OS << "][";
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000552 outputOneDimension(OS, Flags, Dimensions->Nodes[I]);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000553 }
554}
555
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000556void ArrayTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000557 OS << "[";
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000558 outputDimensionsImpl(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000559 OS << "]";
560
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000561 ElementType->outputPost(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000562}
563
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000564void SymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
565 Name->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000566}
567
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000568void FunctionSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000569 Signature->outputPre(OS, Flags);
570 outputSpaceIfNecessary(OS);
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000571 Name->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000572 Signature->outputPost(OS, Flags);
573}
574
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000575void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000576 switch (SC) {
577 case StorageClass::PrivateStatic:
Nico Weber65bbcca2018-11-13 20:18:26 +0000578 OS << "private: static ";
579 break;
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000580 case StorageClass::PublicStatic:
Nico Weber65bbcca2018-11-13 20:18:26 +0000581 OS << "public: static ";
582 break;
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000583 case StorageClass::ProtectedStatic:
Nico Weber65bbcca2018-11-13 20:18:26 +0000584 OS << "protected: static ";
Reid Klecknerb7d45e12018-11-01 19:54:45 +0000585 break;
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000586 default:
587 break;
588 }
589
590 if (Type) {
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000591 Type->outputPre(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000592 outputSpaceIfNecessary(OS);
593 }
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000594 Name->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000595 if (Type)
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000596 Type->outputPost(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000597}
598
Zachary Turneref6d9042018-08-29 04:12:44 +0000599void CustomTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const {
600 Identifier->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000601}
Zachary Turneref6d9042018-08-29 04:12:44 +0000602void CustomTypeNode::outputPost(OutputStream &OS, OutputFlags Flags) const {}
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000603
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000604void QualifiedNameNode::output(OutputStream &OS, OutputFlags Flags) const {
605 Components->output(OS, Flags, "::");
606}
607
608void RttiBaseClassDescriptorNode::output(OutputStream &OS,
609 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000610 OS << "`RTTI Base Class Descriptor at (";
611 OS << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000612 << this->Flags;
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000613 OS << ")'";
614}
615
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000616void LocalStaticGuardVariableNode::output(OutputStream &OS,
617 OutputFlags Flags) const {
618 Name->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000619}
620
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000621void VcallThunkIdentifierNode::output(OutputStream &OS,
622 OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000623 OS << "`vcall'{" << OffsetInVTable << ", {flat}}";
624}
625
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000626void SpecialTableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const {
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000627 outputQualifiers(OS, Quals, false, true);
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000628 Name->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000629 if (TargetName) {
630 OS << "{for `";
Zachary Turner2e2b1e22018-08-29 03:59:17 +0000631 TargetName->output(OS, Flags);
Zachary Turner6e3e8a72018-08-27 03:48:03 +0000632 OS << "'}";
633 }
634 return;
635}