mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-14 12:22:27 +00:00

to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
195 lines
6.2 KiB
C++
195 lines
6.2 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, StringRef FilterString,
|
|
bool DumpLookups = false)
|
|
: Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
|
|
OutputKind(K), FilterString(FilterString), DumpLookups(DumpLookups) {}
|
|
|
|
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);
|
|
}
|
|
|
|
raw_ostream &Out;
|
|
std::unique_ptr<raw_ostream> OwnedOut;
|
|
|
|
/// How to output individual declarations.
|
|
Kind OutputKind;
|
|
|
|
/// 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;
|
|
};
|
|
|
|
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 llvm::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
|
|
FilterString);
|
|
}
|
|
|
|
std::unique_ptr<ASTConsumer>
|
|
clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out,
|
|
StringRef FilterString,
|
|
bool DumpDecls,
|
|
bool Deserialize,
|
|
bool DumpLookups) {
|
|
assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
|
|
return llvm::make_unique<ASTPrinter>(std::move(Out),
|
|
Deserialize ? ASTPrinter::DumpFull :
|
|
DumpDecls ? ASTPrinter::Dump :
|
|
ASTPrinter::None,
|
|
FilterString, DumpLookups);
|
|
}
|
|
|
|
std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
|
|
return llvm::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 llvm::make_unique<ASTViewer>();
|
|
}
|