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