xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Frontend/ASTConsumers.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // AST Consumer Implementations.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "clang/Frontend/ASTConsumers.h"
147330f729Sjoerg #include "clang/AST/AST.h"
157330f729Sjoerg #include "clang/AST/ASTConsumer.h"
167330f729Sjoerg #include "clang/AST/ASTContext.h"
177330f729Sjoerg #include "clang/AST/PrettyPrinter.h"
187330f729Sjoerg #include "clang/AST/RecordLayout.h"
197330f729Sjoerg #include "clang/AST/RecursiveASTVisitor.h"
207330f729Sjoerg #include "clang/Basic/Diagnostic.h"
217330f729Sjoerg #include "clang/Basic/SourceManager.h"
227330f729Sjoerg #include "llvm/Support/Path.h"
237330f729Sjoerg #include "llvm/Support/Timer.h"
247330f729Sjoerg #include "llvm/Support/raw_ostream.h"
257330f729Sjoerg using namespace clang;
267330f729Sjoerg 
277330f729Sjoerg //===----------------------------------------------------------------------===//
287330f729Sjoerg /// ASTPrinter - Pretty-printer and dumper of ASTs
297330f729Sjoerg 
307330f729Sjoerg namespace {
317330f729Sjoerg   class ASTPrinter : public ASTConsumer,
327330f729Sjoerg                      public RecursiveASTVisitor<ASTPrinter> {
337330f729Sjoerg     typedef RecursiveASTVisitor<ASTPrinter> base;
347330f729Sjoerg 
357330f729Sjoerg   public:
367330f729Sjoerg     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)377330f729Sjoerg     ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K,
387330f729Sjoerg                ASTDumpOutputFormat Format, StringRef FilterString,
39*e038c9c4Sjoerg                bool DumpLookups = false, bool DumpDeclTypes = false)
407330f729Sjoerg         : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
417330f729Sjoerg           OutputKind(K), OutputFormat(Format), FilterString(FilterString),
42*e038c9c4Sjoerg           DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {}
437330f729Sjoerg 
HandleTranslationUnit(ASTContext & Context)447330f729Sjoerg     void HandleTranslationUnit(ASTContext &Context) override {
457330f729Sjoerg       TranslationUnitDecl *D = Context.getTranslationUnitDecl();
467330f729Sjoerg 
477330f729Sjoerg       if (FilterString.empty())
487330f729Sjoerg         return print(D);
497330f729Sjoerg 
507330f729Sjoerg       TraverseDecl(D);
517330f729Sjoerg     }
527330f729Sjoerg 
shouldWalkTypesOfTypeLocs() const537330f729Sjoerg     bool shouldWalkTypesOfTypeLocs() const { return false; }
547330f729Sjoerg 
TraverseDecl(Decl * D)557330f729Sjoerg     bool TraverseDecl(Decl *D) {
567330f729Sjoerg       if (D && filterMatches(D)) {
577330f729Sjoerg         bool ShowColors = Out.has_colors();
587330f729Sjoerg         if (ShowColors)
597330f729Sjoerg           Out.changeColor(raw_ostream::BLUE);
607330f729Sjoerg         Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D)
617330f729Sjoerg             << ":\n";
627330f729Sjoerg         if (ShowColors)
637330f729Sjoerg           Out.resetColor();
647330f729Sjoerg         print(D);
657330f729Sjoerg         Out << "\n";
667330f729Sjoerg         // Don't traverse child nodes to avoid output duplication.
677330f729Sjoerg         return true;
687330f729Sjoerg       }
697330f729Sjoerg       return base::TraverseDecl(D);
707330f729Sjoerg     }
717330f729Sjoerg 
727330f729Sjoerg   private:
getName(Decl * D)737330f729Sjoerg     std::string getName(Decl *D) {
747330f729Sjoerg       if (isa<NamedDecl>(D))
757330f729Sjoerg         return cast<NamedDecl>(D)->getQualifiedNameAsString();
767330f729Sjoerg       return "";
777330f729Sjoerg     }
filterMatches(Decl * D)787330f729Sjoerg     bool filterMatches(Decl *D) {
797330f729Sjoerg       return getName(D).find(FilterString) != std::string::npos;
807330f729Sjoerg     }
print(Decl * D)817330f729Sjoerg     void print(Decl *D) {
827330f729Sjoerg       if (DumpLookups) {
837330f729Sjoerg         if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
847330f729Sjoerg           if (DC == DC->getPrimaryContext())
857330f729Sjoerg             DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull);
867330f729Sjoerg           else
877330f729Sjoerg             Out << "Lookup map is in primary DeclContext "
887330f729Sjoerg                 << DC->getPrimaryContext() << "\n";
897330f729Sjoerg         } else
907330f729Sjoerg           Out << "Not a DeclContext\n";
917330f729Sjoerg       } else if (OutputKind == Print) {
927330f729Sjoerg         PrintingPolicy Policy(D->getASTContext().getLangOpts());
937330f729Sjoerg         D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
94*e038c9c4Sjoerg       } else if (OutputKind != None) {
957330f729Sjoerg         D->dump(Out, OutputKind == DumpFull, OutputFormat);
967330f729Sjoerg       }
977330f729Sjoerg 
98*e038c9c4Sjoerg       if (DumpDeclTypes) {
99*e038c9c4Sjoerg         Decl *InnerD = D;
100*e038c9c4Sjoerg         if (auto *TD = dyn_cast<TemplateDecl>(D))
101*e038c9c4Sjoerg           InnerD = TD->getTemplatedDecl();
102*e038c9c4Sjoerg 
103*e038c9c4Sjoerg         // FIXME: Support OutputFormat in type dumping.
104*e038c9c4Sjoerg         // FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups.
105*e038c9c4Sjoerg         if (auto *VD = dyn_cast<ValueDecl>(InnerD))
106*e038c9c4Sjoerg           VD->getType().dump(Out, VD->getASTContext());
107*e038c9c4Sjoerg         if (auto *TD = dyn_cast<TypeDecl>(InnerD))
108*e038c9c4Sjoerg           TD->getTypeForDecl()->dump(Out, TD->getASTContext());
109*e038c9c4Sjoerg       }
110*e038c9c4Sjoerg     }
111*e038c9c4Sjoerg 
1127330f729Sjoerg     raw_ostream &Out;
1137330f729Sjoerg     std::unique_ptr<raw_ostream> OwnedOut;
1147330f729Sjoerg 
1157330f729Sjoerg     /// How to output individual declarations.
1167330f729Sjoerg     Kind OutputKind;
1177330f729Sjoerg 
1187330f729Sjoerg     /// What format should the output take?
1197330f729Sjoerg     ASTDumpOutputFormat OutputFormat;
1207330f729Sjoerg 
1217330f729Sjoerg     /// Which declarations or DeclContexts to display.
1227330f729Sjoerg     std::string FilterString;
1237330f729Sjoerg 
1247330f729Sjoerg     /// Whether the primary output is lookup results or declarations. Individual
1257330f729Sjoerg     /// results will be output with a format determined by OutputKind. This is
1267330f729Sjoerg     /// incompatible with OutputKind == Print.
1277330f729Sjoerg     bool DumpLookups;
128*e038c9c4Sjoerg 
129*e038c9c4Sjoerg     /// Whether to dump the type for each declaration dumped.
130*e038c9c4Sjoerg     bool DumpDeclTypes;
1317330f729Sjoerg   };
1327330f729Sjoerg 
1337330f729Sjoerg   class ASTDeclNodeLister : public ASTConsumer,
1347330f729Sjoerg                      public RecursiveASTVisitor<ASTDeclNodeLister> {
1357330f729Sjoerg   public:
ASTDeclNodeLister(raw_ostream * Out=nullptr)1367330f729Sjoerg     ASTDeclNodeLister(raw_ostream *Out = nullptr)
1377330f729Sjoerg         : Out(Out ? *Out : llvm::outs()) {}
1387330f729Sjoerg 
HandleTranslationUnit(ASTContext & Context)1397330f729Sjoerg     void HandleTranslationUnit(ASTContext &Context) override {
1407330f729Sjoerg       TraverseDecl(Context.getTranslationUnitDecl());
1417330f729Sjoerg     }
1427330f729Sjoerg 
shouldWalkTypesOfTypeLocs() const1437330f729Sjoerg     bool shouldWalkTypesOfTypeLocs() const { return false; }
1447330f729Sjoerg 
VisitNamedDecl(NamedDecl * D)1457330f729Sjoerg     bool VisitNamedDecl(NamedDecl *D) {
1467330f729Sjoerg       D->printQualifiedName(Out);
1477330f729Sjoerg       Out << '\n';
1487330f729Sjoerg       return true;
1497330f729Sjoerg     }
1507330f729Sjoerg 
1517330f729Sjoerg   private:
1527330f729Sjoerg     raw_ostream &Out;
1537330f729Sjoerg   };
1547330f729Sjoerg } // end anonymous namespace
1557330f729Sjoerg 
1567330f729Sjoerg std::unique_ptr<ASTConsumer>
CreateASTPrinter(std::unique_ptr<raw_ostream> Out,StringRef FilterString)1577330f729Sjoerg clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
1587330f729Sjoerg                         StringRef FilterString) {
1597330f729Sjoerg   return std::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
1607330f729Sjoerg                                        ADOF_Default, FilterString);
1617330f729Sjoerg }
1627330f729Sjoerg 
1637330f729Sjoerg std::unique_ptr<ASTConsumer>
CreateASTDumper(std::unique_ptr<raw_ostream> Out,StringRef FilterString,bool DumpDecls,bool Deserialize,bool DumpLookups,bool DumpDeclTypes,ASTDumpOutputFormat Format)1647330f729Sjoerg clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, StringRef FilterString,
1657330f729Sjoerg                        bool DumpDecls, bool Deserialize, bool DumpLookups,
166*e038c9c4Sjoerg                        bool DumpDeclTypes, ASTDumpOutputFormat Format) {
1677330f729Sjoerg   assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
168*e038c9c4Sjoerg   return std::make_unique<ASTPrinter>(
169*e038c9c4Sjoerg       std::move(Out),
170*e038c9c4Sjoerg       Deserialize ? ASTPrinter::DumpFull
171*e038c9c4Sjoerg                   : DumpDecls ? ASTPrinter::Dump : ASTPrinter::None,
172*e038c9c4Sjoerg       Format, FilterString, DumpLookups, DumpDeclTypes);
1737330f729Sjoerg }
1747330f729Sjoerg 
CreateASTDeclNodeLister()1757330f729Sjoerg std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
1767330f729Sjoerg   return std::make_unique<ASTDeclNodeLister>(nullptr);
1777330f729Sjoerg }
1787330f729Sjoerg 
1797330f729Sjoerg //===----------------------------------------------------------------------===//
1807330f729Sjoerg /// ASTViewer - AST Visualization
1817330f729Sjoerg 
1827330f729Sjoerg namespace {
1837330f729Sjoerg   class ASTViewer : public ASTConsumer {
1847330f729Sjoerg     ASTContext *Context;
1857330f729Sjoerg   public:
Initialize(ASTContext & Context)1867330f729Sjoerg     void Initialize(ASTContext &Context) override {
1877330f729Sjoerg       this->Context = &Context;
1887330f729Sjoerg     }
1897330f729Sjoerg 
HandleTopLevelDecl(DeclGroupRef D)1907330f729Sjoerg     bool HandleTopLevelDecl(DeclGroupRef D) override {
1917330f729Sjoerg       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
1927330f729Sjoerg         HandleTopLevelSingleDecl(*I);
1937330f729Sjoerg       return true;
1947330f729Sjoerg     }
1957330f729Sjoerg 
1967330f729Sjoerg     void HandleTopLevelSingleDecl(Decl *D);
1977330f729Sjoerg   };
1987330f729Sjoerg }
1997330f729Sjoerg 
HandleTopLevelSingleDecl(Decl * D)2007330f729Sjoerg void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
2017330f729Sjoerg   if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
2027330f729Sjoerg     D->print(llvm::errs());
2037330f729Sjoerg 
2047330f729Sjoerg     if (Stmt *Body = D->getBody()) {
2057330f729Sjoerg       llvm::errs() << '\n';
2067330f729Sjoerg       Body->viewAST();
2077330f729Sjoerg       llvm::errs() << '\n';
2087330f729Sjoerg     }
2097330f729Sjoerg   }
2107330f729Sjoerg }
2117330f729Sjoerg 
CreateASTViewer()2127330f729Sjoerg std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
2137330f729Sjoerg   return std::make_unique<ASTViewer>();
2147330f729Sjoerg }
215