llvm-project

Форк
0
/
MicrosoftDemangleNodes.cpp 
658 строк · 21.7 Кб
1
//===- MicrosoftDemangle.cpp ----------------------------------------------===//
2
//
3
// 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
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file defines a demangler for MSVC-style mangled symbols.
10
//
11
//===----------------------------------------------------------------------===//
12

13
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
14
#include "llvm/Demangle/Utility.h"
15
#include <cctype>
16
#include <string>
17

18
using namespace llvm;
19
using namespace ms_demangle;
20

21
#define OUTPUT_ENUM_CLASS_VALUE(Enum, Value, Desc)                             \
22
  case Enum::Value:                                                            \
23
    OB << Desc;                                                                \
24
    break;
25

26
// Writes a space if the last token does not end with a punctuation.
27
static void outputSpaceIfNecessary(OutputBuffer &OB) {
28
  if (OB.empty())
29
    return;
30

31
  char C = OB.back();
32
  if (std::isalnum(C) || C == '>')
33
    OB << " ";
34
}
35

36
static void outputSingleQualifier(OutputBuffer &OB, Qualifiers Q) {
37
  switch (Q) {
38
  case Q_Const:
39
    OB << "const";
40
    break;
41
  case Q_Volatile:
42
    OB << "volatile";
43
    break;
44
  case Q_Restrict:
45
    OB << "__restrict";
46
    break;
47
  default:
48
    break;
49
  }
50
}
51

52
static bool outputQualifierIfPresent(OutputBuffer &OB, Qualifiers Q,
53
                                     Qualifiers Mask, bool NeedSpace) {
54
  if (!(Q & Mask))
55
    return NeedSpace;
56

57
  if (NeedSpace)
58
    OB << " ";
59

60
  outputSingleQualifier(OB, Mask);
61
  return true;
62
}
63

64
static void outputQualifiers(OutputBuffer &OB, Qualifiers Q, bool SpaceBefore,
65
                             bool SpaceAfter) {
66
  if (Q == Q_None)
67
    return;
68

69
  size_t Pos1 = OB.getCurrentPosition();
70
  SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Const, SpaceBefore);
71
  SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Volatile, SpaceBefore);
72
  SpaceBefore = outputQualifierIfPresent(OB, Q, Q_Restrict, SpaceBefore);
73
  size_t Pos2 = OB.getCurrentPosition();
74
  if (SpaceAfter && Pos2 > Pos1)
75
    OB << " ";
76
}
77

78
static void outputCallingConvention(OutputBuffer &OB, CallingConv CC) {
79
  outputSpaceIfNecessary(OB);
80

81
  switch (CC) {
82
  case CallingConv::Cdecl:
83
    OB << "__cdecl";
84
    break;
85
  case CallingConv::Fastcall:
86
    OB << "__fastcall";
87
    break;
88
  case CallingConv::Pascal:
89
    OB << "__pascal";
90
    break;
91
  case CallingConv::Regcall:
92
    OB << "__regcall";
93
    break;
94
  case CallingConv::Stdcall:
95
    OB << "__stdcall";
96
    break;
97
  case CallingConv::Thiscall:
98
    OB << "__thiscall";
99
    break;
100
  case CallingConv::Eabi:
101
    OB << "__eabi";
102
    break;
103
  case CallingConv::Vectorcall:
104
    OB << "__vectorcall";
105
    break;
106
  case CallingConv::Clrcall:
107
    OB << "__clrcall";
108
    break;
109
  case CallingConv::Swift:
110
    OB << "__attribute__((__swiftcall__)) ";
111
    break;
112
  case CallingConv::SwiftAsync:
113
    OB << "__attribute__((__swiftasynccall__)) ";
114
    break;
115
  default:
116
    break;
117
  }
118
}
119

120
std::string Node::toString(OutputFlags Flags) const {
121
  OutputBuffer OB;
122
  this->output(OB, Flags);
123
  std::string_view SV = OB;
124
  std::string Owned(SV.begin(), SV.end());
125
  std::free(OB.getBuffer());
126
  return Owned;
127
}
128

129
void PrimitiveTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
130
  switch (PrimKind) {
131
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void");
132
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Bool, "bool");
133
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char, "char");
134
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Schar, "signed char");
135
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uchar, "unsigned char");
136
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char8, "char8_t");
137
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char16, "char16_t");
138
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Char32, "char32_t");
139
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Short, "short");
140
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ushort, "unsigned short");
141
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int, "int");
142
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint, "unsigned int");
143
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Long, "long");
144
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ulong, "unsigned long");
145
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Int64, "__int64");
146
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Uint64, "unsigned __int64");
147
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Wchar, "wchar_t");
148
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Float, "float");
149
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Double, "double");
150
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Ldouble, "long double");
151
    OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Nullptr, "std::nullptr_t");
