Clang Project

clang_source_code/lib/AST/ASTDumper.cpp
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
14#include "clang/AST/ASTContext.h"
15#include "clang/AST/ASTNodeTraverser.h"
16#include "clang/AST/DeclLookups.h"
17#include "clang/AST/TextNodeDumper.h"
18#include "clang/Basic/Builtins.h"
19#include "clang/Basic/Module.h"
20#include "clang/Basic/SourceManager.h"
21#include "llvm/Support/raw_ostream.h"
22using namespace clang;
23using namespace clang::comments;
24
25//===----------------------------------------------------------------------===//
26// ASTDumper Visitor
27//===----------------------------------------------------------------------===//
28
29namespace  {
30
31class ASTDumper : public ASTNodeTraverser<ASTDumperTextNodeDumper> {
32
33  TextNodeDumper NodeDumper;
34
35  raw_ostream &OS;
36
37  const bool ShowColors;
38
39public:
40  ASTDumper(raw_ostream &OSconst CommandTraits *Traits,
41            const SourceManager *SM)
42      : ASTDumper(OSTraitsSMSM && SM->getDiagnostics().getShowColors()) {}
43
44  ASTDumper(raw_ostream &OSconst CommandTraits *Traits,
45            const SourceManager *SMbool ShowColors)
46      : ASTDumper(OS, Traits, SM, ShowColors, LangOptions()) {}
47  ASTDumper(raw_ostream &OSconst CommandTraits *Traits,
48            const SourceManager *SMbool ShowColors,
49            const PrintingPolicy &PrintPolicy)
50      : NodeDumper(OS, ShowColors, SM, PrintPolicy, Traits), OS(OS),
51        ShowColors(ShowColors) {}
52
53  TextNodeDumper &doGetNodeDelegate() { return NodeDumper; }
54
55  void dumpLookups(const DeclContext *DCbool DumpDecls);
56
57  template <typename SpecializationDecl>
58  void dumpTemplateDeclSpecialization(const SpecializationDecl *D,
59                                      bool DumpExplicitInstbool DumpRefOnly);
60  template <typename TemplateDecl>
61  void dumpTemplateDecl(const TemplateDecl *Dbool DumpExplicitInst);
62
63  void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
64  void VisitClassTemplateDecl(const ClassTemplateDecl *D);
65  void VisitVarTemplateDecl(const VarTemplateDecl *D);
66};
67// namespace
68
69void ASTDumper::dumpLookups(const DeclContext *DCbool DumpDecls) {
70  NodeDumper.AddChild([=] {
71    OS << "StoredDeclsMap ";
72    NodeDumper.dumpBareDeclRef(cast<Decl>(DC));
73
74    const DeclContext *Primary = DC->getPrimaryContext();
75    if (Primary != DC) {
76      OS << " primary";
77      NodeDumper.dumpPointer(cast<Decl>(Primary));
78    }
79
80    bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
81
82    auto Range = getDeserialize()
83                     ? Primary->lookups()
84                     : Primary->noload_lookups(/*PreserveInternalState=*/true);
85    for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {
86      DeclarationName Name = I.getLookupName();
87      DeclContextLookupResult R = *I;
88
89      NodeDumper.AddChild([=] {
90        OS << "DeclarationName ";
91        {
92          ColorScope Color(OS, ShowColors, DeclNameColor);
93          OS << '\'' << Name << '\'';
94        }
95
96        for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
97             RI != RE; ++RI) {
98          NodeDumper.AddChild([=] {
99            NodeDumper.dumpBareDeclRef(*RI);
100
101            if ((*RI)->isHidden())
102              OS << " hidden";
103
104            // If requested, dump the redecl chain for this lookup.
105            if (DumpDecls) {
106              // Dump earliest decl first.
107              std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {
108                if (Decl *Prev = D->getPreviousDecl())
109                  DumpWithPrev(Prev);
110                Visit(D);
111              };
112              DumpWithPrev(*RI);
113            }
114          });
115        }
116      });
117    }
118
119    if (HasUndeserializedLookups) {
120      NodeDumper.AddChild([=] {
121        ColorScope Color(OS, ShowColors, UndeserializedColor);
122        OS << "<undeserialized lookups>";
123      });
124    }
125  });
126}
127
128template <typename SpecializationDecl>
129void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
130                                               bool DumpExplicitInst,
131                                               bool DumpRefOnly) {
132  bool DumpedAny = false;
133  for (const auto *RedeclWithBadType : D->redecls()) {
134    // FIXME: The redecls() range sometimes has elements of a less-specific
135    // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
136    // us TagDecls, and should give CXXRecordDecls).
137    auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
138    if (!Redecl) {
139      // Found the injected-class-name for a class template. This will be dumped
140      // as part of its surrounding class so we don't need to dump it here.
141       (0) . __assert_fail ("isa(RedeclWithBadType) && \"expected an injected-class-name\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ASTDumper.cpp", 142, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
142 (0) . __assert_fail ("isa(RedeclWithBadType) && \"expected an injected-class-name\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ASTDumper.cpp", 142, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">             "expected an injected-class-name");
143      continue;
144    }
145
146    switch (Redecl->getTemplateSpecializationKind()) {
147    case TSK_ExplicitInstantiationDeclaration:
148    case TSK_ExplicitInstantiationDefinition:
149      if (!DumpExplicitInst)
150        break;
151      LLVM_FALLTHROUGH;
152    case TSK_Undeclared:
153    case TSK_ImplicitInstantiation:
154      if (DumpRefOnly)
155        NodeDumper.dumpDeclRef(Redecl);
156      else
157        Visit(Redecl);
158      DumpedAny = true;
159      break;
160    case TSK_ExplicitSpecialization:
161      break;
162    }
163  }
164
165  // Ensure we dump at least one decl for each specialization.
166  if (!DumpedAny)
167    NodeDumper.dumpDeclRef(D);
168}
169
170template <typename TemplateDecl>
171void ASTDumper::dumpTemplateDecl(const TemplateDecl *Dbool DumpExplicitInst) {
172  dumpTemplateParameters(D->getTemplateParameters());
173
174  Visit(D->getTemplatedDecl());
175
176  for (const auto *Child : D->specializations())
177    dumpTemplateDeclSpecialization(ChildDumpExplicitInst,
178                                   !D->isCanonicalDecl());
179}
180
181void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
182  // FIXME: We don't add a declaration of a function template specialization
183  // to its context when it's explicitly instantiated, so dump explicit
184  // instantiations when we dump the template itself.
185  dumpTemplateDecl(Dtrue);
186}
187
188void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
189  dumpTemplateDecl(Dfalse);
190}
191
192void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
193  dumpTemplateDecl(Dfalse);
194}
195
196//===----------------------------------------------------------------------===//
197// Type method implementations
198//===----------------------------------------------------------------------===//
199
200void QualType::dump(const char *msgconst {
201  if (msg)
202    llvm::errs() << msg << ": ";
203  dump();
204}
205
206LLVM_DUMP_METHOD void QualType::dump() const { dump(llvm::errs()); }
207
208LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS) const {
209  ASTDumper Dumper(OSnullptrnullptr);
210  Dumper.Visit(*this);
211}
212
213LLVM_DUMP_METHOD void Type::dump() const { dump(llvm::errs()); }
214
215LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const {
216  QualType(this0).dump(OS);
217}
218
219//===----------------------------------------------------------------------===//
220// Decl method implementations
221//===----------------------------------------------------------------------===//
222
223LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }
224
225LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize) const {
226  const ASTContext &Ctx = getASTContext();
227  const SourceManager &SM = Ctx.getSourceManager();
228  ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &SM,
229              SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy());
230  P.setDeserialize(Deserialize);
231  P.Visit(this);
232}
233
234LLVM_DUMP_METHOD void Decl::dumpColor() const {
235  const ASTContext &Ctx = getASTContext();
236  ASTDumper P(llvm::errs(), &Ctx.getCommentCommandTraits(),
237              &Ctx.getSourceManager(), /*ShowColors*/ true,
238              Ctx.getPrintingPolicy());
239  P.Visit(this);
240}
241
242LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
243  dumpLookups(llvm::errs());
244}
245
246LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
247                                               bool DumpDecls,
248                                               bool Deserialize) const {
249  const DeclContext *DC = this;
250  while (!DC->isTranslationUnit())
251    DC = DC->getParent();
252  ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
253  const SourceManager &SM = Ctx.getSourceManager();
254  ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager(),
255              SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy());
256  P.setDeserialize(Deserialize);
257  P.dumpLookups(thisDumpDecls);
258}
259
260//===----------------------------------------------------------------------===//
261// Stmt method implementations
262//===----------------------------------------------------------------------===//
263
264LLVM_DUMP_METHOD void Stmt::dump(SourceManager &SM) const {
265  dump(llvm::errs(), SM);
266}
267
268LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
269  ASTDumper P(OSnullptr, &SM);
270  P.Visit(this);
271}
272
273LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS) const {
274  ASTDumper P(OSnullptrnullptr);
275  P.Visit(this);
276}
277
278LLVM_DUMP_METHOD void Stmt::dump() const {
279  ASTDumper P(llvm::errs(), nullptrnullptr);
280  P.Visit(this);
281}
282
283LLVM_DUMP_METHOD void Stmt::dumpColor() const {
284  ASTDumper P(llvm::errs(), nullptrnullptr/*ShowColors*/true);
285  P.Visit(this);
286}
287
288//===----------------------------------------------------------------------===//
289// Comment method implementations
290//===----------------------------------------------------------------------===//
291
292LLVM_DUMP_METHOD void Comment::dump() const {
293  dump(llvm::errs(), nullptrnullptr);
294}
295
296LLVM_DUMP_METHOD void Comment::dump(const ASTContext &Context) const {
297  dump(llvm::errs(), &Context.getCommentCommandTraits(),
298       &Context.getSourceManager());
299}
300
301void Comment::dump(raw_ostream &OSconst CommandTraits *Traits,
302                   const SourceManager *SMconst {
303  const FullComment *FC = dyn_cast<FullComment>(this);
304  if (!FC)
305    return;
306  ASTDumper D(OSTraitsSM);
307  D.Visit(FCFC);
308}
309
310LLVM_DUMP_METHOD void Comment::dumpColor() const {
311  const FullComment *FC = dyn_cast<FullComment>(this);
312  if (!FC)
313    return;
314  ASTDumper D(llvm::errs(), nullptrnullptr/*ShowColors*/true);
315  D.Visit(FCFC);
316}
317
clang::QualType::dump
clang::QualType::dump
clang::QualType::dump
clang::Type::dump
clang::Type::dump
clang::Decl::dump
clang::Decl::dump
clang::Decl::dumpColor
clang::DeclContext::dumpLookups
clang::DeclContext::dumpLookups
clang::Stmt::dump
clang::Stmt::dump
clang::Stmt::dump
clang::Stmt::dump
clang::Stmt::dumpColor
clang::comments::Comment::dump
clang::comments::Comment::dump
clang::comments::Comment::dump
clang::comments::Comment::dumpColor