ASTDumper.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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)->isHidden())
  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 = dyn_cast<SpecializationDecl>(RedeclWithBadType);
  83. if (!Redecl) {
  84. // Found the injected-class-name for a class template. This will be dumped
  85. // as part of its surrounding class so we don't need to dump it here.
  86. assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
  87. "expected an injected-class-name");
  88. continue;
  89. }
  90. switch (Redecl->getTemplateSpecializationKind()) {
  91. case TSK_ExplicitInstantiationDeclaration:
  92. case TSK_ExplicitInstantiationDefinition:
  93. if (!DumpExplicitInst)
  94. break;
  95. LLVM_FALLTHROUGH;
  96. case TSK_Undeclared:
  97. case TSK_ImplicitInstantiation:
  98. if (DumpRefOnly)
  99. NodeDumper.dumpDeclRef(Redecl);
  100. else
  101. Visit(Redecl);
  102. DumpedAny = true;
  103. break;
  104. case TSK_ExplicitSpecialization:
  105. break;
  106. }
  107. }
  108. // Ensure we dump at least one decl for each specialization.
  109. if (!DumpedAny)
  110. NodeDumper.dumpDeclRef(D);
  111. }
  112. template <typename TemplateDecl>
  113. void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
  114. dumpTemplateParameters(D->getTemplateParameters());
  115. Visit(D->getTemplatedDecl());
  116. for (const auto *Child : D->specializations())
  117. dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
  118. !D->isCanonicalDecl());
  119. }
  120. void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
  121. // FIXME: We don't add a declaration of a function template specialization
  122. // to its context when it's explicitly instantiated, so dump explicit
  123. // instantiations when we dump the template itself.
  124. dumpTemplateDecl(D, true);
  125. }
  126. void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
  127. dumpTemplateDecl(D, false);
  128. }
  129. void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
  130. dumpTemplateDecl(D, false);
  131. }
  132. //===----------------------------------------------------------------------===//
  133. // Type method implementations
  134. //===----------------------------------------------------------------------===//
  135. void QualType::dump(const char *msg) const {
  136. if (msg)
  137. llvm::errs() << msg << ": ";
  138. dump();
  139. }
  140. LLVM_DUMP_METHOD void QualType::dump() const { dump(llvm::errs()); }
  141. LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS) const {
  142. ASTDumper Dumper(OS, nullptr, nullptr);
  143. Dumper.Visit(*this);
  144. }
  145. LLVM_DUMP_METHOD void Type::dump() const { dump(llvm::errs()); }
  146. LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const {
  147. QualType(this, 0).dump(OS);
  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.getCommentCommandTraits(), &SM,
  164. SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy());
  165. P.setDeserialize(Deserialize);
  166. P.Visit(this);
  167. }
  168. }
  169. LLVM_DUMP_METHOD void Decl::dumpColor() const {
  170. const ASTContext &Ctx = getASTContext();
  171. ASTDumper P(llvm::errs(), &Ctx.getCommentCommandTraits(),
  172. &Ctx.getSourceManager(), /*ShowColors*/ true,
  173. Ctx.getPrintingPolicy());
  174. P.Visit(this);
  175. }
  176. LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
  177. dumpLookups(llvm::errs());
  178. }
  179. LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
  180. bool DumpDecls,
  181. bool Deserialize) const {
  182. const DeclContext *DC = this;
  183. while (!DC->isTranslationUnit())
  184. DC = DC->getParent();
  185. ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
  186. const SourceManager &SM = Ctx.getSourceManager();
  187. ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager(),
  188. SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy());
  189. P.setDeserialize(Deserialize);
  190. P.dumpLookups(this, DumpDecls);
  191. }
  192. //===----------------------------------------------------------------------===//
  193. // Stmt method implementations
  194. //===----------------------------------------------------------------------===//
  195. LLVM_DUMP_METHOD void Stmt::dump(SourceManager &SM) const {
  196. dump(llvm::errs(), SM);
  197. }
  198. LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
  199. ASTDumper P(OS, nullptr, &SM);
  200. P.Visit(this);
  201. }
  202. LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS) const {
  203. ASTDumper P(OS, nullptr, nullptr);
  204. P.Visit(this);
  205. }
  206. LLVM_DUMP_METHOD void Stmt::dump() const {
  207. ASTDumper P(llvm::errs(), nullptr, nullptr);
  208. P.Visit(this);
  209. }
  210. LLVM_DUMP_METHOD void Stmt::dumpColor() const {
  211. ASTDumper P(llvm::errs(), nullptr, nullptr, /*ShowColors*/true);
  212. P.Visit(this);
  213. }
  214. //===----------------------------------------------------------------------===//
  215. // Comment method implementations
  216. //===----------------------------------------------------------------------===//
  217. LLVM_DUMP_METHOD void Comment::dump() const {
  218. dump(llvm::errs(), nullptr, nullptr);
  219. }
  220. LLVM_DUMP_METHOD void Comment::dump(const ASTContext &Context) const {
  221. dump(llvm::errs(), &Context.getCommentCommandTraits(),
  222. &Context.getSourceManager());
  223. }
  224. void Comment::dump(raw_ostream &OS, const CommandTraits *Traits,
  225. const SourceManager *SM) const {
  226. const FullComment *FC = dyn_cast<FullComment>(this);
  227. if (!FC)
  228. return;
  229. ASTDumper D(OS, Traits, SM);
  230. D.Visit(FC, FC);
  231. }
  232. LLVM_DUMP_METHOD void Comment::dumpColor() const {
  233. const FullComment *FC = dyn_cast<FullComment>(this);
  234. if (!FC)
  235. return;
  236. ASTDumper D(llvm::errs(), nullptr, nullptr, /*ShowColors*/true);
  237. D.Visit(FC, FC);
  238. }