clang 24.0.0git
ASTConsumers.cpp
Go to the documentation of this file.
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
22#include "llvm/Support/Error.h"
23#include "llvm/Support/GlobPattern.h"
24#include "llvm/Support/Timer.h"
25#include "llvm/Support/raw_ostream.h"
26using namespace clang;
27
28//===----------------------------------------------------------------------===//
29/// ASTPrinter - Pretty-printer and dumper of ASTs
30
31namespace {
32 class ASTPrinter : public ASTConsumer,
33 public RecursiveASTVisitor<ASTPrinter> {
34 typedef RecursiveASTVisitor<ASTPrinter> base;
35
36 public:
37 enum Kind { DumpFull, Dump, Print, None };
38 ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K,
39 ASTDumpOutputFormat Format, StringRef FilterString,
40 StringRef FilterPath, bool DumpLookups = false,
41 bool DumpDeclTypes = false)
42 : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
43 OutputKind(K), OutputFormat(Format), FilterString(FilterString),
44 FilterPath(FilterPath), DumpLookups(DumpLookups),
45 DumpDeclTypes(DumpDeclTypes) {}
46
47 ASTPrinter(raw_ostream &Out, Kind K, ASTDumpOutputFormat Format,
48 StringRef FilterString, StringRef FilterPath,
49 bool DumpLookups = false, bool DumpDeclTypes = false)
50 : Out(Out), OwnedOut(nullptr), OutputKind(K), OutputFormat(Format),
51 FilterString(FilterString), FilterPath(FilterPath),
52 DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {}
53
54 void HandleTranslationUnit(ASTContext &Context) override {
55 TranslationUnitDecl *D = Context.getTranslationUnitDecl();
56
57 if (FilterString.empty() && FilterPath.empty())
58 return print(D);
59
60 TraverseDecl(D);
61 }
62
63 bool shouldWalkTypesOfTypeLocs() const { return false; }
64
65 bool TraverseDecl(Decl *D) {
66 if (D && filterMatches(D)) {
67 bool ShowColors = Out.has_colors();
68 if (ShowColors)
69 Out.changeColor(raw_ostream::BLUE);
70
71 if (OutputFormat == ADOF_Default)
72 Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D)
73 << ":\n";
74
75 if (ShowColors)
76 Out.resetColor();
77 print(D);
78 Out << "\n";
79 // Don't traverse child nodes to avoid output duplication.
80 return true;
81 }
82 return base::TraverseDecl(D);
83 }
84
85 private:
86 std::string getName(Decl *D) {
87 if (isa<NamedDecl>(D))
88 return cast<NamedDecl>(D)->getQualifiedNameAsString();
89 return "";
90 }
91 bool filterMatches(Decl *D) {
92 if (!FilterString.empty() &&
93 getName(D).find(FilterString) == std::string::npos)
94 return false;
95
96 if (!FilterPath.empty()) {
97 const SourceManager &SM = D->getASTContext().getSourceManager();
98
99 SourceLocation Loc = D->getLocation();
100 if (Loc.isInvalid())
101 return false;
102
103 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
104 if (PLoc.isInvalid())
105 return false;
106
107 llvm::Expected<llvm::GlobPattern> Pattern =
108 llvm::GlobPattern::create(FilterPath);
109 if (!Pattern) {
110 llvm::consumeError(Pattern.takeError());
111 return false;
112 }
113
114 if (!Pattern->match(PLoc.getFilename()))
115 return false;
116 }
117
118 return true;
119 }
120 void print(Decl *D) {
121 if (DumpLookups) {
122 if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
123 if (DC == DC->getPrimaryContext())
124 DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull);
125 else
126 Out << "Lookup map is in primary DeclContext "
127 << DC->getPrimaryContext() << "\n";
128 } else
129 Out << "Not a DeclContext\n";
130 } else if (OutputKind == Print) {
131 PrintingPolicy Policy(D->getASTContext().getLangOpts());
132 Policy.IncludeTagDefinition = true;
133 Policy.PrettyEnums = false;
134 D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
135 } else if (OutputKind != None) {
136 D->dump(Out, OutputKind == DumpFull, OutputFormat);
137 }
138
139 if (DumpDeclTypes) {
140 Decl *InnerD = D;
141 if (auto *TD = dyn_cast<TemplateDecl>(D))
142 if (Decl *TempD = TD->getTemplatedDecl())
143 InnerD = TempD;
144
145 // FIXME: Support OutputFormat in type dumping.
146 // FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups.
147 if (auto *VD = dyn_cast<ValueDecl>(InnerD))
148 VD->getType().dump(Out, VD->getASTContext());
149 if (auto *TD = dyn_cast<TypeDecl>(InnerD)) {
150 const ASTContext &Ctx = TD->getASTContext();
151 Ctx.getTypeDeclType(TD)->dump(Out, Ctx);
152 }
153 }
154 }
155
156 raw_ostream &Out;
157 std::unique_ptr<raw_ostream> OwnedOut;
158
159 /// How to output individual declarations.
160 Kind OutputKind;
161
162 /// What format should the output take?
163 ASTDumpOutputFormat OutputFormat;
164
165 /// Which declarations or DeclContexts to display.
166 std::string FilterString;
167
168 /// Which source file paths to display.
169 std::string FilterPath;
170
171 /// Whether the primary output is lookup results or declarations. Individual
172 /// results will be output with a format determined by OutputKind. This is
173 /// incompatible with OutputKind == Print.
174 bool DumpLookups;
175
176 /// Whether to dump the type for each declaration dumped.
177 bool DumpDeclTypes;
178 };
179
180 class ASTDeclNodeLister : public ASTConsumer,
182 public:
183 ASTDeclNodeLister(raw_ostream *Out = nullptr)
184 : Out(Out ? *Out : llvm::outs()) {
185 ShouldWalkTypesOfTypeLocs = false;
186 }
187
188 void HandleTranslationUnit(ASTContext &Context) override {
189 TraverseDecl(Context.getTranslationUnitDecl());
190 }
191
192 bool VisitNamedDecl(NamedDecl *D) override {
193 D->printQualifiedName(Out);
194 Out << '\n';
195 return true;
196 }
197
198 private:
199 raw_ostream &Out;
200 };
201} // end anonymous namespace
202
203std::unique_ptr<ASTConsumer>
204clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
205 StringRef FilterString) {
206 return std::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
207 ADOF_Default, FilterString, "");
208}
209
210std::unique_ptr<ASTConsumer>
211clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, StringRef FilterString,
212 StringRef FilterPath, bool DumpDecls, bool Deserialize,
213 bool DumpLookups, bool DumpDeclTypes,
214 ASTDumpOutputFormat Format) {
215 assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
216 return std::make_unique<ASTPrinter>(std::move(Out),
217 Deserialize ? ASTPrinter::DumpFull
218 : DumpDecls ? ASTPrinter::Dump
219 : ASTPrinter::None,
220 Format, FilterString, FilterPath,
221 DumpLookups, DumpDeclTypes);
222}
223
224std::unique_ptr<ASTConsumer>
225clang::CreateASTDumper(raw_ostream &Out, StringRef FilterString,
226 StringRef FilterPath, bool DumpDecls, bool Deserialize,
227 bool DumpLookups, bool DumpDeclTypes,
228 ASTDumpOutputFormat Format) {
229 assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
230 return std::make_unique<ASTPrinter>(Out,
231 Deserialize ? ASTPrinter::DumpFull
232 : DumpDecls ? ASTPrinter::Dump
233 : ASTPrinter::None,
234 Format, FilterString, FilterPath,
235 DumpLookups, DumpDeclTypes);
236}
237
238std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
239 return std::make_unique<ASTDeclNodeLister>(nullptr);
240}
241
242//===----------------------------------------------------------------------===//
243/// ASTViewer - AST Visualization
244
245namespace {
246class ASTViewer : public ASTConsumer {
247 ASTContext *Context = nullptr;
248
249public:
250 void Initialize(ASTContext &Context) override { this->Context = &Context; }
251
252 bool HandleTopLevelDecl(DeclGroupRef D) override {
253 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
254 HandleTopLevelSingleDecl(*I);
255 return true;
256 }
257
258 void HandleTopLevelSingleDecl(Decl *D);
259};
260}
261
262void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
264 D->print(llvm::errs());
265
266 if (Stmt *Body = D->getBody()) {
267 llvm::errs() << '\n';
268 Body->viewAST();
269 llvm::errs() << '\n';
270 }
271 }
272}
273
274std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
275 return std::make_unique<ASTViewer>();
276}
Defines the clang::ASTContext interface.
Defines the Diagnostic-related interfaces.
static void print(llvm::raw_ostream &OS, const T &V, const Context &Ctx, QualType Ty)
Defines the SourceManager interface.
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs.
Definition ASTConsumer.h:35
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
SourceManager & getSourceManager()
Definition ASTContext.h:913
TranslationUnitDecl * getTranslationUnitDecl() const
const LangOptions & getLangOpts() const
QualType getTypeDeclType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypeDecl *Decl) const
iterator begin()
Definition DeclGroup.h:95
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:550
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition DeclBase.h:1106
void dump() const
SourceLocation getLocation() const
Definition DeclBase.h:449
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
void printQualifiedName(raw_ostream &OS) const
Returns a human-readable qualified name for this declaration, like A::B::i, for i being member of nam...
Definition Decl.cpp:1690
const char * getFilename() const
Return the presumed filename of this location.
bool isInvalid() const
Return true if this object is invalid or uninitialized.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
void dump() const
StringRef getName(const HeaderType T)
Definition HeaderFile.h:38
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
Top level wrappers for InstallAPI frontend operations.
ASTDumpOutputFormat
Used to specify the format for printing AST dump information.
bool isa(CodeGen::Address addr)
Definition Address.h:330
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
std::unique_ptr< ASTConsumer > CreateASTDeclNodeLister()
std::unique_ptr< ASTConsumer > CreateASTPrinter(std::unique_ptr< raw_ostream > OS, StringRef FilterString)
std::unique_ptr< ASTConsumer > CreateASTViewer()
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
Definition Address.h:327
std::unique_ptr< ASTConsumer > CreateASTDumper(std::unique_ptr< raw_ostream > OS, StringRef FilterString, StringRef FilterPath, bool DumpDecls, bool Deserialize, bool DumpLookups, bool DumpDeclTypes, ASTDumpOutputFormat Format)