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)
40         : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
41           OutputKind(K), OutputFormat(Format), FilterString(FilterString),
42           DumpLookups(DumpLookups) {}
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     raw_ostream &Out;
99     std::unique_ptr<raw_ostream> OwnedOut;
100 
101     /// How to output individual declarations.
102     Kind OutputKind;
103 
104     /// What format should the output take?
105     ASTDumpOutputFormat OutputFormat;
106 
107     /// Which declarations or DeclContexts to display.
108     std::string FilterString;
109 
110     /// Whether the primary output is lookup results or declarations. Individual
111     /// results will be output with a format determined by OutputKind. This is
112     /// incompatible with OutputKind == Print.
113     bool DumpLookups;
114   };
115 
116   class ASTDeclNodeLister : public ASTConsumer,
117                      public RecursiveASTVisitor<ASTDeclNodeLister> {
118   public:
119     ASTDeclNodeLister(raw_ostream *Out = nullptr)
120         : Out(Out ? *Out : llvm::outs()) {}
121 
122     void HandleTranslationUnit(ASTContext &Context) override {
123       TraverseDecl(Context.getTranslationUnitDecl());
124     }
125 
126     bool shouldWalkTypesOfTypeLocs() const { return false; }
127 
128     bool VisitNamedDecl(NamedDecl *D) {
129       D->printQualifiedName(Out);
130       Out << '\n';
131       return true;
132     }
133 
134   private:
135     raw_ostream &Out;
136   };
137 } // end anonymous namespace
138 
139 std::unique_ptr<ASTConsumer>
140 clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
141                         StringRef FilterString) {
142   return std::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
143                                        ADOF_Default, FilterString);
144 }
145 
146 std::unique_ptr<ASTConsumer>
147 clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, StringRef FilterString,
148                        bool DumpDecls, bool Deserialize, bool DumpLookups,
149                        ASTDumpOutputFormat Format) {
150   assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
151   return std::make_unique<ASTPrinter>(std::move(Out),
152                                        Deserialize ? ASTPrinter::DumpFull :
153                                        DumpDecls ? ASTPrinter::Dump :
154                                        ASTPrinter::None, Format,
155                                        FilterString, DumpLookups);
156 }
157 
158 std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
159   return std::make_unique<ASTDeclNodeLister>(nullptr);
160 }
161 
162 //===----------------------------------------------------------------------===//
163 /// ASTViewer - AST Visualization
164 
165 namespace {
166   class ASTViewer : public ASTConsumer {
167     ASTContext *Context;
168   public:
169     void Initialize(ASTContext &Context) override {
170       this->Context = &Context;
171     }
172 
173     bool HandleTopLevelDecl(DeclGroupRef D) override {
174       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
175         HandleTopLevelSingleDecl(*I);
176       return true;
177     }
178 
179     void HandleTopLevelSingleDecl(Decl *D);
180   };
181 }
182 
183 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
184   if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
185     D->print(llvm::errs());
186 
187     if (Stmt *Body = D->getBody()) {
188       llvm::errs() << '\n';
189       Body->viewAST();
190       llvm::errs() << '\n';
191     }
192   }
193 }
194 
195 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
196   return std::make_unique<ASTViewer>();
197 }
198