xref: /freebsd-src/contrib/llvm-project/clang/lib/Frontend/ASTConsumers.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // AST Consumer Implementations.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/Frontend/ASTConsumers.h"
140b57cec5SDimitry Andric #include "clang/AST/AST.h"
150b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h"
160b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
170b57cec5SDimitry Andric #include "clang/AST/PrettyPrinter.h"
180b57cec5SDimitry Andric #include "clang/AST/RecordLayout.h"
190b57cec5SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
200b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h"
210b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
220b57cec5SDimitry Andric #include "llvm/Support/Path.h"
230b57cec5SDimitry Andric #include "llvm/Support/Timer.h"
240b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
250b57cec5SDimitry Andric using namespace clang;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
280b57cec5SDimitry Andric /// ASTPrinter - Pretty-printer and dumper of ASTs
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric namespace {
310b57cec5SDimitry Andric   class ASTPrinter : public ASTConsumer,
320b57cec5SDimitry Andric                      public RecursiveASTVisitor<ASTPrinter> {
330b57cec5SDimitry Andric     typedef RecursiveASTVisitor<ASTPrinter> base;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   public:
360b57cec5SDimitry Andric     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)370b57cec5SDimitry Andric     ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K,
380b57cec5SDimitry Andric                ASTDumpOutputFormat Format, StringRef FilterString,
395ffd83dbSDimitry Andric                bool DumpLookups = false, bool DumpDeclTypes = false)
400b57cec5SDimitry Andric         : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
410b57cec5SDimitry Andric           OutputKind(K), OutputFormat(Format), FilterString(FilterString),
425ffd83dbSDimitry Andric           DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {}
430b57cec5SDimitry Andric 
HandleTranslationUnit(ASTContext & Context)440b57cec5SDimitry Andric     void HandleTranslationUnit(ASTContext &Context) override {
450b57cec5SDimitry Andric       TranslationUnitDecl *D = Context.getTranslationUnitDecl();
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric       if (FilterString.empty())
480b57cec5SDimitry Andric         return print(D);
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric       TraverseDecl(D);
510b57cec5SDimitry Andric     }
520b57cec5SDimitry Andric 
shouldWalkTypesOfTypeLocs() const530b57cec5SDimitry Andric     bool shouldWalkTypesOfTypeLocs() const { return false; }
540b57cec5SDimitry Andric 
TraverseDecl(Decl * D)550b57cec5SDimitry Andric     bool TraverseDecl(Decl *D) {
560b57cec5SDimitry Andric       if (D && filterMatches(D)) {
570b57cec5SDimitry Andric         bool ShowColors = Out.has_colors();
580b57cec5SDimitry Andric         if (ShowColors)
590b57cec5SDimitry Andric           Out.changeColor(raw_ostream::BLUE);
60349cc55cSDimitry Andric 
61349cc55cSDimitry Andric         if (OutputFormat == ADOF_Default)
620b57cec5SDimitry Andric           Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D)
630b57cec5SDimitry Andric               << ":\n";
64349cc55cSDimitry Andric 
650b57cec5SDimitry Andric         if (ShowColors)
660b57cec5SDimitry Andric           Out.resetColor();
670b57cec5SDimitry Andric         print(D);
680b57cec5SDimitry Andric         Out << "\n";
690b57cec5SDimitry Andric         // Don't traverse child nodes to avoid output duplication.
700b57cec5SDimitry Andric         return true;
710b57cec5SDimitry Andric       }
720b57cec5SDimitry Andric       return base::TraverseDecl(D);
730b57cec5SDimitry Andric     }
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   private:
getName(Decl * D)760b57cec5SDimitry Andric     std::string getName(Decl *D) {
770b57cec5SDimitry Andric       if (isa<NamedDecl>(D))
780b57cec5SDimitry Andric         return cast<NamedDecl>(D)->getQualifiedNameAsString();
790b57cec5SDimitry Andric       return "";
800b57cec5SDimitry Andric     }
filterMatches(Decl * D)810b57cec5SDimitry Andric     bool filterMatches(Decl *D) {
820b57cec5SDimitry Andric       return getName(D).find(FilterString) != std::string::npos;
830b57cec5SDimitry Andric     }
print(Decl * D)840b57cec5SDimitry Andric     void print(Decl *D) {
850b57cec5SDimitry Andric       if (DumpLookups) {
860b57cec5SDimitry Andric         if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
870b57cec5SDimitry Andric           if (DC == DC->getPrimaryContext())
880b57cec5SDimitry Andric             DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull);
890b57cec5SDimitry Andric           else
900b57cec5SDimitry Andric             Out << "Lookup map is in primary DeclContext "
910b57cec5SDimitry Andric                 << DC->getPrimaryContext() << "\n";
920b57cec5SDimitry Andric         } else
930b57cec5SDimitry Andric           Out << "Not a DeclContext\n";
940b57cec5SDimitry Andric       } else if (OutputKind == Print) {
950b57cec5SDimitry Andric         PrintingPolicy Policy(D->getASTContext().getLangOpts());
960b57cec5SDimitry Andric         D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
975ffd83dbSDimitry Andric       } else if (OutputKind != None) {
980b57cec5SDimitry Andric         D->dump(Out, OutputKind == DumpFull, OutputFormat);
990b57cec5SDimitry Andric       }
1000b57cec5SDimitry Andric 
1015ffd83dbSDimitry Andric       if (DumpDeclTypes) {
1025ffd83dbSDimitry Andric         Decl *InnerD = D;
1035ffd83dbSDimitry Andric         if (auto *TD = dyn_cast<TemplateDecl>(D))
1045ffd83dbSDimitry Andric           InnerD = TD->getTemplatedDecl();
1055ffd83dbSDimitry Andric 
1065ffd83dbSDimitry Andric         // FIXME: Support OutputFormat in type dumping.
1075ffd83dbSDimitry Andric         // FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups.
1085ffd83dbSDimitry Andric         if (auto *VD = dyn_cast<ValueDecl>(InnerD))
1095ffd83dbSDimitry Andric           VD->getType().dump(Out, VD->getASTContext());
1105ffd83dbSDimitry Andric         if (auto *TD = dyn_cast<TypeDecl>(InnerD))
1115ffd83dbSDimitry Andric           TD->getTypeForDecl()->dump(Out, TD->getASTContext());
1125ffd83dbSDimitry Andric       }
1135ffd83dbSDimitry Andric     }
1145ffd83dbSDimitry Andric 
1150b57cec5SDimitry Andric     raw_ostream &Out;
1160b57cec5SDimitry Andric     std::unique_ptr<raw_ostream> OwnedOut;
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric     /// How to output individual declarations.
1190b57cec5SDimitry Andric     Kind OutputKind;
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric     /// What format should the output take?
1220b57cec5SDimitry Andric     ASTDumpOutputFormat OutputFormat;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric     /// Which declarations or DeclContexts to display.
1250b57cec5SDimitry Andric     std::string FilterString;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     /// Whether the primary output is lookup results or declarations. Individual
1280b57cec5SDimitry Andric     /// results will be output with a format determined by OutputKind. This is
1290b57cec5SDimitry Andric     /// incompatible with OutputKind == Print.
1300b57cec5SDimitry Andric     bool DumpLookups;
1315ffd83dbSDimitry Andric 
1325ffd83dbSDimitry Andric     /// Whether to dump the type for each declaration dumped.
1335ffd83dbSDimitry Andric     bool DumpDeclTypes;
1340b57cec5SDimitry Andric   };
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   class ASTDeclNodeLister : public ASTConsumer,
1370b57cec5SDimitry Andric                      public RecursiveASTVisitor<ASTDeclNodeLister> {
1380b57cec5SDimitry Andric   public:
ASTDeclNodeLister(raw_ostream * Out=nullptr)1390b57cec5SDimitry Andric     ASTDeclNodeLister(raw_ostream *Out = nullptr)
1400b57cec5SDimitry Andric         : Out(Out ? *Out : llvm::outs()) {}
1410b57cec5SDimitry Andric 
HandleTranslationUnit(ASTContext & Context)1420b57cec5SDimitry Andric     void HandleTranslationUnit(ASTContext &Context) override {
1430b57cec5SDimitry Andric       TraverseDecl(Context.getTranslationUnitDecl());
1440b57cec5SDimitry Andric     }
1450b57cec5SDimitry Andric 
shouldWalkTypesOfTypeLocs() const1460b57cec5SDimitry Andric     bool shouldWalkTypesOfTypeLocs() const { return false; }
1470b57cec5SDimitry Andric 
VisitNamedDecl(NamedDecl * D)1480b57cec5SDimitry Andric     bool VisitNamedDecl(NamedDecl *D) {
1490b57cec5SDimitry Andric       D->printQualifiedName(Out);
1500b57cec5SDimitry Andric       Out << '\n';
1510b57cec5SDimitry Andric       return true;
1520b57cec5SDimitry Andric     }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   private:
1550b57cec5SDimitry Andric     raw_ostream &Out;
1560b57cec5SDimitry Andric   };
1570b57cec5SDimitry Andric } // end anonymous namespace
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
CreateASTPrinter(std::unique_ptr<raw_ostream> Out,StringRef FilterString)1600b57cec5SDimitry Andric clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
1610b57cec5SDimitry Andric                         StringRef FilterString) {
162a7dea167SDimitry Andric   return std::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
1630b57cec5SDimitry Andric                                        ADOF_Default, FilterString);
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
CreateASTDumper(std::unique_ptr<raw_ostream> Out,StringRef FilterString,bool DumpDecls,bool Deserialize,bool DumpLookups,bool DumpDeclTypes,ASTDumpOutputFormat Format)1670b57cec5SDimitry Andric clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, StringRef FilterString,
1680b57cec5SDimitry Andric                        bool DumpDecls, bool Deserialize, bool DumpLookups,
1695ffd83dbSDimitry Andric                        bool DumpDeclTypes, ASTDumpOutputFormat Format) {
1700b57cec5SDimitry Andric   assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
1715ffd83dbSDimitry Andric   return std::make_unique<ASTPrinter>(
1725ffd83dbSDimitry Andric       std::move(Out),
1735ffd83dbSDimitry Andric       Deserialize ? ASTPrinter::DumpFull
1745ffd83dbSDimitry Andric                   : DumpDecls ? ASTPrinter::Dump : ASTPrinter::None,
1755ffd83dbSDimitry Andric       Format, FilterString, DumpLookups, DumpDeclTypes);
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
CreateASTDeclNodeLister()1780b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
179a7dea167SDimitry Andric   return std::make_unique<ASTDeclNodeLister>(nullptr);
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1830b57cec5SDimitry Andric /// ASTViewer - AST Visualization
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric namespace {
1860b57cec5SDimitry Andric class ASTViewer : public ASTConsumer {
187*06c3fb27SDimitry Andric   ASTContext *Context = nullptr;
188*06c3fb27SDimitry Andric 
1890b57cec5SDimitry Andric public:
Initialize(ASTContext & Context)190*06c3fb27SDimitry Andric   void Initialize(ASTContext &Context) override { this->Context = &Context; }
1910b57cec5SDimitry Andric 
HandleTopLevelDecl(DeclGroupRef D)1920b57cec5SDimitry Andric   bool HandleTopLevelDecl(DeclGroupRef D) override {
1930b57cec5SDimitry Andric     for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
1940b57cec5SDimitry Andric       HandleTopLevelSingleDecl(*I);
1950b57cec5SDimitry Andric     return true;
1960b57cec5SDimitry Andric   }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   void HandleTopLevelSingleDecl(Decl *D);
1990b57cec5SDimitry Andric };
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
HandleTopLevelSingleDecl(Decl * D)2020b57cec5SDimitry Andric void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
2030b57cec5SDimitry Andric   if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
2040b57cec5SDimitry Andric     D->print(llvm::errs());
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric     if (Stmt *Body = D->getBody()) {
2070b57cec5SDimitry Andric       llvm::errs() << '\n';
2080b57cec5SDimitry Andric       Body->viewAST();
2090b57cec5SDimitry Andric       llvm::errs() << '\n';
2100b57cec5SDimitry Andric     }
2110b57cec5SDimitry Andric   }
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
CreateASTViewer()2140b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
215a7dea167SDimitry Andric   return std::make_unique<ASTViewer>();
2160b57cec5SDimitry Andric }
217