Home | History | Annotate | Line # | Download | only in AST
ASTDumper.cpp revision 1.1.1.1.4.1
      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/ASTContext.h"
     16 #include "clang/AST/DeclLookups.h"
     17 #include "clang/AST/JSONNodeDumper.h"
     18 #include "clang/Basic/Builtins.h"
     19 #include "clang/Basic/Module.h"
     20 #include "clang/Basic/SourceManager.h"
     21 #include "llvm/Support/raw_ostream.h"
     22 using namespace clang;
     23 using namespace clang::comments;
     24 
     25 void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
     26   NodeDumper.AddChild([=] {
     27     OS << "StoredDeclsMap ";
     28     NodeDumper.dumpBareDeclRef(cast<Decl>(DC));
     29 
     30     const DeclContext *Primary = DC->getPrimaryContext();
     31     if (Primary != DC) {
     32       OS << " primary";
     33       NodeDumper.dumpPointer(cast<Decl>(Primary));
     34     }
     35 
     36     bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
     37 
     38     auto Range = getDeserialize()
     39                      ? Primary->lookups()
     40                      : Primary->noload_lookups(/*PreserveInternalState=*/true);
     41     for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {
     42       DeclarationName Name = I.getLookupName();
     43       DeclContextLookupResult R = *I;
     44 
     45       NodeDumper.AddChild([=] {
     46         OS << "DeclarationName ";
     47         {
     48           ColorScope Color(OS, ShowColors, DeclNameColor);
     49           OS << '\'' << Name << '\'';
     50         }
     51 
     52         for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
     53              RI != RE; ++RI) {
     54           NodeDumper.AddChild([=] {
     55             NodeDumper.dumpBareDeclRef(*RI);
     56 
     57             if (!(*RI)->isUnconditionallyVisible())
     58               OS << " hidden";
     59 
     60             // If requested, dump the redecl chain for this lookup.
     61             if (DumpDecls) {
     62               // Dump earliest decl first.
     63               std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {
     64                 if (Decl *Prev = D->getPreviousDecl())
     65                   DumpWithPrev(Prev);
     66                 Visit(D);
     67               };
     68               DumpWithPrev(*RI);
     69             }
     70           });
     71         }
     72       });
     73     }
     74 
     75     if (HasUndeserializedLookups) {
     76       NodeDumper.AddChild([=] {
     77         ColorScope Color(OS, ShowColors, UndeserializedColor);
     78         OS << "<undeserialized lookups>";
     79       });
     80     }
     81   });
     82 }
     83 
     84 template <typename SpecializationDecl>
     85 void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
     86                                                bool DumpExplicitInst,
     87                                                bool DumpRefOnly) {
     88   bool DumpedAny = false;
     89   for (const auto *RedeclWithBadType : D->redecls()) {
     90     // FIXME: The redecls() range sometimes has elements of a less-specific
     91     // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
     92     // us TagDecls, and should give CXXRecordDecls).
     93     auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
     94     if (!Redecl) {
     95       // Found the injected-class-name for a class template. This will be dumped
     96       // as part of its surrounding class so we don't need to dump it here.
     97       assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
     98              "expected an injected-class-name");
     99       continue;
    100     }
    101 
    102     switch (Redecl->getTemplateSpecializationKind()) {
    103     case TSK_ExplicitInstantiationDeclaration:
    104     case TSK_ExplicitInstantiationDefinition:
    105       if (!DumpExplicitInst)
    106         break;
    107       LLVM_FALLTHROUGH;
    108     case TSK_Undeclared:
    109     case TSK_ImplicitInstantiation:
    110       if (DumpRefOnly)
    111         NodeDumper.dumpDeclRef(Redecl);
    112       else
    113         Visit(Redecl);
    114       DumpedAny = true;
    115       break;
    116     case TSK_ExplicitSpecialization:
    117       break;
    118     }
    119   }
    120 
    121   // Ensure we dump at least one decl for each specialization.
    122   if (!DumpedAny)
    123     NodeDumper.dumpDeclRef(D);
    124 }
    125 
    126 template <typename TemplateDecl>
    127 void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
    128   dumpTemplateParameters(D->getTemplateParameters());
    129 
    130   Visit(D->getTemplatedDecl());
    131 
    132   if (GetTraversalKind() == TK_AsIs) {
    133     for (const auto *Child : D->specializations())
    134       dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
    135                                      !D->isCanonicalDecl());
    136   }
    137 }
    138 
    139 void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
    140   // FIXME: We don't add a declaration of a function template specialization
    141   // to its context when it's explicitly instantiated, so dump explicit
    142   // instantiations when we dump the template itself.
    143   dumpTemplateDecl(D, true);
    144 }
    145 
    146 void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
    147   dumpTemplateDecl(D, false);
    148 }
    149 
    150 void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
    151   dumpTemplateDecl(D, false);
    152 }
    153 
    154 //===----------------------------------------------------------------------===//
    155 // Type method implementations
    156 //===----------------------------------------------------------------------===//
    157 
    158 void QualType::dump(const char *msg) const {
    159   if (msg)
    160     llvm::errs() << msg << ": ";
    161   dump();
    162 }
    163 
    164 LLVM_DUMP_METHOD void QualType::dump() const {
    165   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
    166   Dumper.Visit(*this);
    167 }
    168 
    169 LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS,
    170                                      const ASTContext &Context) const {
    171   ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
    172   Dumper.Visit(*this);
    173 }
    174 
    175 LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
    176 
    177 LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS,
    178                                  const ASTContext &Context) const {
    179   QualType(this, 0).dump(OS, Context);
    180 }
    181 
    182 //===----------------------------------------------------------------------===//
    183 // Decl method implementations
    184 //===----------------------------------------------------------------------===//
    185 
    186 LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }
    187 
    188 LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,
    189                                  ASTDumpOutputFormat Format) const {
    190   ASTContext &Ctx = getASTContext();
    191   const SourceManager &SM = Ctx.getSourceManager();
    192 
    193   if (ADOF_JSON == Format) {
    194     JSONDumper P(OS, SM, Ctx, Ctx.getPrintingPolicy(),
    195                  &Ctx.getCommentCommandTraits());
    196     (void)Deserialize; // FIXME?
    197     P.Visit(this);
    198   } else {
    199     ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
    200     P.setDeserialize(Deserialize);
    201     P.Visit(this);
    202   }
    203 }
    204 
    205 LLVM_DUMP_METHOD void Decl::dumpColor() const {
    206   const ASTContext &Ctx = getASTContext();
    207   ASTDumper P(llvm::errs(), Ctx, /*ShowColors=*/true);
    208   P.Visit(this);
    209 }
    210 
    211 LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
    212   dumpLookups(llvm::errs());
    213 }
    214 
    215 LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
    216                                                bool DumpDecls,
    217                                                bool Deserialize) const {
    218   const DeclContext *DC = this;
    219   while (!DC->isTranslationUnit())
    220     DC = DC->getParent();
    221   const ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
    222   ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
    223   P.setDeserialize(Deserialize);
    224   P.dumpLookups(this, DumpDecls);
    225 }
    226 
    227 //===----------------------------------------------------------------------===//
    228 // Stmt method implementations
    229 //===----------------------------------------------------------------------===//
    230 
    231 LLVM_DUMP_METHOD void Stmt::dump() const {
    232   ASTDumper P(llvm::errs(), /*ShowColors=*/false);
    233   P.Visit(this);
    234 }
    235 
    236 LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS,
    237                                  const ASTContext &Context) const {
    238   ASTDumper P(OS, Context, Context.getDiagnostics().getShowColors());
    239   P.Visit(this);
    240 }
    241 
    242 LLVM_DUMP_METHOD void Stmt::dumpColor() const {
    243   ASTDumper P(llvm::errs(), /*ShowColors=*/true);
    244   P.Visit(this);
    245 }
    246 
    247 //===----------------------------------------------------------------------===//
    248 // Comment method implementations
    249 //===----------------------------------------------------------------------===//
    250 
    251 LLVM_DUMP_METHOD void Comment::dump() const {
    252   const auto *FC = dyn_cast<FullComment>(this);
    253   if (!FC)
    254     return;
    255   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
    256   Dumper.Visit(FC, FC);
    257 }
    258 
    259 LLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS,
    260                                     const ASTContext &Context) const {
    261   const auto *FC = dyn_cast<FullComment>(this);
    262   if (!FC)
    263     return;
    264   ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
    265   Dumper.Visit(FC, FC);
    266 }
    267 
    268 LLVM_DUMP_METHOD void Comment::dumpColor() const {
    269   const auto *FC = dyn_cast<FullComment>(this);
    270   if (!FC)
    271     return;
    272   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/true);
    273   Dumper.Visit(FC, FC);
    274 }
    275 
    276 //===----------------------------------------------------------------------===//
    277 // APValue method implementations
    278 //===----------------------------------------------------------------------===//
    279 
    280 LLVM_DUMP_METHOD void APValue::dump() const {
    281   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
    282   Dumper.Visit(*this, /*Ty=*/QualType());
    283 }
    284 
    285 LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
    286                                     const ASTContext &Context) const {
    287   ASTDumper Dumper(llvm::errs(), Context,
    288                    Context.getDiagnostics().getShowColors());
    289   Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
    290 }
    291