152
  }
153
  outputQualifiers(OB, Quals, true, false);
154
}
155

156
void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags) const {
157
  output(OB, Flags, ", ");
158
}
159

160
void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags,
161
                           std::string_view Separator) const {
162
  if (Count == 0)
163
    return;
164
  if (Nodes[0])
165
    Nodes[0]->output(OB, Flags);
166
  for (size_t I = 1; I < Count; ++I) {
167
    OB << Separator;
168
    Nodes[I]->output(OB, Flags);
169
  }
170
}
171

172
void EncodedStringLiteralNode::output(OutputBuffer &OB,
173
                                      OutputFlags Flags) const {
174
  switch (Char) {
175
  case CharKind::Wchar:
176
    OB << "L\"";
177
    break;
178
  case CharKind::Char:
179
    OB << "\"";
180
    break;
181
  case CharKind::Char16:
182
    OB << "u\"";
183
    break;
184
  case CharKind::Char32:
185
    OB << "U\"";
186
    break;
187
  }
188
  OB << DecodedString << "\"";
189
  if (IsTruncated)
190
    OB << "...";
191
}
192

193
void IntegerLiteralNode::output(OutputBuffer &OB, OutputFlags Flags) const {
194
  if (IsNegative)
195
    OB << '-';
196
  OB << Value;
197
}
198

199
void TemplateParameterReferenceNode::output(OutputBuffer &OB,
200
                                            OutputFlags Flags) const {
201
  if (ThunkOffsetCount > 0)
202
    OB << "{";
203
  else if (Affinity == PointerAffinity::Pointer)
204
    OB << "&";
205

206
  if (Symbol) {
207
    Symbol->output(OB, Flags);
208
    if (ThunkOffsetCount > 0)
209
      OB << ", ";
210
  }
211

212
  if (ThunkOffsetCount > 0)
213
    OB << ThunkOffsets[0];
214
  for (int I = 1; I < ThunkOffsetCount; ++I) {
215
    OB << ", " << ThunkOffsets[I];
216
  }
217
  if (ThunkOffsetCount > 0)
218
    OB << "}";
219
}
220

221
void IdentifierNode::outputTemplateParameters(OutputBuffer &OB,
222
                                              OutputFlags Flags) const {
223
  if (!TemplateParams)
224
    return;
225
  OB << "<";
226
  TemplateParams->output(OB, Flags);
227
  OB << ">";
228
}
229

230
void DynamicStructorIdentifierNode::output(OutputBuffer &OB,
231
                                           OutputFlags Flags) const {
232
  if (IsDestructor)
233
    OB << "`dynamic atexit destructor for ";
234
  else
235
    OB << "`dynamic initializer for ";
236

237
  if (Variable) {
238
    OB << "`";
239
    Variable->output(OB, Flags);
240
    OB << "''";
241
  } else {
242
    OB << "'";
243
    Name->output(OB, Flags);
244
    OB << "''";
245
  }
246
}
247

248
void NamedIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {
249
  OB << Name;
250
  outputTemplateParameters(OB, Flags);
251
}
252

253
void IntrinsicFunctionIdentifierNode::output(OutputBuffer &OB,
254
                                             OutputFlags Flags) const {
255
  switch (Operator) {
256
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, New, "operator new");
257
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Delete, "operator delete");
258
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Assign, "operator=");
259
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RightShift, "operator>>");
260
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LeftShift, "operator<<");
261
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalNot, "operator!");
262
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Equals, "operator==");
263
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, NotEquals, "operator!=");
264
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArraySubscript,
265
                            "operator[]");
266
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Pointer, "operator->");
267
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Increment, "operator++");
268
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Decrement, "operator--");
269
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Minus, "operator-");
270
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Plus, "operator+");
271
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Dereference, "operator*");
272
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAnd, "operator&");
273
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MemberPointer,
274
                            "operator->*");
275
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Divide, "operator/");
276
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Modulus, "operator%");
277
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThan, "operator<");
278
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LessThanEqual, "operator<=");
279
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThan, "operator>");
280
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, GreaterThanEqual,
281
                            "operator>=");
282
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Comma, "operator,");
283
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Parens, "operator()");
284
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseNot, "operator~");
285
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXor, "operator^");
286
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOr, "operator|");
287
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalAnd, "operator&&");
288
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LogicalOr, "operator||");
289
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, TimesEqual, "operator*=");
290
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, PlusEqual, "operator+=");
291
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, MinusEqual, "operator-=");
292
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DivEqual, "operator/=");
293
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ModEqual, "operator%=");
294
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, RshEqual, "operator>>=");
295
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LshEqual, "operator<<=");
296
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseAndEqual,
297
                            "operator&=");
