llvm-project
395 строк · 13.6 Кб
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/ASTDumper.h"15#include "clang/AST/ASTConcept.h"16#include "clang/AST/ASTContext.h"17#include "clang/AST/DeclLookups.h"18#include "clang/AST/JSONNodeDumper.h"19#include "clang/Basic/Builtins.h"20#include "clang/Basic/SourceManager.h"21#include "llvm/Support/raw_ostream.h"22
23using namespace clang;24using namespace clang::comments;25
26void ASTDumper::dumpInvalidDeclContext(const DeclContext *DC) {27NodeDumper.AddChild([=] {28if (!DC) {29ColorScope Color(OS, ShowColors, NullColor);30OS << "<<<NULL>>>";31return;32}33// An invalid DeclContext is one for which a dyn_cast() from a DeclContext34// pointer to a Decl pointer would fail an assertion or otherwise fall prey35// to undefined behavior as a result of an invalid associated DeclKind.36// Such invalidity is not supposed to happen of course, but, when it does,37// the information provided below is intended to provide some hints about38// what might have gone awry.39{40ColorScope Color(OS, ShowColors, DeclKindNameColor);41OS << "DeclContext";42}43NodeDumper.dumpPointer(DC);44OS << " <";45{46ColorScope Color(OS, ShowColors, DeclNameColor);47OS << "unrecognized Decl kind " << (unsigned)DC->getDeclKind();48}49OS << ">";50});51}
52
53void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {54NodeDumper.AddChild([=] {55OS << "StoredDeclsMap ";56NodeDumper.dumpBareDeclRef(cast<Decl>(DC));57
58const DeclContext *Primary = DC->getPrimaryContext();59if (Primary != DC) {60OS << " primary";61NodeDumper.dumpPointer(cast<Decl>(Primary));62}63
64bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();65
66auto Range = getDeserialize()67? Primary->lookups()68: Primary->noload_lookups(/*PreserveInternalState=*/true);69for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {70DeclarationName Name = I.getLookupName();71DeclContextLookupResult R = *I;72
73NodeDumper.AddChild([=] {74OS << "DeclarationName ";75{76ColorScope Color(OS, ShowColors, DeclNameColor);77OS << '\'' << Name << '\'';78}79
80for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();81RI != RE; ++RI) {82NodeDumper.AddChild([=] {83NodeDumper.dumpBareDeclRef(*RI);84
85if (!(*RI)->isUnconditionallyVisible())86OS << " hidden";87
88// If requested, dump the redecl chain for this lookup.89if (DumpDecls) {90// Dump earliest decl first.91std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {92if (Decl *Prev = D->getPreviousDecl())93DumpWithPrev(Prev);94Visit(D);95};96DumpWithPrev(*RI);97}98});99}100});101}102
103if (HasUndeserializedLookups) {104NodeDumper.AddChild([=] {105ColorScope Color(OS, ShowColors, UndeserializedColor);106OS << "<undeserialized lookups>";107});108}109});110}
111
112template <typename SpecializationDecl>113void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,114bool DumpExplicitInst,115bool DumpRefOnly) {116bool DumpedAny = false;117for (const auto *RedeclWithBadType : D->redecls()) {118// FIXME: The redecls() range sometimes has elements of a less-specific119// type. (In particular, ClassTemplateSpecializationDecl::redecls() gives120// us TagDecls, and should give CXXRecordDecls).121auto *Redecl = cast<SpecializationDecl>(RedeclWithBadType);122switch (Redecl->getTemplateSpecializationKind()) {123case TSK_ExplicitInstantiationDeclaration:124case TSK_ExplicitInstantiationDefinition:125if (!DumpExplicitInst)126break;127[[fallthrough]];128case TSK_Undeclared:129case TSK_ImplicitInstantiation:130if (DumpRefOnly)131NodeDumper.dumpDeclRef(Redecl);132else133Visit(Redecl);134DumpedAny = true;135break;136case TSK_ExplicitSpecialization:137break;138}139}140
141// Ensure we dump at least one decl for each specialization.142if (!DumpedAny)143NodeDumper.dumpDeclRef(D);144}
145
146template <typename TemplateDecl>147void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {148dumpTemplateParameters(D->getTemplateParameters());149
150Visit(D->getTemplatedDecl());151
152if (GetTraversalKind() == TK_AsIs) {153for (const auto *Child : D->specializations())154dumpTemplateDeclSpecialization(Child, DumpExplicitInst,155!D->isCanonicalDecl());156}157}
158
159void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {160// FIXME: We don't add a declaration of a function template specialization161// to its context when it's explicitly instantiated, so dump explicit162// instantiations when we dump the template itself.163dumpTemplateDecl(D, true);164}
165
166void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {167dumpTemplateDecl(D, false);168}
169
170void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {171dumpTemplateDecl(D, false);172}
173
174//===----------------------------------------------------------------------===//
175// Type method implementations
176//===----------------------------------------------------------------------===//
177
178void QualType::dump(const char *msg) const {179if (msg)180llvm::errs() << msg << ": ";181dump();182}
183
184LLVM_DUMP_METHOD void QualType::dump() const {185ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);186Dumper.Visit(*this);187}
188
189LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS,190const ASTContext &Context) const {191ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());192Dumper.Visit(*this);193}
194
195LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }196
197LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS,198const ASTContext &Context) const {199QualType(this, 0).dump(OS, Context);200}
201
202//===----------------------------------------------------------------------===//
203// TypeLoc method implementations
204//===----------------------------------------------------------------------===//
205
206LLVM_DUMP_METHOD void TypeLoc::dump() const {207ASTDumper(llvm::errs(), /*ShowColors=*/false).Visit(*this);208}
209
210LLVM_DUMP_METHOD void TypeLoc::dump(llvm::raw_ostream &OS,211const ASTContext &Context) const {212ASTDumper(OS, Context, Context.getDiagnostics().getShowColors()).Visit(*this);213}
214
215//===----------------------------------------------------------------------===//
216// Decl method implementations
217//===----------------------------------------------------------------------===//
218
219LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }220
221LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,222ASTDumpOutputFormat Format) const {223ASTContext &Ctx = getASTContext();224const SourceManager &SM = Ctx.getSourceManager();225
226if (ADOF_JSON == Format) {227JSONDumper P(OS, SM, Ctx, Ctx.getPrintingPolicy(),228&Ctx.getCommentCommandTraits());229(void)Deserialize; // FIXME?230P.Visit(this);231} else {232ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());233P.setDeserialize(Deserialize);234P.Visit(this);235}236}
237
238LLVM_DUMP_METHOD void Decl::dumpColor() const {239const ASTContext &Ctx = getASTContext();240ASTDumper P(llvm::errs(), Ctx, /*ShowColors=*/true);241P.Visit(this);242}
243
244LLVM_DUMP_METHOD void DeclContext::dumpAsDecl() const {245dumpAsDecl(nullptr);246}
247
248LLVM_DUMP_METHOD void DeclContext::dumpAsDecl(const ASTContext *Ctx) const {249// By design, DeclContext is required to be a base class of some class that250// derives from Decl. Thus, it should always be possible to dyn_cast() from251// a DeclContext pointer to a Decl pointer and Decl::castFromDeclContext()252// asserts that to be the case. Since this function is intended for use in a253// debugger, it performs an additional check in order to prevent a failed254// cast and assertion. If that check fails, then the (invalid) DeclContext255// is dumped with an indication of its invalidity.256if (hasValidDeclKind()) {257const auto *D = cast<Decl>(this);258D->dump();259} else {260// If an ASTContext is not available, a less capable ASTDumper is261// constructed for which color diagnostics are, regrettably, disabled.262ASTDumper P = Ctx ? ASTDumper(llvm::errs(), *Ctx,263Ctx->getDiagnostics().getShowColors())264: ASTDumper(llvm::errs(), /*ShowColors*/ false);265P.dumpInvalidDeclContext(this);266}267}
268
269LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {270dumpLookups(llvm::errs());271}
272
273LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,274bool DumpDecls,275bool Deserialize) const {276const DeclContext *DC = this;277while (!DC->isTranslationUnit())278DC = DC->getParent();279const ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();280ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());281P.setDeserialize(Deserialize);282P.dumpLookups(this, DumpDecls);283}
284
285//===----------------------------------------------------------------------===//
286// Stmt method implementations
287//===----------------------------------------------------------------------===//
288
289LLVM_DUMP_METHOD void Stmt::dump() const {290ASTDumper P(llvm::errs(), /*ShowColors=*/false);291P.Visit(this);292}
293
294LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS,295const ASTContext &Context) const {296ASTDumper P(OS, Context, Context.getDiagnostics().getShowColors());297P.Visit(this);298}
299
300LLVM_DUMP_METHOD void Stmt::dumpColor() const {301ASTDumper P(llvm::errs(), /*ShowColors=*/true);302P.Visit(this);303}
304
305//===----------------------------------------------------------------------===//
306// Comment method implementations
307//===----------------------------------------------------------------------===//
308
309LLVM_DUMP_METHOD void Comment::dump() const {310const auto *FC = dyn_cast<FullComment>(this);311if (!FC)312return;313ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);314Dumper.Visit(FC, FC);315}
316
317LLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS,318const ASTContext &Context) const {319const auto *FC = dyn_cast<FullComment>(this);320if (!FC)321return;322ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());323Dumper.Visit(FC, FC);324}
325
326LLVM_DUMP_METHOD void Comment::dumpColor() const {327const auto *FC = dyn_cast<FullComment>(this);328if (!FC)329return;330ASTDumper Dumper(llvm::errs(), /*ShowColors=*/true);331Dumper.Visit(FC, FC);332}
333
334//===----------------------------------------------------------------------===//
335// APValue method implementations
336//===----------------------------------------------------------------------===//
337
338LLVM_DUMP_METHOD void APValue::dump() const {339ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);340Dumper.Visit(*this, /*Ty=*/QualType());341}
342
343LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,344const ASTContext &Context) const {345ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());346Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));347}
348
349//===----------------------------------------------------------------------===//
350// ConceptReference method implementations
351//===----------------------------------------------------------------------===//
352
353LLVM_DUMP_METHOD void ConceptReference::dump() const {354dump(llvm::errs());355}
356
357LLVM_DUMP_METHOD void ConceptReference::dump(raw_ostream &OS) const {358auto &Ctx = getNamedConcept()->getASTContext();359ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());360P.Visit(this);361}
362
363//===----------------------------------------------------------------------===//
364// TemplateName method implementations
365//===----------------------------------------------------------------------===//
366
367// FIXME: These are actually using the TemplateArgument dumper, through
368// an implicit conversion. The dump will claim this is a template argument,
369// which is misleading.
370
371LLVM_DUMP_METHOD void TemplateName::dump() const {372ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);373Dumper.Visit(*this);374}
375
376LLVM_DUMP_METHOD void TemplateName::dump(llvm::raw_ostream &OS,377const ASTContext &Context) const {378ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());379Dumper.Visit(*this);380}
381
382//===----------------------------------------------------------------------===//
383// TemplateArgument method implementations
384//===----------------------------------------------------------------------===//
385
386LLVM_DUMP_METHOD void TemplateArgument::dump() const {387ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);388Dumper.Visit(*this);389}
390
391LLVM_DUMP_METHOD void TemplateArgument::dump(llvm::raw_ostream &OS,392const ASTContext &Context) const {393ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());394Dumper.Visit(*this);395}
396