xref: /freebsd/contrib/llvm-project/clang/lib/AST/ASTDumper.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
10b57cec5SDimitry Andric //===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the AST dump methods, which dump out the
100b57cec5SDimitry Andric // AST in a form that exposes type details and other fields.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/AST/ASTDumper.h"
150b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
160b57cec5SDimitry Andric #include "clang/AST/DeclLookups.h"
170b57cec5SDimitry Andric #include "clang/AST/JSONNodeDumper.h"
180b57cec5SDimitry Andric #include "clang/Basic/Builtins.h"
190b57cec5SDimitry Andric #include "clang/Basic/Module.h"
200b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
220b57cec5SDimitry Andric using namespace clang;
230b57cec5SDimitry Andric using namespace clang::comments;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
260b57cec5SDimitry Andric   NodeDumper.AddChild([=] {
270b57cec5SDimitry Andric     OS << "StoredDeclsMap ";
280b57cec5SDimitry Andric     NodeDumper.dumpBareDeclRef(cast<Decl>(DC));
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric     const DeclContext *Primary = DC->getPrimaryContext();
310b57cec5SDimitry Andric     if (Primary != DC) {
320b57cec5SDimitry Andric       OS << " primary";
330b57cec5SDimitry Andric       NodeDumper.dumpPointer(cast<Decl>(Primary));
340b57cec5SDimitry Andric     }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric     bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric     auto Range = getDeserialize()
390b57cec5SDimitry Andric                      ? Primary->lookups()
400b57cec5SDimitry Andric                      : Primary->noload_lookups(/*PreserveInternalState=*/true);
410b57cec5SDimitry Andric     for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {
420b57cec5SDimitry Andric       DeclarationName Name = I.getLookupName();
430b57cec5SDimitry Andric       DeclContextLookupResult R = *I;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric       NodeDumper.AddChild([=] {
460b57cec5SDimitry Andric         OS << "DeclarationName ";
470b57cec5SDimitry Andric         {
480b57cec5SDimitry Andric           ColorScope Color(OS, ShowColors, DeclNameColor);
490b57cec5SDimitry Andric           OS << '\'' << Name << '\'';
500b57cec5SDimitry Andric         }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric         for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
530b57cec5SDimitry Andric              RI != RE; ++RI) {
540b57cec5SDimitry Andric           NodeDumper.AddChild([=] {
550b57cec5SDimitry Andric             NodeDumper.dumpBareDeclRef(*RI);
560b57cec5SDimitry Andric 
575ffd83dbSDimitry Andric             if (!(*RI)->isUnconditionallyVisible())
580b57cec5SDimitry Andric               OS << " hidden";
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric             // If requested, dump the redecl chain for this lookup.
610b57cec5SDimitry Andric             if (DumpDecls) {
620b57cec5SDimitry Andric               // Dump earliest decl first.
630b57cec5SDimitry Andric               std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {
640b57cec5SDimitry Andric                 if (Decl *Prev = D->getPreviousDecl())
650b57cec5SDimitry Andric                   DumpWithPrev(Prev);
660b57cec5SDimitry Andric                 Visit(D);
670b57cec5SDimitry Andric               };
680b57cec5SDimitry Andric               DumpWithPrev(*RI);
690b57cec5SDimitry Andric             }
700b57cec5SDimitry Andric           });
710b57cec5SDimitry Andric         }
720b57cec5SDimitry Andric       });
730b57cec5SDimitry Andric     }
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric     if (HasUndeserializedLookups) {
760b57cec5SDimitry Andric       NodeDumper.AddChild([=] {
770b57cec5SDimitry Andric         ColorScope Color(OS, ShowColors, UndeserializedColor);
780b57cec5SDimitry Andric         OS << "<undeserialized lookups>";
790b57cec5SDimitry Andric       });
800b57cec5SDimitry Andric     }
810b57cec5SDimitry Andric   });
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric template <typename SpecializationDecl>
850b57cec5SDimitry Andric void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
860b57cec5SDimitry Andric                                                bool DumpExplicitInst,
870b57cec5SDimitry Andric                                                bool DumpRefOnly) {
880b57cec5SDimitry Andric   bool DumpedAny = false;
890b57cec5SDimitry Andric   for (const auto *RedeclWithBadType : D->redecls()) {
900b57cec5SDimitry Andric     // FIXME: The redecls() range sometimes has elements of a less-specific
910b57cec5SDimitry Andric     // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
920b57cec5SDimitry Andric     // us TagDecls, and should give CXXRecordDecls).
930b57cec5SDimitry Andric     auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
940b57cec5SDimitry Andric     if (!Redecl) {
950b57cec5SDimitry Andric       // Found the injected-class-name for a class template. This will be dumped
960b57cec5SDimitry Andric       // as part of its surrounding class so we don't need to dump it here.
970b57cec5SDimitry Andric       assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
980b57cec5SDimitry Andric              "expected an injected-class-name");
990b57cec5SDimitry Andric       continue;
1000b57cec5SDimitry Andric     }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric     switch (Redecl->getTemplateSpecializationKind()) {
1030b57cec5SDimitry Andric     case TSK_ExplicitInstantiationDeclaration:
1040b57cec5SDimitry Andric     case TSK_ExplicitInstantiationDefinition:
1050b57cec5SDimitry Andric       if (!DumpExplicitInst)
1060b57cec5SDimitry Andric         break;
1070b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
1080b57cec5SDimitry Andric     case TSK_Undeclared:
1090b57cec5SDimitry Andric     case TSK_ImplicitInstantiation:
1100b57cec5SDimitry Andric       if (DumpRefOnly)
1110b57cec5SDimitry Andric         NodeDumper.dumpDeclRef(Redecl);
1120b57cec5SDimitry Andric       else
1130b57cec5SDimitry Andric         Visit(Redecl);
1140b57cec5SDimitry Andric       DumpedAny = true;
1150b57cec5SDimitry Andric       break;
1160b57cec5SDimitry Andric     case TSK_ExplicitSpecialization:
1170b57cec5SDimitry Andric       break;
1180b57cec5SDimitry Andric     }
1190b57cec5SDimitry Andric   }
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   // Ensure we dump at least one decl for each specialization.
1220b57cec5SDimitry Andric   if (!DumpedAny)
1230b57cec5SDimitry Andric     NodeDumper.dumpDeclRef(D);
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric template <typename TemplateDecl>
1270b57cec5SDimitry Andric void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
1280b57cec5SDimitry Andric   dumpTemplateParameters(D->getTemplateParameters());
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   Visit(D->getTemplatedDecl());
1310b57cec5SDimitry Andric 
132*e8d8bef9SDimitry Andric   if (GetTraversalKind() == TK_AsIs) {
1330b57cec5SDimitry Andric     for (const auto *Child : D->specializations())
1340b57cec5SDimitry Andric       dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
1350b57cec5SDimitry Andric                                      !D->isCanonicalDecl());
1360b57cec5SDimitry Andric   }
137*e8d8bef9SDimitry Andric }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
1400b57cec5SDimitry Andric   // FIXME: We don't add a declaration of a function template specialization
1410b57cec5SDimitry Andric   // to its context when it's explicitly instantiated, so dump explicit
1420b57cec5SDimitry Andric   // instantiations when we dump the template itself.
1430b57cec5SDimitry Andric   dumpTemplateDecl(D, true);
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
1470b57cec5SDimitry Andric   dumpTemplateDecl(D, false);
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
1510b57cec5SDimitry Andric   dumpTemplateDecl(D, false);
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1550b57cec5SDimitry Andric // Type method implementations
1560b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric void QualType::dump(const char *msg) const {
1590b57cec5SDimitry Andric   if (msg)
1600b57cec5SDimitry Andric     llvm::errs() << msg << ": ";
1610b57cec5SDimitry Andric   dump();
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
1645ffd83dbSDimitry Andric LLVM_DUMP_METHOD void QualType::dump() const {
1655ffd83dbSDimitry Andric   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
1660b57cec5SDimitry Andric   Dumper.Visit(*this);
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric 
1695ffd83dbSDimitry Andric LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS,
1705ffd83dbSDimitry Andric                                      const ASTContext &Context) const {
1715ffd83dbSDimitry Andric   ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
1725ffd83dbSDimitry Andric   Dumper.Visit(*this);
1735ffd83dbSDimitry Andric }
1740b57cec5SDimitry Andric 
1755ffd83dbSDimitry Andric LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
1765ffd83dbSDimitry Andric 
1775ffd83dbSDimitry Andric LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS,
1785ffd83dbSDimitry Andric                                  const ASTContext &Context) const {
1795ffd83dbSDimitry Andric   QualType(this, 0).dump(OS, Context);
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1830b57cec5SDimitry Andric // Decl method implementations
1840b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,
1890b57cec5SDimitry Andric                                  ASTDumpOutputFormat Format) const {
1900b57cec5SDimitry Andric   ASTContext &Ctx = getASTContext();
1910b57cec5SDimitry Andric   const SourceManager &SM = Ctx.getSourceManager();
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   if (ADOF_JSON == Format) {
1940b57cec5SDimitry Andric     JSONDumper P(OS, SM, Ctx, Ctx.getPrintingPolicy(),
1950b57cec5SDimitry Andric                  &Ctx.getCommentCommandTraits());
1960b57cec5SDimitry Andric     (void)Deserialize; // FIXME?
1970b57cec5SDimitry Andric     P.Visit(this);
1980b57cec5SDimitry Andric   } else {
1995ffd83dbSDimitry Andric     ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
2000b57cec5SDimitry Andric     P.setDeserialize(Deserialize);
2010b57cec5SDimitry Andric     P.Visit(this);
2020b57cec5SDimitry Andric   }
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric LLVM_DUMP_METHOD void Decl::dumpColor() const {
2060b57cec5SDimitry Andric   const ASTContext &Ctx = getASTContext();
2075ffd83dbSDimitry Andric   ASTDumper P(llvm::errs(), Ctx, /*ShowColors=*/true);
2080b57cec5SDimitry Andric   P.Visit(this);
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
2120b57cec5SDimitry Andric   dumpLookups(llvm::errs());
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
2160b57cec5SDimitry Andric                                                bool DumpDecls,
2170b57cec5SDimitry Andric                                                bool Deserialize) const {
2180b57cec5SDimitry Andric   const DeclContext *DC = this;
2190b57cec5SDimitry Andric   while (!DC->isTranslationUnit())
2200b57cec5SDimitry Andric     DC = DC->getParent();
2215ffd83dbSDimitry Andric   const ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
2225ffd83dbSDimitry Andric   ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
2230b57cec5SDimitry Andric   P.setDeserialize(Deserialize);
2240b57cec5SDimitry Andric   P.dumpLookups(this, DumpDecls);
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2280b57cec5SDimitry Andric // Stmt method implementations
2290b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric LLVM_DUMP_METHOD void Stmt::dump() const {
2325ffd83dbSDimitry Andric   ASTDumper P(llvm::errs(), /*ShowColors=*/false);
2335ffd83dbSDimitry Andric   P.Visit(this);
2345ffd83dbSDimitry Andric }
2355ffd83dbSDimitry Andric 
2365ffd83dbSDimitry Andric LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS,
2375ffd83dbSDimitry Andric                                  const ASTContext &Context) const {
2385ffd83dbSDimitry Andric   ASTDumper P(OS, Context, Context.getDiagnostics().getShowColors());
2390b57cec5SDimitry Andric   P.Visit(this);
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric LLVM_DUMP_METHOD void Stmt::dumpColor() const {
2435ffd83dbSDimitry Andric   ASTDumper P(llvm::errs(), /*ShowColors=*/true);
2440b57cec5SDimitry Andric   P.Visit(this);
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2480b57cec5SDimitry Andric // Comment method implementations
2490b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric LLVM_DUMP_METHOD void Comment::dump() const {
2525ffd83dbSDimitry Andric   const auto *FC = dyn_cast<FullComment>(this);
2530b57cec5SDimitry Andric   if (!FC)
2540b57cec5SDimitry Andric     return;
2555ffd83dbSDimitry Andric   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
2565ffd83dbSDimitry Andric   Dumper.Visit(FC, FC);
2575ffd83dbSDimitry Andric }
2585ffd83dbSDimitry Andric 
2595ffd83dbSDimitry Andric LLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS,
2605ffd83dbSDimitry Andric                                     const ASTContext &Context) const {
2615ffd83dbSDimitry Andric   const auto *FC = dyn_cast<FullComment>(this);
2625ffd83dbSDimitry Andric   if (!FC)
2635ffd83dbSDimitry Andric     return;
2645ffd83dbSDimitry Andric   ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
2655ffd83dbSDimitry Andric   Dumper.Visit(FC, FC);
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric LLVM_DUMP_METHOD void Comment::dumpColor() const {
2695ffd83dbSDimitry Andric   const auto *FC = dyn_cast<FullComment>(this);
2700b57cec5SDimitry Andric   if (!FC)
2710b57cec5SDimitry Andric     return;
2725ffd83dbSDimitry Andric   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/true);
2735ffd83dbSDimitry Andric   Dumper.Visit(FC, FC);
2745ffd83dbSDimitry Andric }
2755ffd83dbSDimitry Andric 
2765ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
2775ffd83dbSDimitry Andric // APValue method implementations
2785ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
2795ffd83dbSDimitry Andric 
2805ffd83dbSDimitry Andric LLVM_DUMP_METHOD void APValue::dump() const {
2815ffd83dbSDimitry Andric   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
2825ffd83dbSDimitry Andric   Dumper.Visit(*this, /*Ty=*/QualType());
2835ffd83dbSDimitry Andric }
2845ffd83dbSDimitry Andric 
2855ffd83dbSDimitry Andric LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
2865ffd83dbSDimitry Andric                                     const ASTContext &Context) const {
2875ffd83dbSDimitry Andric   ASTDumper Dumper(llvm::errs(), Context,
2885ffd83dbSDimitry Andric                    Context.getDiagnostics().getShowColors());
2895ffd83dbSDimitry Andric   Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
2900b57cec5SDimitry Andric }
291