298
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseOrEqual,
299
                            "operator|=");
300
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, BitwiseXorEqual,
301
                            "operator^=");
302
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VbaseDtor, "`vbase dtor'");
303
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDelDtor,
304
                            "`vector deleting dtor'");
305
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, DefaultCtorClosure,
306
                            "`default ctor closure'");
307
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ScalarDelDtor,
308
                            "`scalar deleting dtor'");
309
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecCtorIter,
310
                            "`vector ctor iterator'");
311
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecDtorIter,
312
                            "`vector dtor iterator'");
313
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VecVbaseCtorIter,
314
                            "`vector vbase ctor iterator'");
315
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VdispMap,
316
                            "`virtual displacement map'");
317
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecCtorIter,
318
                            "`eh vector ctor iterator'");
319
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecDtorIter,
320
                            "`eh vector dtor iterator'");
321
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVecVbaseCtorIter,
322
                            "`eh vector vbase ctor iterator'");
323
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CopyCtorClosure,
324
                            "`copy ctor closure'");
325
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, LocalVftableCtorClosure,
326
                            "`local vftable ctor closure'");
327
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayNew, "operator new[]");
328
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ArrayDelete,
329
                            "operator delete[]");
330
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorCtorIter,
331
                            "`managed vector ctor iterator'");
332
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorDtorIter,
333
                            "`managed vector dtor iterator'");
334
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorCopyCtorIter,
335
                            "`EH vector copy ctor iterator'");
336
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, EHVectorVbaseCopyCtorIter,
337
                            "`EH vector vbase copy ctor iterator'");
338
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorCopyCtorIter,
339
                            "`vector copy ctor iterator'");
340
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, VectorVbaseCopyCtorIter,
341
                            "`vector vbase copy constructor iterator'");
342
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, ManVectorVbaseCopyCtorIter,
343
                            "`managed vector vbase copy constructor iterator'");
344
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, CoAwait,
345
                            "operator co_await");
346
    OUTPUT_ENUM_CLASS_VALUE(IntrinsicFunctionKind, Spaceship, "operator<=>");
347
  case IntrinsicFunctionKind::MaxIntrinsic:
348
  case IntrinsicFunctionKind::None:
349
    break;
350
  }
351
  outputTemplateParameters(OB, Flags);
352
}
353

354
void LocalStaticGuardIdentifierNode::output(OutputBuffer &OB,
355
                                            OutputFlags Flags) const {
356
  if (IsThread)
357
    OB << "`local static thread guard'";
358
  else
359
    OB << "`local static guard'";
360
  if (ScopeIndex > 0)
361
    OB << "{" << ScopeIndex << "}";
362
}
363

364
void ConversionOperatorIdentifierNode::output(OutputBuffer &OB,
365
                                              OutputFlags Flags) const {
366
  OB << "operator";
367
  outputTemplateParameters(OB, Flags);
368
  OB << " ";
369
  TargetType->output(OB, Flags);
370
}
371

372
void StructorIdentifierNode::output(OutputBuffer &OB, OutputFlags Flags) const {
373
  if (IsDestructor)
374
    OB << "~";
375
  Class->output(OB, Flags);
376
  outputTemplateParameters(OB, Flags);
377
}
378

379
void LiteralOperatorIdentifierNode::output(OutputBuffer &OB,
380
                                           OutputFlags Flags) const {
381
  OB << "operator \"\"" << Name;
382
  outputTemplateParameters(OB, Flags);
383
}
384

385
void FunctionSignatureNode::outputPre(OutputBuffer &OB,
386
                                      OutputFlags Flags) const {
387
  if (!(Flags & OF_NoAccessSpecifier)) {
388
    if (FunctionClass & FC_Public)
389
      OB << "public: ";
390
    if (FunctionClass & FC_Protected)
391
      OB << "protected: ";
392
    if (FunctionClass & FC_Private)
393
      OB << "private: ";
394
  }
395

396
  if (!(Flags & OF_NoMemberType)) {
397
    if (!(FunctionClass & FC_Global)) {
398
      if (FunctionClass & FC_Static)
399
        OB << "static ";
400
    }
401
    if (FunctionClass & FC_Virtual)
402
      OB << "virtual ";
403

404
    if (FunctionClass & FC_ExternC)
405
      OB << "extern \"C\" ";
406
  }
407

408
  if (!(Flags & OF_NoReturnType) && ReturnType) {
409
    ReturnType->outputPre(OB, Flags);
410
    OB << " ";
411
  }
412

413
  if (!(Flags & OF_NoCallingConvention))
414
    outputCallingConvention(OB, CallConvention);
415
}
416

