brintos

brintos / llvm-project-archived public Read only

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