llvm-capstone/clang/lib/Frontend/ASTConsumers.cpp
Bruno Ricci 473fbc90d1
[clang][NFC] Store a pointer to the ASTContext in ASTDumper and TextNodeDumper
In general there is no way to get to the ASTContext from most AST nodes
(Decls are one of the exception). This will be a problem when implementing
the rest of APValue::dump since we need the ASTContext to dump some kinds of
APValues.

The ASTContext* in ASTDumper and TextNodeDumper is not always non-null.
This is because we still want to be able to use the various dump() functions
in a debugger.

No functional changes intended.

Reverted in fcf4d5e4499a391dff42ea1a096f146db44147b6 since a few dump()
functions in lldb where missed.
2020-07-03 13:59:22 +01:00

215 lines
6.9 KiB
C++

//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// AST Consumer Implementations.
//
//===----------------------------------------------------------------------===//
#include "clang/Frontend/ASTConsumers.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
//===----------------------------------------------------------------------===//
/// ASTPrinter - Pretty-printer and dumper of ASTs
namespace {
class ASTPrinter : public ASTConsumer,
public RecursiveASTVisitor<ASTPrinter> {
typedef RecursiveASTVisitor<ASTPrinter> base;
public:
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)
: Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
OutputKind(K), OutputFormat(Format), FilterString(FilterString),
DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {}
void HandleTranslationUnit(ASTContext &Context) override {
TranslationUnitDecl *D = Context.getTranslationUnitDecl();
if (FilterString.empty())
return print(D);
TraverseDecl(D);
}
bool shouldWalkTypesOfTypeLocs() const { return false; }
bool TraverseDecl(Decl *D) {
if (D && filterMatches(D)) {
bool ShowColors = Out.has_colors();
if (ShowColors)
Out.changeColor(raw_ostream::BLUE);
Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D)
<< ":\n";
if (ShowColors)
Out.resetColor();
print(D);
Out << "\n";
// Don't traverse child nodes to avoid output duplication.
return true;
}
return base::TraverseDecl(D);
}
private:
std::string getName(Decl *D) {
if (isa<NamedDecl>(D))
return cast<NamedDecl>(D)->getQualifiedNameAsString();
return "";
}
bool filterMatches(Decl *D) {
return getName(D).find(FilterString) != std::string::npos;
}
void print(Decl *D) {
if (DumpLookups) {
if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
if (DC == DC->getPrimaryContext())
DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull);
else
Out << "Lookup map is in primary DeclContext "
<< DC->getPrimaryContext() << "\n";
} else
Out << "Not a DeclContext\n";
} else if (OutputKind == Print) {
PrintingPolicy Policy(D->getASTContext().getLangOpts());
D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
} else if (OutputKind != None) {
D->dump(Out, OutputKind == DumpFull, OutputFormat);
}
if (DumpDeclTypes) {
Decl *InnerD = D;
if (auto *TD = dyn_cast<TemplateDecl>(D))
InnerD = TD->getTemplatedDecl();
// FIXME: Support OutputFormat in type dumping.
// FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups.
if (auto *VD = dyn_cast<ValueDecl>(InnerD))
VD->getType().dump(Out, VD->getASTContext());
if (auto *TD = dyn_cast<TypeDecl>(InnerD))
TD->getTypeForDecl()->dump(Out, TD->getASTContext());
}
}
raw_ostream &Out;
std::unique_ptr<raw_ostream> OwnedOut;
/// How to output individual declarations.
Kind OutputKind;
/// What format should the output take?
ASTDumpOutputFormat OutputFormat;
/// Which declarations or DeclContexts to display.
std::string FilterString;
/// Whether the primary output is lookup results or declarations. Individual
/// results will be output with a format determined by OutputKind. This is
/// incompatible with OutputKind == Print.
bool DumpLookups;
/// Whether to dump the type for each declaration dumped.
bool DumpDeclTypes;
};
class ASTDeclNodeLister : public ASTConsumer,
public RecursiveASTVisitor<ASTDeclNodeLister> {
public:
ASTDeclNodeLister(raw_ostream *Out = nullptr)
: Out(Out ? *Out : llvm::outs()) {}
void HandleTranslationUnit(ASTContext &Context) override {
TraverseDecl(Context.getTranslationUnitDecl());
}
bool shouldWalkTypesOfTypeLocs() const { return false; }
bool VisitNamedDecl(NamedDecl *D) {
D->printQualifiedName(Out);
Out << '\n';
return true;
}
private:
raw_ostream &Out;
};
} // end anonymous namespace
std::unique_ptr<ASTConsumer>
clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
StringRef FilterString) {
return std::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
ADOF_Default, FilterString);
}
std::unique_ptr<ASTConsumer>
clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, StringRef FilterString,
bool DumpDecls, bool Deserialize, bool DumpLookups,
bool DumpDeclTypes, ASTDumpOutputFormat Format) {
assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
return std::make_unique<ASTPrinter>(
std::move(Out),
Deserialize ? ASTPrinter::DumpFull
: DumpDecls ? ASTPrinter::Dump : ASTPrinter::None,
Format, FilterString, DumpLookups, DumpDeclTypes);
}
std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
return std::make_unique<ASTDeclNodeLister>(nullptr);
}
//===----------------------------------------------------------------------===//
/// ASTViewer - AST Visualization
namespace {
class ASTViewer : public ASTConsumer {
ASTContext *Context;
public:
void Initialize(ASTContext &Context) override {
this->Context = &Context;
}
bool HandleTopLevelDecl(DeclGroupRef D) override {
for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
HandleTopLevelSingleDecl(*I);
return true;
}
void HandleTopLevelSingleDecl(Decl *D);
};
}
void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
D->print(llvm::errs());
if (Stmt *Body = D->getBody()) {
llvm::errs() << '\n';
Body->viewAST();
llvm::errs() << '\n';
}
}
}
std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
return std::make_unique<ASTViewer>();
}