From 4da216637fa1ad4bdfd31bc265edb57ca35c2c12 Mon Sep 17 00:00:00 2001 From: Manuel Klimek Date: Fri, 6 Jul 2012 05:48:52 +0000 Subject: [PATCH] Adds the AST Matcher library, which provides a in-C++ DSL to express matches on interesting parts of the AST, and callback mechanisms to act on them. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159805 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/ASTMatchers/ASTMatchFinder.h | 141 ++ include/clang/ASTMatchers/ASTMatchers.h | 1403 ++++++++++++ .../clang/ASTMatchers/ASTMatchersInternal.h | 888 ++++++++ include/clang/ASTMatchers/ASTMatchersMacros.h | 224 ++ lib/ASTMatchers/ASTMatchFinder.cpp | 556 +++++ lib/ASTMatchers/ASTMatchersInternal.cpp | 102 + lib/ASTMatchers/CMakeLists.txt | 7 + lib/ASTMatchers/Makefile | 15 + lib/CMakeLists.txt | 1 + lib/Makefile | 2 +- unittests/ASTMatchers/ASTMatchersTest.cpp | 1979 +++++++++++++++++ unittests/ASTMatchers/ASTMatchersTest.h | 128 ++ unittests/ASTMatchers/CMakeLists.txt | 5 + unittests/ASTMatchers/Makefile | 19 + unittests/CMakeLists.txt | 1 + unittests/Makefile | 2 +- 16 files changed, 5471 insertions(+), 2 deletions(-) create mode 100644 include/clang/ASTMatchers/ASTMatchFinder.h create mode 100644 include/clang/ASTMatchers/ASTMatchers.h create mode 100644 include/clang/ASTMatchers/ASTMatchersInternal.h create mode 100644 include/clang/ASTMatchers/ASTMatchersMacros.h create mode 100644 lib/ASTMatchers/ASTMatchFinder.cpp create mode 100644 lib/ASTMatchers/ASTMatchersInternal.cpp create mode 100644 lib/ASTMatchers/CMakeLists.txt create mode 100644 lib/ASTMatchers/Makefile create mode 100644 unittests/ASTMatchers/ASTMatchersTest.cpp create mode 100644 unittests/ASTMatchers/ASTMatchersTest.h create mode 100644 unittests/ASTMatchers/CMakeLists.txt create mode 100644 unittests/ASTMatchers/Makefile diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h new file mode 100644 index 0000000000..dd237eece3 --- /dev/null +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -0,0 +1,141 @@ +//===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Provides a way to construct an ASTConsumer that runs given matchers +// over the AST and invokes a given callback on every match. +// +// The general idea is to construct a matcher expression that describes a +// subtree match on the AST. Next, a callback that is executed every time the +// expression matches is registered, and the matcher is run over the AST of +// some code. Matched subexpressions can be bound to string IDs and easily +// be accessed from the registered callback. The callback can than use the +// AST nodes that the subexpressions matched on to output information about +// the match or construct changes that can be applied to the code. +// +// Example: +// class HandleMatch : public MatchFinder::MatchCallback { +// public: +// virtual void Run(const MatchFinder::MatchResult &Result) { +// const CXXRecordDecl *Class = +// Result.Nodes.GetDeclAs("id"); +// ... +// } +// }; +// +// int main(int argc, char **argv) { +// ClangTool Tool(argc, argv); +// MatchFinder finder; +// finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))), +// new HandleMatch); +// return Tool.Run(newFrontendActionFactory(&finder)); +// } +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H +#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H + +#include "clang/ASTMatchers/ASTMatchers.h" + +namespace clang { + +namespace ast_matchers { + +/// \brief A class to allow finding matches over the Clang AST. +/// +/// After creation, you can add multiple matchers to the MatchFinder via +/// calls to addMatcher(...). +/// +/// Once all matchers are added, newASTConsumer() returns an ASTConsumer +/// that will trigger the callbacks specified via addMatcher(...) when a match +/// is found. +/// +/// See ASTMatchers.h for more information about how to create matchers. +/// +/// Not intended to be subclassed. +class MatchFinder { +public: + /// \brief Contains all information for a given match. + /// + /// Every time a match is found, the MatchFinder will invoke the registered + /// MatchCallback with a MatchResult containing information about the match. + struct MatchResult { + MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context); + + /// \brief Contains the nodes bound on the current match. + /// + /// This allows user code to easily extract matched AST nodes. + const BoundNodes Nodes; + + /// \brief Utilities for interpreting the matched AST structures. + /// @{ + clang::ASTContext * const Context; + clang::SourceManager * const SourceManager; + /// @} + }; + + /// \brief Called when the Match registered for it was successfully found + /// in the AST. + class MatchCallback { + public: + virtual ~MatchCallback(); + virtual void run(const MatchResult &Result) = 0; + }; + + /// \brief Called when parsing is finished. Intended for testing only. + class ParsingDoneTestCallback { + public: + virtual ~ParsingDoneTestCallback(); + virtual void run() = 0; + }; + + MatchFinder(); + ~MatchFinder(); + + /// \brief Adds a matcher to execute when running over the AST. + /// + /// Calls 'Action' with the BoundNodes on every match. + /// Adding more than one 'NodeMatch' allows finding different matches in a + /// single pass over the AST. + /// + /// Does not take ownership of 'Action'. + /// @{ + void addMatcher(const DeclarationMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const TypeMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const StatementMatcher &NodeMatch, + MatchCallback *Action); + /// @} + + /// \brief Creates a clang ASTConsumer that finds all matches. + clang::ASTConsumer *newASTConsumer(); + + /// \brief Registers a callback to notify the end of parsing. + /// + /// The provided closure is called after parsing is done, before the AST is + /// traversed. Useful for benchmarking. + /// Each call to FindAll(...) will call the closure once. + void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); + +private: + /// \brief The MatchCallback*'s will be called every time the + /// UntypedBaseMatcher matches on the AST. + std::vector< std::pair< + const internal::UntypedBaseMatcher*, + MatchCallback*> > Triggers; + + /// \brief Called when parsing is done. + ParsingDoneTestCallback *ParsingDone; +}; + +} // end namespace ast_matchers +} // end namespace clang + +#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h new file mode 100644 index 0000000000..69e9c4b53d --- /dev/null +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -0,0 +1,1403 @@ +//===--- ASTMatchers.h - Structural query framework -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements matchers to be used together with the MatchFinder to +// match AST nodes. +// +// Matchers are created by generator functions, which can be combined in +// a functional in-language DSL to express queries over the C++ AST. +// +// For example, to match a class with a certain name, one would call: +// record(hasName("MyClass")) +// which returns a matcher that can be used to find all AST nodes that declare +// a class named 'MyClass'. +// +// For more complicated match expressions we're often interested in accessing +// multiple parts of the matched AST nodes once a match is found. In that case, +// use the id(...) matcher around the match expressions that match the nodes +// you want to access. +// +// For example, when we're interested in child classes of a certain class, we +// would write: +// record(hasName("MyClass"), hasChild(id("child", record()))) +// When the match is found via the MatchFinder, a user provided callback will +// be called with a BoundNodes instance that contains a mapping from the +// strings that we provided for the id(...) calls to the nodes that were +// matched. +// In the given example, each time our matcher finds a match we get a callback +// where "child" is bound to the CXXRecordDecl node of the matching child +// class declaration. +// +// See ASTMatchersInternal.h for a more in-depth explanation of the +// implementation details of the matcher framework. +// +// See ASTMatchFinder.h for how to use the generated matchers to run over +// an AST. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H +#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H + +#include "clang/ASTMatchers/ASTMatchersInternal.h" +#include "clang/ASTMatchers/ASTMatchersMacros.h" +#include "llvm/ADT/Twine.h" + +namespace clang { +namespace ast_matchers { + +/// \brief Maps string IDs to AST nodes matched by parts of a matcher. +/// +/// The bound nodes are generated by adding id(...) matchers into the +/// match expression around the matchers for the nodes we want to access later. +/// +/// The instances of BoundNodes are created by MatchFinder when the user's +/// callbacks are executed every time a match is found. +class BoundNodes { +public: + /// \brief Returns the AST node bound to 'ID'. + /// Returns NULL if there was no node bound to 'ID' or if there is a node but + /// it cannot be converted to the specified type. + /// FIXME: We'll need one of those for every base type. + /// @{ + template + const T *getDeclAs(StringRef ID) const { + return getNodeAs(DeclBindings, ID); + } + template + const T *getStmtAs(StringRef ID) const { + return getNodeAs(StmtBindings, ID); + } + /// @} + +private: + /// \brief Create BoundNodes from a pre-filled map of bindings. + BoundNodes(const std::map &DeclBindings, + const std::map &StmtBindings) + : DeclBindings(DeclBindings), StmtBindings(StmtBindings) {} + + template + const T *getNodeAs(const MapT &Bindings, StringRef ID) const { + typename MapT::const_iterator It = Bindings.find(ID); + if (It == Bindings.end()) { + return NULL; + } + return llvm::dyn_cast(It->second); + } + + std::map DeclBindings; + std::map StmtBindings; + + friend class internal::BoundNodesTree; +}; + +/// \brief If the provided matcher matches a node, binds the node to 'ID'. +/// +/// FIXME: Add example for accessing it. +template +internal::Matcher id(const std::string &ID, + const internal::Matcher &InnerMatcher) { + return internal::Matcher(new internal::IdMatcher(ID, InnerMatcher)); +} + +/// \brief Types of matchers for the top-level classes in the AST class +/// hierarchy. +/// @{ +typedef internal::Matcher DeclarationMatcher; +typedef internal::Matcher TypeMatcher; +typedef internal::Matcher StatementMatcher; +/// @} + +/// \brief Matches any node. +/// +/// Useful when another matcher requires a child matcher, but there's no +/// additional constraint. This will often be used with an explicit conversion +/// to a internal::Matcher<> type such as TypeMatcher. +/// +/// Example: DeclarationMatcher(anything()) matches all declarations, e.g., +/// "int* p" and "void f()" in +/// int* p; +/// void f(); +inline internal::PolymorphicMatcherWithParam0 anything() { + return internal::PolymorphicMatcherWithParam0(); +} + +/// \brief Matches a declaration of anything that could have a name. +/// +/// Example matches X, S, the anonymous union type, i, and U; +/// typedef int X; +/// struct S { +/// union { +/// int i; +/// } U; +/// }; +const internal::VariadicDynCastAllOfMatcher< + clang::Decl, + clang::NamedDecl> nameableDeclaration; + +/// \brief Matches C++ class declarations. +/// +/// Example matches X, Z +/// class X; +/// template class Z {}; +const internal::VariadicDynCastAllOfMatcher< + clang::Decl, + clang::CXXRecordDecl> record; + +/// \brief Matches C++ constructor declarations. +/// +/// Example matches Foo::Foo() and Foo::Foo(int) +/// class Foo { +/// public: +/// Foo(); +/// Foo(int); +/// int DoSomething(); +/// }; +const internal::VariadicDynCastAllOfMatcher< + clang::Decl, + clang::CXXConstructorDecl> constructor; + +/// \brief Matches method declarations. +/// +/// Example matches y +/// class X { void y() }; +const internal::VariadicDynCastAllOfMatcher< + clang::Decl, + clang::CXXMethodDecl> method; + +/// \brief Matches variable declarations. +/// +/// Note: this does not match declarations of member variables, which are +/// "field" declarations in Clang parlance. +/// +/// Example matches a +/// int a; +const internal::VariadicDynCastAllOfMatcher< + clang::Decl, + clang::VarDecl> variable; + +/// \brief Matches field declarations. +/// +/// Given +/// class X { int m; }; +/// field() +/// matches 'm'. +const internal::VariadicDynCastAllOfMatcher< + clang::Decl, + clang::FieldDecl> field; + +/// \brief Matches function declarations. +/// +/// Example matches f +/// void f(); +const internal::VariadicDynCastAllOfMatcher< + clang::Decl, + clang::FunctionDecl> function; + + +/// \brief Matches statements. +/// +/// Given +/// { ++a; } +/// statement() +/// matches both the compound statement '{ ++a; }' and '++a'. +const internal::VariadicDynCastAllOfMatcher statement; + +/// \brief Matches declaration statements. +/// +/// Given +/// int a; +/// declarationStatement() +/// matches 'int a'. +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::DeclStmt> declarationStatement; + +/// \brief Matches member expressions. +/// +/// Given +/// class Y { +/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } +/// int a; static int b; +/// }; +/// memberExpression() +/// matches this->x, x, y.x, a, this->b +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::MemberExpr> memberExpression; + +/// \brief Matches call expressions. +/// +/// Example matches x.y() +/// X x; +/// x.y(); +const internal::VariadicDynCastAllOfMatcher call; + +/// \brief Matches constructor call expressions (including implicit ones). +/// +/// Example matches string(ptr, n) and ptr within arguments of f +/// (matcher = constructorCall()) +/// void f(const string &a, const string &b); +/// char *ptr; +/// int n; +/// f(string(ptr, n), ptr); +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::CXXConstructExpr> constructorCall; + +/// \brief Matches nodes where temporaries are created. +/// +/// Example matches FunctionTakesString(GetStringByValue()) +/// (matcher = bindTemporaryExpr()) +/// FunctionTakesString(GetStringByValue()); +/// FunctionTakesStringByPointer(GetStringPointer()); +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::CXXBindTemporaryExpr> bindTemporaryExpression; + +/// \brief Matches new expressions. +/// +/// Given +/// new X; +/// newExpression() +/// matches 'new X'. +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::CXXNewExpr> newExpression; + +/// \brief Matches the value of a default argument at the call site. +/// +/// Example matches the CXXDefaultArgExpr placeholder inserted for the +/// default value of the second parameter in the call expression f(42) +/// (matcher = defaultArgument()) +/// void f(int x, int y = 0); +/// f(42); +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::CXXDefaultArgExpr> defaultArgument; + +/// \brief Matches overloaded operator calls. +/// +/// Note that if an operator isn't overloaded, it won't match. Instead, use +/// binaryOperator matcher. +/// Currently it does not match operators such as new delete. +/// FIXME: figure out why these do not match? +/// +/// Example matches both operator<<((o << b), c) and operator<<(o, b) +/// (matcher = overloadedOperatorCall()) +/// ostream &operator<< (ostream &out, int i) { }; +/// ostream &o; int b = 1, c = 1; +/// o << b << c; +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::CXXOperatorCallExpr> overloadedOperatorCall; + +/// \brief Matches expressions. +/// +/// Example matches x() +/// void f() { x(); } +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::Expr> expression; + +/// \brief Matches expressions that refer to declarations. +/// +/// Example matches x in if (x) +/// bool x; +/// if (x) {} +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::DeclRefExpr> declarationReference; + +/// \brief Matches if statements. +/// +/// Example matches 'if (x) {}' +/// if (x) {} +const internal::VariadicDynCastAllOfMatcher ifStmt; + +/// \brief Matches for statements. +/// +/// Example matches 'for (;;) {}' +/// for (;;) {} +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, clang::ForStmt> forStmt; + +/// \brief Matches while statements. +/// +/// Given +/// while (true) {} +/// whileStmt() +/// matches 'while (true) {}'. +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::WhileStmt> whileStmt; + +/// \brief Matches do statements. +/// +/// Given +/// do {} while (true); +/// doStmt() +/// matches 'do {} while(true)' +const internal::VariadicDynCastAllOfMatcher doStmt; + +/// \brief Matches case and default statements inside switch statements. +/// +/// Given +/// switch(a) { case 42: break; default: break; } +/// switchCase() +/// matches 'case 42: break;' and 'default: break;'. +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::SwitchCase> switchCase; + +/// \brief Matches compound statements. +/// +/// Example matches '{}' and '{{}}'in 'for (;;) {{}}' +/// for (;;) {{}} +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::CompoundStmt> compoundStatement; + +/// \brief Matches bool literals. +/// +/// Example matches true +/// true +const internal::VariadicDynCastAllOfMatcher< + clang::Expr, + clang::CXXBoolLiteralExpr> boolLiteral; + +/// \brief Matches string literals (also matches wide string literals). +/// +/// Example matches "abcd", L"abcd" +/// char *s = "abcd"; wchar_t *ws = L"abcd" +const internal::VariadicDynCastAllOfMatcher< + clang::Expr, + clang::StringLiteral> stringLiteral; + +/// \brief Matches character literals (also matches wchar_t). +/// +/// Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral), +/// though. +/// +/// Example matches 'a', L'a' +/// char ch = 'a'; wchar_t chw = L'a'; +const internal::VariadicDynCastAllOfMatcher< + clang::Expr, + clang::CharacterLiteral> characterLiteral; + +/// \brief Matches integer literals of all sizes / encodings. +/// +/// Not matching character-encoded integers such as L'a'. +/// +/// Example matches 1, 1L, 0x1, 1U +const internal::VariadicDynCastAllOfMatcher< + clang::Expr, + clang::IntegerLiteral> integerLiteral; + +/// \brief Matches binary operator expressions. +/// +/// Example matches a || b +/// !(a || b) +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::BinaryOperator> binaryOperator; + +/// \brief Matches unary operator expressions. +/// +/// Example matches !a +/// !a || b +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::UnaryOperator> unaryOperator; + +/// \brief Matches conditional operator expressions. +/// +/// Example matches a ? b : c +/// (a ? b : c) + 42 +const internal::VariadicDynCastAllOfMatcher< + clang::Stmt, + clang::ConditionalOperator> conditionalOperator; + +/// \brief Matches a reinterpret_cast expression. +/// +/// Either the source expression or the destination type can be matched +/// using has(), but hasDestinationType() is more specific and can be +/// more readable. +/// +/// Example matches reinterpret_cast(&p) in +/// void* p = reinterpret_cast(&p); +const internal::VariadicDynCastAllOfMatcher< + clang::Expr, + clang::CXXReinterpretCastExpr> reinterpretCast; + +/// \brief Matches a C++ static_cast expression. +/// +/// \see hasDestinationType +/// \see reinterpretCast +/// +/// Example: +/// staticCast() +/// matches +/// static_cast(8) +/// in +/// long eight(static_cast(8)); +const internal::VariadicDynCastAllOfMatcher< + clang::Expr, + clang::CXXStaticCastExpr> staticCast; + +/// \brief Matches a dynamic_cast expression. +/// +/// Example: +/// dynamicCast() +/// matches +/// dynamic_cast(&b); +/// in +/// struct B { virtual ~B() {} }; struct D : B {}; +/// B b; +/// D* p = dynamic_cast(&b); +const internal::VariadicDynCastAllOfMatcher< + clang::Expr, + clang::CXXDynamicCastExpr> dynamicCast; + +/// \brief Matches a const_cast expression. +/// +/// Example: Matches const_cast(&r) in +/// int n = 42; +/// const int& r(n); +/// int* p = const_cast(&r); +const internal::VariadicDynCastAllOfMatcher< + clang::Expr, + clang::CXXConstCastExpr> constCast; + +/// \brief Matches explicit cast expressions. +/// +/// Matches any cast expression written in user code, whether it be a +/// C-style cast, a functional-style cast, or a keyword cast. +/// +/// Does not match implicit conversions. +/// +/// Note: the name "explicitCast" is chosen to match Clang's terminology, as +/// Clang uses the term "cast" to apply to implicit conversions as well as to +/// actual cast expressions. +/// +/// \see hasDestinationType. +/// +/// Example: matches all five of the casts in +/// int((int)(reinterpret_cast(static_cast(const_cast(42))))) +/// but does not match the implicit conversion in +/// long ell = 42; +const internal::VariadicDynCastAllOfMatcher< + clang::Expr, + clang::ExplicitCastExpr> explicitCast; + +/// \brief Matches the implicit cast nodes of Clang's AST. +/// +/// This matches many different places, including function call return value +/// eliding, as well as any type conversions. +const internal::VariadicDynCastAllOfMatcher< + clang::Expr, + clang::ImplicitCastExpr> implicitCast; + +/// \brief Matches functional cast expressions +/// +/// Example: Matches Foo(bar); +/// Foo f = bar; +/// Foo g = (Foo) bar; +/// Foo h = Foo(bar); +const internal::VariadicDynCastAllOfMatcher< + clang::Expr, + clang::CXXFunctionalCastExpr> functionalCast; + +/// \brief Various overloads for the anyOf matcher. +/// @{ +template +internal::PolymorphicMatcherWithParam2 +anyOf(const C1 &P1, const C2 &P2) { + return internal::PolymorphicMatcherWithParam2(P1, P2); +} +template +internal::PolymorphicMatcherWithParam2 > +anyOf(const C1 &P1, const C2 &P2, const C3 &P3) { + return anyOf(P1, anyOf(P2, P3)); +} +template +internal::PolymorphicMatcherWithParam2 > > +anyOf(const C1 &P1, const C2 &P2, const C3 &P3, const C4 &P4) { + return AnyOf(P1, AnyOf(P2, AnyOf(P3, P4))); +} +template +internal::PolymorphicMatcherWithParam2 > > > +anyOf(const C1& P1, const C2& P2, const C3& P3, const C4& P4, const C5& P5) { + return anyOf(P1, anyOf(P2, anyOf(P3, anyOf(P4, P5)))); +} +/// @} + +/// \brief Various overloads for the allOf matcher. +/// @{ +template +internal::PolymorphicMatcherWithParam2 +allOf(const C1 &P1, const C2 &P2) { + return internal::PolymorphicMatcherWithParam2(P1, P2); +} +template +internal::PolymorphicMatcherWithParam2 > +allOf(const C1& P1, const C2& P2, const C3& P3) { + return AllOf(P1, AllOf(P2, P3)); +} +/// @} + +/// \brief Matches NamedDecl nodes that have the specified name. +/// +/// Supports specifying enclosing namespaces or classes by prefixing the name +/// with '::'. +/// Does not match typedefs of an underlying type with the given name. +/// +/// Example matches X (Name == "X") +/// class X; +/// +/// Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X") +/// namespace a { namespace b { class X; } } +AST_MATCHER_P(clang::NamedDecl, hasName, std::string, Name) { + assert(!Name.empty()); + const std::string FullNameString = "::" + Node.getQualifiedNameAsString(); + const llvm::StringRef FullName = FullNameString; + const llvm::StringRef Pattern = Name; + if (Pattern.startswith("::")) { + return FullName == Pattern; + } else { + return FullName.endswith(("::" + Pattern).str()); + } +} + +/// \brief Matches overloaded operator names. +/// +/// Matches overloaded operator names specified in strings without the +/// "operator" prefix, such as "<<", for OverloadedOperatorCall's. +/// +/// Example matches a << b +/// (matcher == overloadedOperatorCall(hasOverloadedOperatorName("<<"))) +/// a << b; +/// c && d; // assuming both operator<< +/// // and operator&& are overloaded somewhere. +AST_MATCHER_P(clang::CXXOperatorCallExpr, + hasOverloadedOperatorName, std::string, Name) { + return clang::getOperatorSpelling(Node.getOperator()) == Name; +} + +/// \brief Matches C++ classes that are directly or indirectly derived from +/// the given base class. +/// +/// Note that a class is considered to be also derived from itself. +/// The parameter specified the name of the base type (either a class or a +/// typedef), and does not allow structural matches for namespaces or template +/// type parameters. +/// +/// Example matches X, Y, Z, C (Base == "X") +/// class X; // A class is considered to be derived from itself +/// class Y : public X {}; // directly derived +/// class Z : public Y {}; // indirectly derived +/// typedef X A; +/// typedef A B; +/// class C : public B {}; // derived from a typedef of X +/// +/// In the following example, Bar matches isDerivedFrom("X"): +/// class Foo; +/// typedef Foo X; +/// class Bar : public Foo {}; // derived from a type that X is a typedef of +AST_MATCHER_P(clang::CXXRecordDecl, isDerivedFrom, std::string, Base) { + assert(!Base.empty()); + return Finder->classIsDerivedFrom(&Node, Base); +} + +/// \brief Matches AST nodes that have child AST nodes that match the +/// provided matcher. +/// +/// Example matches X, Y (matcher = record(has(record(hasName("X"))) +/// class X {}; // Matches X, because X::X is a class of name X inside X. +/// class Y { class X {}; }; +/// class Z { class Y { class X {}; }; }; // Does not match Z. +/// +/// ChildT must be an AST base type. +template +internal::ArgumentAdaptingMatcher has( + const internal::Matcher &ChildMatcher) { + return internal::ArgumentAdaptingMatcher(ChildMatcher); +} + +/// \brief Matches AST nodes that have descendant AST nodes that match the +/// provided matcher. +/// +/// Example matches X, Y, Z +/// (matcher = record(hasDescendant(record(hasName("X"))))) +/// class X {}; // Matches X, because X::X is a class of name X inside X. +/// class Y { class X {}; }; +/// class Z { class Y { class X {}; }; }; +/// +/// DescendantT must be an AST base type. +template +internal::ArgumentAdaptingMatcher +hasDescendant(const internal::Matcher &DescendantMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::HasDescendantMatcher, + DescendantT>(DescendantMatcher); +} + + +/// \brief Matches AST nodes that have child AST nodes that match the +/// provided matcher. +/// +/// Example matches X, Y (matcher = record(forEach(record(hasName("X"))) +/// class X {}; // Matches X, because X::X is a class of name X inside X. +/// class Y { class X {}; }; +/// class Z { class Y { class X {}; }; }; // Does not match Z. +/// +/// ChildT must be an AST base type. +/// +/// As opposed to 'has', 'forEach' will cause a match for each result that +/// matches instead of only on the first one. +template +internal::ArgumentAdaptingMatcher forEach( + const internal::Matcher& ChildMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::ForEachMatcher, + ChildT>(ChildMatcher); +} + +/// \brief Matches AST nodes that have descendant AST nodes that match the +/// provided matcher. +/// +/// Example matches X, A, B, C +/// (matcher = record(forEachDescendant(record(hasName("X"))))) +/// class X {}; // Matches X, because X::X is a class of name X inside X. +/// class A { class X {}; }; +/// class B { class C { class X {}; }; }; +/// +/// DescendantT must be an AST base type. +/// +/// As opposed to 'hasDescendant', 'forEachDescendant' will cause a match for +/// each result that matches instead of only on the first one. +/// +/// Note: Recursively combined ForEachDescendant can cause many matches: +/// record(forEachDescendant(record(forEachDescendant(record())))) +/// will match 10 times (plus injected class name matches) on: +/// class A { class B { class C { class D { class E {}; }; }; }; }; +template +internal::ArgumentAdaptingMatcher +forEachDescendant( + const internal::Matcher& DescendantMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::ForEachDescendantMatcher, + DescendantT>(DescendantMatcher); +} + +/// \brief Matches if the provided matcher does not match. +/// +/// Example matches Y (matcher = record(unless(hasName("X")))) +/// class X {}; +/// class Y {}; +template +internal::PolymorphicMatcherWithParam1 unless(const M &InnerMatcher) { + return internal::PolymorphicMatcherWithParam1< + internal::NotMatcher, M>(InnerMatcher); +} + +/// \brief Matches a type if the declaration of the type matches the given +/// matcher. +inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, + internal::Matcher > + hasDeclaration(const internal::Matcher &InnerMatcher) { + return internal::PolymorphicMatcherWithParam1< + internal::HasDeclarationMatcher, + internal::Matcher >(InnerMatcher); +} + +/// \brief Matches on the implicit object argument of a member call expression. +/// +/// Example matches y.x() (matcher = call(on(hasType(record(hasName("Y")))))) +/// class Y { public: void x(); }; +/// void z() { Y y; y.x(); }", +/// +/// FIXME: Overload to allow directly matching types? +AST_MATCHER_P(clang::CXXMemberCallExpr, on, internal::Matcher, + InnerMatcher) { + const clang::Expr *ExprNode = const_cast(Node) + .getImplicitObjectArgument() + ->IgnoreParenImpCasts(); + return (ExprNode != NULL && + InnerMatcher.matches(*ExprNode, Finder, Builder)); +} + +/// \brief Matches if the call expression's callee expression matches. +/// +/// Given +/// class Y { void x() { this->x(); x(); Y y; y.x(); } }; +/// void f() { f(); } +/// call(callee(expression())) +/// matches this->x(), x(), y.x(), f() +/// with callee(...) +/// matching this->x, x, y.x, f respectively +/// +/// Note: Callee cannot take the more general internal::Matcher +/// because this introduces ambiguous overloads with calls to Callee taking a +/// internal::Matcher, as the matcher hierarchy is purely +/// implemented in terms of implicit casts. +AST_MATCHER_P(clang::CallExpr, callee, internal::Matcher, + InnerMatcher) { + const clang::Expr *ExprNode = Node.getCallee(); + return (ExprNode != NULL && + InnerMatcher.matches(*ExprNode, Finder, Builder)); +} + +/// \brief Matches if the call expression's callee's declaration matches the +/// given matcher. +/// +/// Example matches y.x() (matcher = call(callee(method(hasName("x"))))) +/// class Y { public: void x(); }; +/// void z() { Y y; y.x(); +inline internal::Matcher callee( + const internal::Matcher &InnerMatcher) { + return internal::Matcher(hasDeclaration(InnerMatcher)); +} + +/// \brief Matches if the expression's or declaration's type matches a type +/// matcher. +/// +/// Example matches x (matcher = expression(hasType( +/// hasDeclaration(record(hasName("X")))))) +/// and z (matcher = variable(hasType( +/// hasDeclaration(record(hasName("X")))))) +/// class X {}; +/// void y(X &x) { x; X z; } +AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher, + InnerMatcher) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || + llvm::is_base_of::value), + instantiated_with_wrong_types); + return InnerMatcher.matches(Node.getType(), Finder, Builder); +} + +/// \brief Overloaded to match the declaration of the expression's or value +/// declaration's type. +/// +/// In case of a value declaration (for example a variable declaration), +/// this resolves one layer of indirection. For example, in the value +/// declaration "X x;", record(hasName("X")) matches the declaration of X, +/// while variable(hasType(record(hasName("X")))) matches the declaration +/// of x." +/// +/// Example matches x (matcher = expression(hasType(record(hasName("X"))))) +/// and z (matcher = variable(hasType(record(hasName("X"))))) +/// class X {}; +/// void y(X &x) { x; X z; } +inline internal::PolymorphicMatcherWithParam1< + internal::matcher_hasTypeMatcher, + internal::Matcher > +hasType(const internal::Matcher &InnerMatcher) { + return hasType(internal::Matcher( + hasDeclaration(InnerMatcher))); +} + +/// \brief Matches if the matched type is a pointer type and the pointee type +/// matches the specified matcher. +/// +/// Example matches y->x() +/// (matcher = call(on(hasType(pointsTo(record(hasName("Y"))))))) +/// class Y { public: void x(); }; +/// void z() { Y *y; y->x(); } +AST_MATCHER_P( + clang::QualType, pointsTo, internal::Matcher, + InnerMatcher) { + return (Node->isPointerType() && + InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); +} + +/// \brief Overloaded to match the pointee type's declaration. +inline internal::Matcher pointsTo( + const internal::Matcher &InnerMatcher) { + return pointsTo(internal::Matcher( + hasDeclaration(InnerMatcher))); +} + +/// \brief Matches if the matched type is a reference type and the referenced +/// type matches the specified matcher. +/// +/// Example matches X &x and const X &y +/// (matcher = variable(hasType(references(record(hasName("X")))))) +/// class X { +/// void a(X b) { +/// X &x = b; +/// const X &y = b; +/// }; +AST_MATCHER_P(clang::QualType, references, internal::Matcher, + InnerMatcher) { + return (Node->isReferenceType() && + InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); +} + +/// \brief Overloaded to match the referenced type's declaration. +inline internal::Matcher references( + const internal::Matcher &InnerMatcher) { + return references(internal::Matcher( + hasDeclaration(InnerMatcher))); +} + +AST_MATCHER_P(clang::CXXMemberCallExpr, onImplicitObjectArgument, + internal::Matcher, InnerMatcher) { + const clang::Expr *ExprNode = + const_cast(Node).getImplicitObjectArgument(); + return (ExprNode != NULL && + InnerMatcher.matches(*ExprNode, Finder, Builder)); +} + +/// \brief Matches if the expression's type either matches the specified +/// matcher, or is a pointer to a type that matches the InnerMatcher. +inline internal::Matcher thisPointerType( + const internal::Matcher &InnerMatcher) { + return onImplicitObjectArgument( + anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher)))); +} + +/// \brief Overloaded to match the type's declaration. +inline internal::Matcher thisPointerType( + const internal::Matcher &InnerMatcher) { + return onImplicitObjectArgument( + anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher)))); +} + +/// \brief Matches a DeclRefExpr that refers to a declaration that matches the +/// specified matcher. +/// +/// Example matches x in if(x) +/// (matcher = declarationReference(to(variable(hasName("x"))))) +/// bool x; +/// if (x) {} +AST_MATCHER_P(clang::DeclRefExpr, to, internal::Matcher, + InnerMatcher) { + const clang::Decl *DeclNode = Node.getDecl(); + return (DeclNode != NULL && + InnerMatcher.matches(*DeclNode, Finder, Builder)); +} + +/// \brief Matches a variable declaration that has an initializer expression +/// that matches the given matcher. +/// +/// Example matches x (matcher = variable(hasInitializer(call()))) +/// bool y() { return true; } +/// bool x = y(); +AST_MATCHER_P( + clang::VarDecl, hasInitializer, internal::Matcher, + InnerMatcher) { + const clang::Expr *Initializer = Node.getAnyInitializer(); + return (Initializer != NULL && + InnerMatcher.matches(*Initializer, Finder, Builder)); +} + +/// \brief Checks that a call expression or a constructor call expression has +/// a specific number of arguments (including absent default arguments). +/// +/// Example matches f(0, 0) (matcher = call(argumentCountIs(2))) +/// void f(int x, int y); +/// f(0, 0); +AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || + llvm::is_base_of::value), + instantiated_with_wrong_types); + return Node.getNumArgs() == N; +} + +/// \brief Matches the n'th argument of a call expression or a constructor +/// call expression. +/// +/// Example matches y in x(y) +/// (matcher = call(hasArgument(0, declarationReference()))) +/// void x(int) { int y; x(y); } +AST_POLYMORPHIC_MATCHER_P2( + hasArgument, unsigned, N, internal::Matcher, InnerMatcher) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || + llvm::is_base_of::value), + instantiated_with_wrong_types); + return (N < Node.getNumArgs() && + InnerMatcher.matches( + *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder)); +} + +/// \brief Matches a constructor initializer. +/// +/// Given +/// struct Foo { +/// Foo() : foo_(1) { } +/// int foo_; +/// }; +/// record(Has(Constructor(hasAnyConstructorInitializer(anything())))) +/// Class matches Foo, hasAnyConstructorInitializer matches foo_(1) +AST_MATCHER_P(clang::CXXConstructorDecl, hasAnyConstructorInitializer, + internal::Matcher, InnerMatcher) { + for (clang::CXXConstructorDecl::init_const_iterator I = Node.init_begin(); + I != Node.init_end(); ++I) { + if (InnerMatcher.matches(**I, Finder, Builder)) { + return true; + } + } + return false; +} + +/// \brief Matches the field declaration of a constructor initializer. +/// +/// Given +/// struct Foo { +/// Foo() : foo_(1) { } +/// int foo_; +/// }; +/// record(has(constructor(hasAnyConstructorInitializer( +/// forField(hasName("foo_")))))) +/// matches Foo +/// with forField matching foo_ +AST_MATCHER_P(clang::CXXCtorInitializer, forField, + internal::Matcher, InnerMatcher) { + const clang::FieldDecl *NodeAsDecl = Node.getMember(); + return (NodeAsDecl != NULL && + InnerMatcher.matches(*NodeAsDecl, Finder, Builder)); +} + +/// \brief Matches the initializer expression of a constructor initializer. +/// +/// Given +/// struct Foo { +/// Foo() : foo_(1) { } +/// int foo_; +/// }; +/// record(has(constructor(hasAnyConstructorInitializer( +/// withInitializer(integerLiteral(equals(1))))))) +/// matches Foo +/// with withInitializer matching (1) +AST_MATCHER_P(clang::CXXCtorInitializer, withInitializer, + internal::Matcher, InnerMatcher) { + const clang::Expr* NodeAsExpr = Node.getInit(); + return (NodeAsExpr != NULL && + InnerMatcher.matches(*NodeAsExpr, Finder, Builder)); +} + +/// \brief Matches a contructor initializer if it is explicitly written in +/// code (as opposed to implicitly added by the compiler). +/// +/// Given +/// struct Foo { +/// Foo() { } +/// Foo(int) : foo_("A") { } +/// string foo_; +/// }; +/// constructor(hasAnyConstructorInitializer(isWritten())) +/// will match Foo(int), but not Foo() +AST_MATCHER(clang::CXXCtorInitializer, isWritten) { + return Node.isWritten(); +} + +/// \brief Matches a constructor declaration that has been implicitly added +/// by the compiler (eg. implicit default/copy constructors). +AST_MATCHER(clang::CXXConstructorDecl, isImplicit) { + return Node.isImplicit(); +} + +/// \brief Matches any argument of a call expression or a constructor call +/// expression. +/// +/// Given +/// void x(int, int, int) { int y; x(1, y, 42); } +/// call(hasAnyArgument(declarationReference())) +/// matches x(1, y, 42) +/// with hasAnyArgument(...) +/// matching y +AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher, + InnerMatcher) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || + llvm::is_base_of::value), + instantiated_with_wrong_types); + for (unsigned I = 0; I < Node.getNumArgs(); ++I) { + if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), + Finder, Builder)) { + return true; + } + } + return false; +} + +/// \brief Matches the n'th parameter of a function declaration. +/// +/// Given +/// class X { void f(int x) {} }; +/// method(hasParameter(0, hasType(variable()))) +/// matches f(int x) {} +/// with hasParameter(...) +/// matching int x +AST_MATCHER_P2(clang::FunctionDecl, hasParameter, + unsigned, N, internal::Matcher, + InnerMatcher) { + return (N < Node.getNumParams() && + InnerMatcher.matches( + *Node.getParamDecl(N), Finder, Builder)); +} + +/// \brief Matches any parameter of a function declaration. +/// +/// Does not match the 'this' parameter of a method. +/// +/// Given +/// class X { void f(int x, int y, int z) {} }; +/// method(hasAnyParameter(hasName("y"))) +/// matches f(int x, int y, int z) {} +/// with hasAnyParameter(...) +/// matching int y +AST_MATCHER_P(clang::FunctionDecl, hasAnyParameter, + internal::Matcher, InnerMatcher) { + for (unsigned I = 0; I < Node.getNumParams(); ++I) { + if (InnerMatcher.matches(*Node.getParamDecl(I), Finder, Builder)) { + return true; + } + } + return false; +} + +/// \brief Matches the condition expression of an if statement or conditional +/// operator. +/// +/// Example matches true (matcher = hasCondition(boolLiteral(equals(true)))) +/// if (true) {} +AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher, + InnerMatcher) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of::value) || + (llvm::is_base_of::value), + has_condition_requires_if_statement_or_conditional_operator); + const clang::Expr *const Condition = Node.getCond(); + return (Condition != NULL && + InnerMatcher.matches(*Condition, Finder, Builder)); +} + +/// \brief Matches the condition variable statement in an if statement. +/// +/// Given +/// if (A* a = GetAPointer()) {} +/// hasConditionVariableStatment(...) +/// matches 'A* a = GetAPointer()'. +AST_MATCHER_P(clang::IfStmt, hasConditionVariableStatement, + internal::Matcher, InnerMatcher) { + const clang::DeclStmt* const DeclarationStatement = + Node.getConditionVariableDeclStmt(); + return DeclarationStatement != NULL && + InnerMatcher.matches(*DeclarationStatement, Finder, Builder); +} + +/// \brief Matches a 'for' statement that has a given body. +/// +/// Given +/// for (;;) {} +/// hasBody(compoundStatement()) +/// matches 'for (;;) {}' +/// with compoundStatement() +/// matching '{}' +AST_MATCHER_P(clang::ForStmt, hasBody, internal::Matcher, + InnerMatcher) { + const clang::Stmt *const Statement = Node.getBody(); + return (Statement != NULL && + InnerMatcher.matches(*Statement, Finder, Builder)); +} + +/// \brief Matches compound statements where at least one substatement matches +/// a given matcher. +/// +/// Given +/// { {}; 1+2; } +/// hasAnySubstatement(compoundStatement()) +/// matches '{ {}; 1+2; }' +/// with compoundStatement() +/// matching '{}' +AST_MATCHER_P(clang::CompoundStmt, hasAnySubstatement, + internal::Matcher, InnerMatcher) { + for (clang::CompoundStmt::const_body_iterator It = Node.body_begin(); + It != Node.body_end(); + ++It) { + if (InnerMatcher.matches(**It, Finder, Builder)) return true; + } + return false; +} + +/// \brief Checks that a compound statement contains a specific number of +/// child statements. +/// +/// Example: Given +/// { for (;;) {} } +/// compoundStatement(statementCountIs(0))) +/// matches '{}' +/// but does not match the outer compound statement. +AST_MATCHER_P(clang::CompoundStmt, statementCountIs, unsigned, N) { + return Node.size() == N; +} + +/// \brief Matches literals that are equal to the given value. +/// +/// Example matches true (matcher = boolLiteral(equals(true))) +/// true +template +internal::PolymorphicMatcherWithParam1 +equals(const ValueT &Value) { + return internal::PolymorphicMatcherWithParam1< + internal::ValueEqualsMatcher, + ValueT>(Value); +} + +/// \brief Matches the operator Name of operator expressions (binary or +/// unary). +/// +/// Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) +/// !(a || b) +AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of::value) || + (llvm::is_base_of::value), + has_condition_requires_if_statement_or_conditional_operator); + return Name == Node.getOpcodeStr(Node.getOpcode()); +} + +/// \brief Matches the left hand side of binary operator expressions. +/// +/// Example matches a (matcher = binaryOperator(hasLHS())) +/// a || b +AST_MATCHER_P(clang::BinaryOperator, hasLHS, + internal::Matcher, InnerMatcher) { + clang::Expr *LeftHandSide = Node.getLHS(); + return (LeftHandSide != NULL && + InnerMatcher.matches(*LeftHandSide, Finder, Builder)); +} + +/// \brief Matches the right hand side of binary operator expressions. +/// +/// Example matches b (matcher = binaryOperator(hasRHS())) +/// a || b +AST_MATCHER_P(clang::BinaryOperator, hasRHS, + internal::Matcher, InnerMatcher) { + clang::Expr *RightHandSide = Node.getRHS(); + return (RightHandSide != NULL && + InnerMatcher.matches(*RightHandSide, Finder, Builder)); +} + +/// \brief Matches if either the left hand side or the right hand side of a +/// binary operator matches. +inline internal::Matcher hasEitherOperand( + const internal::Matcher &InnerMatcher) { + return anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher)); +} + +/// \brief Matches if the operand of a unary operator matches. +/// +/// Example matches true (matcher = hasOperand(boolLiteral(equals(true)))) +/// !true +AST_MATCHER_P(clang::UnaryOperator, hasUnaryOperand, + internal::Matcher, InnerMatcher) { + const clang::Expr * const Operand = Node.getSubExpr(); + return (Operand != NULL && + InnerMatcher.matches(*Operand, Finder, Builder)); +} + +/// Matches if the implicit cast's source expression matches the given matcher. +/// +/// Example: matches "a string" (matcher = +/// hasSourceExpression(constructorCall())) +/// +/// class URL { URL(string); }; +/// URL url = "a string"; +AST_MATCHER_P(clang::ImplicitCastExpr, hasSourceExpression, + internal::Matcher, InnerMatcher) { + const clang::Expr* const SubExpression = Node.getSubExpr(); + return (SubExpression != NULL && + InnerMatcher.matches(*SubExpression, Finder, Builder)); +} + +/// \brief Matches casts whose destination type matches a given matcher. +/// +/// (Note: Clang's AST refers to other conversions as "casts" too, and calls +/// actual casts "explicit" casts.) +AST_MATCHER_P(clang::ExplicitCastExpr, hasDestinationType, + internal::Matcher, InnerMatcher) { + const clang::QualType NodeType = Node.getTypeAsWritten(); + return InnerMatcher.matches(NodeType, Finder, Builder); +} + +/// \brief Matches implicit casts whose destination type matches a given +/// matcher. +/// +/// FIXME: Unit test this matcher +AST_MATCHER_P(clang::ImplicitCastExpr, hasImplicitDestinationType, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(Node.getType(), Finder, Builder); +} + +/// \brief Matches the true branch expression of a conditional operator. +/// +/// Example matches a +/// condition ? a : b +AST_MATCHER_P(clang::ConditionalOperator, hasTrueExpression, + internal::Matcher, InnerMatcher) { + clang::Expr *Expression = Node.getTrueExpr(); + return (Expression != NULL && + InnerMatcher.matches(*Expression, Finder, Builder)); +} + +/// \brief Matches the false branch expression of a conditional operator. +/// +/// Example matches b +/// condition ? a : b +AST_MATCHER_P(clang::ConditionalOperator, hasFalseExpression, + internal::Matcher, InnerMatcher) { + clang::Expr *Expression = Node.getFalseExpr(); + return (Expression != NULL && + InnerMatcher.matches(*Expression, Finder, Builder)); +} + +/// \brief Matches if a declaration has a body attached. +/// +/// Example matches A, va, fa +/// class A {}; +/// class B; // Doesn't match, as it has no body. +/// int va; +/// extern int vb; // Doesn't match, as it doesn't define the variable. +/// void fa() {} +/// void fb(); // Doesn't match, as it has no body. +inline internal::PolymorphicMatcherWithParam0 +isDefinition() { + return internal::PolymorphicMatcherWithParam0< + internal::IsDefinitionMatcher>(); +} + +/// \brief Matches the class declaration that the given method declaration +/// belongs to. +/// +/// FIXME: Generalize this for other kinds of declarations. +/// FIXME: What other kind of declarations would we need to generalize +/// this to? +/// +/// Example matches A() in the last line +/// (matcher = constructorCall(hasDeclaration(method( +/// ofClass(hasName("A")))))) +/// class A { +/// public: +/// A(); +/// }; +/// A a = A(); +AST_MATCHER_P(clang::CXXMethodDecl, ofClass, + internal::Matcher, InnerMatcher) { + const clang::CXXRecordDecl *Parent = Node.getParent(); + return (Parent != NULL && + InnerMatcher.matches(*Parent, Finder, Builder)); +} + +/// \brief Matches member expressions that are called with '->' as opposed +/// to '.'. +/// +/// Member calls on the implicit this pointer match as called with '->'. +/// +/// Given +/// class Y { +/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } +/// int a; +/// static int b; +/// }; +/// memberExpression(isArrow()) +/// matches this->x, x, y.x, a, this->b +inline internal::Matcher isArrow() { + return makeMatcher(new internal::IsArrowMatcher()); +} + +/// \brief Matches clang::QualType nodes that are const-qualified, i.e., that +/// include "top-level" const. +/// +/// Given +/// void a(int); +/// void b(int const); +/// void c(const int); +/// void d(const int*); +/// void e(int const) {}; +/// function(hasAnyParameter(hasType(isConstQualified()))) +/// matches "void b(int const)", "void c(const int)" and +/// "void e(int const) {}". It does not match d as there +/// is no top-level const on the parameter type "const int *". +inline internal::Matcher isConstQualified() { + return makeMatcher(new internal::IsConstQualifiedMatcher()); +} + +/// \brief Matches a member expression where the member is matched by a +/// given matcher. +/// +/// Given +/// struct { int first, second; } first, second; +/// int i(second.first); +/// int j(first.second); +/// memberExpression(member(hasName("first"))) +/// matches second.first +/// but not first.second (because the member name there is "second"). +AST_MATCHER_P(clang::MemberExpr, member, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder); +} + +/// \brief Matches a member expression where the object expression is +/// matched by a given matcher. +/// +/// Given +/// struct X { int m; }; +/// void f(X x) { x.m; m; } +/// memberExpression(hasObjectExpression(hasType(record(hasName("X"))))))) +/// matches "x.m" and "m" +/// with hasObjectExpression(...) +/// matching "x" and the implicit object expression of "m" which has type X*. +AST_MATCHER_P(clang::MemberExpr, hasObjectExpression, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(*Node.getBase(), Finder, Builder); +} + +/// \brief Matches template instantiations of function, class, or static +/// member variable template instantiations. +/// +/// Given +/// template class X {}; class A {}; X x; +/// or +/// template class X {}; class A {}; template class X; +/// record(hasName("::X"), isTemplateInstantiation()) +/// matches the template instantiation of X. +/// +/// But given +/// template class X {}; class A {}; +/// template <> class X {}; X x; +/// record(hasName("::X"), isTemplateInstantiation()) +/// does not match, as X is an explicit template specialization. +inline internal::PolymorphicMatcherWithParam0< + internal::IsTemplateInstantiationMatcher> +isTemplateInstantiation() { + return internal::PolymorphicMatcherWithParam0< + internal::IsTemplateInstantiationMatcher>(); +} + +} // end namespace ast_matchers +} // end namespace clang + +#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h new file mode 100644 index 0000000000..d9a557e78c --- /dev/null +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -0,0 +1,888 @@ +//===--- ASTMatchersInternal.h - Structural query framework -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements the base layer of the matcher framework. +// +// Matchers are methods that return a Matcher which provides a method +// Matches(...) which is a predicate on an AST node. The Matches method's +// parameters define the context of the match, which allows matchers to recurse +// or store the current node as bound to a specific string, so that it can be +// retrieved later. +// +// In general, matchers have two parts: +// 1. A function Matcher MatcherName() which returns a Matcher +// based on the arguments and optionally on template type deduction based +// on the arguments. Matchers form an implicit reverse hierarchy +// to clang's AST class hierarchy, meaning that you can use a Matcher +// everywhere a Matcher is required. +// 2. An implementation of a class derived from MatcherInterface. +// +// The matcher functions are defined in ASTMatchers.h. To make it possible +// to implement both the matcher function and the implementation of the matcher +// interface in one place, ASTMatcherMacros.h defines macros that allow +// implementing a matcher in a single place. +// +// This file contains the base classes needed to construct the actual matchers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H +#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/Stmt.h" +#include "llvm/ADT/VariadicFunction.h" +#include +#include +#include + +/// FIXME: Move into the llvm support library. +template struct CompileAssert {}; +#define TOOLING_COMPILE_ASSERT(Expr, Msg) \ + typedef CompileAssert<(bool(Expr))> Msg[bool(Expr) ? 1 : -1] + +namespace clang { +namespace ast_matchers { + +class BoundNodes; + +namespace internal { + +class BoundNodesTreeBuilder; + +/// \brief A tree of bound nodes in match results. +/// +/// If a match can contain multiple matches on the same node with different +/// matching subexpressions, BoundNodesTree contains a branch for each of +/// those matching subexpressions. +/// +/// BoundNodesTree's are created during the matching process; when a match +/// is found, we iterate over the tree and create a BoundNodes object containing +/// the union of all bound nodes on the path from the root to a each leaf. +class BoundNodesTree { +public: + /// \brief A visitor interface to visit all BoundNodes results for a + /// BoundNodesTree. + class Visitor { + public: + virtual ~Visitor() {} + + /// \brief Called multiple times during a single call to VisitMatches(...). + /// + /// 'BoundNodesView' contains the bound nodes for a single match. + virtual void visitMatch(const BoundNodes& BoundNodesView) = 0; + }; + + BoundNodesTree(); + + /// \brief Create a BoundNodesTree from pre-filled maps of bindings. + BoundNodesTree(const std::map& DeclBindings, + const std::map& StmtBindings, + const std::vector RecursiveBindings); + + /// \brief Adds all bound nodes to bound_nodes_builder. + void copyTo(BoundNodesTreeBuilder* Builder) const; + + /// \brief Visits all matches that this BoundNodesTree represents. + /// + /// The ownership of 'ResultVisitor' remains at the caller. + void visitMatches(Visitor* ResultVisitor); + +private: + void visitMatchesRecursively( + Visitor* ResultVistior, + std::map DeclBindings, + std::map StmtBindings); + + template + void copyBindingsTo(const T& bindings, BoundNodesTreeBuilder* Builder) const; + + // FIXME: Find out whether we want to use different data structures here - + // first benchmarks indicate that it doesn't matter though. + + std::map DeclBindings; + std::map StmtBindings; + + std::vector RecursiveBindings; +}; + +/// \brief Creates BoundNodesTree objects. +/// +/// The tree builder is used during the matching process to insert the bound +/// nodes from the Id matcher. +class BoundNodesTreeBuilder { +public: + BoundNodesTreeBuilder(); + + /// \brief Add a binding from an id to a node. + /// + /// FIXME: Add overloads for all AST base types. + /// @{ + void setBinding(const std::pair& binding); + void setBinding(const std::pair& binding); + /// @} + + /// \brief Adds a branch in the tree. + void addMatch(const BoundNodesTree& Bindings); + + /// \brief Returns a BoundNodes object containing all current bindings. + BoundNodesTree build() const; + +private: + BoundNodesTreeBuilder(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT + void operator=(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT + + std::map DeclBindings; + std::map StmtBindings; + + std::vector RecursiveBindings; +}; + +class ASTMatchFinder; + +/// \brief Generic interface for matchers on an AST node of type T. +/// +/// Implement this if your matcher may need to inspect the children or +/// descendants of the node or bind matched nodes to names. If you are +/// writing a simple matcher that only inspects properties of the +/// current node and doesn't care about its children or descendants, +/// implement SingleNodeMatcherInterface instead. +template +class MatcherInterface : public llvm::RefCountedBaseVPTR { +public: + virtual ~MatcherInterface() {} + + /// \brief Returns true if 'Node' can be matched. + /// + /// May bind 'Node' to an ID via 'Builder', or recurse into + /// the AST via 'Finder'. + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const = 0; +}; + +/// \brief Interface for matchers that only evaluate properties on a single node. +template +class SingleNodeMatcherInterface : public MatcherInterface { +public: + /// \brief Returns true if the matcher matches the provided node. + /// + /// A subclass must implement this instead of Matches(). + virtual bool matchesNode(const T &Node) const = 0; + +private: + /// Implements MatcherInterface::Matches. + virtual bool matches(const T &Node, + ASTMatchFinder * /* Finder */, + BoundNodesTreeBuilder * /* Builder */) const { + return matchesNode(Node); + } +}; + +/// \brief Wrapper of a MatcherInterface *that allows copying. +/// +/// A Matcher can be used anywhere a Matcher is +/// required. This establishes an is-a relationship which is reverse +/// to the AST hierarchy. In other words, Matcher is contravariant +/// with respect to T. The relationship is built via a type conversion +/// operator rather than a type hierarchy to be able to templatize the +/// type hierarchy instead of spelling it out. +template +class Matcher { +public: + /// \brief Takes ownership of the provided implementation pointer. + explicit Matcher(MatcherInterface *Implementation) + : Implementation(Implementation) {} + + /// \brief Forwards the call to the underlying MatcherInterface pointer. + bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Implementation->matches(Node, Finder, Builder); + } + + /// \brief Implicitly converts this object to a Matcher. + /// + /// Requires Derived to be derived from T. + template + operator Matcher() const { + return Matcher(new ImplicitCastMatcher(*this)); + } + + /// \brief Returns an ID that uniquely identifies the matcher. + uint64_t getID() const { + /// FIXME: Document the requirements this imposes on matcher + /// implementations (no new() implementation_ during a Matches()). + return reinterpret_cast(Implementation.getPtr()); + } + +private: + /// \brief Allows conversion from Matcher to Matcher if Derived + /// is derived from T. + template + class ImplicitCastMatcher : public MatcherInterface { + public: + explicit ImplicitCastMatcher(const Matcher &From) + : From(From) {} + + virtual bool matches(const Derived &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return From.matches(Node, Finder, Builder); + } + + private: + const Matcher From; + }; + + llvm::IntrusiveRefCntPtr< MatcherInterface > Implementation; +}; // class Matcher + +/// \brief A convenient helper for creating a Matcher without specifying +/// the template type argument. +template +inline Matcher makeMatcher(MatcherInterface *Implementation) { + return Matcher(Implementation); +} + +/// \brief Matches declarations for QualType and CallExpr. +/// +/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but +/// not actually used. +template +class HasDeclarationMatcher : public MatcherInterface { + TOOLING_COMPILE_ASSERT((llvm::is_same< DeclMatcherT, + Matcher >::value), + instantiated_with_wrong_types); +public: + explicit HasDeclarationMatcher(const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesSpecialized(Node, Finder, Builder); + } + +private: + /// \brief Extracts the CXXRecordDecl of a QualType and returns whether the + /// inner matcher matches on it. + bool matchesSpecialized(const clang::QualType &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + /// FIXME: Add other ways to convert... + clang::CXXRecordDecl *NodeAsRecordDecl = Node->getAsCXXRecordDecl(); + return NodeAsRecordDecl != NULL && + InnerMatcher.matches(*NodeAsRecordDecl, Finder, Builder); + } + + /// \brief Extracts the Decl of the callee of a CallExpr and returns whether + /// the inner matcher matches on it. + bool matchesSpecialized(const clang::CallExpr &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + const clang::Decl *NodeAsDecl = Node.getCalleeDecl(); + return NodeAsDecl != NULL && + InnerMatcher.matches(*NodeAsDecl, Finder, Builder); + } + + /// \brief Extracts the Decl of the constructor call and returns whether the + /// inner matcher matches on it. + bool matchesSpecialized(const clang::CXXConstructExpr &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + const clang::Decl *NodeAsDecl = Node.getConstructor(); + return NodeAsDecl != NULL && + InnerMatcher.matches(*NodeAsDecl, Finder, Builder); + } + + const Matcher InnerMatcher; +}; + +/// \brief IsBaseType::value is true if T is a "base" type in the AST +/// node class hierarchies (i.e. if T is Decl, Stmt, or QualType). +template +struct IsBaseType { + static const bool value = + (llvm::is_same::value || + llvm::is_same::value || + llvm::is_same::value || + llvm::is_same::value); +}; +template +const bool IsBaseType::value; + +/// \brief Interface that can match any AST base node type and contains default +/// implementations returning false. +class UntypedBaseMatcher : public llvm::RefCountedBaseVPTR { +public: + virtual ~UntypedBaseMatcher() {} + + virtual bool matches(const clang::Decl &DeclNode, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return false; + } + virtual bool matches(const clang::QualType &TypeNode, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return false; + } + virtual bool matches(const clang::Stmt &StmtNode, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return false; + } + virtual bool matches(const clang::CXXCtorInitializer &CtorInitNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return false; + } + + /// \brief Returns a unique ID for the matcher. + virtual uint64_t getID() const = 0; +}; + +/// \brief An UntypedBaseMatcher that overwrites the Matches(...) method for +/// node type T. T must be an AST base type. +template +class TypedBaseMatcher : public UntypedBaseMatcher { + TOOLING_COMPILE_ASSERT(IsBaseType::value, + typed_base_matcher_can_only_be_used_with_base_type); +public: + explicit TypedBaseMatcher(const Matcher &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + using UntypedBaseMatcher::matches; + /// \brief Implements UntypedBaseMatcher::Matches. + /// + /// Since T is guaranteed to be a "base" AST node type, this method is + /// guaranteed to override one of the matches() methods from + /// UntypedBaseMatcher. + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return InnerMatcher.matches(Node, Finder, Builder); + } + + /// \brief Implements UntypedBaseMatcher::getID. + virtual uint64_t getID() const { + return InnerMatcher.getID(); + } + +private: + Matcher InnerMatcher; +}; + +/// \brief Interface that allows matchers to traverse the AST. +/// FIXME: Find a better name. +/// +/// This provides two entry methods for each base node type in the AST: +/// - matchesChildOf: +/// Matches a matcher on every child node of the given node. Returns true +/// if at least one child node could be matched. +/// - matchesDescendantOf: +/// Matches a matcher on all descendant nodes of the given node. Returns true +/// if at least one descendant matched. +class ASTMatchFinder { +public: + /// \brief Defines how we descend a level in the AST when we pass + /// through expressions. + enum TraversalKind { + /// Will traverse any child nodes. + TK_AsIs, + /// Will not traverse implicit casts and parentheses. + TK_IgnoreImplicitCastsAndParentheses + }; + + /// \brief Defines how bindings are processed on recursive matches. + enum BindKind { + /// Stop at the first match and only bind the first match. + BK_First, + /// Create results for all combinations of bindings that match. + BK_All + }; + + virtual ~ASTMatchFinder() {} + + /// \brief 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. + virtual bool classIsDerivedFrom(const clang::CXXRecordDecl *Declaration, + StringRef BaseName) const = 0; + + // FIXME: Implement for other base nodes. + virtual bool matchesChildOf(const clang::Decl &DeclNode, + const UntypedBaseMatcher &BaseMatcher, + BoundNodesTreeBuilder *Builder, + TraversalKind Traverse, + BindKind Bind) = 0; + virtual bool matchesChildOf(const clang::Stmt &StmtNode, + const UntypedBaseMatcher &BaseMatcher, + BoundNodesTreeBuilder *Builder, + TraversalKind Traverse, + BindKind Bind) = 0; + + virtual bool matchesDescendantOf(const clang::Decl &DeclNode, + const UntypedBaseMatcher &BaseMatcher, + BoundNodesTreeBuilder *Builder, + BindKind Bind) = 0; + virtual bool matchesDescendantOf(const clang::Stmt &StmtNode, + const UntypedBaseMatcher &BaseMatcher, + BoundNodesTreeBuilder *Builder, + BindKind Bind) = 0; +}; + +/// \brief Converts a Matcher to a matcher of desired type To by "adapting" +/// a To into a T. +/// +/// The ArgumentAdapterT argument specifies how the adaptation is done. +/// +/// For example: +/// ArgumentAdaptingMatcher(InnerMatcher); +/// returns a matcher that can be used where a Matcher is required, if +/// To and T are in the same type hierarchy, and thus dyn_cast can be +/// called to convert a To to a T. +/// +/// FIXME: Make sure all our applications of this class actually require +/// knowledge about the inner type. DynCastMatcher obviously does, but the +/// Has *matchers require the inner type solely for COMPILE_ASSERT purposes. +template