Path: blob/main/contrib/llvm-project/clang/lib/AST/ASTDumper.cpp
35259 views
//===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the AST dump methods, which dump out the9// AST in a form that exposes type details and other fields.10//11//===----------------------------------------------------------------------===//1213#include "clang/AST/ASTDumper.h"14#include "clang/AST/ASTConcept.h"15#include "clang/AST/ASTContext.h"16#include "clang/AST/DeclLookups.h"17#include "clang/AST/JSONNodeDumper.h"18#include "clang/Basic/Builtins.h"19#include "clang/Basic/SourceManager.h"20#include "llvm/Support/raw_ostream.h"2122using namespace clang;23using namespace clang::comments;2425void ASTDumper::dumpInvalidDeclContext(const DeclContext *DC) {26NodeDumper.AddChild([=] {27if (!DC) {28ColorScope Color(OS, ShowColors, NullColor);29OS << "<<<NULL>>>";30return;31}32// An invalid DeclContext is one for which a dyn_cast() from a DeclContext33// pointer to a Decl pointer would fail an assertion or otherwise fall prey34// to undefined behavior as a result of an invalid associated DeclKind.35// Such invalidity is not supposed to happen of course, but, when it does,36// the information provided below is intended to provide some hints about37// what might have gone awry.38{39ColorScope Color(OS, ShowColors, DeclKindNameColor);40OS << "DeclContext";41}42NodeDumper.dumpPointer(DC);43OS << " <";44{45ColorScope Color(OS, ShowColors, DeclNameColor);46OS << "unrecognized Decl kind " << (unsigned)DC->getDeclKind();47}48OS << ">";49});50}5152void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {53NodeDumper.AddChild([=] {54OS << "StoredDeclsMap ";55NodeDumper.dumpBareDeclRef(cast<Decl>(DC));5657const DeclContext *Primary = DC->getPrimaryContext();58if (Primary != DC) {59OS << " primary";60NodeDumper.dumpPointer(cast<Decl>(Primary));61}6263bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();6465auto Range = getDeserialize()66? Primary->lookups()67: Primary->noload_lookups(/*PreserveInternalState=*/true);68for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {69DeclarationName Name = I.getLookupName();70DeclContextLookupResult R = *I;7172NodeDumper.AddChild([=] {73OS << "DeclarationName ";74{75ColorScope Color(OS, ShowColors, DeclNameColor);76OS << '\'' << Name << '\'';77}7879for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();80RI != RE; ++RI) {81NodeDumper.AddChild([=] {82NodeDumper.dumpBareDeclRef(*RI);8384if (!(*RI)->isUnconditionallyVisible())85OS << " hidden";8687// If requested, dump the redecl chain for this lookup.88if (DumpDecls) {89// Dump earliest decl first.90std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {91if (Decl *Prev = D->getPreviousDecl())92DumpWithPrev(Prev);93Visit(D);94};95DumpWithPrev(*RI);96}97});98}99});100}101102if (HasUndeserializedLookups) {103NodeDumper.AddChild([=] {104ColorScope Color(OS, ShowColors, UndeserializedColor);105OS << "<undeserialized lookups>";106});107}108});109}110111template <typename SpecializationDecl>112void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,113bool DumpExplicitInst,114bool DumpRefOnly) {115bool DumpedAny = false;116for (const auto *RedeclWithBadType : D->redecls()) {117// FIXME: The redecls() range sometimes has elements of a less-specific118// type. (In particular, ClassTemplateSpecializationDecl::redecls() gives119// us TagDecls, and should give CXXRecordDecls).120auto *Redecl = cast<SpecializationDecl>(RedeclWithBadType);121switch (Redecl->getTemplateSpecializationKind()) {122case TSK_ExplicitInstantiationDeclaration:123case TSK_ExplicitInstantiationDefinition:124if (!DumpExplicitInst)125break;126[[fallthrough]];127case TSK_Undeclared:128case TSK_ImplicitInstantiation:129if (DumpRefOnly)130NodeDumper.dumpDeclRef(Redecl);131else132Visit(Redecl);133DumpedAny = true;134break;135case TSK_ExplicitSpecialization:136break;137}138}139140// Ensure we dump at least one decl for each specialization.141if (!DumpedAny)142NodeDumper.dumpDeclRef(D);143}144145template <typename TemplateDecl>146void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {147dumpTemplateParameters(D->getTemplateParameters());148149Visit(D->getTemplatedDecl());150151if (GetTraversalKind() == TK_AsIs) {152for (const auto *Child : D->specializations())153dumpTemplateDeclSpecialization(Child, DumpExplicitInst,154!D->isCanonicalDecl());155}156}157158void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {159// FIXME: We don't add a declaration of a function template specialization160// to its context when it's explicitly instantiated, so dump explicit161// instantiations when we dump the template itself.162dumpTemplateDecl(D, true);163}164165void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {166dumpTemplateDecl(D, false);167}168169void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {170dumpTemplateDecl(D, false);171}172173//===----------------------------------------------------------------------===//174// Type method implementations175//===----------------------------------------------------------------------===//176177void QualType::dump(const char *msg) const {178if (msg)179llvm::errs() << msg << ": ";180dump();181}182183LLVM_DUMP_METHOD void QualType::dump() const {184ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);185Dumper.Visit(*this);186}187188LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS,189const ASTContext &Context) const {190ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());191Dumper.Visit(*this);192}193194LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }195196LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS,197const ASTContext &Context) const {198QualType(this, 0).dump(OS, Context);199}200201//===----------------------------------------------------------------------===//202// TypeLoc method implementations203//===----------------------------------------------------------------------===//204205LLVM_DUMP_METHOD void TypeLoc::dump() const {206ASTDumper(llvm::errs(), /*ShowColors=*/false).Visit(*this);207}208209LLVM_DUMP_METHOD void TypeLoc::dump(llvm::raw_ostream &OS,210const ASTContext &Context) const {211ASTDumper(OS, Context, Context.getDiagnostics().getShowColors()).Visit(*this);212}213214//===----------------------------------------------------------------------===//215// Decl method implementations216//===----------------------------------------------------------------------===//217218LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }219220LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,221ASTDumpOutputFormat Format) const {222ASTContext &Ctx = getASTContext();223const SourceManager &SM = Ctx.getSourceManager();224225if (ADOF_JSON == Format) {226JSONDumper P(OS, SM, Ctx, Ctx.getPrintingPolicy(),227&Ctx.getCommentCommandTraits());228(void)Deserialize; // FIXME?229P.Visit(this);230} else {231ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());232P.setDeserialize(Deserialize);233P.Visit(this);234}235}236237LLVM_DUMP_METHOD void Decl::dumpColor() const {238const ASTContext &Ctx = getASTContext();239ASTDumper P(llvm::errs(), Ctx, /*ShowColors=*/true);240P.Visit(this);241}242243LLVM_DUMP_METHOD void DeclContext::dumpAsDecl() const {244dumpAsDecl(nullptr);245}246247LLVM_DUMP_METHOD void DeclContext::dumpAsDecl(const ASTContext *Ctx) const {248// By design, DeclContext is required to be a base class of some class that249// derives from Decl. Thus, it should always be possible to dyn_cast() from250// a DeclContext pointer to a Decl pointer and Decl::castFromDeclContext()251// asserts that to be the case. Since this function is intended for use in a252// debugger, it performs an additional check in order to prevent a failed253// cast and assertion. If that check fails, then the (invalid) DeclContext254// is dumped with an indication of its invalidity.255if (hasValidDeclKind()) {256const auto *D = cast<Decl>(this);257D->dump();258} else {259// If an ASTContext is not available, a less capable ASTDumper is260// constructed for which color diagnostics are, regrettably, disabled.261ASTDumper P = Ctx ? ASTDumper(llvm::errs(), *Ctx,262Ctx->getDiagnostics().getShowColors())263: ASTDumper(llvm::errs(), /*ShowColors*/ false);264P.dumpInvalidDeclContext(this);265}266}267268LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {269dumpLookups(llvm::errs());270}271272LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,273bool DumpDecls,274bool Deserialize) const {275const DeclContext *DC = this;276while (!DC->isTranslationUnit())277DC = DC->getParent();278const ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();279ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());280P.setDeserialize(Deserialize);281P.dumpLookups(this, DumpDecls);282}283284//===----------------------------------------------------------------------===//285// Stmt method implementations286//===----------------------------------------------------------------------===//287288LLVM_DUMP_METHOD void Stmt::dump() const {289ASTDumper P(llvm::errs(), /*ShowColors=*/false);290P.Visit(this);291}292293LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS,294const ASTContext &Context) const {295ASTDumper P(OS, Context, Context.getDiagnostics().getShowColors());296P.Visit(this);297}298299LLVM_DUMP_METHOD void Stmt::dumpColor() const {300ASTDumper P(llvm::errs(), /*ShowColors=*/true);301P.Visit(this);302}303304//===----------------------------------------------------------------------===//305// Comment method implementations306//===----------------------------------------------------------------------===//307308LLVM_DUMP_METHOD void Comment::dump() const {309const auto *FC = dyn_cast<FullComment>(this);310if (!FC)311return;312ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);313Dumper.Visit(FC, FC);314}315316LLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS,317const ASTContext &Context) const {318const auto *FC = dyn_cast<FullComment>(this);319if (!FC)320return;321ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());322Dumper.Visit(FC, FC);323}324325LLVM_DUMP_METHOD void Comment::dumpColor() const {326const auto *FC = dyn_cast<FullComment>(this);327if (!FC)328return;329ASTDumper Dumper(llvm::errs(), /*ShowColors=*/true);330Dumper.Visit(FC, FC);331}332333//===----------------------------------------------------------------------===//334// APValue method implementations335//===----------------------------------------------------------------------===//336337LLVM_DUMP_METHOD void APValue::dump() const {338ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);339Dumper.Visit(*this, /*Ty=*/QualType());340}341342LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,343const ASTContext &Context) const {344ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());345Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));346}347348//===----------------------------------------------------------------------===//349// ConceptReference method implementations350//===----------------------------------------------------------------------===//351352LLVM_DUMP_METHOD void ConceptReference::dump() const {353dump(llvm::errs());354}355356LLVM_DUMP_METHOD void ConceptReference::dump(raw_ostream &OS) const {357auto &Ctx = getNamedConcept()->getASTContext();358ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());359P.Visit(this);360}361362//===----------------------------------------------------------------------===//363// TemplateName method implementations364//===----------------------------------------------------------------------===//365366// FIXME: These are actually using the TemplateArgument dumper, through367// an implicit conversion. The dump will claim this is a template argument,368// which is misleading.369370LLVM_DUMP_METHOD void TemplateName::dump() const {371ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);372Dumper.Visit(*this);373}374375LLVM_DUMP_METHOD void TemplateName::dump(llvm::raw_ostream &OS,376const ASTContext &Context) const {377ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());378Dumper.Visit(*this);379}380381//===----------------------------------------------------------------------===//382// TemplateArgument method implementations383//===----------------------------------------------------------------------===//384385LLVM_DUMP_METHOD void TemplateArgument::dump() const {386ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);387Dumper.Visit(*this);388}389390LLVM_DUMP_METHOD void TemplateArgument::dump(llvm::raw_ostream &OS,391const ASTContext &Context) const {392ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());393Dumper.Visit(*this);394}395396397