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