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, StringRef FilterString,
38                bool DumpLookups = false)
39         : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
40           OutputKind(K), FilterString(FilterString), DumpLookups(DumpLookups) {}
41 
42     void HandleTranslationUnit(ASTContext &Context) override {
43       TranslationUnitDecl *D = Context.getTranslationUnitDecl();
44 
45       if (FilterString.empty())
46         return print(D);
47 
48       TraverseDecl(D);
49     }
50 
51     bool shouldWalkTypesOfTypeLocs() const { return false; }
52 
53     bool TraverseDecl(Decl *D) {
54       if (D && filterMatches(D)) {
55         bool ShowColors = Out.has_colors();
56         if (ShowColors)
57           Out.changeColor(raw_ostream::BLUE);
58         Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D)
59             << ":\n";
60         if (ShowColors)
61           Out.resetColor();
62         print(D);
63         Out << "\n";
64         // Don't traverse child nodes to avoid output duplication.
65         return true;
66       }
67       return base::TraverseDecl(D);
68     }
69 
70   private:
71     std::string getName(Decl *D) {
72       if (isa<NamedDecl>(D))
73         return cast<NamedDecl>(D)->getQualifiedNameAsString();
74       return "";
75     }
76     bool filterMatches(Decl *D) {
77       return getName(D).find(FilterString) != std::string::npos;
78     }
79     void print(Decl *D) {
80       if (DumpLookups) {
81         if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
82           if (DC == DC->getPrimaryContext())
83             DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull);
84           else
85             Out << "Lookup map is in primary DeclContext "
86                 << DC->getPrimaryContext() << "\n";
87         } else
88           Out << "Not a DeclContext\n";
89       } else if (OutputKind == Print) {
90         PrintingPolicy Policy(D->getASTContext().getLangOpts());
91         D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
92       } else if (OutputKind != None)
93         D->dump(Out, OutputKind == DumpFull);
94     }
95 
96     raw_ostream &Out;
97     std::unique_ptr<raw_ostream> OwnedOut;
98 
99     /// How to output individual declarations.
100     Kind OutputKind;
101 
102     /// Which declarations or DeclContexts to display.
103     std::string FilterString;
104 
105     /// Whether the primary output is lookup results or declarations. Individual
106     /// results will be output with a format determined by OutputKind. This is
107     /// incompatible with OutputKind == Print.
108     bool DumpLookups;
109   };
110 
111   class ASTDeclNodeLister : public ASTConsumer,
112                      public RecursiveASTVisitor<ASTDeclNodeLister> {
113   public:
114     ASTDeclNodeLister(raw_ostream *Out = nullptr)
115         : Out(Out ? *Out : llvm::outs()) {}
116 
117     void HandleTranslationUnit(ASTContext &Context) override {
118       TraverseDecl(Context.getTranslationUnitDecl());
119     }
120 
121     bool shouldWalkTypesOfTypeLocs() const { return false; }
122 
123     bool VisitNamedDecl(NamedDecl *D) {
124       D->printQualifiedName(Out);
125       Out << '\n';
126       return true;
127     }
128 
129   private:
130     raw_ostream &Out;
131   };
132 } // end anonymous namespace
133 
134 std::unique_ptr<ASTConsumer>
135 clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
136                         StringRef FilterString) {
137   return llvm::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
138                                        FilterString);
139 }
140 
141 std::unique_ptr<ASTConsumer>
142 clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out,
143                        StringRef FilterString,
144                        bool DumpDecls,
145                        bool Deserialize,
146                        bool DumpLookups) {
147   assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
148   return llvm::make_unique<ASTPrinter>(std::move(Out),
149                                        Deserialize ? ASTPrinter::DumpFull :
150                                        DumpDecls ? ASTPrinter::Dump :
151                                        ASTPrinter::None,
152                                        FilterString, DumpLookups);
153 }
154 
155 std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
156   return llvm::make_unique<ASTDeclNodeLister>(nullptr);
157 }
158 
159 //===----------------------------------------------------------------------===//
160 /// ASTViewer - AST Visualization
161 
162 namespace {
163   class ASTViewer : public ASTConsumer {
164     ASTContext *Context;
165   public:
166     void Initialize(ASTContext &Context) override {
167       this->Context = &Context;
168     }
169 
170     bool HandleTopLevelDecl(DeclGroupRef D) override {
171       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
172         HandleTopLevelSingleDecl(*I);
173       return true;
174     }
175 
176     void HandleTopLevelSingleDecl(Decl *D);
177   };
178 }
179 
180 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
181   if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
182     D->print(llvm::errs());
183 
184     if (Stmt *Body = D->getBody()) {
185       llvm::errs() << '\n';
186       Body->viewAST();
187       llvm::errs() << '\n';
188     }
189   }
190 }
191 
192 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
193   return llvm::make_unique<ASTViewer>();
194 }
195