LCOV - code coverage report
Current view: top level - lib/Demangle - MicrosoftDemangleNodes.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 371 391 94.9 %
Date: 2018-10-20 13:21:21 Functions: 41 42 97.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13