ASTDumper.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. //===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===//
  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 implements the AST dump methods, which dump out the
  10. // AST in a form that exposes type details and other fields.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/AST/ASTDumper.h"
  14. #include "clang/AST/ASTContext.h"
  15. #include "clang/AST/DeclLookups.h"
  16. #include "clang/AST/JSONNodeDumper.h"
  17. #include "clang/Basic/Builtins.h"
  18. #include "clang/Basic/Module.h"
  19. #include "clang/Basic/SourceManager.h"
  20. #include "llvm/Support/raw_ostream.h"
  21. using namespace clang;
  22. using namespace clang::comments;
  23. void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
  24. NodeDumper.AddChild([=] {
  25. OS << "StoredDeclsMap ";
  26. NodeDumper.dumpBareDeclRef(cast<Decl>(DC));
  27. const DeclContext *Primary = DC->getPrimaryContext();
  28. if (Primary != DC) {
  29. OS << " primary";
  30. NodeDumper.dumpPointer(cast<Decl>(Primary));
  31. }
  32. bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
  33. auto Range = getDeserialize()
  34. ? Primary->lookups()
  35. : Primary->noload_lookups(/*PreserveInternalState=*/true);
  36. for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {
  37. DeclarationName Name = I.getLookupName();
  38. DeclContextLookupResult R = *I;
  39. NodeDumper.AddChild([=] {
  40. OS << "DeclarationName ";
  41. {
  42. ColorScope Color(OS, ShowColors, DeclNameColor);
  43. OS << '\'' << Name << '\'';
  44. }
  45. for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
  46. RI != RE; ++RI) {
  47. NodeDumper.AddChild([=] {
  48. NodeDumper.dumpBareDeclRef(*RI);
  49. if (!(*RI)->isUnconditionallyVisible())
  50. OS << " hidden";
  51. // If requested, dump the redecl chain for this lookup.
  52. if (DumpDecls) {
  53. // Dump earliest decl first.
  54. std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {
  55. if (Decl *Prev = D->getPreviousDecl())
  56. DumpWithPrev(Prev);
  57. Visit(D);
  58. };
  59. DumpWithPrev(*RI);
  60. }
  61. });
  62. }
  63. });
  64. }
  65. if (HasUndeserializedLookups) {
  66. NodeDumper.AddChild([=] {
  67. ColorScope Color(OS, ShowColors, UndeserializedColor);
  68. OS << "<undeserialized lookups>";
  69. });
  70. }
  71. });
  72. }
  73. template <typename SpecializationDecl>
  74. void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
  75. bool DumpExplicitInst,
  76. bool DumpRefOnly) {
  77. bool DumpedAny = false;
  78. for (const auto *RedeclWithBadType : D->redecls()) {
  79. // FIXME: The redecls() range sometimes has elements of a less-specific
  80. // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
  81. // us TagDecls, and should give CXXRecordDecls).
  82. auto *Redecl = cast<SpecializationDecl>(RedeclWithBadType);
  83. switch (Redecl->getTemplateSpecializationKind()) {
  84. case TSK_ExplicitInstantiationDeclaration:
  85. case TSK_ExplicitInstantiationDefinition:
  86. if (!DumpExplicitInst)
  87. break;
  88. LLVM_FALLTHROUGH;
  89. case TSK_Undeclared:
  90. case TSK_ImplicitInstantiation:
  91. if (DumpRefOnly)
  92. NodeDumper.dumpDeclRef(Redecl);
  93. else
  94. Visit(Redecl);
  95. DumpedAny = true;
  96. break;
  97. case TSK_ExplicitSpecialization:
  98. break;
  99. }
  100. }
  101. // Ensure we dump at least one decl for each specialization.
  102. if (!DumpedAny)
  103. NodeDumper.dumpDeclRef(D);
  104. }
  105. template <typename TemplateDecl>
  106. void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
  107. dumpTemplateParameters(D->getTemplateParameters());
  108. Visit(D->getTemplatedDecl());
  109. if (GetTraversalKind() == TK_AsIs) {
  110. for (const auto *Child : D->specializations())
  111. dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
  112. !D->isCanonicalDecl());
  113. }
  114. }
  115. void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
  116. // FIXME: We don't add a declaration of a function template specialization
  117. // to its context when it's explicitly instantiated, so dump explicit
  118. // instantiations when we dump the template itself.
  119. dumpTemplateDecl(D, true);
  120. }
  121. void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
  122. dumpTemplateDecl(D, false);
  123. }
  124. void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
  125. dumpTemplateDecl(D, false);
  126. }
  127. //===----------------------------------------------------------------------===//
  128. // Type method implementations
  129. //===----------------------------------------------------------------------===//
  130. void QualType::dump(const char *msg) const {
  131. if (msg)
  132. llvm::errs() << msg << ": ";
  133. dump();
  134. }
  135. LLVM_DUMP_METHOD void QualType::dump() const {
  136. ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
  137. Dumper.Visit(*this);
  138. }
  139. LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS,
  140. const ASTContext &Context) const {
  141. ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
  142. Dumper.Visit(*this);
  143. }
  144. LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
  145. LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS,
  146. const ASTContext &Context) const {
  147. QualType(this, 0).dump(OS, Context);
  148. }
  149. //===----------------------------------------------------------------------===//
  150. // Decl method implementations
  151. //===----------------------------------------------------------------------===//
  152. LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }
  153. LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,
  154. ASTDumpOutputFormat Format) const {
  155. ASTContext &Ctx = getASTContext();
  156. const SourceManager &SM = Ctx.getSourceManager();
  157. if (ADOF_JSON == Format) {
  158. JSONDumper P(OS, SM, Ctx, Ctx.getPrintingPolicy(),
  159. &Ctx.getCommentCommandTraits());
  160. (void)Deserialize; // FIXME?
  161. P.Visit(this);
  162. } else {
  163. ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
  164. P.setDeserialize(Deserialize);
  165. P.Visit(this);
  166. }
  167. }
  168. LLVM_DUMP_METHOD void Decl::dumpColor() const {
  169. const ASTContext &Ctx = getASTContext();
  170. ASTDumper P(llvm::errs(), Ctx, /*ShowColors=*/true);
  171. P.Visit(this);
  172. }
  173. LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
  174. dumpLookups(llvm::errs());
  175. }
  176. LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
  177. bool DumpDecls,
  178. bool Deserialize) const {
  179. const DeclContext *DC = this;
  180. while (!DC->isTranslationUnit())
  181. DC = DC->getParent();
  182. const ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
  183. ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
  184. P.setDeserialize(Deserialize);
  185. P.dumpLookups(this, DumpDecls);
  186. }
  187. //===----------------------------------------------------------------------===//
  188. // Stmt method implementations
  189. //===----------------------------------------------------------------------===//
  190. LLVM_DUMP_METHOD void Stmt::dump() const {
  191. ASTDumper P(llvm::errs(), /*ShowColors=*/false);
  192. P.Visit(this);
  193. }
  194. LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS,
  195. const ASTContext &Context) const {
  196. ASTDumper P(OS, Context, Context.getDiagnostics().getShowColors());
  197. P.Visit(this);
  198. }
  199. LLVM_DUMP_METHOD void Stmt::dumpColor() const {
  200. ASTDumper P(llvm::errs(), /*ShowColors=*/true);
  201. P.Visit(this);
  202. }
  203. //===----------------------------------------------------------------------===//
  204. // Comment method implementations
  205. //===----------------------------------------------------------------------===//
  206. LLVM_DUMP_METHOD void Comment::dump() const {
  207. const auto *FC = dyn_cast<FullComment>(this);
  208. if (!FC)
  209. return;
  210. ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
  211. Dumper.Visit(FC, FC);
  212. }
  213. LLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS,
  214. const ASTContext &Context) const {
  215. const auto *FC = dyn_cast<FullComment>(this);
  216. if (!FC)
  217. return;
  218. ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
  219. Dumper.Visit(FC, FC);
  220. }
  221. LLVM_DUMP_METHOD void Comment::dumpColor() const {
  222. const auto *FC = dyn_cast<FullComment>(this);
  223. if (!FC)
  224. return;
  225. ASTDumper Dumper(llvm::errs(), /*ShowColors=*/true);
  226. Dumper.Visit(FC, FC);
  227. }
  228. //===----------------------------------------------------------------------===//
  229. // APValue method implementations
  230. //===----------------------------------------------------------------------===//
  231. LLVM_DUMP_METHOD void APValue::dump() const {
  232. ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
  233. Dumper.Visit(*this, /*Ty=*/QualType());
  234. }
  235. LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
  236. const ASTContext &Context) const {
  237. ASTDumper Dumper(llvm::errs(), Context,
  238. Context.getDiagnostics().getShowColors());
  239. Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
  240. }