417
void FunctionSignatureNode::outputPost(OutputBuffer &OB,
418
                                       OutputFlags Flags) const {
419
  if (!(FunctionClass & FC_NoParameterList)) {
420
    OB << "(";
421
    if (Params)
422
      Params->output(OB, Flags);
423
    else
424
      OB << "void";
425

426
    if (IsVariadic) {
427
      if (OB.back() != '(')
428
        OB << ", ";
429
      OB << "...";
430
    }
431
    OB << ")";
432
  }
433

434
  if (Quals & Q_Const)
435
    OB << " const";
436
  if (Quals & Q_Volatile)
437
    OB << " volatile";
438
  if (Quals & Q_Restrict)
439
    OB << " __restrict";
440
  if (Quals & Q_Unaligned)
441
    OB << " __unaligned";
442

443
  if (IsNoexcept)
444
    OB << " noexcept";
445

446
  if (RefQualifier == FunctionRefQualifier::Reference)
447
    OB << " &";
448
  else if (RefQualifier == FunctionRefQualifier::RValueReference)
449
    OB << " &&";
450

451
  if (!(Flags & OF_NoReturnType) && ReturnType)
452
    ReturnType->outputPost(OB, Flags);
453
}
454

455
void ThunkSignatureNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
456
  OB << "[thunk]: ";
457

458
  FunctionSignatureNode::outputPre(OB, Flags);
459
}
460

461
void ThunkSignatureNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
462
  if (FunctionClass & FC_StaticThisAdjust) {
463
    OB << "`adjustor{" << ThisAdjust.StaticOffset << "}'";
464
  } else if (FunctionClass & FC_VirtualThisAdjust) {
465
    if (FunctionClass & FC_VirtualThisAdjustEx) {
466
      OB << "`vtordispex{" << ThisAdjust.VBPtrOffset << ", "
467
         << ThisAdjust.VBOffsetOffset << ", " << ThisAdjust.VtordispOffset
468
         << ", " << ThisAdjust.StaticOffset << "}'";
469
    } else {
470
      OB << "`vtordisp{" << ThisAdjust.VtordispOffset << ", "
471
         << ThisAdjust.StaticOffset << "}'";
472
    }
473
  }
474

475
  FunctionSignatureNode::outputPost(OB, Flags);
476
}
477

478
void PointerTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
479
  if (Pointee->kind() == NodeKind::FunctionSignature) {
480
    // If this is a pointer to a function, don't output the calling convention.
481
    // It needs to go inside the parentheses.
482
    const FunctionSignatureNode *Sig =
483
        static_cast<const FunctionSignatureNode *>(Pointee);
484
    Sig->outputPre(OB, OF_NoCallingConvention);
485
  } else
486
    Pointee->outputPre(OB, Flags);
487

488
  outputSpaceIfNecessary(OB);
489

490
  if (Quals & Q_Unaligned)
491
    OB << "__unaligned ";
492

493
  if (Pointee->kind() == NodeKind::ArrayType) {
494
    OB << "(";
495
  } else if (Pointee->kind() == NodeKind::FunctionSignature) {
496
    OB << "(";
497
    const FunctionSignatureNode *Sig =
498
        static_cast<const FunctionSignatureNode *>(Pointee);
499
    outputCallingConvention(OB, Sig->CallConvention);
500
    OB << " ";
501
  }
502

503
  if (ClassParent) {
504
    ClassParent->output(OB, Flags);
505
    OB << "::";
506
  }
507

508
  switch (Affinity) {
509
  case PointerAffinity::Pointer:
510
    OB << "*";
511
    break;
512
  case PointerAffinity::Reference:
513
    OB << "&";
514
    break;
515
  case PointerAffinity::RValueReference:
516
    OB << "&&";
517
    break;
518
  default:
519
    assert(false);
520
  }
521
  outputQualifiers(OB, Quals, false, false);
522
}
523

524
void PointerTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
525
  if (Pointee->kind() == NodeKind::ArrayType ||
526
      Pointee->kind() == NodeKind::FunctionSignature)
527
    OB << ")";
528

529
  Pointee->outputPost(OB, Flags);
530
}
531

