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 };
ASTPrinter(std::unique_ptr<raw_ostream> Out,Kind K,ASTDumpOutputFormat Format,StringRef FilterString,bool DumpLookups=false,bool DumpDeclTypes=false)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
HandleTranslationUnit(ASTContext & Context)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
shouldWalkTypesOfTypeLocs() const53 bool shouldWalkTypesOfTypeLocs() const { return false; }
54
TraverseDecl(Decl * D)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:
getName(Decl * D)73 std::string getName(Decl *D) {
74 if (isa<NamedDecl>(D))
75 return cast<NamedDecl>(D)->getQualifiedNameAsString();
76 return "";
77 }
filterMatches(Decl * D)78 bool filterMatches(Decl *D) {
79 return getName(D).find(FilterString) != std::string::npos;
80 }
print(Decl * D)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:
ASTDeclNodeLister(raw_ostream * Out=nullptr)136 ASTDeclNodeLister(raw_ostream *Out = nullptr)
137 : Out(Out ? *Out : llvm::outs()) {}
138
HandleTranslationUnit(ASTContext & Context)139 void HandleTranslationUnit(ASTContext &Context) override {
140 TraverseDecl(Context.getTranslationUnitDecl());
141 }
142
shouldWalkTypesOfTypeLocs() const143 bool shouldWalkTypesOfTypeLocs() const { return false; }
144
VisitNamedDecl(NamedDecl * D)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>
CreateASTPrinter(std::unique_ptr<raw_ostream> Out,StringRef FilterString)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>
CreateASTDumper(std::unique_ptr<raw_ostream> Out,StringRef FilterString,bool DumpDecls,bool Deserialize,bool DumpLookups,bool DumpDeclTypes,ASTDumpOutputFormat Format)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
CreateASTDeclNodeLister()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:
Initialize(ASTContext & Context)186 void Initialize(ASTContext &Context) override {
187 this->Context = &Context;
188 }
189
HandleTopLevelDecl(DeclGroupRef D)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
HandleTopLevelSingleDecl(Decl * D)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
CreateASTViewer()212 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
213 return std::make_unique<ASTViewer>();
214 }
215