diff options
Diffstat (limited to 'include/clang/ASTMatchers/ASTMatchers.h')
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchers.h | 1799 |
1 files changed, 1799 insertions, 0 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h new file mode 100644 index 0000000..37e82e8 --- /dev/null +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -0,0 +1,1799 @@ +//===--- 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/AST/DeclTemplate.h" +#include "clang/ASTMatchers/ASTMatchersInternal.h" +#include "clang/ASTMatchers/ASTMatchersMacros.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Regex.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 <typename T> + const T *getDeclAs(StringRef ID) const { + return getNodeAs<T>(DeclBindings, ID); + } + template <typename T> + const T *getStmtAs(StringRef ID) const { + return getNodeAs<T>(StmtBindings, ID); + } + /// @} + +private: + /// \brief Create BoundNodes from a pre-filled map of bindings. + BoundNodes(const std::map<std::string, const Decl*> &DeclBindings, + const std::map<std::string, const Stmt*> &StmtBindings) + : DeclBindings(DeclBindings), StmtBindings(StmtBindings) {} + + template <typename T, typename MapT> + 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<T>(It->second); + } + + std::map<std::string, const Decl*> DeclBindings; + std::map<std::string, const Stmt*> 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 <typename T> +internal::Matcher<T> id(const std::string &ID, + const internal::BindableMatcher<T> &InnerMatcher) { + return InnerMatcher.bind(ID); +} + +/// \brief Types of matchers for the top-level classes in the AST class +/// hierarchy. +/// @{ +typedef internal::Matcher<Decl> DeclarationMatcher; +typedef internal::Matcher<QualType> TypeMatcher; +typedef internal::Matcher<Stmt> 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<internal::TrueMatcher> anything() { + return internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>(); +} + +/// \brief Matches declarations. +/// +/// Examples matches \c X, \c C, and the friend declaration inside \c C; +/// \code +/// void X(); +/// class C { +/// friend X; +/// }; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Decl, Decl> decl; + +/// \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< + Decl, + NamedDecl> nameableDeclaration; + +/// \brief Matches C++ class declarations. +/// +/// Example matches X, Z +/// class X; +/// template<class T> class Z {}; +const internal::VariadicDynCastAllOfMatcher< + Decl, + CXXRecordDecl> record; + +/// \brief Matches C++ class template specializations. +/// +/// Given +/// template<typename T> class A {}; +/// template<> class A<double> {}; +/// A<int> a; +/// classTemplateSpecialization() +/// matches the specializations \c A<int> and \c A<double> +const internal::VariadicDynCastAllOfMatcher< + Decl, + ClassTemplateSpecializationDecl> classTemplateSpecialization; + +/// \brief Matches classTemplateSpecializations that have at least one +/// TemplateArgument matching the given Matcher. +/// +/// Given +/// template<typename T> class A {}; +/// template<> class A<double> {}; +/// A<int> a; +/// classTemplateSpecialization(hasAnyTemplateArgument( +/// refersToType(asString("int")))) +/// matches the specialization \c A<int> +AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument, + internal::Matcher<TemplateArgument>, Matcher) { + const TemplateArgumentList &List = Node.getTemplateArgs(); + for (unsigned i = 0; i < List.size(); ++i) { + if (Matcher.matches(List.get(i), Finder, Builder)) + return true; + } + return false; +} + +/// \brief Matches classTemplateSpecializations where the n'th TemplateArgument +/// matches the given Matcher. +/// +/// Given +/// template<typename T, typename U> class A {}; +/// A<bool, int> b; +/// A<int, bool> c; +/// classTemplateSpecialization(hasTemplateArgument( +/// 1, refersToType(asString("int")))) +/// matches the specialization \c A<bool, int> +AST_MATCHER_P2(ClassTemplateSpecializationDecl, hasTemplateArgument, + unsigned, N, internal::Matcher<TemplateArgument>, Matcher) { + const TemplateArgumentList &List = Node.getTemplateArgs(); + if (List.size() <= N) + return false; + return Matcher.matches(List.get(N), Finder, Builder); +} + +/// \brief Matches a TemplateArgument that refers to a certain type. +/// +/// Given +/// struct X {}; +/// template<typename T> struct A {}; +/// A<X> a; +/// classTemplateSpecialization(hasAnyTemplateArgument( +/// refersToType(class(hasName("X"))))) +/// matches the specialization \c A<X> +AST_MATCHER_P(TemplateArgument, refersToType, + internal::Matcher<QualType>, Matcher) { + if (Node.getKind() != TemplateArgument::Type) + return false; + return Matcher.matches(Node.getAsType(), Finder, Builder); +} + +/// \brief Matches a TemplateArgument that refers to a certain declaration. +/// +/// Given +/// template<typename T> struct A {}; +/// struct B { B* next; }; +/// A<&B::next> a; +/// classTemplateSpecialization(hasAnyTemplateArgument( +/// refersToDeclaration(field(hasName("next")))) +/// matches the specialization \c A<&B::next> with \c field(...) matching +/// \c B::next +AST_MATCHER_P(TemplateArgument, refersToDeclaration, + internal::Matcher<Decl>, Matcher) { + if (const Decl *Declaration = Node.getAsDecl()) + return Matcher.matches(*Declaration, Finder, Builder); + return false; +} + +/// \brief Matches C++ constructor declarations. +/// +/// Example matches Foo::Foo() and Foo::Foo(int) +/// class Foo { +/// public: +/// Foo(); +/// Foo(int); +/// int DoSomething(); +/// }; +const internal::VariadicDynCastAllOfMatcher< + Decl, + CXXConstructorDecl> constructor; + +/// \brief Matches explicit C++ destructor declarations. +/// +/// Example matches Foo::~Foo() +/// class Foo { +/// public: +/// virtual ~Foo(); +/// }; +const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> destructor; + +/// \brief Matches enum declarations. +/// +/// Example matches X +/// enum X { +/// A, B, C +/// }; +const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; + +/// \brief Matches enum constants. +/// +/// Example matches A, B, C +/// enum X { +/// A, B, C +/// }; +const internal::VariadicDynCastAllOfMatcher< + Decl, + EnumConstantDecl> enumConstant; + +/// \brief Matches method declarations. +/// +/// Example matches y +/// class X { void y() }; +const internal::VariadicDynCastAllOfMatcher<Decl, 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<Decl, VarDecl> variable; + +/// \brief Matches field declarations. +/// +/// Given +/// class X { int m; }; +/// field() +/// matches 'm'. +const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> field; + +/// \brief Matches function declarations. +/// +/// Example matches f +/// void f(); +const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> function; + + +/// \brief Matches statements. +/// +/// Given +/// { ++a; } +/// statement() +/// matches both the compound statement '{ ++a; }' and '++a'. +const internal::VariadicDynCastAllOfMatcher<Stmt, Stmt> statement; + +/// \brief Matches declaration statements. +/// +/// Given +/// int a; +/// declarationStatement() +/// matches 'int a'. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + 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< + Stmt, + MemberExpr> memberExpression; + +/// \brief Matches call expressions. +/// +/// Example matches x.y() and y() +/// X x; +/// x.y(); +/// y(); +const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> call; + +/// \brief Matches member call expressions. +/// +/// Example matches x.y() +/// X x; +/// x.y(); +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr> memberCall; + +/// \brief Matches init list expressions. +/// +/// Given +/// int a[] = { 1, 2 }; +/// struct B { int x, y; }; +/// B b = { 5, 6 }; +/// initList() +/// matches "{ 1, 2 }" and "{ 5, 6 }" +const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr; + +/// \brief Matches using declarations. +/// +/// Given +/// namespace X { int x; } +/// using X::x; +/// usingDecl() +/// matches \code using X::x \endcode +const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; + +/// \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< + Stmt, + CXXConstructExpr> constructorCall; + +/// \brief Matches nodes where temporaries are created. +/// +/// Example matches FunctionTakesString(GetStringByValue()) +/// (matcher = bindTemporaryExpression()) +/// FunctionTakesString(GetStringByValue()); +/// FunctionTakesStringByPointer(GetStringPointer()); +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXBindTemporaryExpr> bindTemporaryExpression; + +/// \brief Matches new expressions. +/// +/// Given +/// new X; +/// newExpression() +/// matches 'new X'. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXNewExpr> newExpression; + +/// \brief Matches delete expressions. +/// +/// Given +/// delete X; +/// deleteExpression() +/// matches 'delete X'. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXDeleteExpr> deleteExpression; + +/// \brief Matches array subscript expressions. +/// +/// Given +/// int i = a[1]; +/// arraySubscriptExpr() +/// matches "a[1]" +const internal::VariadicDynCastAllOfMatcher< + Stmt, + ArraySubscriptExpr> arraySubscriptExpr; + +/// \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< + Stmt, + 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< + Stmt, + CXXOperatorCallExpr> overloadedOperatorCall; + +/// \brief Matches expressions. +/// +/// Example matches x() +/// void f() { x(); } +const internal::VariadicDynCastAllOfMatcher< + Stmt, + Expr> expression; + +/// \brief Matches expressions that refer to declarations. +/// +/// Example matches x in if (x) +/// bool x; +/// if (x) {} +const internal::VariadicDynCastAllOfMatcher< + Stmt, + DeclRefExpr> declarationReference; + +/// \brief Matches if statements. +/// +/// Example matches 'if (x) {}' +/// if (x) {} +const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; + +/// \brief Matches for statements. +/// +/// Example matches 'for (;;) {}' +/// for (;;) {} +const internal::VariadicDynCastAllOfMatcher< + Stmt, ForStmt> forStmt; + +/// \brief Matches the increment statement of a for loop. +/// +/// Example: +/// forStmt(hasIncrement(unaryOperator(hasOperatorName("++")))) +/// matches '++x' in +/// for (x; x < N; ++x) { } +AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>, + InnerMatcher) { + const Stmt *const Increment = Node.getInc(); + return (Increment != NULL && + InnerMatcher.matches(*Increment, Finder, Builder)); +} + +/// \brief Matches the initialization statement of a for loop. +/// +/// Example: +/// forStmt(hasLoopInit(declarationStatement())) +/// matches 'int x = 0' in +/// for (int x = 0; x < N; ++x) { } +AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>, + InnerMatcher) { + const Stmt *const Init = Node.getInit(); + return (Init != NULL && InnerMatcher.matches(*Init, Finder, Builder)); +} + +/// \brief Matches while statements. +/// +/// Given +/// while (true) {} +/// whileStmt() +/// matches 'while (true) {}'. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + WhileStmt> whileStmt; + +/// \brief Matches do statements. +/// +/// Given +/// do {} while (true); +/// doStmt() +/// matches 'do {} while(true)' +const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> 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< + Stmt, + SwitchCase> switchCase; + +/// \brief Matches compound statements. +/// +/// Example matches '{}' and '{{}}'in 'for (;;) {{}}' +/// for (;;) {{}} +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CompoundStmt> compoundStatement; + +/// \brief Matches bool literals. +/// +/// Example matches true +/// true +const internal::VariadicDynCastAllOfMatcher< + Expr, + 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< + Expr, + 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< + Expr, + 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< + Expr, + IntegerLiteral> integerLiteral; + +/// \brief Matches binary operator expressions. +/// +/// Example matches a || b +/// !(a || b) +const internal::VariadicDynCastAllOfMatcher< + Stmt, + BinaryOperator> binaryOperator; + +/// \brief Matches unary operator expressions. +/// +/// Example matches !a +/// !a || b +const internal::VariadicDynCastAllOfMatcher< + Stmt, + UnaryOperator> unaryOperator; + +/// \brief Matches conditional operator expressions. +/// +/// Example matches a ? b : c +/// (a ? b : c) + 42 +const internal::VariadicDynCastAllOfMatcher< + Stmt, + 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<char*>(&p) in +/// void* p = reinterpret_cast<char*>(&p); +const internal::VariadicDynCastAllOfMatcher< + Expr, + CXXReinterpretCastExpr> reinterpretCast; + +/// \brief Matches a C++ static_cast expression. +/// +/// \see hasDestinationType +/// \see reinterpretCast +/// +/// Example: +/// staticCast() +/// matches +/// static_cast<long>(8) +/// in +/// long eight(static_cast<long>(8)); +const internal::VariadicDynCastAllOfMatcher< + Expr, + CXXStaticCastExpr> staticCast; + +/// \brief Matches a dynamic_cast expression. +/// +/// Example: +/// dynamicCast() +/// matches +/// dynamic_cast<D*>(&b); +/// in +/// struct B { virtual ~B() {} }; struct D : B {}; +/// B b; +/// D* p = dynamic_cast<D*>(&b); +const internal::VariadicDynCastAllOfMatcher< + Expr, + CXXDynamicCastExpr> dynamicCast; + +/// \brief Matches a const_cast expression. +/// +/// Example: Matches const_cast<int*>(&r) in +/// int n = 42; +/// const int& r(n); +/// int* p = const_cast<int*>(&r); +const internal::VariadicDynCastAllOfMatcher< + Expr, + 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<int>(static_cast<int>(const_cast<int>(42))))) +/// but does not match the implicit conversion in +/// long ell = 42; +const internal::VariadicDynCastAllOfMatcher< + Expr, + 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< + Expr, + 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< + Expr, + CXXFunctionalCastExpr> functionalCast; + +/// \brief Various overloads for the anyOf matcher. +/// @{ +template<typename C1, typename C2> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1, C2> +anyOf(const C1 &P1, const C2 &P2) { + return internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, + C1, C2 >(P1, P2); +} +template<typename C1, typename C2, typename C3> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2, C3> > +anyOf(const C1 &P1, const C2 &P2, const C3 &P3) { + return anyOf(P1, anyOf(P2, P3)); +} +template<typename C1, typename C2, typename C3, typename C4> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, + C3, C4> > > +anyOf(const C1 &P1, const C2 &P2, const C3 &P3, const C4 &P4) { + return anyOf(P1, anyOf(P2, anyOf(P3, P4))); +} +template<typename C1, typename C2, typename C3, typename C4, typename C5> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C3, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, + C4, C5> > > > +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<typename C1, typename C2> +internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C1, C2> +allOf(const C1 &P1, const C2 &P2) { + return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, + C1, C2>(P1, P2); +} +template<typename C1, typename C2, typename C3> +internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C1, + internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C2, C3> > +allOf(const C1& P1, const C2& P2, const C3& P3) { + return allOf(P1, allOf(P2, P3)); +} +/// @} + +/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL) +/// +/// Given +/// Foo x = bar; +/// int y = sizeof(x) + alignof(x); +/// unaryExprOrTypeTraitExpr() +/// matches \c sizeof(x) and \c alignof(x) +const internal::VariadicDynCastAllOfMatcher< + Stmt, + UnaryExprOrTypeTraitExpr> unaryExprOrTypeTraitExpr; + +/// \brief Matches unary expressions that have a specific type of argument. +/// +/// Given +/// int a, c; float b; int s = sizeof(a) + sizeof(b) + alignof(c); +/// unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int")) +/// matches \c sizeof(a) and \c alignof(c) +AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType, + internal::Matcher<QualType>, Matcher) { + const QualType ArgumentType = Node.getTypeOfArgument(); + return Matcher.matches(ArgumentType, Finder, Builder); +} + +/// \brief Matches unary expressions of a certain kind. +/// +/// Given +/// int x; +/// int s = sizeof(x) + alignof(x) +/// unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf)) +/// matches \c sizeof(x) +AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { + return Node.getKind() == Kind; +} + +/// \brief Same as unaryExprOrTypeTraitExpr, but only matching +/// alignof. +inline internal::Matcher<Stmt> alignOfExpr( + const internal::Matcher<UnaryExprOrTypeTraitExpr> &Matcher) { + return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( + ofKind(UETT_AlignOf), Matcher))); +} + +/// \brief Same as unaryExprOrTypeTraitExpr, but only matching +/// sizeof. +inline internal::Matcher<Stmt> sizeOfExpr( + const internal::Matcher<UnaryExprOrTypeTraitExpr> &Matcher) { + return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( + ofKind(UETT_SizeOf), Matcher))); +} + +/// \brief Matches NamedDecl nodes that have the specified name. +/// +/// Supports specifying enclosing namespaces or classes by prefixing the name +/// with '<enclosing>::'. +/// 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(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 NamedDecl nodes whose full names partially match the +/// given RegExp. +/// +/// Supports specifying enclosing namespaces or classes by +/// prefixing the name with '<enclosing>::'. Does not match typedefs +/// of an underlying type with the given name. +/// +/// Example matches X (regexp == "::X") +/// class X; +/// +/// Example matches X (regexp is one of "::X", "^foo::.*X", among others) +/// namespace foo { namespace bar { class X; } } +AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { + assert(!RegExp.empty()); + std::string FullNameString = "::" + Node.getQualifiedNameAsString(); + llvm::Regex RE(RegExp); + return RE.match(FullNameString); +} + +/// \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(CXXOperatorCallExpr, + hasOverloadedOperatorName, std::string, Name) { + return getOperatorSpelling(Node.getOperator()) == Name; +} + +/// \brief Matches C++ classes that are directly or indirectly derived from +/// a class matching \c Base. +/// +/// Note that a class is considered to be also derived from itself. +/// +/// Example matches X, Y, Z, C (Base == hasName("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(hasName("X")): +/// class Foo; +/// typedef Foo X; +/// class Bar : public Foo {}; // derived from a type that X is a typedef of +AST_MATCHER_P(CXXRecordDecl, isDerivedFrom, + internal::Matcher<NamedDecl>, Base) { + return Finder->classIsDerivedFrom(&Node, Base, Builder); +} + +/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)). +inline internal::Matcher<CXXRecordDecl> isDerivedFrom(StringRef BaseName) { + assert(!BaseName.empty()); + return isDerivedFrom(hasName(BaseName)); +} + +/// \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 <typename ChildT> +internal::ArgumentAdaptingMatcher<internal::HasMatcher, ChildT> has( + const internal::Matcher<ChildT> &ChildMatcher) { + return internal::ArgumentAdaptingMatcher<internal::HasMatcher, + ChildT>(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 <typename DescendantT> +internal::ArgumentAdaptingMatcher<internal::HasDescendantMatcher, DescendantT> +hasDescendant(const internal::Matcher<DescendantT> &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 <typename ChildT> +internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT> forEach( + const internal::Matcher<ChildT>& 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 <typename DescendantT> +internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, DescendantT> +forEachDescendant( + const internal::Matcher<DescendantT>& 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 <typename M> +internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M> 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. +/// +/// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr> +inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, + internal::Matcher<Decl> > + hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) { + return internal::PolymorphicMatcherWithParam1< + internal::HasDeclarationMatcher, + internal::Matcher<Decl> >(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(CXXMemberCallExpr, on, internal::Matcher<Expr>, + InnerMatcher) { + const Expr *ExprNode = const_cast<CXXMemberCallExpr&>(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<Expr> +/// because this introduces ambiguous overloads with calls to Callee taking a +/// internal::Matcher<Decl>, as the matcher hierarchy is purely +/// implemented in terms of implicit casts. +AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>, + InnerMatcher) { + const 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<CallExpr> callee( + const internal::Matcher<Decl> &InnerMatcher) { + return internal::Matcher<CallExpr>(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<QualType>, + InnerMatcher) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<Expr, NodeType>::value || + llvm::is_base_of<ValueDecl, NodeType>::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; } +/// +/// Usable as: Matcher<Expr>, Matcher<ValueDecl> +inline internal::PolymorphicMatcherWithParam1< + internal::matcher_hasTypeMatcher, + internal::Matcher<QualType> > +hasType(const internal::Matcher<Decl> &InnerMatcher) { + return hasType(internal::Matcher<QualType>( + hasDeclaration(InnerMatcher))); +} + +/// \brief Matches if the matched type is represented by the given string. +/// +/// Given +/// class Y { public: void x(); }; +/// void z() { Y* y; y->x(); } +/// call(on(hasType(asString("class Y *")))) +/// matches y->x() +AST_MATCHER_P(QualType, asString, std::string, Name) { + return Name == Node.getAsString(); +} + +/// \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( + QualType, pointsTo, internal::Matcher<QualType>, + InnerMatcher) { + return (!Node.isNull() && Node->isPointerType() && + InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); +} + +/// \brief Overloaded to match the pointee type's declaration. +inline internal::Matcher<QualType> pointsTo( + const internal::Matcher<Decl> &InnerMatcher) { + return pointsTo(internal::Matcher<QualType>( + 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(QualType, references, internal::Matcher<QualType>, + InnerMatcher) { + return (!Node.isNull() && Node->isReferenceType() && + InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); +} + +/// \brief Overloaded to match the referenced type's declaration. +inline internal::Matcher<QualType> references( + const internal::Matcher<Decl> &InnerMatcher) { + return references(internal::Matcher<QualType>( + hasDeclaration(InnerMatcher))); +} + +AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument, + internal::Matcher<Expr>, InnerMatcher) { + const Expr *ExprNode = + const_cast<CXXMemberCallExpr&>(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<CXXMemberCallExpr> thisPointerType( + const internal::Matcher<QualType> &InnerMatcher) { + return onImplicitObjectArgument( + anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher)))); +} + +/// \brief Overloaded to match the type's declaration. +inline internal::Matcher<CXXMemberCallExpr> thisPointerType( + const internal::Matcher<Decl> &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(DeclRefExpr, to, internal::Matcher<Decl>, + InnerMatcher) { + const Decl *DeclNode = Node.getDecl(); + return (DeclNode != NULL && + InnerMatcher.matches(*DeclNode, Finder, Builder)); +} + +/// \brief Matches a \c DeclRefExpr that refers to a declaration through a +/// specific using shadow declaration. +/// +/// FIXME: This currently only works for functions. Fix. +/// +/// Given +/// namespace a { void f() {} } +/// using a::f; +/// void g() { +/// f(); // Matches this .. +/// a::f(); // .. but not this. +/// } +/// declarationReference(throughUsingDeclaration(anything())) +/// matches \c f() +AST_MATCHER_P(DeclRefExpr, throughUsingDecl, + internal::Matcher<UsingShadowDecl>, Matcher) { + const NamedDecl *FoundDecl = Node.getFoundDecl(); + if (const UsingShadowDecl *UsingDecl = + llvm::dyn_cast<UsingShadowDecl>(FoundDecl)) + return Matcher.matches(*UsingDecl, Finder, Builder); + return false; +} + +/// \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( + VarDecl, hasInitializer, internal::Matcher<Expr>, + InnerMatcher) { + const 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<CallExpr, NodeType>::value || + llvm::is_base_of<CXXConstructExpr, + NodeType>::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<Expr>, InnerMatcher) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value || + llvm::is_base_of<CXXConstructExpr, + NodeType>::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())))) +/// record matches Foo, hasAnyConstructorInitializer matches foo_(1) +AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, + internal::Matcher<CXXCtorInitializer>, InnerMatcher) { + for (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(CXXCtorInitializer, forField, + internal::Matcher<FieldDecl>, InnerMatcher) { + const 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(CXXCtorInitializer, withInitializer, + internal::Matcher<Expr>, InnerMatcher) { + const 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(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(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<Expr>, + InnerMatcher) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value || + llvm::is_base_of<CXXConstructExpr, + NodeType>::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(FunctionDecl, hasParameter, + unsigned, N, internal::Matcher<ParmVarDecl>, + 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(FunctionDecl, hasAnyParameter, + internal::Matcher<ParmVarDecl>, InnerMatcher) { + for (unsigned I = 0; I < Node.getNumParams(); ++I) { + if (InnerMatcher.matches(*Node.getParamDecl(I), Finder, Builder)) { + return true; + } + } + return false; +} + +/// \brief Matches the return type of a function declaration. +/// +/// Given: +/// class X { int f() { return 1; } }; +/// method(returns(asString("int"))) +/// matches int f() { return 1; } +AST_MATCHER_P(FunctionDecl, returns, internal::Matcher<QualType>, Matcher) { + return Matcher.matches(Node.getResultType(), Finder, Builder); +} + +/// \brief Matches the condition expression of an if statement, for loop, +/// or conditional operator. +/// +/// Example matches true (matcher = hasCondition(boolLiteral(equals(true)))) +/// if (true) {} +AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher<Expr>, + InnerMatcher) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of<IfStmt, NodeType>::value) || + (llvm::is_base_of<ForStmt, NodeType>::value) || + (llvm::is_base_of<WhileStmt, NodeType>::value) || + (llvm::is_base_of<DoStmt, NodeType>::value) || + (llvm::is_base_of<ConditionalOperator, NodeType>::value), + has_condition_requires_if_statement_conditional_operator_or_loop); + const 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(IfStmt, hasConditionVariableStatement, + internal::Matcher<DeclStmt>, InnerMatcher) { + const DeclStmt* const DeclarationStatement = + Node.getConditionVariableDeclStmt(); + return DeclarationStatement != NULL && + InnerMatcher.matches(*DeclarationStatement, Finder, Builder); +} + +/// \brief Matches the index expression of an array subscript expression. +/// +/// Given +/// int i[5]; +/// void f() { i[1] = 42; } +/// arraySubscriptExpression(hasIndex(integerLiteral())) +/// matches \c i[1] with the \c integerLiteral() matching \c 1 +AST_MATCHER_P(ArraySubscriptExpr, hasIndex, + internal::Matcher<Expr>, matcher) { + if (const Expr* Expression = Node.getIdx()) + return matcher.matches(*Expression, Finder, Builder); + return false; +} + +/// \brief Matches the base expression of an array subscript expression. +/// +/// Given +/// int i[5]; +/// void f() { i[1] = 42; } +/// arraySubscriptExpression(hasBase(implicitCast( +/// hasSourceExpression(declarationReference())))) +/// matches \c i[1] with the \c declarationReference() matching \c i +AST_MATCHER_P(ArraySubscriptExpr, hasBase, + internal::Matcher<Expr>, matcher) { + if (const Expr* Expression = Node.getBase()) + return matcher.matches(*Expression, Finder, Builder); + return false; +} + +/// \brief Matches a 'for', 'while', or 'do while' statement that has +/// a given body. +/// +/// Given +/// for (;;) {} +/// hasBody(compoundStatement()) +/// matches 'for (;;) {}' +/// with compoundStatement() +/// matching '{}' +AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>, + InnerMatcher) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of<DoStmt, NodeType>::value) || + (llvm::is_base_of<ForStmt, NodeType>::value) || + (llvm::is_base_of<WhileStmt, NodeType>::value), + has_body_requires_for_while_or_do_statement); + const 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(CompoundStmt, hasAnySubstatement, + internal::Matcher<Stmt>, InnerMatcher) { + for (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(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 +/// +/// Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteral>, +/// Matcher<FloatingLiteral>, Matcher<IntegerLiteral> +template <typename ValueT> +internal::PolymorphicMatcherWithParam1<internal::ValueEqualsMatcher, ValueT> +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<BinaryOperator, NodeType>::value) || + (llvm::is_base_of<UnaryOperator, NodeType>::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(BinaryOperator, hasLHS, + internal::Matcher<Expr>, InnerMatcher) { + 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(BinaryOperator, hasRHS, + internal::Matcher<Expr>, InnerMatcher) { + 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<BinaryOperator> hasEitherOperand( + const internal::Matcher<Expr> &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(UnaryOperator, hasUnaryOperand, + internal::Matcher<Expr>, InnerMatcher) { + const Expr * const Operand = Node.getSubExpr(); + return (Operand != NULL && + InnerMatcher.matches(*Operand, Finder, Builder)); +} + +/// \brief Matches if the 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(CastExpr, hasSourceExpression, + internal::Matcher<Expr>, InnerMatcher) { + const 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(ExplicitCastExpr, hasDestinationType, + internal::Matcher<QualType>, InnerMatcher) { + const 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(ImplicitCastExpr, hasImplicitDestinationType, + internal::Matcher<QualType>, 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(ConditionalOperator, hasTrueExpression, + internal::Matcher<Expr>, InnerMatcher) { + 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(ConditionalOperator, hasFalseExpression, + internal::Matcher<Expr>, InnerMatcher) { + 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. +/// +/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl> +inline internal::PolymorphicMatcherWithParam0<internal::IsDefinitionMatcher> +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(CXXMethodDecl, ofClass, + internal::Matcher<CXXRecordDecl>, InnerMatcher) { + const 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<MemberExpr> isArrow() { + return makeMatcher(new internal::IsArrowMatcher()); +} + +/// \brief Matches QualType nodes that are of integer type. +/// +/// Given +/// void a(int); +/// void b(long); +/// void c(double); +/// function(hasAnyParameter(hasType(isInteger()))) +/// matches "a(int)", "b(long)", but not "c(double)". +AST_MATCHER(QualType, isInteger) { + return Node->isIntegerType(); +} + +/// \brief Matches 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<QualType> 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(MemberExpr, member, + internal::Matcher<ValueDecl>, 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(MemberExpr, hasObjectExpression, + internal::Matcher<Expr>, InnerMatcher) { + return InnerMatcher.matches(*Node.getBase(), Finder, Builder); +} + +/// \brief Matches any using shadow declaration. +/// +/// Given +/// namespace X { void b(); } +/// using X::b; +/// usingDecl(hasAnyUsingShadowDecl(hasName("b")))) +/// matches \code using X::b \endcode +AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl, + internal::Matcher<UsingShadowDecl>, Matcher) { + for (UsingDecl::shadow_iterator II = Node.shadow_begin(); + II != Node.shadow_end(); ++II) { + if (Matcher.matches(**II, Finder, Builder)) + return true; + } + return false; +} + +/// \brief Matches a using shadow declaration where the target declaration is +/// matched by the given matcher. +/// +/// Given +/// namespace X { int a; void b(); } +/// using X::a; +/// using X::b; +/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(function()))) +/// matches \code using X::b \endcode +/// but not \code using X::a \endcode +AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, + internal::Matcher<NamedDecl>, Matcher) { + return Matcher.matches(*Node.getTargetDecl(), Finder, Builder); +} + +/// \brief Matches template instantiations of function, class, or static +/// member variable template instantiations. +/// +/// Given +/// template <typename T> class X {}; class A {}; X<A> x; +/// or +/// template <typename T> class X {}; class A {}; template class X<A>; +/// record(hasName("::X"), isTemplateInstantiation()) +/// matches the template instantiation of X<A>. +/// +/// But given +/// template <typename T> class X {}; class A {}; +/// template <> class X<A> {}; X<A> x; +/// record(hasName("::X"), isTemplateInstantiation()) +/// does not match, as X<A> is an explicit template specialization. +/// +/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> +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 |