Home | History | Annotate | Line # | Download | only in Frontend
      1 //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
      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 // AST Consumer Implementations.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "clang/Frontend/ASTConsumers.h"
     14 #include "clang/AST/AST.h"
     15 #include "clang/AST/ASTConsumer.h"
     16 #include "clang/AST/ASTContext.h"
     17 #include "clang/AST/PrettyPrinter.h"
     18 #include "clang/AST/RecordLayout.h"
     19 #include "clang/AST/RecursiveASTVisitor.h"
     20 #include "clang/Basic/Diagnostic.h"
     21 #include "clang/Basic/SourceManager.h"
     22 #include "llvm/Support/Path.h"
     23 #include "llvm/Support/Timer.h"
     24 #include "llvm/Support/raw_ostream.h"
     25 using namespace clang;
     26 
     27 //===----------------------------------------------------------------------===//
     28 /// ASTPrinter - Pretty-printer and dumper of ASTs
     29 
     30 namespace {
     31   class ASTPrinter : public ASTConsumer,
     32                      public RecursiveASTVisitor<ASTPrinter> {
     33     typedef RecursiveASTVisitor<ASTPrinter> base;
     34 
     35   public:
     36     enum Kind { DumpFull, Dump, Print, None };
     37     ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K,
     38                ASTDumpOutputFormat Format, StringRef FilterString,
     39                bool DumpLookups = false, bool DumpDeclTypes = false)
     40         : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
     41           OutputKind(K), OutputFormat(Format), FilterString(FilterString),
     42           DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {}
     43 
     44     void HandleTranslationUnit(ASTContext &Context) override {
     45       TranslationUnitDecl *D = Context.getTranslationUnitDecl();
     46 
     47       if (FilterString.empty())
     48         return print(D);
     49 
     50       TraverseDecl(D);
     51     }
     52 
     53     bool shouldWalkTypesOfTypeLocs() const { return false; }
     54 
     55     bool TraverseDecl(Decl *D) {
     56       if (D && filterMatches(D)) {
     57         bool ShowColors = Out.has_colors();
     58         if (ShowColors)
     59           Out.changeColor(raw_ostream::BLUE);
     60         Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D)
     61             << ":\n";
     62         if (ShowColors)
     63           Out.resetColor();
     64         print(D);
     65         Out << "\n";
     66         // Don't traverse child nodes to avoid output duplication.
     67         return true;
     68       }
     69       return base::TraverseDecl(D);
     70     }
     71 
     72   private:
     73     std::string getName(Decl *D) {
     74       if (isa<NamedDecl>(D))
     75         return cast<NamedDecl>(D)->getQualifiedNameAsString();
     76       return "";
     77     }
     78     bool filterMatches(Decl *D) {
     79       return getName(D).find(FilterString) != std::string::npos;
     80     }
     81     void print(Decl *D) {
     82       if (DumpLookups) {
     83         if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
     84           if (DC == DC->getPrimaryContext())
     85             DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull);
     86           else
     87             Out << "Lookup map is in primary DeclContext "
     88                 << DC->getPrimaryContext() << "\n";
     89         } else
     90           Out << "Not a DeclContext\n";
     91       } else if (OutputKind == Print) {
     92         PrintingPolicy Policy(D->getASTContext().getLangOpts());
     93         D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
     94       } else if (OutputKind != None) {
     95         D->dump(Out, OutputKind == DumpFull, OutputFormat);
     96       }
     97 
     98       if (DumpDeclTypes) {
     99         Decl *InnerD = D;
    100         if (auto *TD = dyn_cast<TemplateDecl>(D))
    101           InnerD = TD->getTemplatedDecl();
    102 
    103         // FIXME: Support OutputFormat in type dumping.
    104         // FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups.
    105         if (auto *VD = dyn_cast<ValueDecl>(InnerD))
    106           VD->getType().dump(Out, VD->getASTContext());
    107         if (auto *TD = dyn_cast<TypeDecl>(InnerD))
    108           TD->getTypeForDecl()->dump(Out, TD->getASTContext());
    109       }
    110     }
    111 
    112     raw_ostream &Out;
    113     std::unique_ptr<raw_ostream> OwnedOut;
    114 
    115     /// How to output individual declarations.
    116     Kind OutputKind;
    117 
    118     /// What format should the output take?
    119     ASTDumpOutputFormat OutputFormat;
    120 
    121     /// Which declarations or DeclContexts to display.
    122     std::string FilterString;
    123 
    124     /// Whether the primary output is lookup results or declarations. Individual
    125     /// results will be output with a format determined by OutputKind. This is
    126     /// incompatible with OutputKind == Print.
    127     bool DumpLookups;
    128 
    129     /// Whether to dump the type for each declaration dumped.
    130     bool DumpDeclTypes;
    131   };
    132 
    133   class ASTDeclNodeLister : public ASTConsumer,
    134                      public RecursiveASTVisitor<ASTDeclNodeLister> {
    135   public:
    136     ASTDeclNodeLister(raw_ostream *Out = nullptr)
    137         : Out(Out ? *Out : llvm::outs()) {}
    138 
    139     void HandleTranslationUnit(ASTContext &Context) override {
    140       TraverseDecl(Context.getTranslationUnitDecl());
    141     }
    142 
    143     bool shouldWalkTypesOfTypeLocs() const { return false; }
    144 
    145     bool VisitNamedDecl(NamedDecl *D) {
    146       D->printQualifiedName(Out);
    147       Out << '\n';
    148       return true;
    149     }
    150 
    151   private:
    152     raw_ostream &Out;
    153   };
    154 } // end anonymous namespace
    155 
    156 std::unique_ptr<ASTConsumer>
    157 clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
    158                         StringRef FilterString) {
    159   return std::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
    160                                        ADOF_Default, FilterString);
    161 }
    162 
    163 std::unique_ptr<ASTConsumer>
    164 clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, StringRef FilterString,
    165                        bool DumpDecls, bool Deserialize, bool DumpLookups,
    166                        bool DumpDeclTypes, ASTDumpOutputFormat Format) {
    167   assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
    168   return std::make_unique<ASTPrinter>(
    169       std::move(Out),
    170       Deserialize ? ASTPrinter::DumpFull
    171                   : DumpDecls ? ASTPrinter::Dump : ASTPrinter::None,
    172       Format, FilterString, DumpLookups, DumpDeclTypes);
    173 }
    174 
    175 std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
    176   return std::make_unique<ASTDeclNodeLister>(nullptr);
    177 }
    178 
    179 //===----------------------------------------------------------------------===//
    180 /// ASTViewer - AST Visualization
    181 
    182 namespace {
    183   class ASTViewer : public ASTConsumer {
    184     ASTContext *Context;
    185   public:
    186     void Initialize(ASTContext &Context) override {
    187       this->Context = &Context;
    188     }
    189 
    190     bool HandleTopLevelDecl(DeclGroupRef D) override {
    191       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
    192         HandleTopLevelSingleDecl(*I);
    193       return true;
    194     }
    195 
    196     void HandleTopLevelSingleDecl(Decl *D);
    197   };
    198 }
    199 
    200 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
    201   if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
    202     D->print(llvm::errs());
    203 
    204     if (Stmt *Body = D->getBody()) {
    205       llvm::errs() << '\n';
    206       Body->viewAST();
    207       llvm::errs() << '\n';
    208     }
    209   }
    210 }
    211 
    212 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
    213   return std::make_unique<ASTViewer>();
    214 }
    215