1119998Sgad//===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===//
2119998Sgad//
3119998Sgad// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4119998Sgad// See https://llvm.org/LICENSE.txt for license information.
5119998Sgad// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6119998Sgad//
7119998Sgad//===----------------------------------------------------------------------===//
8119998Sgad//
9119998Sgad// This file implements the AST dump methods, which dump out the
10119998Sgad// AST in a form that exposes type details and other fields.
11119998Sgad//
12119998Sgad//===----------------------------------------------------------------------===//
13119998Sgad
14119998Sgad#include "clang/AST/ASTDumper.h"
15119998Sgad#include "clang/AST/ASTContext.h"
16119998Sgad#include "clang/AST/DeclLookups.h"
17119998Sgad#include "clang/AST/JSONNodeDumper.h"
18119998Sgad#include "clang/Basic/Builtins.h"
19119998Sgad#include "clang/Basic/Module.h"
20119998Sgad#include "clang/Basic/SourceManager.h"
21119998Sgad#include "llvm/Support/raw_ostream.h"
22119998Sgad
23119998Sgadusing namespace clang;
24119998Sgadusing namespace clang::comments;
25119998Sgad
26119998Sgadvoid ASTDumper::dumpInvalidDeclContext(const DeclContext *DC) {
27119998Sgad  NodeDumper.AddChild([=] {
28119998Sgad    if (!DC) {
29119998Sgad      ColorScope Color(OS, ShowColors, NullColor);
30119998Sgad      OS << "<<<NULL>>>";
31119998Sgad      return;
32119998Sgad    }
33119998Sgad    // An invalid DeclContext is one for which a dyn_cast() from a DeclContext
34119998Sgad    // pointer to a Decl pointer would fail an assertion or otherwise fall prey
35119998Sgad    // to undefined behavior as a result of an invalid associated DeclKind.
36119998Sgad    // Such invalidity is not supposed to happen of course, but, when it does,
37120361Sgad    // the information provided below is intended to provide some hints about
38120361Sgad    // what might have gone awry.
39120361Sgad    {
40120361Sgad      ColorScope Color(OS, ShowColors, DeclKindNameColor);
41119998Sgad      OS << "DeclContext";
42119998Sgad    }
43119998Sgad    NodeDumper.dumpPointer(DC);
44119998Sgad    OS << " <";
45119998Sgad    {
46119998Sgad      ColorScope Color(OS, ShowColors, DeclNameColor);
47119998Sgad      OS << "unrecognized Decl kind " << (unsigned)DC->getDeclKind();
48119998Sgad    }
49119998Sgad    OS << ">";
50120361Sgad  });
51119998Sgad}
52119998Sgad
53119998Sgadvoid ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
54119998Sgad  NodeDumper.AddChild([=] {
55120361Sgad    OS << "StoredDeclsMap ";
56120361Sgad    NodeDumper.dumpBareDeclRef(cast<Decl>(DC));
57120361Sgad
58120361Sgad    const DeclContext *Primary = DC->getPrimaryContext();
59120361Sgad    if (Primary != DC) {
60120361Sgad      OS << " primary";
61120361Sgad      NodeDumper.dumpPointer(cast<Decl>(Primary));
62120361Sgad    }
63120361Sgad
64120361Sgad    bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
65120361Sgad
66120361Sgad    auto Range = getDeserialize()
67120361Sgad                     ? Primary->lookups()
68120361Sgad                     : Primary->noload_lookups(/*PreserveInternalState=*/true);
69120361Sgad    for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {
70120361Sgad      DeclarationName Name = I.getLookupName();
71120361Sgad      DeclContextLookupResult R = *I;
72120361Sgad
73120361Sgad      NodeDumper.AddChild([=] {
74120361Sgad        OS << "DeclarationName ";
75120361Sgad        {
76120361Sgad          ColorScope Color(OS, ShowColors, DeclNameColor);
77120361Sgad          OS << '\'' << Name << '\'';
78120361Sgad        }
79120361Sgad
80120361Sgad        for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
81120361Sgad             RI != RE; ++RI) {
82120046Sgad          NodeDumper.AddChild([=] {
83120361Sgad            NodeDumper.dumpBareDeclRef(*RI);
84120361Sgad
85120046Sgad            if (!(*RI)->isUnconditionallyVisible())
86120046Sgad              OS << " hidden";
87120046Sgad
88120046Sgad            // If requested, dump the redecl chain for this lookup.
89120046Sgad            if (DumpDecls) {
90120046Sgad              // Dump earliest decl first.
91120046Sgad              std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {
92120046Sgad                if (Decl *Prev = D->getPreviousDecl())
93120046Sgad                  DumpWithPrev(Prev);
94120046Sgad                Visit(D);
95120046Sgad              };
96120046Sgad              DumpWithPrev(*RI);
97120046Sgad            }
98120046Sgad          });
99120046Sgad        }
100120046Sgad      });
101120046Sgad    }
102120046Sgad
103120046Sgad    if (HasUndeserializedLookups) {
104120046Sgad      NodeDumper.AddChild([=] {
105120046Sgad        ColorScope Color(OS, ShowColors, UndeserializedColor);
106120046Sgad        OS << "<undeserialized lookups>";
107120046Sgad      });
108120046Sgad    }
109120046Sgad  });
110120046Sgad}
111120046Sgad
112120046Sgadtemplate <typename SpecializationDecl>
113120046Sgadvoid ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
114120046Sgad                                               bool DumpExplicitInst,
115120046Sgad                                               bool DumpRefOnly) {
116120046Sgad  bool DumpedAny = false;
117120046Sgad  for (const auto *RedeclWithBadType : D->redecls()) {
118120046Sgad    // FIXME: The redecls() range sometimes has elements of a less-specific
119120046Sgad    // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
120119998Sgad    // us TagDecls, and should give CXXRecordDecls).
121119998Sgad    auto *Redecl = cast<SpecializationDecl>(RedeclWithBadType);
122119998Sgad    switch (Redecl->getTemplateSpecializationKind()) {
123119998Sgad    case TSK_ExplicitInstantiationDeclaration:
124119998Sgad    case TSK_ExplicitInstantiationDefinition:
125119998Sgad      if (!DumpExplicitInst)
126119998Sgad        break;
127119998Sgad      [[fallthrough]];
128120361Sgad    case TSK_Undeclared:
129120361Sgad    case TSK_ImplicitInstantiation:
130119998Sgad      if (DumpRefOnly)
131119998Sgad        NodeDumper.dumpDeclRef(Redecl);
132119998Sgad      else
133120361Sgad        Visit(Redecl);
134119998Sgad      DumpedAny = true;
135119998Sgad      break;
136119998Sgad    case TSK_ExplicitSpecialization:
137119998Sgad      break;
138119998Sgad    }
139119998Sgad  }
140119998Sgad
141119998Sgad  // Ensure we dump at least one decl for each specialization.
142119998Sgad  if (!DumpedAny)
143119998Sgad    NodeDumper.dumpDeclRef(D);
144120361Sgad}
145120361Sgad
146119998Sgadtemplate <typename TemplateDecl>
147119998Sgadvoid ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
148119998Sgad  dumpTemplateParameters(D->getTemplateParameters());
149119998Sgad
150119998Sgad  Visit(D->getTemplatedDecl());
151120361Sgad
152119998Sgad  if (GetTraversalKind() == TK_AsIs) {
153119998Sgad    for (const auto *Child : D->specializations())
154119998Sgad      dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
155119998Sgad                                     !D->isCanonicalDecl());
156120361Sgad  }
157119998Sgad}
158119998Sgad
159119998Sgadvoid ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
160120361Sgad  // FIXME: We don't add a declaration of a function template specialization
161119998Sgad  // to its context when it's explicitly instantiated, so dump explicit
162119998Sgad  // instantiations when we dump the template itself.
163119998Sgad  dumpTemplateDecl(D, true);
164119998Sgad}
165119998Sgad
166119998Sgadvoid ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
167119998Sgad  dumpTemplateDecl(D, false);
168119998Sgad}
169119998Sgad
170119998Sgadvoid ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
171119998Sgad  dumpTemplateDecl(D, false);
172119998Sgad}
173119998Sgad
174119998Sgad//===----------------------------------------------------------------------===//
175119998Sgad// Type method implementations
176119998Sgad//===----------------------------------------------------------------------===//
177119998Sgad
178119998Sgadvoid QualType::dump(const char *msg) const {
179119998Sgad  if (msg)
180119998Sgad    llvm::errs() << msg << ": ";
181119998Sgad  dump();
182119998Sgad}
183119998Sgad
184119998SgadLLVM_DUMP_METHOD void QualType::dump() const {
185119998Sgad  ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
186119998Sgad  Dumper.Visit(*this);
187120361Sgad}
188119998Sgad
189119998SgadLLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS,
190119998Sgad                                     const ASTContext &Context) const {
191119998Sgad  ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
192119998Sgad  Dumper.Visit(*this);
193119998Sgad}
194119998Sgad
195119998SgadLLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
196119998Sgad
197119998SgadLLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS,
198119998Sgad                                 const ASTContext &Context) const {
199119998Sgad  QualType(this, 0).dump(OS, Context);
200119998Sgad}
201120361Sgad
202120361Sgad//===----------------------------------------------------------------------===//
203119998Sgad// Decl method implementations
204119998Sgad//===----------------------------------------------------------------------===//
205119998Sgad
206119998SgadLLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }
207119998Sgad
208119998SgadLLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,
209119998Sgad                                 ASTDumpOutputFormat Format) const {
210119998Sgad  ASTContext &Ctx = getASTContext();
211119998Sgad  const SourceManager &SM = Ctx.getSourceManager();
212119998Sgad
213119998Sgad  if (ADOF_JSON == Format) {
214119998Sgad    JSONDumper P(OS, SM, Ctx, Ctx.getPrintingPolicy(),
215119998Sgad                 &Ctx.getCommentCommandTraits());
216119998Sgad    (void)Deserialize; // FIXME?
217119998Sgad    P.Visit(this);
218119998Sgad  } else {
219120361Sgad    ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
220120361Sgad    P.setDeserialize(Deserialize);
221119998Sgad    P.Visit(this);
222120361Sgad  }
223120726Sgad}
224120726Sgad
225119998SgadLLVM_DUMP_METHOD void Decl::dumpColor() const {
226120361Sgad  const ASTContext &Ctx = getASTContext();
227119998Sgad  ASTDumper P(llvm::errs(), Ctx, /*ShowColors=*/true);
228120046Sgad  P.Visit(this);
229120361Sgad}
230120046Sgad
231119998SgadLLVM_DUMP_METHOD void DeclContext::dumpAsDecl() const {
232120361Sgad  dumpAsDecl(nullptr);
233120361Sgad}
234119998Sgad
235120726SgadLLVM_DUMP_METHOD void DeclContext::dumpAsDecl(const ASTContext *Ctx) const {
236119998Sgad  // By design, DeclContext is required to be a base class of some class that
237119998Sgad  // derives from Decl. Thus, it should always be possible to dyn_cast() from
238119998Sgad  // a DeclContext pointer to a Decl pointer and Decl::castFromDeclContext()
239119998Sgad  // asserts that to be the case. Since this function is intended for use in a
240119998Sgad  // debugger, it performs an additional check in order to prevent a failed
241120361Sgad  // cast and assertion. If that check fails, then the (invalid) DeclContext
242119998Sgad  // is dumped with an indication of its invalidity.
243120726Sgad  if (hasValidDeclKind()) {
244119998Sgad    const auto *D = cast<Decl>(this);
245119998Sgad    D->dump();
246120726Sgad  } else {
247119998Sgad    // If an ASTContext is not available, a less capable ASTDumper is
248119998Sgad    // constructed for which color diagnostics are, regrettably, disabled.
249119998Sgad    ASTDumper P = Ctx ? ASTDumper(llvm::errs(), *Ctx,
250119998Sgad                                  Ctx->getDiagnostics().getShowColors())
251119998Sgad                      : ASTDumper(llvm::errs(), /*ShowColors*/ false);
252119998Sgad    P.dumpInvalidDeclContext(this);
253119998Sgad  }
254120361Sgad}
255119998Sgad
256120726SgadLLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
257119998Sgad  dumpLookups(llvm::errs());
258119998Sgad}
259120726Sgad
260119998SgadLLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
261119998Sgad                                               bool DumpDecls,
262119998Sgad                                               bool Deserialize) const {
263119998Sgad  const DeclContext *DC = this;
264119998Sgad  while (!DC->isTranslationUnit())
265119998Sgad    DC = DC->getParent();
266119998Sgad  const ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
267119998Sgad  ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
268119998Sgad  P.setDeserialize(Deserialize);
269119998Sgad  P.dumpLookups(this, DumpDecls);
270119998Sgad}
271119998Sgad
272120046Sgad//===----------------------------------------------------------------------===//
273119998Sgad// Stmt method implementations
274120046Sgad//===----------------------------------------------------------------------===//
275119998Sgad
276119998SgadLLVM_DUMP_METHOD void Stmt::dump() const {
277119998Sgad  ASTDumper P(llvm::errs(), /*ShowColors=*/false);
278119998Sgad  P.Visit(this);
279119998Sgad}
280119998Sgad
281119998SgadLLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS,
282119998Sgad                                 const ASTContext &Context) const {
283120361Sgad  ASTDumper P(OS, Context, Context.getDiagnostics().getShowColors());
284119998Sgad  P.Visit(this);
285119998Sgad}
286120361Sgad
287120361SgadLLVM_DUMP_METHOD void Stmt::dumpColor() const {
288120046Sgad  ASTDumper P(llvm::errs(), /*ShowColors=*/true);
289120726Sgad  P.Visit(this);
290119998Sgad}
291120726Sgad
292119998Sgad//===----------------------------------------------------------------------===//
293119998Sgad// Comment method implementations
294119998Sgad//===----------------------------------------------------------------------===//
295120046Sgad
296119998SgadLLVM_DUMP_METHOD void Comment::dump() const {
297120726Sgad  const auto *FC = dyn_cast<FullComment>(this);
298119998Sgad  if (!FC)
299119998Sgad    return;
300119998Sgad  ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
301119998Sgad  Dumper.Visit(FC, FC);
302119998Sgad}
303119998Sgad
304119998SgadLLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS,
305119998Sgad                                    const ASTContext &Context) const {
306119998Sgad  const auto *FC = dyn_cast<FullComment>(this);
307120726Sgad  if (!FC)
308120726Sgad    return;
309120726Sgad  ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
310119998Sgad  Dumper.Visit(FC, FC);
311119998Sgad}
312120726Sgad
313119998SgadLLVM_DUMP_METHOD void Comment::dumpColor() const {
314119998Sgad  const auto *FC = dyn_cast<FullComment>(this);
315120361Sgad  if (!FC)
316120361Sgad    return;
317120361Sgad  ASTDumper Dumper(llvm::errs(), /*ShowColors=*/true);
318120361Sgad  Dumper.Visit(FC, FC);
319120361Sgad}
320120361Sgad
321120361Sgad//===----------------------------------------------------------------------===//
322120361Sgad// APValue method implementations
323120361Sgad//===----------------------------------------------------------------------===//
324120361Sgad
325120361SgadLLVM_DUMP_METHOD void APValue::dump() const {
326120361Sgad  ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
327120361Sgad  Dumper.Visit(*this, /*Ty=*/QualType());
328120361Sgad}
329120361Sgad
330120361SgadLLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
331120361Sgad                                    const ASTContext &Context) const {
332120361Sgad  ASTDumper Dumper(llvm::errs(), Context,
333120361Sgad                   Context.getDiagnostics().getShowColors());
334120361Sgad  Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
335120361Sgad}
336120361Sgad