532
void TagTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
533
  if (!(Flags & OF_NoTagSpecifier)) {
534
    switch (Tag) {
535
      OUTPUT_ENUM_CLASS_VALUE(TagKind, Class, "class");
536
      OUTPUT_ENUM_CLASS_VALUE(TagKind, Struct, "struct");
537
      OUTPUT_ENUM_CLASS_VALUE(TagKind, Union, "union");
538
      OUTPUT_ENUM_CLASS_VALUE(TagKind, Enum, "enum");
539
    }
540
    OB << " ";
541
  }
542
  QualifiedName->output(OB, Flags);
543
  outputQualifiers(OB, Quals, true, false);
544
}
545

546
void TagTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}
547

548
void ArrayTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
549
  ElementType->outputPre(OB, Flags);
550
  outputQualifiers(OB, Quals, true, false);
551
}
552

553
void ArrayTypeNode::outputOneDimension(OutputBuffer &OB, OutputFlags Flags,
554
                                       Node *N) const {
555
  assert(N->kind() == NodeKind::IntegerLiteral);
556
  IntegerLiteralNode *ILN = static_cast<IntegerLiteralNode *>(N);
557
  if (ILN->Value != 0)
558
    ILN->output(OB, Flags);
559
}
560

561
void ArrayTypeNode::outputDimensionsImpl(OutputBuffer &OB,
562
                                         OutputFlags Flags) const {
563
  if (Dimensions->Count == 0)
564
    return;
565

566
  outputOneDimension(OB, Flags, Dimensions->Nodes[0]);
567
  for (size_t I = 1; I < Dimensions->Count; ++I) {
568
    OB << "][";
569
    outputOneDimension(OB, Flags, Dimensions->Nodes[I]);
570
  }
571
}
572

573
void ArrayTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {
574
  OB << "[";
575
  outputDimensionsImpl(OB, Flags);
576
  OB << "]";
577

578
  ElementType->outputPost(OB, Flags);
579
}
580

581
void SymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
582
  Name->output(OB, Flags);
583
}
584

585
void FunctionSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
586
  Signature->outputPre(OB, Flags);
587
  outputSpaceIfNecessary(OB);
588
  Name->output(OB, Flags);
589
  Signature->outputPost(OB, Flags);
590
}
591

592
void VariableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
593
  const char *AccessSpec = nullptr;
594
  bool IsStatic = true;
595
  switch (SC) {
596
  case StorageClass::PrivateStatic:
597
    AccessSpec = "private";
598
    break;
599
  case StorageClass::PublicStatic:
600
    AccessSpec = "public";
601
    break;
602
  case StorageClass::ProtectedStatic:
603
    AccessSpec = "protected";
604
    break;
605
  default:
606
    IsStatic = false;
607
    break;
608
  }
609
  if (!(Flags & OF_NoAccessSpecifier) && AccessSpec)
610
    OB << AccessSpec << ": ";
611
  if (!(Flags & OF_NoMemberType) && IsStatic)
612
    OB << "static ";
613

614
  if (!(Flags & OF_NoVariableType) && Type) {
615
    Type->outputPre(OB, Flags);
616
    outputSpaceIfNecessary(OB);
617
  }
618
  Name->output(OB, Flags);
619
  if (!(Flags & OF_NoVariableType) && Type)
620
    Type->outputPost(OB, Flags);
621
}
622

623
void CustomTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
624
  Identifier->output(OB, Flags);
625
}
626
void CustomTypeNode::outputPost(OutputBuffer &OB, OutputFlags Flags) const {}
627

628
void QualifiedNameNode::output(OutputBuffer &OB, OutputFlags Flags) const {
629
  Components->output(OB, Flags, "::");
630
}
631

632
void RttiBaseClassDescriptorNode::output(OutputBuffer &OB,
633
                                         OutputFlags Flags) const {
634
  OB << "`RTTI Base Class Descriptor at (";
635
  OB << NVOffset << ", " << VBPtrOffset << ", " << VBTableOffset << ", "
636
     << this->Flags;
637
  OB << ")'";
638
}
639

640
void LocalStaticGuardVariableNode::output(OutputBuffer &OB,
641
                                          OutputFlags Flags) const {
642
  Name->output(OB, Flags);
643
}
644

645
void VcallThunkIdentifierNode::output(OutputBuffer &OB,
646
                                      OutputFlags Flags) const {
647
  OB << "`vcall'{" << OffsetInVTable << ", {flat}}";
648
}
649

650
void SpecialTableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
651
  outputQualifiers(OB, Quals, false, true);
652
  Name->output(OB, Flags);
653
  if (TargetName) {
654
    OB << "{for `";
655
    TargetName->output(OB, Flags);
656
    OB << "'}";
657
  }
658
}
659

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.