MicrosoftDemangleNodes.cpp 21 KB

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