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