2007-10-07 14:04:32 +08:00
|
|
|
//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
|
2007-06-23 08:39:57 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2007-06-23 08:39:57 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2007-10-07 14:04:32 +08:00
|
|
|
// AST Consumer Implementations.
|
2007-06-23 08:39:57 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-05-19 06:50:54 +08:00
|
|
|
#include "clang/Frontend/ASTConsumers.h"
|
2007-06-23 08:39:57 +08:00
|
|
|
#include "clang/AST/AST.h"
|
2007-09-16 07:02:28 +08:00
|
|
|
#include "clang/AST/ASTConsumer.h"
|
2009-03-28 12:27:18 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2009-05-30 04:38:28 +08:00
|
|
|
#include "clang/AST/PrettyPrinter.h"
|
2012-07-27 00:01:23 +08:00
|
|
|
#include "clang/AST/RecordLayout.h"
|
|
|
|
#include "clang/AST/RecursiveASTVisitor.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
|
|
|
#include "clang/Basic/SourceManager.h"
|
2010-11-30 02:12:39 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2012-07-27 00:01:23 +08:00
|
|
|
#include "llvm/Support/Timer.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2007-08-09 06:51:59 +08:00
|
|
|
using namespace clang;
|
2007-06-23 08:39:57 +08:00
|
|
|
|
2007-11-28 05:46:50 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2009-05-30 08:08:05 +08:00
|
|
|
/// ASTPrinter - Pretty-printer and dumper of ASTs
|
2007-11-28 05:46:50 +08:00
|
|
|
|
|
|
|
namespace {
|
2012-07-27 00:01:23 +08:00
|
|
|
class ASTPrinter : public ASTConsumer,
|
|
|
|
public RecursiveASTVisitor<ASTPrinter> {
|
|
|
|
typedef RecursiveASTVisitor<ASTPrinter> base;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-28 05:46:50 +08:00
|
|
|
public:
|
2017-03-10 06:00:01 +08:00
|
|
|
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) {}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2014-03-13 14:07:04 +08:00
|
|
|
void HandleTranslationUnit(ASTContext &Context) override {
|
2012-07-27 00:01:23 +08:00
|
|
|
TranslationUnitDecl *D = Context.getTranslationUnitDecl();
|
|
|
|
|
2013-06-24 09:45:33 +08:00
|
|
|
if (FilterString.empty())
|
|
|
|
return print(D);
|
2012-07-27 00:01:23 +08:00
|
|
|
|
|
|
|
TraverseDecl(D);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool shouldWalkTypesOfTypeLocs() const { return false; }
|
|
|
|
|
|
|
|
bool TraverseDecl(Decl *D) {
|
2014-05-22 12:46:25 +08:00
|
|
|
if (D && filterMatches(D)) {
|
2012-11-21 18:54:55 +08:00
|
|
|
bool ShowColors = Out.has_colors();
|
|
|
|
if (ShowColors)
|
2013-01-13 03:30:44 +08:00
|
|
|
Out.changeColor(raw_ostream::BLUE);
|
2017-03-10 06:00:01 +08:00
|
|
|
Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D)
|
2014-08-12 06:11:07 +08:00
|
|
|
<< ":\n";
|
2012-11-21 18:54:55 +08:00
|
|
|
if (ShowColors)
|
|
|
|
Out.resetColor();
|
2013-06-24 09:45:33 +08:00
|
|
|
print(D);
|
2012-08-18 01:38:39 +08:00
|
|
|
Out << "\n";
|
2012-07-27 00:01:23 +08:00
|
|
|
// 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;
|
2007-06-23 08:39:57 +08:00
|
|
|
}
|
2013-06-24 09:45:33 +08:00
|
|
|
void print(Decl *D) {
|
|
|
|
if (DumpLookups) {
|
2014-08-12 06:11:07 +08:00
|
|
|
if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
|
|
|
|
if (DC == DC->getPrimaryContext())
|
2017-03-10 06:00:01 +08:00
|
|
|
DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull);
|
2014-08-12 06:11:07 +08:00
|
|
|
else
|
|
|
|
Out << "Lookup map is in primary DeclContext "
|
|
|
|
<< DC->getPrimaryContext() << "\n";
|
|
|
|
} else
|
2013-06-24 09:45:33 +08:00
|
|
|
Out << "Not a DeclContext\n";
|
2018-05-15 02:41:44 +08:00
|
|
|
} else if (OutputKind == Print) {
|
|
|
|
PrintingPolicy Policy(D->getASTContext().getLangOpts());
|
|
|
|
D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
|
|
|
|
} else if (OutputKind != None)
|
2017-03-10 06:00:01 +08:00
|
|
|
D->dump(Out, OutputKind == DumpFull);
|
2013-06-24 09:45:33 +08:00
|
|
|
}
|
2012-07-27 00:01:23 +08:00
|
|
|
|
|
|
|
raw_ostream &Out;
|
2016-07-15 08:55:40 +08:00
|
|
|
std::unique_ptr<raw_ostream> OwnedOut;
|
2017-03-10 06:00:01 +08:00
|
|
|
|
|
|
|
/// How to output individual declarations.
|
|
|
|
Kind OutputKind;
|
|
|
|
|
|
|
|
/// Which declarations or DeclContexts to display.
|
2012-07-27 00:01:23 +08:00
|
|
|
std::string FilterString;
|
2017-03-10 06:00:01 +08:00
|
|
|
|
|
|
|
/// 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.
|
2013-06-24 09:45:33 +08:00
|
|
|
bool DumpLookups;
|
2007-09-16 07:02:28 +08:00
|
|
|
};
|
2012-07-31 17:37:40 +08:00
|
|
|
|
|
|
|
class ASTDeclNodeLister : public ASTConsumer,
|
|
|
|
public RecursiveASTVisitor<ASTDeclNodeLister> {
|
|
|
|
public:
|
2014-05-22 12:46:25 +08:00
|
|
|
ASTDeclNodeLister(raw_ostream *Out = nullptr)
|
2012-07-31 17:37:40 +08:00
|
|
|
: Out(Out ? *Out : llvm::outs()) {}
|
|
|
|
|
2014-03-13 14:07:04 +08:00
|
|
|
void HandleTranslationUnit(ASTContext &Context) override {
|
2012-07-31 17:37:40 +08:00
|
|
|
TraverseDecl(Context.getTranslationUnitDecl());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool shouldWalkTypesOfTypeLocs() const { return false; }
|
|
|
|
|
2014-03-13 15:14:47 +08:00
|
|
|
bool VisitNamedDecl(NamedDecl *D) {
|
2013-02-23 21:53:57 +08:00
|
|
|
D->printQualifiedName(Out);
|
|
|
|
Out << '\n';
|
2012-07-31 17:37:40 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
raw_ostream &Out;
|
|
|
|
};
|
2009-03-28 13:44:17 +08:00
|
|
|
} // end anonymous namespace
|
2007-08-09 06:51:59 +08:00
|
|
|
|
2016-07-15 08:55:40 +08:00
|
|
|
std::unique_ptr<ASTConsumer>
|
|
|
|
clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
|
|
|
|
StringRef FilterString) {
|
2017-03-10 06:00:01 +08:00
|
|
|
return llvm::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
|
2016-07-15 08:55:40 +08:00
|
|
|
FilterString);
|
2007-11-29 05:32:21 +08:00
|
|
|
}
|
2007-11-28 05:46:50 +08:00
|
|
|
|
Allow the creation of human-friendly ASTDumper to arbitrary output stream
Summary:
`ASTPrinter` allows setting the ouput to any O-Stream, but that printer creates source-code-like syntax (and is also marked with a `FIXME`). The nice, colourful, mostly human-readable `ASTDumper` only works on the standard output, which is not feasible in case a user wants to see the AST of a file through a code navigation/comprehension tool.
This small addition of an overload solves generating a nice colourful AST block for the users of a tool I'm working on, [[ http://github.com/Ericsson/CodeCompass | CodeCompass ]], as opposed to having to duplicate the behaviour of definitions that only exist in the anonymous namespace of implementation TUs related to this module.
Reviewers: alexfh, klimek, rsmith
Reviewed By: alexfh
Subscribers: rnkovacs, dkrupp, gsd, xazax.hun, cfe-commits, #clang
Tags: #clang
Patch by Whisperity!
Differential Revision: https://reviews.llvm.org/D45096
llvm-svn: 329391
2018-04-06 21:01:12 +08:00
|
|
|
std::unique_ptr<ASTConsumer>
|
|
|
|
clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out,
|
|
|
|
StringRef FilterString,
|
|
|
|
bool DumpDecls,
|
|
|
|
bool Deserialize,
|
|
|
|
bool DumpLookups) {
|
2017-06-15 08:00:08 +08:00
|
|
|
assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
|
Allow the creation of human-friendly ASTDumper to arbitrary output stream
Summary:
`ASTPrinter` allows setting the ouput to any O-Stream, but that printer creates source-code-like syntax (and is also marked with a `FIXME`). The nice, colourful, mostly human-readable `ASTDumper` only works on the standard output, which is not feasible in case a user wants to see the AST of a file through a code navigation/comprehension tool.
This small addition of an overload solves generating a nice colourful AST block for the users of a tool I'm working on, [[ http://github.com/Ericsson/CodeCompass | CodeCompass ]], as opposed to having to duplicate the behaviour of definitions that only exist in the anonymous namespace of implementation TUs related to this module.
Reviewers: alexfh, klimek, rsmith
Reviewed By: alexfh
Subscribers: rnkovacs, dkrupp, gsd, xazax.hun, cfe-commits, #clang
Tags: #clang
Patch by Whisperity!
Differential Revision: https://reviews.llvm.org/D45096
llvm-svn: 329391
2018-04-06 21:01:12 +08:00
|
|
|
return llvm::make_unique<ASTPrinter>(std::move(Out),
|
2017-03-10 06:00:01 +08:00
|
|
|
Deserialize ? ASTPrinter::DumpFull :
|
|
|
|
DumpDecls ? ASTPrinter::Dump :
|
|
|
|
ASTPrinter::None,
|
|
|
|
FilterString, DumpLookups);
|
2009-04-26 10:02:08 +08:00
|
|
|
}
|
2007-09-16 07:02:28 +08:00
|
|
|
|
2014-08-11 03:56:51 +08:00
|
|
|
std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
|
|
|
|
return llvm::make_unique<ASTDeclNodeLister>(nullptr);
|
2012-07-31 17:37:40 +08:00
|
|
|
}
|
|
|
|
|
2007-11-28 05:46:50 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// ASTViewer - AST Visualization
|
|
|
|
|
2007-09-20 05:29:43 +08:00
|
|
|
namespace {
|
|
|
|
class ASTViewer : public ASTConsumer {
|
2009-05-30 08:08:05 +08:00
|
|
|
ASTContext *Context;
|
2007-09-20 05:29:43 +08:00
|
|
|
public:
|
2014-03-13 14:07:04 +08:00
|
|
|
void Initialize(ASTContext &Context) override {
|
2009-05-30 08:08:05 +08:00
|
|
|
this->Context = &Context;
|
2007-09-20 05:29:43 +08:00
|
|
|
}
|
2009-03-30 00:50:03 +08:00
|
|
|
|
2014-03-13 14:07:04 +08:00
|
|
|
bool HandleTopLevelDecl(DeclGroupRef D) override {
|
2009-03-30 00:50:03 +08:00
|
|
|
for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
|
|
|
|
HandleTopLevelSingleDecl(*I);
|
2011-11-18 08:26:59 +08:00
|
|
|
return true;
|
2009-03-30 00:50:03 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-30 00:50:03 +08:00
|
|
|
void HandleTopLevelSingleDecl(Decl *D);
|
2007-09-20 05:29:43 +08:00
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2007-09-20 05:29:43 +08:00
|
|
|
|
2009-03-30 00:50:03 +08:00
|
|
|
void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
|
2010-07-07 19:31:23 +08:00
|
|
|
if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
|
|
|
|
D->print(llvm::errs());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-07-07 19:31:23 +08:00
|
|
|
if (Stmt *Body = D->getBody()) {
|
2009-08-23 20:08:50 +08:00
|
|
|
llvm::errs() << '\n';
|
2009-09-12 08:08:48 +08:00
|
|
|
Body->viewAST();
|
2009-08-23 20:08:50 +08:00
|
|
|
llvm::errs() << '\n';
|
2009-03-28 13:44:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-11 03:56:51 +08:00
|
|
|
std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
|
|
|
|
return llvm::make_unique<ASTViewer>();
|
|
|
|
}
|