summaryrefslogtreecommitdiffstats
path: root/lib/Tooling
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2011-05-31 23:49:32 +0000
committerManuel Klimek <klimek@google.com>2011-05-31 23:49:32 +0000
commit64cbdf370984783911bb6d3bc25ec35a8b59e998 (patch)
treed9f1e5c11584852365aeef877c1f1a36db5548e3 /lib/Tooling
parentd65e091631cc521fcb95a16d6587c0fed8b7164b (diff)
This patch implements an AST matching framework that allows to write
tools that match on the C++ ASTs. The main interface is in ASTMatchers.h, an example implementation of a tool that removes redundant .c_str() calls is in the example RemoveCStrCalls.cpp. Various contributions: Zhanyong Wan, Chandler Carruth, Marcin Kowalczyk, Wei Xu, James Dennett. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132374 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Tooling')
-rw-r--r--lib/Tooling/ASTMatchers.cpp564
-rw-r--r--lib/Tooling/CMakeLists.txt1
-rw-r--r--lib/Tooling/Tooling.cpp60
3 files changed, 595 insertions, 30 deletions
diff --git a/lib/Tooling/ASTMatchers.cpp b/lib/Tooling/ASTMatchers.cpp
new file mode 100644
index 0000000000..f03580ea34
--- /dev/null
+++ b/lib/Tooling/ASTMatchers.cpp
@@ -0,0 +1,564 @@
+//===--- ASTMatchers.cpp - Structural query framework ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a framework of AST matchers that can be used to express
+// structural queries on C++ code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Tooling/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/DenseMap.h"
+#include <assert.h>
+#include <stddef.h>
+#include <set>
+#include <utility>
+
+namespace clang {
+namespace tooling {
+
+// Returns the value that 'a_map' maps 'key' to, or NULL if 'key' is
+// not in 'a_map'.
+template <typename Map>
+static const typename Map::mapped_type *Find(
+ const Map &AMap, const typename Map::key_type &Key) {
+ typename Map::const_iterator It = AMap.find(Key);
+ return It == AMap.end() ? NULL : &It->second;
+}
+
+// We use memoization to avoid running the same matcher on the same
+// AST node twice. This pair is the key for looking up match
+// result. It consists of an ID of the MatcherInterface (for
+// identifying the matcher) and a pointer to the AST node.
+typedef std::pair<uint64_t, const void*> UntypedMatchInput;
+
+// Used to store the result of a match and possibly bound nodes.
+struct MemoizedMatchResult {
+ bool ResultOfMatch;
+ BoundNodes Nodes;
+};
+
+// A RecursiveASTVisitor that traverses all children or all descendants of
+// a node.
+class MatchChildASTVisitor
+ : public clang::RecursiveASTVisitor<MatchChildASTVisitor> {
+ public:
+ typedef clang::RecursiveASTVisitor<MatchChildASTVisitor> VisitorBase;
+
+ // Creates an AST visitor that matches 'matcher' on all children or
+ // descendants of a traversed node. max_depth is the maximum depth
+ // to traverse: use 1 for matching the children and INT_MAX for
+ // matching the descendants.
+ MatchChildASTVisitor(const UntypedBaseMatcher *BaseMatcher,
+ ASTMatchFinder *Finder,
+ BoundNodesBuilder *Builder,
+ int MaxDepth,
+ ASTMatchFinder::TraversalMethod Traversal)
+ : BaseMatcher(BaseMatcher),
+ Finder(Finder),
+ Builder(Builder),
+ CurrentDepth(-1),
+ MaxDepth(MaxDepth),
+ Traversal(Traversal),
+ Matches(false) {}
+
+ // Returns true if a match is found in the subtree rooted at the
+ // given AST node. This is done via a set of mutually recursive
+ // functions. Here's how the recursion is done (the *wildcard can
+ // actually be Decl, Stmt, or Type):
+ //
+ // - Traverse(node) calls BaseTraverse(node) when it needs
+ // to visit the descendants of node.
+ // - BaseTraverse(node) then calls (via VisitorBase::Traverse*(node))
+ // Traverse*(c) for each child c of 'node'.
+ // - Traverse*(c) in turn calls Traverse(c), completing the
+ // recursion.
+ template <typename T>
+ bool FindMatch(const T &Node) {
+ Reset();
+ Traverse(Node);
+ return Matches;
+ }
+
+ // The following are overriding methods from the base visitor class.
+ // They are public only to allow CRTP to work. They are *not *part
+ // of the public API of this class.
+ bool TraverseDecl(clang::Decl *DeclNode) {
+ return (DeclNode == NULL) || Traverse(*DeclNode);
+ }
+ bool TraverseStmt(clang::Stmt *StmtNode) {
+ const clang::Stmt *StmtToTraverse = StmtNode;
+ if (Traversal ==
+ ASTMatchFinder::kIgnoreImplicitCastsAndParentheses) {
+ const clang::Expr *ExprNode = dyn_cast_or_null<clang::Expr>(StmtNode);
+ if (ExprNode != NULL) {
+ StmtToTraverse = ExprNode->IgnoreParenImpCasts();
+ }
+ }
+ return (StmtToTraverse == NULL) || Traverse(*StmtToTraverse);
+ }
+ bool TraverseType(clang::QualType TypeNode) {
+ return Traverse(TypeNode);
+ }
+
+ bool shouldVisitTemplateInstantiations() const { return true; }
+
+ private:
+ // Resets the state of this object.
+ void Reset() {
+ Matches = false;
+ CurrentDepth = -1;
+ }
+
+ // Forwards the call to the corresponding Traverse*() method in the
+ // base visitor class.
+ bool BaseTraverse(const clang::Decl &DeclNode) {
+ return VisitorBase::TraverseDecl(const_cast<clang::Decl*>(&DeclNode));
+ }
+ bool BaseTraverse(const clang::Stmt &StmtNode) {
+ return VisitorBase::TraverseStmt(const_cast<clang::Stmt*>(&StmtNode));
+ }
+ bool BaseTraverse(clang::QualType TypeNode) {
+ return VisitorBase::TraverseType(TypeNode);
+ }
+
+ // Traverses the subtree rooted at 'node'; returns true if the
+ // traversal should continue after this function returns; also sets
+ // matched_ to true if a match is found during the traversal.
+ template <typename T>
+ bool Traverse(const T &Node) {
+ COMPILE_ASSERT(IsBaseType<T>::value,
+ traverse_can_only_be_instantiated_with_base_type);
+ ++CurrentDepth;
+ bool ShouldContinue;
+ if (CurrentDepth == 0) {
+ // We don't want to match the root node, so just recurse.
+ ShouldContinue = BaseTraverse(Node);
+ } else if (BaseMatcher->Matches(Node, Finder, Builder)) {
+ Matches = true;
+ ShouldContinue = false; // Abort as soon as a match is found.
+ } else if (CurrentDepth < MaxDepth) {
+ // The current node doesn't match, and we haven't reached the
+ // maximum depth yet, so recurse.
+ ShouldContinue = BaseTraverse(Node);
+ } else {
+ // The current node doesn't match, and we have reached the
+ // maximum depth, so don't recurse (but continue the traversal
+ // such that other nodes at the current level can be visited).
+ ShouldContinue = true;
+ }
+ --CurrentDepth;
+ return ShouldContinue;
+ }
+
+ const UntypedBaseMatcher *const BaseMatcher;
+ ASTMatchFinder *const Finder;
+ BoundNodesBuilder *const Builder;
+ int CurrentDepth;
+ const int MaxDepth;
+ const ASTMatchFinder::TraversalMethod Traversal;
+ bool Matches;
+};
+
+// Controls the outermost traversal of the AST and allows to match multiple
+// matchers.
+class MatchASTVisitor : public clang::RecursiveASTVisitor<MatchASTVisitor>,
+ public ASTMatchFinder {
+ public:
+ MatchASTVisitor(std::vector< std::pair<const UntypedBaseMatcher*,
+ MatchFinder::MatchCallback*> > *Triggers,
+ clang::SourceManager *VisitorSourceManager,
+ clang::LangOptions *LanguageOptions)
+ : Triggers(Triggers),
+ VisitorSourceManager(VisitorSourceManager),
+ LanguageOptions(LanguageOptions),
+ ActiveASTContext(NULL) {
+ assert(VisitorSourceManager != NULL);
+ assert(LanguageOptions != NULL);
+ // FIXME: add rewriter_(*source_manager, *language_options)
+ }
+
+ void set_active_ast_context(clang::ASTContext *NewActiveASTContext) {
+ ActiveASTContext = NewActiveASTContext;
+ }
+
+ // The following Visit*() and Traverse*() functions "override"
+ // methods in RecursiveASTVisitor.
+
+ bool VisitTypedefDecl(clang::TypedefDecl *DeclNode) {
+ // When we see 'typedef A B', we add name 'B' to the set of names
+ // A's canonical type maps to. This is necessary for implementing
+ // IsDerivedFrom(x) properly, where x can be the name of the base
+ // class or any of its aliases.
+ //
+ // In general, the is-alias-of (as defined by typedefs) relation
+ // is tree-shaped, as you can typedef a type more than once. For
+ // example,
+ //
+ // typedef A B;
+ // typedef A C;
+ // typedef C D;
+ // typedef C E;
+ //
+ // gives you
+ //
+ // A
+ // |- B
+ // `- C
+ // |- D
+ // `- E
+ //
+ // It is wrong to assume that the relation is a chain. A correct
+ // implementation of IsDerivedFrom() needs to recognize that B and
+ // E are aliases, even though neither is a typedef of the other.
+ // Therefore, we cannot simply walk through one typedef chain to
+ // find out whether the type name matches.
+ const clang::Type *TypeNode = DeclNode->getUnderlyingType().getTypePtr();
+ const clang::Type *CanonicalType = // root of the typedef tree
+ ActiveASTContext->getCanonicalType(TypeNode);
+ TypeToUnqualifiedAliases[CanonicalType].insert(
+ DeclNode->getName().str());
+ return true;
+ }
+
+ bool TraverseDecl(clang::Decl *DeclNode);
+ bool TraverseStmt(clang::Stmt *StmtNode);
+ bool TraverseType(clang::QualType TypeNode);
+ bool TraverseTypeLoc(clang::TypeLoc TypeNode);
+
+ // Matches children or descendants of 'Node' with 'BaseMatcher'.
+ template <typename T>
+ bool MemoizedMatchesRecursively(
+ const T &Node, const UntypedBaseMatcher &BaseMatcher,
+ BoundNodesBuilder *Builder, int MaxDepth,
+ TraversalMethod Traversal) {
+ COMPILE_ASSERT((llvm::is_same<T, clang::Decl>::value) ||
+ (llvm::is_same<T, clang::Stmt>::value),
+ type_does_not_support_memoization);
+ const UntypedMatchInput input(BaseMatcher.GetID(), &Node);
+ std::pair <MemoizationMap::iterator, bool>
+ InsertResult = ResultCache.insert(
+ std::make_pair(input, MemoizedMatchResult()));
+ if (InsertResult.second) {
+ BoundNodesBuilder DescendantBoundNodesBuilder;
+ InsertResult.first->second.ResultOfMatch =
+ MatchesRecursively(Node, BaseMatcher, &DescendantBoundNodesBuilder,
+ MaxDepth, Traversal);
+ InsertResult.first->second.Nodes =
+ DescendantBoundNodesBuilder.Build();
+ }
+ InsertResult.first->second.Nodes.CopyTo(Builder);
+ return InsertResult.first->second.ResultOfMatch;
+ }
+
+ // Matches children or descendants of 'Node' with 'BaseMatcher'.
+ template <typename T>
+ bool MatchesRecursively(
+ const T &Node, const UntypedBaseMatcher &BaseMatcher,
+ BoundNodesBuilder *Builder, int MaxDepth,
+ TraversalMethod Traversal) {
+ MatchChildASTVisitor Visitor(
+ &BaseMatcher, this, Builder, MaxDepth, Traversal);
+ return Visitor.FindMatch(Node);
+ }
+
+ virtual bool ClassIsDerivedFrom(const clang::CXXRecordDecl *Declaration,
+ const std::string &BaseName) const;
+
+ // Implements ASTMatchFinder::MatchesChildOf.
+ virtual bool MatchesChildOf(const clang::Decl &DeclNode,
+ const UntypedBaseMatcher &BaseMatcher,
+ BoundNodesBuilder *Builder,
+ TraversalMethod Traversal) {
+ return MatchesRecursively(
+ DeclNode, BaseMatcher, Builder, 1, Traversal);
+ }
+ virtual bool MatchesChildOf(const clang::Stmt &StmtNode,
+ const UntypedBaseMatcher &BaseMatcher,
+ BoundNodesBuilder *Builder,
+ TraversalMethod Traversal) {
+ return MatchesRecursively(
+ StmtNode, BaseMatcher, Builder, 1, Traversal);
+ }
+
+ // Implements ASTMatchFinder::MatchesDescendantOf.
+ virtual bool MatchesDescendantOf(const clang::Decl &DeclNode,
+ const UntypedBaseMatcher &BaseMatcher,
+ BoundNodesBuilder *Builder) {
+ return MemoizedMatchesRecursively(
+ DeclNode, BaseMatcher, Builder, INT_MAX, kAsIs);
+ }
+ virtual bool MatchesDescendantOf(const clang::Stmt &StmtNode,
+ const UntypedBaseMatcher &BaseMatcher,
+ BoundNodesBuilder *Builder) {
+ return MemoizedMatchesRecursively(
+ StmtNode, BaseMatcher, Builder, INT_MAX, kAsIs);
+ }
+
+ bool shouldVisitTemplateInstantiations() const { return true; }
+
+ private:
+ // Returns true if 'TypeNode' is also known by the name 'Name'. In other
+ // words, there is a type (including typedef) with the name 'Name'
+ // that is equal to 'TypeNode'.
+ bool TypeHasAlias(
+ const clang::Type *TypeNode, const std::string &Name) const {
+ const clang::Type *const CanonicalType =
+ ActiveASTContext->getCanonicalType(TypeNode);
+ const std::set<std::string> *UnqualifiedAlias =
+ Find(TypeToUnqualifiedAliases, CanonicalType);
+ return UnqualifiedAlias != NULL && UnqualifiedAlias->count(Name) > 0;
+ }
+
+ // Matches all registered matchers on the given node and calls the
+ // result callback for every node that matches.
+ template <typename T>
+ void Match(const T &node) {
+ for (std::vector< std::pair<const UntypedBaseMatcher*,
+ MatchFinder::MatchCallback*> >::const_iterator
+ It = Triggers->begin(), End = Triggers->end();
+ It != End; ++It) {
+ BoundNodesBuilder Builder;
+ if (It->first->Matches(node, this, &Builder)) {
+ MatchFinder::MatchResult Result;
+ Result.Nodes = Builder.Build();
+ Result.Context = ActiveASTContext;
+ Result.SourceManager = VisitorSourceManager;
+ It->second->Run(Result);
+ }
+ }
+ }
+
+ std::vector< std::pair<const UntypedBaseMatcher*,
+ MatchFinder::MatchCallback*> > *const Triggers;
+ clang::SourceManager *const VisitorSourceManager;
+ clang::LangOptions *const LanguageOptions;
+ clang::ASTContext *ActiveASTContext;
+
+ // Maps a canonical type to the names of its typedefs.
+ llvm::DenseMap<const clang::Type*, std::set<std::string> >
+ TypeToUnqualifiedAliases;
+
+ // Maps (matcher, node) -> the match result for memoization.
+ typedef llvm::DenseMap<UntypedMatchInput, MemoizedMatchResult> MemoizationMap;
+ MemoizationMap ResultCache;
+};
+
+// Returns true if the given class is directly or indirectly derived
+// from a base type with the given name. A class is considered to be
+// also derived from itself.
+bool MatchASTVisitor::ClassIsDerivedFrom(
+ const clang::CXXRecordDecl *Declaration,
+ const std::string &BaseName) const {
+ if (std::string(Declaration->getName()) == BaseName) {
+ return true;
+ }
+ if (!Declaration->hasDefinition()) {
+ return false;
+ }
+ typedef clang::CXXRecordDecl::base_class_const_iterator BaseIterator;
+ for (BaseIterator It = Declaration->bases_begin(),
+ End = Declaration->bases_end(); It != End; ++It) {
+ const clang::Type *TypeNode = It->getType().getTypePtr();
+
+ if (TypeHasAlias(TypeNode, BaseName))
+ return true;
+
+ // clang::Type::getAs<...>() drills through typedefs.
+ if (TypeNode->getAs<clang::DependentNameType>() != NULL ||
+ TypeNode->getAs<clang::TemplateTypeParmType>() != NULL) {
+ // Dependent names and template TypeNode parameters will be matched when
+ // the template is instantiated.
+ continue;
+ }
+ clang::CXXRecordDecl *ClassDecl = NULL;
+ clang::TemplateSpecializationType const *TemplateType =
+ TypeNode->getAs<clang::TemplateSpecializationType>();
+ if (TemplateType != NULL) {
+ if (TemplateType->getTemplateName().isDependent()) {
+ // Dependent template specializations will be matched when the
+ // template is instantiated.
+ continue;
+ }
+ // For template specialization types which are specializing a template
+ // declaration which is an explicit or partial specialization of another
+ // template declaration, getAsCXXRecordDecl() returns the corresponding
+ // ClassTemplateSpecializationDecl.
+ //
+ // For template specialization types which are specializing a template
+ // declaration which is neither an explicit nor partial specialization of
+ // another template declaration, getAsCXXRecordDecl() returns NULL and
+ // we get the CXXRecordDecl of the templated declaration.
+ clang::CXXRecordDecl *SpecializationDecl =
+ TemplateType->getAsCXXRecordDecl();
+ if (SpecializationDecl != NULL) {
+ ClassDecl = SpecializationDecl;
+ } else {
+ ClassDecl = llvm::dyn_cast<clang::CXXRecordDecl>(
+ TemplateType->getTemplateName()
+ .getAsTemplateDecl()->getTemplatedDecl());
+ }
+ } else {
+ ClassDecl = TypeNode->getAsCXXRecordDecl();
+ }
+ assert(ClassDecl != NULL);
+ assert(ClassDecl != Declaration);
+ if (ClassIsDerivedFrom(ClassDecl, BaseName)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool MatchASTVisitor::TraverseDecl(clang::Decl *DeclNode) {
+ if (DeclNode == NULL) {
+ return true;
+ }
+ Match(*DeclNode);
+ return clang::RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
+}
+
+bool MatchASTVisitor::TraverseStmt(clang::Stmt *StmtNode) {
+ if (StmtNode == NULL) {
+ return true;
+ }
+ Match(*StmtNode);
+ return clang::RecursiveASTVisitor<MatchASTVisitor>::TraverseStmt(StmtNode);
+}
+
+bool MatchASTVisitor::TraverseType(clang::QualType TypeNode) {
+ Match(TypeNode);
+ return clang::RecursiveASTVisitor<MatchASTVisitor>::TraverseType(TypeNode);
+}
+
+bool MatchASTVisitor::TraverseTypeLoc(clang::TypeLoc TypeLoc) {
+ return clang::RecursiveASTVisitor<MatchASTVisitor>::
+ TraverseType(TypeLoc.getType());
+}
+
+class MatchASTConsumer : public clang::ASTConsumer {
+ public:
+ MatchASTConsumer(std::vector< std::pair<const UntypedBaseMatcher*,
+ MatchFinder::MatchCallback*> > *Triggers,
+ MatchFinder::ParsingDoneTestCallback *ParsingDone,
+ clang::SourceManager *ConsumerSourceManager,
+ clang::LangOptions *LanaguageOptions)
+ : Visitor(Triggers, ConsumerSourceManager, LanaguageOptions),
+ ParsingDone(ParsingDone) {}
+
+ private:
+ virtual void HandleTranslationUnit(
+ clang::ASTContext &Context) { // NOLINT: external API uses refs
+ if (ParsingDone != NULL) {
+ ParsingDone->Run();
+ }
+ Visitor.set_active_ast_context(&Context);
+ Visitor.TraverseDecl(Context.getTranslationUnitDecl());
+ Visitor.set_active_ast_context(NULL);
+ }
+
+ MatchASTVisitor Visitor;
+ MatchFinder::ParsingDoneTestCallback *ParsingDone;
+};
+
+class MatchASTAction : public clang::ASTFrontendAction {
+ public:
+ explicit MatchASTAction(
+ std::vector< std::pair<const UntypedBaseMatcher*,
+ MatchFinder::MatchCallback*> > *Triggers,
+ MatchFinder::ParsingDoneTestCallback *ParsingDone)
+ : Triggers(Triggers),
+ ParsingDone(ParsingDone) {}
+
+ private:
+ clang::ASTConsumer *CreateASTConsumer(
+ clang::CompilerInstance &Compiler,
+ llvm::StringRef) {
+ return new MatchASTConsumer(Triggers,
+ ParsingDone,
+ &Compiler.getSourceManager(),
+ &Compiler.getLangOpts());
+ }
+
+ std::vector< std::pair<const UntypedBaseMatcher*,
+ MatchFinder::MatchCallback*> > *const Triggers;
+ MatchFinder::ParsingDoneTestCallback *ParsingDone;
+};
+
+MatchFinder::MatchCallback::~MatchCallback() {}
+MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
+
+MatchFinder::MatchFinder() : ParsingDone(NULL) {}
+
+MatchFinder::~MatchFinder() {
+ for (std::vector< std::pair<const UntypedBaseMatcher*,
+ MatchFinder::MatchCallback*> >::const_iterator
+ It = Triggers.begin(), End = Triggers.end();
+ It != End; ++It) {
+ delete It->first;
+ delete It->second;
+ }
+}
+
+void MatchFinder::AddMatcher(const Matcher<clang::Decl> &NodeMatch,
+ MatchCallback *Action) {
+ Triggers.push_back(std::make_pair(
+ new TypedBaseMatcher<clang::Decl>(NodeMatch), Action));
+}
+
+void MatchFinder::AddMatcher(const Matcher<clang::QualType> &NodeMatch,
+ MatchCallback *Action) {
+ Triggers.push_back(std::make_pair(
+ new TypedBaseMatcher<clang::QualType>(NodeMatch), Action));
+}
+
+void MatchFinder::AddMatcher(const Matcher<clang::Stmt> &NodeMatch,
+ MatchCallback *Action) {
+ Triggers.push_back(std::make_pair(
+ new TypedBaseMatcher<clang::Stmt>(NodeMatch), Action));
+}
+
+bool MatchFinder::FindAll(const std::string &Code) {
+ return RunSyntaxOnlyToolOnCode(
+ new MatchASTAction(&Triggers, ParsingDone), Code);
+}
+
+clang::FrontendAction *MatchFinder::NewVisitorAction() {
+ return new MatchASTAction(&Triggers, ParsingDone);
+}
+
+class MatchFinderFrontendActionFactory : public FrontendActionFactory {
+ public:
+ explicit MatchFinderFrontendActionFactory(MatchFinder *Finder)
+ : Finder(Finder) {}
+
+ virtual clang::FrontendAction *New() {
+ return Finder->NewVisitorAction();
+ }
+
+ private:
+ MatchFinder *const Finder;
+};
+
+FrontendActionFactory *MatchFinder::NewFrontendActionFactory() {
+ return new MatchFinderFrontendActionFactory(this);
+}
+
+void MatchFinder::RegisterTestCallbackAfterParsing(
+ MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
+ ParsingDone = NewParsingDone;
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/lib/Tooling/CMakeLists.txt b/lib/Tooling/CMakeLists.txt
index f52cf6c891..0a0020a555 100644
--- a/lib/Tooling/CMakeLists.txt
+++ b/lib/Tooling/CMakeLists.txt
@@ -1,6 +1,7 @@
SET(LLVM_USED_LIBS clangBasic clangFrontend clangAST)
add_clang_library(clangTooling
+ ASTMatchers.cpp
JsonCompileCommandLineDatabase.cpp
Tooling.cpp
)
diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp
index 9cc92f1ae6..97a9463852 100644
--- a/lib/Tooling/Tooling.cpp
+++ b/lib/Tooling/Tooling.cpp
@@ -1,4 +1,4 @@
-//===--- Tooling.cpp - Running clang standalone tools --------------------===//
+//===--- Tooling.cpp - Running clang standalone tools ---------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -44,7 +44,7 @@ namespace {
// - it must contain at least a program path,
// - argv[0], ..., and argv[argc - 1] mustn't be NULL, and
// - argv[argc] must be NULL.
-void ValidateArgv(int argc, char* argv[]) {
+void ValidateArgv(int argc, char *argv[]) {
if (argc < 1) {
fprintf(stderr, "ERROR: argc is %d. It must be >= 1.\n", argc);
abort();
@@ -69,7 +69,7 @@ void ValidateArgv(int argc, char* argv[]) {
// code that sets up a compiler to run tools on it, and we should refactor
// it to be based on the same framework.
-static clang::Diagnostic* NewTextDiagnostics() {
+static clang::Diagnostic *NewTextDiagnostics() {
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(
new clang::DiagnosticIDs());
clang::TextDiagnosticPrinter *DiagClient = new clang::TextDiagnosticPrinter(
@@ -81,15 +81,15 @@ static clang::Diagnostic* NewTextDiagnostics() {
static int StaticSymbol;
/// \brief Builds a clang driver initialized for running clang tools.
-static clang::driver::Driver* NewDriver(clang::Diagnostic* Diagnostics,
- const char* BinaryName) {
+static clang::driver::Driver *NewDriver(clang::Diagnostic *Diagnostics,
+ const char *BinaryName) {
// This just needs to be some symbol in the binary.
- void* const SymbolAddr = &StaticSymbol;
+ void *const SymbolAddr = &StaticSymbol;
const llvm::sys::Path ExePath =
llvm::sys::Path::GetMainExecutable(BinaryName, SymbolAddr);
const std::string DefaultOutputName = "a.out";
- clang::driver::Driver* CompilerDriver = new clang::driver::Driver(
+ clang::driver::Driver *CompilerDriver = new clang::driver::Driver(
ExePath.str(), llvm::sys::getHostTriple(),
DefaultOutputName, false, false, *Diagnostics);
CompilerDriver->setTitle("clang_based_tool");
@@ -98,8 +98,8 @@ static clang::driver::Driver* NewDriver(clang::Diagnostic* Diagnostics,
/// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs.
/// Returns NULL on error.
-static const clang::driver::ArgStringList* GetCC1Arguments(
- clang::Diagnostic* Diagnostics, clang::driver::Compilation* Compilation) {
+static const clang::driver::ArgStringList *GetCC1Arguments(
+ clang::Diagnostic *Diagnostics, clang::driver::Compilation *Compilation) {
// We expect to get back exactly one Command job, if we didn't something
// failed. Extract that job from the Compilation.
const clang::driver::JobList &Jobs = Compilation->getJobs();
@@ -124,10 +124,10 @@ static const clang::driver::ArgStringList* GetCC1Arguments(
}
/// \brief Returns a clang build invocation initialized from the CC1 flags.
-static clang::CompilerInvocation* NewInvocation(
- clang::Diagnostic* Diagnostics,
- const clang::driver::ArgStringList& CC1Args) {
- clang::CompilerInvocation* Invocation = new clang::CompilerInvocation;
+static clang::CompilerInvocation *NewInvocation(
+ clang::Diagnostic *Diagnostics,
+ const clang::driver::ArgStringList &CC1Args) {
+ clang::CompilerInvocation *Invocation = new clang::CompilerInvocation;
clang::CompilerInvocation::CreateFromArgs(
*Invocation, CC1Args.data(), CC1Args.data() + CC1Args.size(),
*Diagnostics);
@@ -137,11 +137,11 @@ static clang::CompilerInvocation* NewInvocation(
/// \brief Runs the specified clang tool action and returns whether it executed
/// successfully.
-static bool RunInvocation(const char* BinaryName,
- clang::driver::Compilation* Compilation,
- clang::CompilerInvocation* Invocation,
- const clang::driver::ArgStringList& CC1Args,
- clang::FrontendAction* ToolAction) {
+static bool RunInvocation(const char *BinaryName,
+ clang::driver::Compilation *Compilation,
+ clang::CompilerInvocation *Invocation,
+ const clang::driver::ArgStringList &CC1Args,
+ clang::FrontendAction *ToolAction) {
llvm::OwningPtr<clang::FrontendAction> ScopedToolAction(ToolAction);
// Show the invocation, with -v.
if (Invocation->getHeaderSearchOpts().Verbose) {
@@ -164,7 +164,7 @@ static bool RunInvocation(const char* BinaryName,
if (Compiler.getHeaderSearchOpts().UseBuiltinIncludes &&
Compiler.getHeaderSearchOpts().ResourceDir.empty()) {
// This just needs to be some symbol in the binary.
- void* const SymbolAddr = &StaticSymbol;
+ void *const SymbolAddr = &StaticSymbol;
Compiler.getHeaderSearchOpts().ResourceDir =
clang::CompilerInvocation::GetResourcesPath(BinaryName, SymbolAddr);
}
@@ -175,7 +175,7 @@ static bool RunInvocation(const char* BinaryName,
/// \brief Converts a string vector representing a Command line into a C
/// string vector representing the Argv (including the trailing NULL).
-std::vector<char*> CommandLineToArgv(const std::vector<std::string>* Command) {
+std::vector<char*> CommandLineToArgv(const std::vector<std::string> *Command) {
std::vector<char*> Result(Command->size() + 1);
for (std::vector<char*>::size_type I = 0; I < Command->size(); ++I) {
Result[I] = const_cast<char*>((*Command)[I].c_str());
@@ -185,14 +185,14 @@ std::vector<char*> CommandLineToArgv(const std::vector<std::string>* Command) {
}
bool RunToolWithFlags(
- clang::FrontendAction* ToolAction, int Args, char* Argv[]) {
+ clang::FrontendAction *ToolAction, int Args, char *Argv[]) {
ValidateArgv(Args, Argv);
const llvm::OwningPtr<clang::Diagnostic> Diagnostics(NewTextDiagnostics());
const llvm::OwningPtr<clang::driver::Driver> Driver(
NewDriver(Diagnostics.get(), Argv[0]));
const llvm::OwningPtr<clang::driver::Compilation> Compilation(
Driver->BuildCompilation(llvm::ArrayRef<const char*>(Argv, Args)));
- const clang::driver::ArgStringList* const CC1Args = GetCC1Arguments(
+ const clang::driver::ArgStringList *const CC1Args = GetCC1Arguments(
Diagnostics.get(), Compilation.get());
if (CC1Args == NULL) {
return false;
@@ -208,11 +208,11 @@ bool RunToolWithFlags(
/// \param FileContents A mapping from file name to source code. For each
/// entry a virtual file mapping will be created when running the tool.
bool RunToolWithFlagsOnCode(
- const std::vector<std::string>& CommandLine,
- const std::map<std::string, std::string>& FileContents,
- clang::FrontendAction* ToolAction) {
+ const std::vector<std::string> &CommandLine,
+ const std::map<std::string, std::string> &FileContents,
+ clang::FrontendAction *ToolAction) {
const std::vector<char*> Argv = CommandLineToArgv(&CommandLine);
- const char* const BinaryName = Argv[0];
+ const char *const BinaryName = Argv[0];
const llvm::OwningPtr<clang::Diagnostic> Diagnostics(NewTextDiagnostics());
const llvm::OwningPtr<clang::driver::Driver> Driver(
@@ -224,7 +224,7 @@ bool RunToolWithFlagsOnCode(
const llvm::OwningPtr<clang::driver::Compilation> Compilation(
Driver->BuildCompilation(llvm::ArrayRef<const char*>(&Argv[0],
Argv.size() - 1)));
- const clang::driver::ArgStringList* const CC1Args = GetCC1Arguments(
+ const clang::driver::ArgStringList *const CC1Args = GetCC1Arguments(
Diagnostics.get(), Compilation.get());
if (CC1Args == NULL) {
return false;
@@ -236,7 +236,7 @@ bool RunToolWithFlagsOnCode(
It = FileContents.begin(), End = FileContents.end();
It != End; ++It) {
// Inject the code as the given file name into the preprocessor options.
- const llvm::MemoryBuffer* Input =
+ const llvm::MemoryBuffer *Input =
llvm::MemoryBuffer::getMemBuffer(It->second.c_str());
Invocation->getPreprocessorOpts().addRemappedFile(It->first.c_str(), Input);
}
@@ -247,8 +247,8 @@ bool RunToolWithFlagsOnCode(
bool RunSyntaxOnlyToolOnCode(
clang::FrontendAction *ToolAction, llvm::StringRef Code) {
- const char* const FileName = "input.cc";
- const char* const CommandLine[] = {
+ const char *const FileName = "input.cc";
+ const char *const CommandLine[] = {
"clang-tool", "-fsyntax-only", FileName
};
std::map<std::string, std::string> FileContents;