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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Frontend/ASTConsumers.cpp