1 //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // AST Consumer Implementations.
11 //===----------------------------------------------------------------------===//
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
;
27 //===----------------------------------------------------------------------===//
28 /// ASTPrinter - Pretty-printer and dumper of ASTs
31 class ASTPrinter
: public ASTConsumer
,
32 public RecursiveASTVisitor
<ASTPrinter
> {
33 typedef RecursiveASTVisitor
<ASTPrinter
> base
;
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, 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
) {}
44 void HandleTranslationUnit(ASTContext
&Context
) override
{
45 TranslationUnitDecl
*D
= Context
.getTranslationUnitDecl();
47 if (FilterString
.empty())
53 bool shouldWalkTypesOfTypeLocs() const { return false; }
55 bool TraverseDecl(Decl
*D
) {
56 if (D
&& filterMatches(D
)) {
57 bool ShowColors
= Out
.has_colors();
59 Out
.changeColor(raw_ostream::BLUE
);
61 if (OutputFormat
== ADOF_Default
)
62 Out
<< (OutputKind
!= Print
? "Dumping " : "Printing ") << getName(D
)
69 // Don't traverse child nodes to avoid output duplication.
72 return base::TraverseDecl(D
);
76 std::string
getName(Decl
*D
) {
77 if (isa
<NamedDecl
>(D
))
78 return cast
<NamedDecl
>(D
)->getQualifiedNameAsString();
81 bool filterMatches(Decl
*D
) {
82 return getName(D
).find(FilterString
) != std::string::npos
;
86 if (DeclContext
*DC
= dyn_cast
<DeclContext
>(D
)) {
87 if (DC
== DC
->getPrimaryContext())
88 DC
->dumpLookups(Out
, OutputKind
!= None
, OutputKind
== DumpFull
);
90 Out
<< "Lookup map is in primary DeclContext "
91 << DC
->getPrimaryContext() << "\n";
93 Out
<< "Not a DeclContext\n";
94 } else if (OutputKind
== Print
) {
95 PrintingPolicy
Policy(D
->getASTContext().getLangOpts());
96 D
->print(Out
, Policy
, /*Indentation=*/0, /*PrintInstantiation=*/true);
97 } else if (OutputKind
!= None
) {
98 D
->dump(Out
, OutputKind
== DumpFull
, OutputFormat
);
103 if (auto *TD
= dyn_cast
<TemplateDecl
>(D
))
104 InnerD
= TD
->getTemplatedDecl();
106 // FIXME: Support OutputFormat in type dumping.
107 // FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups.
108 if (auto *VD
= dyn_cast
<ValueDecl
>(InnerD
))
109 VD
->getType().dump(Out
, VD
->getASTContext());
110 if (auto *TD
= dyn_cast
<TypeDecl
>(InnerD
))
111 TD
->getTypeForDecl()->dump(Out
, TD
->getASTContext());
116 std::unique_ptr
<raw_ostream
> OwnedOut
;
118 /// How to output individual declarations.
121 /// What format should the output take?
122 ASTDumpOutputFormat OutputFormat
;
124 /// Which declarations or DeclContexts to display.
125 std::string FilterString
;
127 /// Whether the primary output is lookup results or declarations. Individual
128 /// results will be output with a format determined by OutputKind. This is
129 /// incompatible with OutputKind == Print.
132 /// Whether to dump the type for each declaration dumped.
136 class ASTDeclNodeLister
: public ASTConsumer
,
137 public RecursiveASTVisitor
<ASTDeclNodeLister
> {
139 ASTDeclNodeLister(raw_ostream
*Out
= nullptr)
140 : Out(Out
? *Out
: llvm::outs()) {}
142 void HandleTranslationUnit(ASTContext
&Context
) override
{
143 TraverseDecl(Context
.getTranslationUnitDecl());
146 bool shouldWalkTypesOfTypeLocs() const { return false; }
148 bool VisitNamedDecl(NamedDecl
*D
) {
149 D
->printQualifiedName(Out
);
157 } // end anonymous namespace
159 std::unique_ptr
<ASTConsumer
>
160 clang::CreateASTPrinter(std::unique_ptr
<raw_ostream
> Out
,
161 StringRef FilterString
) {
162 return std::make_unique
<ASTPrinter
>(std::move(Out
), ASTPrinter::Print
,
163 ADOF_Default
, FilterString
);
166 std::unique_ptr
<ASTConsumer
>
167 clang::CreateASTDumper(std::unique_ptr
<raw_ostream
> Out
, StringRef FilterString
,
168 bool DumpDecls
, bool Deserialize
, bool DumpLookups
,
169 bool DumpDeclTypes
, ASTDumpOutputFormat Format
) {
170 assert((DumpDecls
|| Deserialize
|| DumpLookups
) && "nothing to dump");
171 return std::make_unique
<ASTPrinter
>(
173 Deserialize
? ASTPrinter::DumpFull
174 : DumpDecls
? ASTPrinter::Dump
: ASTPrinter::None
,
175 Format
, FilterString
, DumpLookups
, DumpDeclTypes
);
178 std::unique_ptr
<ASTConsumer
> clang::CreateASTDeclNodeLister() {
179 return std::make_unique
<ASTDeclNodeLister
>(nullptr);
182 //===----------------------------------------------------------------------===//
183 /// ASTViewer - AST Visualization
186 class ASTViewer
: public ASTConsumer
{
189 void Initialize(ASTContext
&Context
) override
{
190 this->Context
= &Context
;
193 bool HandleTopLevelDecl(DeclGroupRef D
) override
{
194 for (DeclGroupRef::iterator I
= D
.begin(), E
= D
.end(); I
!= E
; ++I
)
195 HandleTopLevelSingleDecl(*I
);
199 void HandleTopLevelSingleDecl(Decl
*D
);
203 void ASTViewer::HandleTopLevelSingleDecl(Decl
*D
) {
204 if (isa
<FunctionDecl
>(D
) || isa
<ObjCMethodDecl
>(D
)) {
205 D
->print(llvm::errs());
207 if (Stmt
*Body
= D
->getBody()) {
208 llvm::errs() << '\n';
210 llvm::errs() << '\n';
215 std::unique_ptr
<ASTConsumer
> clang::CreateASTViewer() {
216 return std::make_unique
<ASTViewer
>();