diff options
Diffstat (limited to 'include/clang/ASTMatchers/ASTMatchers.h')
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchers.h | 1445 |
1 files changed, 1185 insertions, 260 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 33ef3dc..a70dd5c 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -14,7 +14,7 @@ // 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")) +// recordDecl(hasName("MyClass")) // which returns a matcher that can be used to find all AST nodes that declare // a class named 'MyClass'. // @@ -25,7 +25,7 @@ // // For example, when we're interested in child classes of a certain class, we // would write: -// record(hasName("MyClass"), hasChild(id("child", record()))) +// recordDecl(hasName("MyClass"), hasChild(id("child", recordDecl()))) // 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 @@ -57,52 +57,47 @@ 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 bound nodes are generated by calling \c bind("id") on the node matchers +/// of the nodes we want to access later. /// -/// The instances of BoundNodes are created by MatchFinder when the user's +/// The instances of BoundNodes are created by \c 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 + /// \brief Returns the AST node bound to \c ID. + /// + /// Returns NULL if there was no node bound to \c 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 *getNodeAs(StringRef ID) const { + return MyBoundNodes.getNodeAs<T>(ID); + } + + /// \brief Deprecated. Please use \c getNodeAs instead. /// @{ template <typename T> const T *getDeclAs(StringRef ID) const { - return getNodeAs<T>(DeclBindings, ID); + return getNodeAs<T>(ID); } template <typename T> const T *getStmtAs(StringRef ID) const { - return getNodeAs<T>(StmtBindings, ID); + return getNodeAs<T>(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); - } + BoundNodes(internal::BoundNodesMap &MyBoundNodes) + : MyBoundNodes(MyBoundNodes) {} - std::map<std::string, const Decl*> DeclBindings; - std::map<std::string, const Stmt*> StmtBindings; + internal::BoundNodesMap MyBoundNodes; friend class internal::BoundNodesTree; }; -/// \brief If the provided matcher matches a node, binds the node to 'ID'. +/// \brief If the provided matcher matches a node, binds the node to \c ID. /// -/// FIXME: Add example for accessing it. +/// FIXME: Do we want to support this now that we have bind()? template <typename T> internal::Matcher<T> id(const std::string &ID, const internal::BindableMatcher<T> &InnerMatcher) { @@ -113,20 +108,27 @@ internal::Matcher<T> id(const std::string &ID, /// hierarchy. /// @{ typedef internal::Matcher<Decl> DeclarationMatcher; -typedef internal::Matcher<QualType> TypeMatcher; typedef internal::Matcher<Stmt> StatementMatcher; +typedef internal::Matcher<QualType> TypeMatcher; +typedef internal::Matcher<TypeLoc> TypeLocMatcher; +typedef internal::Matcher<NestedNameSpecifier> NestedNameSpecifierMatcher; +typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher; /// @} /// \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. +/// to an \c internal::Matcher<> type such as \c TypeMatcher. /// -/// Example: DeclarationMatcher(anything()) matches all declarations, e.g., +/// Example: \c DeclarationMatcher(anything()) matches all declarations, e.g., +/// \code /// "int* p" and "void f()" in /// int* p; /// void f(); +/// \endcode +/// +/// Usable as: Any Matcher inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher> anything() { return internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>(); } @@ -144,53 +146,69 @@ 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; +/// Example matches \c X, \c S, the anonymous union type, \c i, and \c U; +/// \code /// typedef int X; /// struct S { /// union { /// int i; /// } U; /// }; -const internal::VariadicDynCastAllOfMatcher< - Decl, - NamedDecl> nameableDeclaration; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl; /// \brief Matches C++ class declarations. /// -/// Example matches X, Z +/// Example matches \c X, \c Z +/// \code /// class X; /// template<class T> class Z {}; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Decl, - CXXRecordDecl> record; + CXXRecordDecl> recordDecl; + +/// \brief Matches C++ class template declarations. +/// +/// Example matches \c Z +/// \code +/// template<class T> class Z {}; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + ClassTemplateDecl> classTemplateDecl; /// \brief Matches C++ class template specializations. /// /// Given +/// \code /// template<typename T> class A {}; /// template<> class A<double> {}; /// A<int> a; -/// classTemplateSpecialization() +/// \endcode +/// classTemplateSpecializationDecl() /// matches the specializations \c A<int> and \c A<double> const internal::VariadicDynCastAllOfMatcher< Decl, - ClassTemplateSpecializationDecl> classTemplateSpecialization; + ClassTemplateSpecializationDecl> classTemplateSpecializationDecl; /// \brief Matches classTemplateSpecializations that have at least one -/// TemplateArgument matching the given Matcher. +/// TemplateArgument matching the given InnerMatcher. /// /// Given +/// \code /// template<typename T> class A {}; /// template<> class A<double> {}; /// A<int> a; -/// classTemplateSpecialization(hasAnyTemplateArgument( +/// \endcode +/// classTemplateSpecializationDecl(hasAnyTemplateArgument( /// refersToType(asString("int")))) /// matches the specialization \c A<int> AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument, - internal::Matcher<TemplateArgument>, Matcher) { + internal::Matcher<TemplateArgument>, InnerMatcher) { const TemplateArgumentList &List = Node.getTemplateArgs(); for (unsigned i = 0; i < List.size(); ++i) { - if (Matcher.matches(List.get(i), Finder, Builder)) + if (InnerMatcher.matches(List.get(i), Finder, Builder)) return true; } return false; @@ -201,19 +219,25 @@ AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument, /// /// Parentheses and explicit casts are not discarded. /// Given +/// \code /// int arr[5]; /// int a = 0; /// char b = 0; /// const int c = a; /// int *d = arr; /// long e = (long) 0l; +/// \endcode /// The matchers -/// variable(hasInitializer(ignoringImpCasts(integerLiteral()))) -/// variable(hasInitializer(ignoringImpCasts(declarationReference()))) +/// \code +/// varDecl(hasInitializer(ignoringImpCasts(integerLiteral()))) +/// varDecl(hasInitializer(ignoringImpCasts(declRefExpr()))) +/// \endcode /// would match the declarations for a, b, c, and d, but not e. -/// while -/// variable(hasInitializer(integerLiteral())) -/// variable(hasInitializer(declarationReference())) +/// While +/// \code +/// varDecl(hasInitializer(integerLiteral())) +/// varDecl(hasInitializer(declRefExpr())) +/// \endcode /// only match the declarations for b, c, and d. AST_MATCHER_P(Expr, ignoringImpCasts, internal::Matcher<Expr>, InnerMatcher) { @@ -225,15 +249,17 @@ AST_MATCHER_P(Expr, ignoringImpCasts, /// /// Implicit and non-C Style casts are also discarded. /// Given +/// \code /// int a = 0; /// char b = (0); /// void* c = reinterpret_cast<char*>(0); /// char d = char(0); +/// \endcode /// The matcher -/// variable(hasInitializer(ignoringParenCasts(integerLiteral()))) +/// varDecl(hasInitializer(ignoringParenCasts(integerLiteral()))) /// would match the declarations for a, b, c, and d. /// while -/// variable(hasInitializer(integerLiteral())) +/// varDecl(hasInitializer(integerLiteral())) /// only match the declaration for a. AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher<Expr>, InnerMatcher) { return InnerMatcher.matches(*Node.IgnoreParenCasts(), Finder, Builder); @@ -244,21 +270,21 @@ AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher<Expr>, InnerMatcher) { /// /// Explicit casts are not discarded. /// Given +/// \code /// int arr[5]; /// int a = 0; /// char b = (0); /// const int c = a; /// int *d = (arr); /// long e = ((long) 0l); +/// \endcode /// The matchers -/// variable(hasInitializer(ignoringParenImpCasts( -/// integerLiteral()))) -/// variable(hasInitializer(ignoringParenImpCasts( -/// declarationReference()))) +/// varDecl(hasInitializer(ignoringParenImpCasts(integerLiteral()))) +/// varDecl(hasInitializer(ignoringParenImpCasts(declRefExpr()))) /// would match the declarations for a, b, c, and d, but not e. /// while -/// variable(hasInitializer(integerLiteral())) -/// variable(hasInitializer(declarationReference())) +/// varDecl(hasInitializer(integerLiteral())) +/// varDecl(hasInitializer(declRefExpr())) /// would only match the declaration for a. AST_MATCHER_P(Expr, ignoringParenImpCasts, internal::Matcher<Expr>, InnerMatcher) { @@ -266,101 +292,119 @@ AST_MATCHER_P(Expr, ignoringParenImpCasts, } /// \brief Matches classTemplateSpecializations where the n'th TemplateArgument -/// matches the given Matcher. +/// matches the given InnerMatcher. /// /// Given +/// \code /// template<typename T, typename U> class A {}; /// A<bool, int> b; /// A<int, bool> c; -/// classTemplateSpecialization(hasTemplateArgument( +/// \endcode +/// classTemplateSpecializationDecl(hasTemplateArgument( /// 1, refersToType(asString("int")))) /// matches the specialization \c A<bool, int> AST_MATCHER_P2(ClassTemplateSpecializationDecl, hasTemplateArgument, - unsigned, N, internal::Matcher<TemplateArgument>, Matcher) { + unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) { const TemplateArgumentList &List = Node.getTemplateArgs(); if (List.size() <= N) return false; - return Matcher.matches(List.get(N), Finder, Builder); + return InnerMatcher.matches(List.get(N), Finder, Builder); } /// \brief Matches a TemplateArgument that refers to a certain type. /// /// Given +/// \code /// struct X {}; /// template<typename T> struct A {}; /// A<X> a; -/// classTemplateSpecialization(hasAnyTemplateArgument( +/// \endcode +/// classTemplateSpecializationDecl(hasAnyTemplateArgument( /// refersToType(class(hasName("X"))))) /// matches the specialization \c A<X> AST_MATCHER_P(TemplateArgument, refersToType, - internal::Matcher<QualType>, Matcher) { + internal::Matcher<QualType>, InnerMatcher) { if (Node.getKind() != TemplateArgument::Type) return false; - return Matcher.matches(Node.getAsType(), Finder, Builder); + return InnerMatcher.matches(Node.getAsType(), Finder, Builder); } /// \brief Matches a TemplateArgument that refers to a certain declaration. /// /// Given +/// \code /// 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 +/// \endcode +/// classTemplateSpecializationDecl(hasAnyTemplateArgument( +/// refersToDeclaration(fieldDecl(hasName("next")))) +/// matches the specialization \c A<&B::next> with \c fieldDecl(...) 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); + internal::Matcher<Decl>, InnerMatcher) { + if (Node.getKind() == TemplateArgument::Declaration) + return InnerMatcher.matches(*Node.getAsDecl(), Finder, Builder); return false; } /// \brief Matches C++ constructor declarations. /// /// Example matches Foo::Foo() and Foo::Foo(int) +/// \code /// class Foo { /// public: /// Foo(); /// Foo(int); /// int DoSomething(); /// }; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Decl, - CXXConstructorDecl> constructor; + CXXConstructorDecl> constructorDecl; /// \brief Matches explicit C++ destructor declarations. /// /// Example matches Foo::~Foo() +/// \code /// class Foo { /// public: /// virtual ~Foo(); /// }; -const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> destructor; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + CXXDestructorDecl> destructorDecl; /// \brief Matches enum declarations. /// /// Example matches X +/// \code /// enum X { /// A, B, C /// }; +/// \endcode const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; /// \brief Matches enum constants. /// /// Example matches A, B, C +/// \code /// enum X { /// A, B, C /// }; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Decl, - EnumConstantDecl> enumConstant; + EnumConstantDecl> enumConstantDecl; /// \brief Matches method declarations. /// /// Example matches y +/// \code /// class X { void y() }; -const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> method; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> methodDecl; /// \brief Matches variable declarations. /// @@ -368,76 +412,111 @@ const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> method; /// "field" declarations in Clang parlance. /// /// Example matches a +/// \code /// int a; -const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> variable; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl; /// \brief Matches field declarations. /// /// Given +/// \code /// class X { int m; }; -/// field() +/// \endcode +/// fieldDecl() /// matches 'm'. -const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> field; +const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl; /// \brief Matches function declarations. /// /// Example matches f +/// \code /// void f(); -const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> function; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl; +/// \brief Matches C++ function template declarations. +/// +/// Example matches f +/// \code +/// template<class T> void f(T t) {} +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + FunctionTemplateDecl> functionTemplateDecl; /// \brief Matches statements. /// /// Given +/// \code /// { ++a; } -/// statement() +/// \endcode +/// stmt() /// matches both the compound statement '{ ++a; }' and '++a'. -const internal::VariadicDynCastAllOfMatcher<Stmt, Stmt> statement; +const internal::VariadicDynCastAllOfMatcher<Stmt, Stmt> stmt; /// \brief Matches declaration statements. /// /// Given +/// \code /// int a; -/// declarationStatement() +/// \endcode +/// declStmt() /// matches 'int a'. const internal::VariadicDynCastAllOfMatcher< Stmt, - DeclStmt> declarationStatement; + DeclStmt> declStmt; /// \brief Matches member expressions. /// /// Given +/// \code /// class Y { /// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } /// int a; static int b; /// }; -/// memberExpression() +/// \endcode +/// memberExpr() /// matches this->x, x, y.x, a, this->b -const internal::VariadicDynCastAllOfMatcher< - Stmt, - MemberExpr> memberExpression; +const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr; /// \brief Matches call expressions. /// /// Example matches x.y() and y() +/// \code /// X x; /// x.y(); /// y(); -const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> call; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr; + +/// \brief Matches lambda expressions. +/// +/// Example matches [&](){return 5;} +/// \code +/// [&](){return 5;} +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr; /// \brief Matches member call expressions. /// /// Example matches x.y() +/// \code /// X x; /// x.y(); -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr> memberCall; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXMemberCallExpr> memberCallExpr; /// \brief Matches init list expressions. /// /// Given +/// \code /// int a[] = { 1, 2 }; /// struct B { int x, y; }; /// B b = { 5, 6 }; +/// \endcode /// initList() /// matches "{ 1, 2 }" and "{ 5, 6 }" const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr; @@ -445,8 +524,10 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr; /// \brief Matches using declarations. /// /// Given +/// \code /// namespace X { int x; } /// using X::x; +/// \endcode /// usingDecl() /// matches \code using X::x \endcode const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; @@ -454,49 +535,89 @@ 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()) +/// (matcher = constructExpr()) +/// \code /// void f(const string &a, const string &b); /// char *ptr; /// int n; /// f(string(ptr, n), ptr); +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXConstructExpr> constructorCall; + CXXConstructExpr> constructExpr; + +/// \brief Matches implicit and explicit this expressions. +/// +/// Example matches the implicit this expression in "return i". +/// (matcher = thisExpr()) +/// \code +/// struct foo { +/// int i; +/// int f() { return i; } +/// }; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> thisExpr; /// \brief Matches nodes where temporaries are created. /// /// Example matches FunctionTakesString(GetStringByValue()) -/// (matcher = bindTemporaryExpression()) +/// (matcher = bindTemporaryExpr()) +/// \code /// FunctionTakesString(GetStringByValue()); /// FunctionTakesStringByPointer(GetStringPointer()); +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXBindTemporaryExpr> bindTemporaryExpression; + CXXBindTemporaryExpr> bindTemporaryExpr; + +/// \brief Matches nodes where temporaries are materialized. +/// +/// Example: Given +/// \code +/// struct T {void func()}; +/// T f(); +/// void g(T); +/// \endcode +/// materializeTemporaryExpr() matches 'f()' in these statements +/// \code +/// T u(f()); +/// g(f()); +/// \endcode +/// but does not match +/// \code +/// f(); +/// f().func(); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + MaterializeTemporaryExpr> materializeTemporaryExpr; /// \brief Matches new expressions. /// /// Given +/// \code /// new X; -/// newExpression() +/// \endcode +/// newExpr() /// matches 'new X'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXNewExpr> newExpression; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> newExpr; /// \brief Matches delete expressions. /// /// Given +/// \code /// delete X; -/// deleteExpression() +/// \endcode +/// deleteExpr() /// matches 'delete X'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXDeleteExpr> deleteExpression; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> deleteExpr; /// \brief Matches array subscript expressions. /// /// Given +/// \code /// int i = a[1]; +/// \endcode /// arraySubscriptExpr() /// matches "a[1]" const internal::VariadicDynCastAllOfMatcher< @@ -507,12 +628,14 @@ const internal::VariadicDynCastAllOfMatcher< /// /// Example matches the CXXDefaultArgExpr placeholder inserted for the /// default value of the second parameter in the call expression f(42) -/// (matcher = defaultArgument()) +/// (matcher = defaultArgExpr()) +/// \code /// void f(int x, int y = 0); /// f(42); +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXDefaultArgExpr> defaultArgument; + CXXDefaultArgExpr> defaultArgExpr; /// \brief Matches overloaded operator calls. /// @@ -522,50 +645,67 @@ const internal::VariadicDynCastAllOfMatcher< /// FIXME: figure out why these do not match? /// /// Example matches both operator<<((o << b), c) and operator<<(o, b) -/// (matcher = overloadedOperatorCall()) +/// (matcher = operatorCallExpr()) +/// \code /// ostream &operator<< (ostream &out, int i) { }; /// ostream &o; int b = 1, c = 1; /// o << b << c; +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, - CXXOperatorCallExpr> overloadedOperatorCall; + CXXOperatorCallExpr> operatorCallExpr; /// \brief Matches expressions. /// /// Example matches x() +/// \code /// void f() { x(); } -const internal::VariadicDynCastAllOfMatcher< - Stmt, - Expr> expression; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr; /// \brief Matches expressions that refer to declarations. /// /// Example matches x in if (x) +/// \code /// bool x; /// if (x) {} -const internal::VariadicDynCastAllOfMatcher< - Stmt, - DeclRefExpr> declarationReference; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr; /// \brief Matches if statements. /// /// Example matches 'if (x) {}' +/// \code /// if (x) {} +/// \endcode const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; /// \brief Matches for statements. /// /// Example matches 'for (;;) {}' +/// \code /// for (;;) {} -const internal::VariadicDynCastAllOfMatcher< - Stmt, ForStmt> forStmt; +/// int i[] = {1, 2, 3}; for (auto a : i); +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt; + +/// \brief Matches range-based for statements. +/// +/// forRangeStmt() matches 'for (auto a : i)' +/// \code +/// int i[] = {1, 2, 3}; for (auto a : i); +/// for(int j = 0; j < 5; ++j); +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt> forRangeStmt; /// \brief Matches the increment statement of a for loop. /// /// Example: /// forStmt(hasIncrement(unaryOperator(hasOperatorName("++")))) /// matches '++x' in +/// \code /// for (x; x < N; ++x) { } +/// \endcode AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>, InnerMatcher) { const Stmt *const Increment = Node.getInc(); @@ -576,9 +716,11 @@ AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>, /// \brief Matches the initialization statement of a for loop. /// /// Example: -/// forStmt(hasLoopInit(declarationStatement())) +/// forStmt(hasLoopInit(declStmt())) /// matches 'int x = 0' in +/// \code /// for (int x = 0; x < N; ++x) { } +/// \endcode AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>, InnerMatcher) { const Stmt *const Init = Node.getInit(); @@ -588,53 +730,167 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>, /// \brief Matches while statements. /// /// Given +/// \code /// while (true) {} +/// \endcode /// whileStmt() /// matches 'while (true) {}'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - WhileStmt> whileStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt; /// \brief Matches do statements. /// /// Given +/// \code /// do {} while (true); +/// \endcode /// doStmt() /// matches 'do {} while(true)' const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt; +/// \brief Matches break statements. +/// +/// Given +/// \code +/// while (true) { break; } +/// \endcode +/// breakStmt() +/// matches 'break' +const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt; + +/// \brief Matches continue statements. +/// +/// Given +/// \code +/// while (true) { continue; } +/// \endcode +/// continueStmt() +/// matches 'continue' +const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt; + +/// \brief Matches return statements. +/// +/// Given +/// \code +/// return 1; +/// \endcode +/// returnStmt() +/// matches 'return 1' +const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt; + +/// \brief Matches goto statements. +/// +/// Given +/// \code +/// goto FOO; +/// FOO: bar(); +/// \endcode +/// gotoStmt() +/// matches 'goto FOO' +const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt; + +/// \brief Matches label statements. +/// +/// Given +/// \code +/// goto FOO; +/// FOO: bar(); +/// \endcode +/// labelStmt() +/// matches 'FOO:' +const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt; + +/// \brief Matches switch statements. +/// +/// Given +/// \code +/// switch(a) { case 42: break; default: break; } +/// \endcode +/// switchStmt() +/// matches 'switch(a)'. +const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt; + /// \brief Matches case and default statements inside switch statements. /// /// Given +/// \code /// switch(a) { case 42: break; default: break; } +/// \endcode /// switchCase() /// matches 'case 42: break;' and 'default: break;'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - SwitchCase> switchCase; +const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase; /// \brief Matches compound statements. /// /// Example matches '{}' and '{{}}'in 'for (;;) {{}}' +/// \code /// for (;;) {{}} -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CompoundStmt> compoundStatement; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt; + +/// \brief Matches catch statements. +/// +/// \code +/// try {} catch(int i) {} +/// \endcode +/// catchStmt() +/// matches 'catch(int i)' +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> catchStmt; + +/// \brief Matches try statements. +/// +/// \code +/// try {} catch(int i) {} +/// \endcode +/// tryStmt() +/// matches 'try {}' +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> tryStmt; + +/// \brief Matches throw expressions. +/// +/// \code +/// try { throw 5; } catch(int i) {} +/// \endcode +/// throwExpr() +/// matches 'throw 5' +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> throwExpr; + +/// \brief Matches null statements. +/// +/// \code +/// foo();; +/// \endcode +/// nullStmt() +/// matches the second ';' +const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt; + +/// \brief Matches asm statements. +/// +/// \code +/// int i = 100; +/// __asm("mov al, 2"); +/// \endcode +/// asmStmt() +/// matches '__asm("mov al, 2")' +const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt; /// \brief Matches bool literals. /// /// Example matches true +/// \code /// true +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, CXXBoolLiteralExpr> boolLiteral; /// \brief Matches string literals (also matches wide string literals). /// /// Example matches "abcd", L"abcd" +/// \code /// char *s = "abcd"; wchar_t *ws = L"abcd" +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, StringLiteral> stringLiteral; /// \brief Matches character literals (also matches wchar_t). @@ -643,9 +899,11 @@ const internal::VariadicDynCastAllOfMatcher< /// though. /// /// Example matches 'a', L'a' +/// \code /// char ch = 'a'; wchar_t chw = L'a'; +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, CharacterLiteral> characterLiteral; /// \brief Matches integer literals of all sizes / encodings. @@ -654,13 +912,27 @@ const internal::VariadicDynCastAllOfMatcher< /// /// Example matches 1, 1L, 0x1, 1U const internal::VariadicDynCastAllOfMatcher< - Expr, + Stmt, IntegerLiteral> integerLiteral; +/// \brief Matches user defined literal operator call. +/// +/// Example match: "foo"_suffix +const internal::VariadicDynCastAllOfMatcher< + Stmt, + UserDefinedLiteral> userDefinedLiteral; + +/// \brief Matches nullptr literal. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXNullPtrLiteralExpr> nullPtrLiteralExpr; + /// \brief Matches binary operator expressions. /// /// Example matches a || b +/// \code /// !(a || b) +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, BinaryOperator> binaryOperator; @@ -668,7 +940,9 @@ const internal::VariadicDynCastAllOfMatcher< /// \brief Matches unary operator expressions. /// /// Example matches !a +/// \code /// !a || b +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, UnaryOperator> unaryOperator; @@ -676,7 +950,9 @@ const internal::VariadicDynCastAllOfMatcher< /// \brief Matches conditional operator expressions. /// /// Example matches a ? b : c +/// \code /// (a ? b : c) + 42 +/// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, ConditionalOperator> conditionalOperator; @@ -688,10 +964,12 @@ const internal::VariadicDynCastAllOfMatcher< /// more readable. /// /// Example matches reinterpret_cast<char*>(&p) in +/// \code /// void* p = reinterpret_cast<char*>(&p); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXReinterpretCastExpr> reinterpretCast; + Stmt, + CXXReinterpretCastExpr> reinterpretCastExpr; /// \brief Matches a C++ static_cast expression. /// @@ -699,38 +977,54 @@ const internal::VariadicDynCastAllOfMatcher< /// \see reinterpretCast /// /// Example: -/// staticCast() +/// staticCastExpr() /// matches /// static_cast<long>(8) /// in +/// \code /// long eight(static_cast<long>(8)); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXStaticCastExpr> staticCast; + Stmt, + CXXStaticCastExpr> staticCastExpr; /// \brief Matches a dynamic_cast expression. /// /// Example: -/// dynamicCast() +/// dynamicCastExpr() /// matches /// dynamic_cast<D*>(&b); /// in +/// \code /// struct B { virtual ~B() {} }; struct D : B {}; /// B b; /// D* p = dynamic_cast<D*>(&b); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXDynamicCastExpr> dynamicCast; + Stmt, + CXXDynamicCastExpr> dynamicCastExpr; /// \brief Matches a const_cast expression. /// /// Example: Matches const_cast<int*>(&r) in +/// \code /// int n = 42; -/// const int& r(n); +/// const int &r(n); /// int* p = const_cast<int*>(&r); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXConstCastExpr> constCastExpr; + +/// \brief Matches a C-style cast expression. +/// +/// Example: Matches (int*) 2.2f in +/// \code +/// int i = (int) 2.2f; +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXConstCastExpr> constCast; + Stmt, + CStyleCastExpr> cStyleCastExpr; /// \brief Matches explicit cast expressions. /// @@ -746,98 +1040,127 @@ const internal::VariadicDynCastAllOfMatcher< /// \see hasDestinationType. /// /// Example: matches all five of the casts in +/// \code /// int((int)(reinterpret_cast<int>(static_cast<int>(const_cast<int>(42))))) +/// \endcode /// but does not match the implicit conversion in +/// \code /// long ell = 42; +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - ExplicitCastExpr> explicitCast; + Stmt, + ExplicitCastExpr> explicitCastExpr; /// \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; + Stmt, + ImplicitCastExpr> implicitCastExpr; /// \brief Matches any cast nodes of Clang's AST. /// /// Example: castExpr() matches each of the following: +/// \code /// (int) 3; /// const_cast<Expr *>(SubExpr); /// char c = 0; +/// \endcode /// but does not match +/// \code /// int i = (0); /// int k = 0; -const internal::VariadicDynCastAllOfMatcher< - Expr, - CastExpr> castExpr; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr; /// \brief Matches functional cast expressions /// /// Example: Matches Foo(bar); +/// \code /// Foo f = bar; /// Foo g = (Foo) bar; /// Foo h = Foo(bar); +/// \endcode const internal::VariadicDynCastAllOfMatcher< - Expr, - CXXFunctionalCastExpr> functionalCast; + Stmt, + CXXFunctionalCastExpr> functionalCastExpr; + +/// \brief Matches \c QualTypes in the clang AST. +const internal::VariadicAllOfMatcher<QualType> qualType; + +/// \brief Matches \c Types in the clang AST. +const internal::VariadicDynCastAllOfMatcher<Type, Type> type; + +/// \brief Matches \c TypeLocs in the clang AST. +const internal::VariadicDynCastAllOfMatcher<TypeLoc, TypeLoc> typeLoc; /// \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) { + +/// \brief Matches if any of the given matchers matches. +/// +/// Usable as: Any Matcher +template<typename M1, typename M2> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1, M2> +anyOf(const M1 &P1, const M2 &P2) { return internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, - C1, C2 >(P1, P2); + M1, M2 >(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) { +template<typename M1, typename M2, typename M3> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M2, M3> > +anyOf(const M1 &P1, const M2 &P2, const M3 &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, +template<typename M1, typename M2, typename M3, typename M4> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M2, internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, - C3, C4> > > -anyOf(const C1 &P1, const C2 &P2, const C3 &P3, const C4 &P4) { + M3, M4> > > +anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &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, +template<typename M1, typename M2, typename M3, typename M4, typename M5> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M2, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M3, internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, - C4, C5> > > > -anyOf(const C1& P1, const C2& P2, const C3& P3, const C4& P4, const C5& P5) { + M4, M5> > > > +anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &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) { + +/// \brief Matches if all given matchers match. +/// +/// Usable as: Any Matcher +template<typename M1, typename M2> +internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, M2> +allOf(const M1 &P1, const M2 &P2) { return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, - C1, C2>(P1, P2); + M1, M2>(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) { +template<typename M1, typename M2, typename M3> +internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, + internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M2, M3> > +allOf(const M1 &P1, const M2 &P2, const M3 &P3) { return allOf(P1, allOf(P2, P3)); } + /// @} /// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL) /// /// Given +/// \code /// Foo x = bar; /// int y = sizeof(x) + alignof(x); +/// \endcode /// unaryExprOrTypeTraitExpr() /// matches \c sizeof(x) and \c alignof(x) const internal::VariadicDynCastAllOfMatcher< @@ -847,20 +1170,24 @@ const internal::VariadicDynCastAllOfMatcher< /// \brief Matches unary expressions that have a specific type of argument. /// /// Given +/// \code /// int a, c; float b; int s = sizeof(a) + sizeof(b) + alignof(c); +/// \endcode /// unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int")) /// matches \c sizeof(a) and \c alignof(c) AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType, - internal::Matcher<QualType>, Matcher) { + internal::Matcher<QualType>, InnerMatcher) { const QualType ArgumentType = Node.getTypeOfArgument(); - return Matcher.matches(ArgumentType, Finder, Builder); + return InnerMatcher.matches(ArgumentType, Finder, Builder); } /// \brief Matches unary expressions of a certain kind. /// /// Given +/// \code /// int x; /// int s = sizeof(x) + alignof(x) +/// \endcode /// unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf)) /// matches \c sizeof(x) AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { @@ -870,17 +1197,17 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { /// \brief Same as unaryExprOrTypeTraitExpr, but only matching /// alignof. inline internal::Matcher<Stmt> alignOfExpr( - const internal::Matcher<UnaryExprOrTypeTraitExpr> &Matcher) { + const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) { return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( - ofKind(UETT_AlignOf), Matcher))); + ofKind(UETT_AlignOf), InnerMatcher))); } /// \brief Same as unaryExprOrTypeTraitExpr, but only matching /// sizeof. inline internal::Matcher<Stmt> sizeOfExpr( - const internal::Matcher<UnaryExprOrTypeTraitExpr> &Matcher) { + const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) { return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( - ofKind(UETT_SizeOf), Matcher))); + ofKind(UETT_SizeOf), InnerMatcher))); } /// \brief Matches NamedDecl nodes that have the specified name. @@ -890,10 +1217,14 @@ inline internal::Matcher<Stmt> sizeOfExpr( /// Does not match typedefs of an underlying type with the given name. /// /// Example matches X (Name == "X") +/// \code /// class X; +/// \endcode /// /// Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X") -/// namespace a { namespace b { class X; } } +/// \code +/// namespace a { namespace b { class X; } } +/// \endcode AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { assert(!Name.empty()); const std::string FullNameString = "::" + Node.getQualifiedNameAsString(); @@ -914,10 +1245,14 @@ AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { /// of an underlying type with the given name. /// /// Example matches X (regexp == "::X") +/// \code /// class X; +/// \endcode /// /// Example matches X (regexp is one of "::X", "^foo::.*X", among others) -/// namespace foo { namespace bar { class X; } } +/// \code +/// namespace foo { namespace bar { class X; } } +/// \endcode AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { assert(!RegExp.empty()); std::string FullNameString = "::" + Node.getQualifiedNameAsString(); @@ -931,10 +1266,12 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { /// "operator" prefix, such as "<<", for OverloadedOperatorCall's. /// /// Example matches a << b -/// (matcher == overloadedOperatorCall(hasOverloadedOperatorName("<<"))) +/// (matcher == operatorCallExpr(hasOverloadedOperatorName("<<"))) +/// \code /// a << b; /// c && d; // assuming both operator<< /// // and operator&& are overloaded somewhere. +/// \endcode AST_MATCHER_P(CXXOperatorCallExpr, hasOverloadedOperatorName, std::string, Name) { return getOperatorSpelling(Node.getOperator()) == Name; @@ -943,20 +1280,24 @@ AST_MATCHER_P(CXXOperatorCallExpr, /// \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. +/// Note that a class is not considered to be derived from itself. /// -/// Example matches X, Y, Z, C (Base == hasName("X")) -/// class X; // A class is considered to be derived from itself +/// Example matches Y, Z, C (Base == hasName("X")) +/// \code +/// class X; /// 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 +/// \endcode /// /// In the following example, Bar matches isDerivedFrom(hasName("X")): +/// \code /// class Foo; /// typedef Foo X; /// class Bar : public Foo {}; // derived from a type that X is a typedef of +/// \endcode AST_MATCHER_P(CXXRecordDecl, isDerivedFrom, internal::Matcher<NamedDecl>, Base) { return Finder->classIsDerivedFrom(&Node, Base, Builder); @@ -968,15 +1309,34 @@ inline internal::Matcher<CXXRecordDecl> isDerivedFrom(StringRef BaseName) { return isDerivedFrom(hasName(BaseName)); } +/// \brief Similar to \c isDerivedFrom(), but also matches classes that directly +/// match \c Base. +inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom( + internal::Matcher<NamedDecl> Base) { + return anyOf(Base, isDerivedFrom(Base)); +} + +/// \brief Overloaded method as shortcut for +/// \c isSameOrDerivedFrom(hasName(...)). +inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom( + StringRef BaseName) { + assert(!BaseName.empty()); + return isSameOrDerivedFrom(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"))) +/// Example matches X, Y (matcher = recordDecl(has(recordDecl(hasName("X"))) +/// \code /// 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. +/// \endcode /// /// ChildT must be an AST base type. +/// +/// Usable as: Any Matcher template <typename ChildT> internal::ArgumentAdaptingMatcher<internal::HasMatcher, ChildT> has( const internal::Matcher<ChildT> &ChildMatcher) { @@ -988,12 +1348,16 @@ internal::ArgumentAdaptingMatcher<internal::HasMatcher, ChildT> has( /// provided matcher. /// /// Example matches X, Y, Z -/// (matcher = record(hasDescendant(record(hasName("X"))))) +/// (matcher = recordDecl(hasDescendant(recordDecl(hasName("X"))))) +/// \code /// 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 {}; }; }; +/// \endcode /// /// DescendantT must be an AST base type. +/// +/// Usable as: Any Matcher template <typename DescendantT> internal::ArgumentAdaptingMatcher<internal::HasDescendantMatcher, DescendantT> hasDescendant(const internal::Matcher<DescendantT> &DescendantMatcher) { @@ -1002,22 +1366,25 @@ hasDescendant(const internal::Matcher<DescendantT> &DescendantMatcher) { 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"))) +/// Example matches X, Y (matcher = recordDecl(forEach(recordDecl(hasName("X"))) +/// \code /// 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. +/// \endcode /// /// 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. +/// +/// Usable as: Any Matcher template <typename ChildT> internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT> forEach( - const internal::Matcher<ChildT>& ChildMatcher) { + const internal::Matcher<ChildT> &ChildMatcher) { return internal::ArgumentAdaptingMatcher< internal::ForEachMatcher, ChildT>(ChildMatcher); @@ -1027,10 +1394,12 @@ internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT> forEach( /// provided matcher. /// /// Example matches X, A, B, C -/// (matcher = record(forEachDescendant(record(hasName("X"))))) +/// (matcher = recordDecl(forEachDescendant(recordDecl(hasName("X"))))) +/// \code /// 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 {}; }; }; +/// \endcode /// /// DescendantT must be an AST base type. /// @@ -1038,25 +1407,72 @@ internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT> forEach( /// each result that matches instead of only on the first one. /// /// Note: Recursively combined ForEachDescendant can cause many matches: -/// record(forEachDescendant(record(forEachDescendant(record())))) +/// recordDecl(forEachDescendant(recordDecl(forEachDescendant(recordDecl())))) /// will match 10 times (plus injected class name matches) on: +/// \code /// class A { class B { class C { class D { class E {}; }; }; }; }; +/// \endcode +/// +/// Usable as: Any Matcher template <typename DescendantT> -internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, DescendantT> +internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, + DescendantT> forEachDescendant( - const internal::Matcher<DescendantT>& DescendantMatcher) { + const internal::Matcher<DescendantT> &DescendantMatcher) { return internal::ArgumentAdaptingMatcher< internal::ForEachDescendantMatcher, DescendantT>(DescendantMatcher); } +/// \brief Matches AST nodes that have a parent that matches the provided +/// matcher. +/// +/// Given +/// \code +/// void f() { for (;;) { int x = 42; if (true) { int x = 43; } } } +/// \endcode +/// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }". +/// +/// Usable as: Any Matcher +template <typename ParentT> +internal::ArgumentAdaptingMatcher<internal::HasParentMatcher, ParentT> +hasParent(const internal::Matcher<ParentT> &ParentMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::HasParentMatcher, + ParentT>(ParentMatcher); +} + +/// \brief Matches AST nodes that have an ancestor that matches the provided +/// matcher. +/// +/// Given +/// \code +/// void f() { if (true) { int x = 42; } } +/// void g() { for (;;) { int x = 43; } } +/// \endcode +/// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43. +/// +/// Usable as: Any Matcher +template <typename AncestorT> +internal::ArgumentAdaptingMatcher<internal::HasAncestorMatcher, AncestorT> +hasAncestor(const internal::Matcher<AncestorT> &AncestorMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::HasAncestorMatcher, + AncestorT>(AncestorMatcher); +} + /// \brief Matches if the provided matcher does not match. /// -/// Example matches Y (matcher = record(unless(hasName("X")))) +/// Example matches Y (matcher = recordDecl(unless(hasName("X")))) +/// \code /// class X {}; /// class Y {}; +/// \endcode +/// +/// Usable as: Any Matcher template <typename M> -internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M> unless(const M &InnerMatcher) { +internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M> +unless(const M &InnerMatcher) { return internal::PolymorphicMatcherWithParam1< internal::NotMatcher, M>(InnerMatcher); } @@ -1064,7 +1480,8 @@ internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M> unless(const M & /// \brief Matches a type if the declaration of the type matches the given /// matcher. /// -/// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr> +/// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr>, +/// Matcher<MemberExpr> inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher<Decl> > hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) { @@ -1075,9 +1492,11 @@ inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, /// \brief Matches on the implicit object argument of a member call expression. /// -/// Example matches y.x() (matcher = call(on(hasType(record(hasName("Y")))))) +/// Example matches y.x() (matcher = callExpr(on(hasType(recordDecl(hasName("Y")))))) +/// \code /// class Y { public: void x(); }; /// void z() { Y y; y.x(); }", +/// \endcode /// /// FIXME: Overload to allow directly matching types? AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>, @@ -1092,9 +1511,11 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>, /// \brief Matches if the call expression's callee expression matches. /// /// Given +/// \code /// class Y { void x() { this->x(); x(); Y y; y.x(); } }; /// void f() { f(); } -/// call(callee(expression())) +/// \endcode +/// callExpr(callee(expr())) /// matches this->x(), x(), y.x(), f() /// with callee(...) /// matching this->x, x, y.x, f respectively @@ -1113,9 +1534,11 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>, /// \brief Matches if the call expression's callee's declaration matches the /// given matcher. /// -/// Example matches y.x() (matcher = call(callee(method(hasName("x"))))) +/// Example matches y.x() (matcher = callExpr(callee(methodDecl(hasName("x"))))) +/// \code /// class Y { public: void x(); }; /// void z() { Y y; y.x(); +/// \endcode inline internal::Matcher<CallExpr> callee( const internal::Matcher<Decl> &InnerMatcher) { return internal::Matcher<CallExpr>(hasDeclaration(InnerMatcher)); @@ -1124,12 +1547,12 @@ inline internal::Matcher<CallExpr> callee( /// \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")))))) +/// Example matches x (matcher = expr(hasType(recordDecl(hasName("X"))))) +/// and z (matcher = varDecl(hasType(recordDecl(hasName("X"))))) +/// \code /// class X {}; /// void y(X &x) { x; X z; } +/// \endcode AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>, InnerMatcher) { TOOLING_COMPILE_ASSERT((llvm::is_base_of<Expr, NodeType>::value || @@ -1143,14 +1566,16 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>, /// /// 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 +/// declaration "X x;", recordDecl(hasName("X")) matches the declaration of X, +/// while varDecl(hasType(recordDecl(hasName("X")))) matches the declaration /// of x." /// -/// Example matches x (matcher = expression(hasType(record(hasName("X"))))) -/// and z (matcher = variable(hasType(record(hasName("X"))))) +/// Example matches x (matcher = expr(hasType(recordDecl(hasName("X"))))) +/// and z (matcher = varDecl(hasType(recordDecl(hasName("X"))))) +/// \code /// class X {}; /// void y(X &x) { x; X z; } +/// \endcode /// /// Usable as: Matcher<Expr>, Matcher<ValueDecl> inline internal::PolymorphicMatcherWithParam1< @@ -1164,9 +1589,11 @@ hasType(const internal::Matcher<Decl> &InnerMatcher) { /// \brief Matches if the matched type is represented by the given string. /// /// Given +/// \code /// class Y { public: void x(); }; /// void z() { Y* y; y->x(); } -/// call(on(hasType(asString("class Y *")))) +/// \endcode +/// callExpr(on(hasType(asString("class Y *")))) /// matches y->x() AST_MATCHER_P(QualType, asString, std::string, Name) { return Name == Node.getAsString(); @@ -1176,9 +1603,11 @@ AST_MATCHER_P(QualType, asString, std::string, Name) { /// matches the specified matcher. /// /// Example matches y->x() -/// (matcher = call(on(hasType(pointsTo(record(hasName("Y"))))))) +/// (matcher = callExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))))) +/// \code /// class Y { public: void x(); }; /// void z() { Y *y; y->x(); } +/// \endcode AST_MATCHER_P( QualType, pointsTo, internal::Matcher<QualType>, InnerMatcher) { @@ -1197,12 +1626,14 @@ inline internal::Matcher<QualType> pointsTo( /// type matches the specified matcher. /// /// Example matches X &x and const X &y -/// (matcher = variable(hasType(references(record(hasName("X")))))) +/// (matcher = varDecl(hasType(references(recordDecl(hasName("X")))))) +/// \code /// class X { /// void a(X b) { /// X &x = b; /// const X &y = b; /// }; +/// \endcode AST_MATCHER_P(QualType, references, internal::Matcher<QualType>, InnerMatcher) { return (!Node.isNull() && Node->isReferenceType() && @@ -1243,9 +1674,11 @@ inline internal::Matcher<CXXMemberCallExpr> thisPointerType( /// specified matcher. /// /// Example matches x in if(x) -/// (matcher = declarationReference(to(variable(hasName("x"))))) +/// (matcher = declRefExpr(to(varDecl(hasName("x"))))) +/// \code /// bool x; /// if (x) {} +/// \endcode AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>, InnerMatcher) { const Decl *DeclNode = Node.getDecl(); @@ -1259,29 +1692,33 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>, /// FIXME: This currently only works for functions. Fix. /// /// Given +/// \code /// namespace a { void f() {} } /// using a::f; /// void g() { /// f(); // Matches this .. /// a::f(); // .. but not this. /// } -/// declarationReference(throughUsingDeclaration(anything())) +/// \endcode +/// declRefExpr(throughUsingDeclaration(anything())) /// matches \c f() AST_MATCHER_P(DeclRefExpr, throughUsingDecl, - internal::Matcher<UsingShadowDecl>, Matcher) { + internal::Matcher<UsingShadowDecl>, InnerMatcher) { const NamedDecl *FoundDecl = Node.getFoundDecl(); if (const UsingShadowDecl *UsingDecl = llvm::dyn_cast<UsingShadowDecl>(FoundDecl)) - return Matcher.matches(*UsingDecl, Finder, Builder); + return InnerMatcher.matches(*UsingDecl, Finder, Builder); return false; } /// \brief Matches the Decl of a DeclStmt which has a single declaration. /// /// Given +/// \code /// int a, b; /// int c; -/// declarationStatement(hasSingleDecl(anything())) +/// \endcode +/// declStmt(hasSingleDecl(anything())) /// matches 'int c;' but not 'int a, b;'. AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher<Decl>, InnerMatcher) { if (Node.isSingleDecl()) { @@ -1294,9 +1731,11 @@ AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher<Decl>, InnerMatcher) { /// \brief Matches a variable declaration that has an initializer expression /// that matches the given matcher. /// -/// Example matches x (matcher = variable(hasInitializer(call()))) +/// Example matches x (matcher = varDecl(hasInitializer(callExpr()))) +/// \code /// bool y() { return true; } /// bool x = y(); +/// \endcode AST_MATCHER_P( VarDecl, hasInitializer, internal::Matcher<Expr>, InnerMatcher) { @@ -1308,9 +1747,11 @@ AST_MATCHER_P( /// \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))) +/// Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2))) +/// \code /// void f(int x, int y); /// f(0, 0); +/// \endcode AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) { TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value || llvm::is_base_of<CXXConstructExpr, @@ -1323,8 +1764,10 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) { /// call expression. /// /// Example matches y in x(y) -/// (matcher = call(hasArgument(0, declarationReference()))) +/// (matcher = callExpr(hasArgument(0, declRefExpr()))) +/// \code /// void x(int) { int y; x(y); } +/// \endcode AST_POLYMORPHIC_MATCHER_P2( hasArgument, unsigned, N, internal::Matcher<Expr>, InnerMatcher) { TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value || @@ -1340,13 +1783,15 @@ AST_POLYMORPHIC_MATCHER_P2( /// declarations. /// /// Example: Given +/// \code /// int a, b; /// int c; /// int d = 2, e; +/// \endcode /// declCountIs(2) /// matches 'int a, b;' and 'int d = 2, e;', but not 'int c;'. AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) { - return std::distance(Node.decl_begin(), Node.decl_end()) == N; + return std::distance(Node.decl_begin(), Node.decl_end()) == (ptrdiff_t)N; } /// \brief Matches the n'th declaration of a declaration statement. @@ -1355,15 +1800,19 @@ AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) { /// breaks up multiple-declaration DeclStmt's into multiple single-declaration /// DeclStmt's. /// Example: Given non-global declarations +/// \code /// int a, b = 0; /// int c; /// int d = 2, e; -/// declarationStatement(containsDeclaration( -/// 0, variable(hasInitializer(anything())))) +/// \endcode +/// declStmt(containsDeclaration( +/// 0, varDecl(hasInitializer(anything())))) /// matches only 'int d = 2, e;', and -/// declarationStatement(containsDeclaration(1, variable())) +/// declStmt(containsDeclaration(1, varDecl())) +/// \code /// matches 'int a, b = 0' as well as 'int d = 2, e;' /// but 'int c;' is not matched. +/// \endcode AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N, internal::Matcher<Decl>, InnerMatcher) { const unsigned NumDecls = std::distance(Node.decl_begin(), Node.decl_end()); @@ -1377,11 +1826,13 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N, /// \brief Matches a constructor initializer. /// /// Given +/// \code /// struct Foo { /// Foo() : foo_(1) { } /// int foo_; /// }; -/// record(has(constructor(hasAnyConstructorInitializer(anything())))) +/// \endcode +/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer(anything())))) /// record matches Foo, hasAnyConstructorInitializer matches foo_(1) AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, internal::Matcher<CXXCtorInitializer>, InnerMatcher) { @@ -1397,11 +1848,13 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, /// \brief Matches the field declaration of a constructor initializer. /// /// Given +/// \code /// struct Foo { /// Foo() : foo_(1) { } /// int foo_; /// }; -/// record(has(constructor(hasAnyConstructorInitializer( +/// \endcode +/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer( /// forField(hasName("foo_")))))) /// matches Foo /// with forField matching foo_ @@ -1415,11 +1868,13 @@ AST_MATCHER_P(CXXCtorInitializer, forField, /// \brief Matches the initializer expression of a constructor initializer. /// /// Given +/// \code /// struct Foo { /// Foo() : foo_(1) { } /// int foo_; /// }; -/// record(has(constructor(hasAnyConstructorInitializer( +/// \endcode +/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer( /// withInitializer(integerLiteral(equals(1))))))) /// matches Foo /// with withInitializer matching (1) @@ -1434,12 +1889,14 @@ AST_MATCHER_P(CXXCtorInitializer, withInitializer, /// code (as opposed to implicitly added by the compiler). /// /// Given +/// \code /// struct Foo { /// Foo() { } /// Foo(int) : foo_("A") { } /// string foo_; /// }; -/// constructor(hasAnyConstructorInitializer(isWritten())) +/// \endcode +/// constructorDecl(hasAnyConstructorInitializer(isWritten())) /// will match Foo(int), but not Foo() AST_MATCHER(CXXCtorInitializer, isWritten) { return Node.isWritten(); @@ -1455,8 +1912,10 @@ AST_MATCHER(CXXConstructorDecl, isImplicit) { /// expression. /// /// Given +/// \code /// void x(int, int, int) { int y; x(1, y, 42); } -/// call(hasAnyArgument(declarationReference())) +/// \endcode +/// callExpr(hasAnyArgument(declRefExpr())) /// matches x(1, y, 42) /// with hasAnyArgument(...) /// matching y @@ -1478,8 +1937,10 @@ AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher<Expr>, /// \brief Matches the n'th parameter of a function declaration. /// /// Given +/// \code /// class X { void f(int x) {} }; -/// method(hasParameter(0, hasType(variable()))) +/// \endcode +/// methodDecl(hasParameter(0, hasType(varDecl()))) /// matches f(int x) {} /// with hasParameter(...) /// matching int x @@ -1496,8 +1957,10 @@ AST_MATCHER_P2(FunctionDecl, hasParameter, /// Does not match the 'this' parameter of a method. /// /// Given +/// \code /// class X { void f(int x, int y, int z) {} }; -/// method(hasAnyParameter(hasName("y"))) +/// \endcode +/// methodDecl(hasAnyParameter(hasName("y"))) /// matches f(int x, int y, int z) {} /// with hasAnyParameter(...) /// matching int y @@ -1514,20 +1977,25 @@ AST_MATCHER_P(FunctionDecl, hasAnyParameter, /// \brief Matches the return type of a function declaration. /// /// Given: +/// \code /// class X { int f() { return 1; } }; -/// method(returns(asString("int"))) +/// \endcode +/// methodDecl(returns(asString("int"))) /// matches int f() { return 1; } -AST_MATCHER_P(FunctionDecl, returns, internal::Matcher<QualType>, Matcher) { - return Matcher.matches(Node.getResultType(), Finder, Builder); +AST_MATCHER_P(FunctionDecl, returns, + internal::Matcher<QualType>, InnerMatcher) { + return InnerMatcher.matches(Node.getResultType(), Finder, Builder); } /// \brief Matches extern "C" function declarations. /// /// Given: +/// \code /// extern "C" void f() {} /// extern "C" { void g() {} } /// void h() {} -/// function(isExternC()) +/// \endcode +/// functionDecl(isExternC()) /// matches the declaration of f and g, but not the declaration h AST_MATCHER(FunctionDecl, isExternC) { return Node.isExternC(); @@ -1537,7 +2005,9 @@ AST_MATCHER(FunctionDecl, isExternC) { /// or conditional operator. /// /// Example matches true (matcher = hasCondition(boolLiteral(equals(true)))) +/// \code /// if (true) {} +/// \endcode AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher<Expr>, InnerMatcher) { TOOLING_COMPILE_ASSERT( @@ -1555,7 +2025,9 @@ AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher<Expr>, /// \brief Matches the condition variable statement in an if statement. /// /// Given +/// \code /// if (A* a = GetAPointer()) {} +/// \endcode /// hasConditionVariableStatment(...) /// matches 'A* a = GetAPointer()'. AST_MATCHER_P(IfStmt, hasConditionVariableStatement, @@ -1569,29 +2041,33 @@ AST_MATCHER_P(IfStmt, hasConditionVariableStatement, /// \brief Matches the index expression of an array subscript expression. /// /// Given +/// \code /// int i[5]; /// void f() { i[1] = 42; } +/// \endcode /// arraySubscriptExpression(hasIndex(integerLiteral())) /// matches \c i[1] with the \c integerLiteral() matching \c 1 AST_MATCHER_P(ArraySubscriptExpr, hasIndex, - internal::Matcher<Expr>, matcher) { + internal::Matcher<Expr>, InnerMatcher) { if (const Expr* Expression = Node.getIdx()) - return matcher.matches(*Expression, Finder, Builder); + return InnerMatcher.matches(*Expression, Finder, Builder); return false; } /// \brief Matches the base expression of an array subscript expression. /// /// Given +/// \code /// int i[5]; /// void f() { i[1] = 42; } -/// arraySubscriptExpression(hasBase(implicitCast( -/// hasSourceExpression(declarationReference())))) -/// matches \c i[1] with the \c declarationReference() matching \c i +/// \endcode +/// arraySubscriptExpression(hasBase(implicitCastExpr( +/// hasSourceExpression(declRefExpr())))) +/// matches \c i[1] with the \c declRefExpr() matching \c i AST_MATCHER_P(ArraySubscriptExpr, hasBase, - internal::Matcher<Expr>, matcher) { + internal::Matcher<Expr>, InnerMatcher) { if (const Expr* Expression = Node.getBase()) - return matcher.matches(*Expression, Finder, Builder); + return InnerMatcher.matches(*Expression, Finder, Builder); return false; } @@ -1599,10 +2075,12 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase, /// a given body. /// /// Given +/// \code /// for (;;) {} -/// hasBody(compoundStatement()) +/// \endcode +/// hasBody(compoundStmt()) /// matches 'for (;;) {}' -/// with compoundStatement() +/// with compoundStmt() /// matching '{}' AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>, InnerMatcher) { @@ -1620,10 +2098,12 @@ AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>, /// a given matcher. /// /// Given +/// \code /// { {}; 1+2; } -/// hasAnySubstatement(compoundStatement()) +/// \endcode +/// hasAnySubstatement(compoundStmt()) /// matches '{ {}; 1+2; }' -/// with compoundStatement() +/// with compoundStmt() /// matching '{}' AST_MATCHER_P(CompoundStmt, hasAnySubstatement, internal::Matcher<Stmt>, InnerMatcher) { @@ -1639,8 +2119,10 @@ AST_MATCHER_P(CompoundStmt, hasAnySubstatement, /// child statements. /// /// Example: Given +/// \code /// { for (;;) {} } -/// compoundStatement(statementCountIs(0))) +/// \endcode +/// compoundStmt(statementCountIs(0))) /// matches '{}' /// but does not match the outer compound statement. AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) { @@ -1650,7 +2132,9 @@ AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) { /// \brief Matches literals that are equal to the given value. /// /// Example matches true (matcher = boolLiteral(equals(true))) +/// \code /// true +/// \endcode /// /// Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteral>, /// Matcher<FloatingLiteral>, Matcher<IntegerLiteral> @@ -1666,7 +2150,9 @@ equals(const ValueT &Value) { /// unary). /// /// Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) +/// \code /// !(a || b) +/// \endcode AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) { TOOLING_COMPILE_ASSERT( (llvm::is_base_of<BinaryOperator, NodeType>::value) || @@ -1678,7 +2164,9 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) { /// \brief Matches the left hand side of binary operator expressions. /// /// Example matches a (matcher = binaryOperator(hasLHS())) +/// \code /// a || b +/// \endcode AST_MATCHER_P(BinaryOperator, hasLHS, internal::Matcher<Expr>, InnerMatcher) { Expr *LeftHandSide = Node.getLHS(); @@ -1689,7 +2177,9 @@ AST_MATCHER_P(BinaryOperator, hasLHS, /// \brief Matches the right hand side of binary operator expressions. /// /// Example matches b (matcher = binaryOperator(hasRHS())) +/// \code /// a || b +/// \endcode AST_MATCHER_P(BinaryOperator, hasRHS, internal::Matcher<Expr>, InnerMatcher) { Expr *RightHandSide = Node.getRHS(); @@ -1706,8 +2196,10 @@ inline internal::Matcher<BinaryOperator> hasEitherOperand( /// \brief Matches if the operand of a unary operator matches. /// -/// Example matches true (matcher = hasOperand(boolLiteral(equals(true)))) +/// Example matches true (matcher = hasUnaryOperand(boolLiteral(equals(true)))) +/// \code /// !true +/// \endcode AST_MATCHER_P(UnaryOperator, hasUnaryOperand, internal::Matcher<Expr>, InnerMatcher) { const Expr * const Operand = Node.getSubExpr(); @@ -1718,8 +2210,8 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand, /// \brief Matches if the cast's source expression matches the given matcher. /// /// Example: matches "a string" (matcher = -/// hasSourceExpression(constructorCall())) -/// +/// hasSourceExpression(constructExpr())) +/// \code /// class URL { URL(string); }; /// URL url = "a string"; AST_MATCHER_P(CastExpr, hasSourceExpression, @@ -1751,7 +2243,9 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType, /// \brief Matches the true branch expression of a conditional operator. /// /// Example matches a +/// \code /// condition ? a : b +/// \endcode AST_MATCHER_P(ConditionalOperator, hasTrueExpression, internal::Matcher<Expr>, InnerMatcher) { Expr *Expression = Node.getTrueExpr(); @@ -1762,7 +2256,9 @@ AST_MATCHER_P(ConditionalOperator, hasTrueExpression, /// \brief Matches the false branch expression of a conditional operator. /// /// Example matches b +/// \code /// condition ? a : b +/// \endcode AST_MATCHER_P(ConditionalOperator, hasFalseExpression, internal::Matcher<Expr>, InnerMatcher) { Expr *Expression = Node.getFalseExpr(); @@ -1773,12 +2269,14 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression, /// \brief Matches if a declaration has a body attached. /// /// Example matches A, va, fa +/// \code /// 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. +/// \endcode /// /// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl> inline internal::PolymorphicMatcherWithParam0<internal::IsDefinitionMatcher> @@ -1795,13 +2293,15 @@ isDefinition() { /// this to? /// /// Example matches A() in the last line -/// (matcher = constructorCall(hasDeclaration(method( +/// (matcher = constructExpr(hasDeclaration(methodDecl( /// ofClass(hasName("A")))))) +/// \code /// class A { /// public: /// A(); /// }; /// A a = A(); +/// \endcode AST_MATCHER_P(CXXMethodDecl, ofClass, internal::Matcher<CXXRecordDecl>, InnerMatcher) { const CXXRecordDecl *Parent = Node.getParent(); @@ -1815,12 +2315,14 @@ AST_MATCHER_P(CXXMethodDecl, ofClass, /// Member calls on the implicit this pointer match as called with '->'. /// /// Given +/// \code /// class Y { /// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } /// int a; /// static int b; /// }; -/// memberExpression(isArrow()) +/// \endcode +/// memberExpr(isArrow()) /// matches this->x, x, y.x, a, this->b inline internal::Matcher<MemberExpr> isArrow() { return makeMatcher(new internal::IsArrowMatcher()); @@ -1829,10 +2331,12 @@ inline internal::Matcher<MemberExpr> isArrow() { /// \brief Matches QualType nodes that are of integer type. /// /// Given +/// \code /// void a(int); /// void b(long); /// void c(double); -/// function(hasAnyParameter(hasType(isInteger()))) +/// \endcode +/// functionDecl(hasAnyParameter(hasType(isInteger()))) /// matches "a(int)", "b(long)", but not "c(double)". AST_MATCHER(QualType, isInteger) { return Node->isIntegerType(); @@ -1842,12 +2346,14 @@ AST_MATCHER(QualType, isInteger) { /// include "top-level" const. /// /// Given +/// \code /// void a(int); /// void b(int const); /// void c(const int); /// void d(const int*); /// void e(int const) {}; -/// function(hasAnyParameter(hasType(isConstQualified()))) +/// \endcode +/// functionDecl(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 *". @@ -1859,10 +2365,12 @@ inline internal::Matcher<QualType> isConstQualified() { /// given matcher. /// /// Given +/// \code /// struct { int first, second; } first, second; /// int i(second.first); /// int j(first.second); -/// memberExpression(member(hasName("first"))) +/// \endcode +/// memberExpr(member(hasName("first"))) /// matches second.first /// but not first.second (because the member name there is "second"). AST_MATCHER_P(MemberExpr, member, @@ -1874,9 +2382,11 @@ AST_MATCHER_P(MemberExpr, member, /// matched by a given matcher. /// /// Given +/// \code /// struct X { int m; }; /// void f(X x) { x.m; m; } -/// memberExpression(hasObjectExpression(hasType(record(hasName("X"))))))) +/// \endcode +/// memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X"))))))) /// matches "x.m" and "m" /// with hasObjectExpression(...) /// matching "x" and the implicit object expression of "m" which has type X*. @@ -1888,15 +2398,17 @@ AST_MATCHER_P(MemberExpr, hasObjectExpression, /// \brief Matches any using shadow declaration. /// /// Given +/// \code /// namespace X { void b(); } /// using X::b; +/// \endcode /// usingDecl(hasAnyUsingShadowDecl(hasName("b")))) /// matches \code using X::b \endcode AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl, - internal::Matcher<UsingShadowDecl>, Matcher) { + internal::Matcher<UsingShadowDecl>, InnerMatcher) { for (UsingDecl::shadow_iterator II = Node.shadow_begin(); II != Node.shadow_end(); ++II) { - if (Matcher.matches(**II, Finder, Builder)) + if (InnerMatcher.matches(**II, Finder, Builder)) return true; } return false; @@ -1906,31 +2418,39 @@ AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl, /// matched by the given matcher. /// /// Given +/// \code /// namespace X { int a; void b(); } /// using X::a; /// using X::b; -/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(function()))) +/// \endcode +/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl()))) /// 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); + internal::Matcher<NamedDecl>, InnerMatcher) { + return InnerMatcher.matches(*Node.getTargetDecl(), Finder, Builder); } /// \brief Matches template instantiations of function, class, or static /// member variable template instantiations. /// /// Given +/// \code /// template <typename T> class X {}; class A {}; X<A> x; +/// \endcode /// or +/// \code /// template <typename T> class X {}; class A {}; template class X<A>; -/// record(hasName("::X"), isTemplateInstantiation()) +/// \endcode +/// recordDecl(hasName("::X"), isTemplateInstantiation()) /// matches the template instantiation of X<A>. /// /// But given -/// template <typename T> class X {}; class A {}; +/// \code +/// template <typename T> class X {}; class A {}; /// template <> class X<A> {}; X<A> x; -/// record(hasName("::X"), isTemplateInstantiation()) +/// \endcode +/// recordDecl(hasName("::X"), isTemplateInstantiation()) /// does not match, as X<A> is an explicit template specialization. /// /// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> @@ -1941,6 +2461,411 @@ isTemplateInstantiation() { internal::IsTemplateInstantiationMatcher>(); } +/// \brief Matches explicit template specializations of function, class, or +/// static member variable template instantiations. +/// +/// Given +/// \code +/// template<typename T> void A(T t) { } +/// template<> void A(int N) { } +/// \endcode +/// functionDecl(isExplicitTemplateSpecialization()) +/// matches the specialization A<int>(). +/// +/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> +inline internal::PolymorphicMatcherWithParam0< + internal::IsExplicitTemplateSpecializationMatcher> +isExplicitTemplateSpecialization() { + return internal::PolymorphicMatcherWithParam0< + internal::IsExplicitTemplateSpecializationMatcher>(); +} + +/// \brief Matches \c TypeLocs for which the given inner +/// QualType-matcher matches. +inline internal::BindableMatcher<TypeLoc> loc( + const internal::Matcher<QualType> &InnerMatcher) { + return internal::BindableMatcher<TypeLoc>( + new internal::TypeLocTypeMatcher(InnerMatcher)); +} + +/// \brief Matches builtin Types. +/// +/// Given +/// \code +/// struct A {}; +/// A a; +/// int b; +/// float c; +/// bool d; +/// \endcode +/// builtinType() +/// matches "int b", "float c" and "bool d" +AST_TYPE_MATCHER(BuiltinType, builtinType); + +/// \brief Matches all kinds of arrays. +/// +/// Given +/// \code +/// int a[] = { 2, 3 }; +/// int b[4]; +/// void f() { int c[a[0]]; } +/// \endcode +/// arrayType() +/// matches "int a[]", "int b[4]" and "int c[a[0]]"; +AST_TYPE_MATCHER(ArrayType, arrayType); + +/// \brief Matches C99 complex types. +/// +/// Given +/// \code +/// _Complex float f; +/// \endcode +/// complexType() +/// matches "_Complex float f" +AST_TYPE_MATCHER(ComplexType, complexType); + +/// \brief Matches arrays and C99 complex types that have a specific element +/// type. +/// +/// Given +/// \code +/// struct A {}; +/// A a[7]; +/// int b[7]; +/// \endcode +/// arrayType(hasElementType(builtinType())) +/// matches "int b[7]" +/// +/// Usable as: Matcher<ArrayType>, Matcher<ComplexType> +AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement); + +/// \brief Matches C arrays with a specified constant size. +/// +/// Given +/// \code +/// void() { +/// int a[2]; +/// int b[] = { 2, 3 }; +/// int c[b[0]]; +/// } +/// \endcode +/// constantArrayType() +/// matches "int a[2]" +AST_TYPE_MATCHER(ConstantArrayType, constantArrayType); + +/// \brief Matches \c ConstantArrayType nodes that have the specified size. +/// +/// Given +/// \code +/// int a[42]; +/// int b[2 * 21]; +/// int c[41], d[43]; +/// \endcode +/// constantArrayType(hasSize(42)) +/// matches "int a[42]" and "int b[2 * 21]" +AST_MATCHER_P(ConstantArrayType, hasSize, unsigned, N) { + return Node.getSize() == N; +} + +/// \brief Matches C++ arrays whose size is a value-dependent expression. +/// +/// Given +/// \code +/// template<typename T, int Size> +/// class array { +/// T data[Size]; +/// }; +/// \endcode +/// dependentSizedArrayType +/// matches "T data[Size]" +AST_TYPE_MATCHER(DependentSizedArrayType, dependentSizedArrayType); + +/// \brief Matches C arrays with unspecified size. +/// +/// Given +/// \code +/// int a[] = { 2, 3 }; +/// int b[42]; +/// void f(int c[]) { int d[a[0]]; }; +/// \endcode +/// incompleteArrayType() +/// matches "int a[]" and "int c[]" +AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType); + +/// \brief Matches C arrays with a specified size that is not an +/// integer-constant-expression. +/// +/// Given +/// \code +/// void f() { +/// int a[] = { 2, 3 } +/// int b[42]; +/// int c[a[0]]; +/// \endcode +/// variableArrayType() +/// matches "int c[a[0]]" +AST_TYPE_MATCHER(VariableArrayType, variableArrayType); + +/// \brief Matches \c VariableArrayType nodes that have a specific size +/// expression. +/// +/// Given +/// \code +/// void f(int b) { +/// int a[b]; +/// } +/// \endcode +/// variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to( +/// varDecl(hasName("b"))))))) +/// matches "int a[b]" +AST_MATCHER_P(VariableArrayType, hasSizeExpr, + internal::Matcher<Expr>, InnerMatcher) { + return InnerMatcher.matches(*Node.getSizeExpr(), Finder, Builder); +} + +/// \brief Matches atomic types. +/// +/// Given +/// \code +/// _Atomic(int) i; +/// \endcode +/// atomicType() +/// matches "_Atomic(int) i" +AST_TYPE_MATCHER(AtomicType, atomicType); + +/// \brief Matches atomic types with a specific value type. +/// +/// Given +/// \code +/// _Atomic(int) i; +/// _Atomic(float) f; +/// \endcode +/// atomicType(hasValueType(isInteger())) +/// matches "_Atomic(int) i" +/// +/// Usable as: Matcher<AtomicType> +AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue); + +/// \brief Matches types nodes representing C++11 auto types. +/// +/// Given: +/// \code +/// auto n = 4; +/// int v[] = { 2, 3 } +/// for (auto i : v) { } +/// \endcode +/// autoType() +/// matches "auto n" and "auto i" +AST_TYPE_MATCHER(AutoType, autoType); + +/// \brief Matches \c AutoType nodes where the deduced type is a specific type. +/// +/// Note: There is no \c TypeLoc for the deduced type and thus no +/// \c getDeducedLoc() matcher. +/// +/// Given +/// \code +/// auto a = 1; +/// auto b = 2.0; +/// \endcode +/// autoType(hasDeducedType(isInteger())) +/// matches "auto a" +/// +/// Usable as: Matcher<AutoType> +AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType); + +/// \brief Matches \c FunctionType nodes. +/// +/// Given +/// \code +/// int (*f)(int); +/// void g(); +/// \endcode +/// functionType() +/// matches "int (*f)(int)" and the type of "g". +AST_TYPE_MATCHER(FunctionType, functionType); + +/// \brief Matches block pointer types, i.e. types syntactically represented as +/// "void (^)(int)". +/// +/// The \c pointee is always required to be a \c FunctionType. +AST_TYPE_MATCHER(BlockPointerType, blockPointerType); + +/// \brief Matches member pointer types. +/// Given +/// \code +/// struct A { int i; } +/// A::* ptr = A::i; +/// \endcode +/// memberPointerType() +/// matches "A::* ptr" +AST_TYPE_MATCHER(MemberPointerType, memberPointerType); + +/// \brief Matches pointer types. +/// +/// Given +/// \code +/// int *a; +/// int &b = *a; +/// int c = 5; +/// \endcode +/// pointerType() +/// matches "int *a" +AST_TYPE_MATCHER(PointerType, pointerType); + +/// \brief Matches reference types. +/// +/// Given +/// \code +/// int *a; +/// int &b = *a; +/// int c = 5; +/// \endcode +/// pointerType() +/// matches "int &b" +AST_TYPE_MATCHER(ReferenceType, referenceType); + +/// \brief Narrows PointerType (and similar) matchers to those where the +/// \c pointee matches a given matcher. +/// +/// Given +/// \code +/// int *a; +/// int const *b; +/// float const *f; +/// \endcode +/// pointerType(pointee(isConstQualified(), isInteger())) +/// matches "int const *b" +/// +/// Usable as: Matcher<BlockPointerType>, Matcher<MemberPointerType>, +/// Matcher<PointerType>, Matcher<ReferenceType> +AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee); + +/// \brief Matches typedef types. +/// +/// Given +/// \code +/// typedef int X; +/// \endcode +/// typedefType() +/// matches "typedef int X" +AST_TYPE_MATCHER(TypedefType, typedefType); + +/// \brief Matches \c TypedefTypes referring to a specific +/// \c TypedefNameDecl. +AST_MATCHER_P(TypedefType, hasDecl, + internal::Matcher<TypedefNameDecl>, InnerMatcher) { + return InnerMatcher.matches(*Node.getDecl(), Finder, Builder); +} + +/// \brief Matches nested name specifiers. +/// +/// Given +/// \code +/// namespace ns { +/// struct A { static void f(); }; +/// void A::f() {} +/// void g() { A::f(); } +/// } +/// ns::A a; +/// \endcode +/// nestedNameSpecifier() +/// matches "ns::" and both "A::" +const internal::VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier; + +/// \brief Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc. +const internal::VariadicAllOfMatcher< + NestedNameSpecifierLoc> nestedNameSpecifierLoc; + +/// \brief Matches \c NestedNameSpecifierLocs for which the given inner +/// NestedNameSpecifier-matcher matches. +inline internal::BindableMatcher<NestedNameSpecifierLoc> loc( + const internal::Matcher<NestedNameSpecifier> &InnerMatcher) { + return internal::BindableMatcher<NestedNameSpecifierLoc>( + new internal::LocMatcher<NestedNameSpecifierLoc, NestedNameSpecifier>( + InnerMatcher)); +} + +/// \brief Matches nested name specifiers that specify a type matching the +/// given \c QualType matcher without qualifiers. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifier(specifiesType(hasDeclaration(recordDecl(hasName("A"))))) +/// matches "A::" +AST_MATCHER_P(NestedNameSpecifier, specifiesType, + internal::Matcher<QualType>, InnerMatcher) { + if (Node.getAsType() == NULL) + return false; + return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder); +} + +/// \brief Matches nested name specifier locs that specify a type matching the +/// given \c TypeLoc. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifierLoc(specifiesTypeLoc(loc(type( +/// hasDeclaration(recordDecl(hasName("A"))))))) +/// matches "A::" +AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, + internal::Matcher<TypeLoc>, InnerMatcher) { + return InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); +} + +/// \brief Matches on the prefix of a \c NestedNameSpecifier. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and +/// matches "A::" +inline internal::Matcher<NestedNameSpecifier> hasPrefix( + const internal::Matcher<NestedNameSpecifier> &InnerMatcher) { + return internal::makeMatcher( + new internal::NestedNameSpecifierPrefixMatcher(InnerMatcher)); +} + +/// \brief Matches on the prefix of a \c NestedNameSpecifierLoc. +/// +/// Given +/// \code +/// struct A { struct B { struct C {}; }; }; +/// A::B::C c; +/// \endcode +/// nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A"))))) +/// matches "A::" +inline internal::Matcher<NestedNameSpecifierLoc> hasPrefix( + const internal::Matcher<NestedNameSpecifierLoc> &InnerMatcher) { + return internal::makeMatcher( + new internal::NestedNameSpecifierLocPrefixMatcher(InnerMatcher)); +} + +/// \brief Matches nested name specifiers that specify a namespace matching the +/// given namespace matcher. +/// +/// Given +/// \code +/// namespace ns { struct A {}; } +/// ns::A a; +/// \endcode +/// nestedNameSpecifier(specifiesNamespace(hasName("ns"))) +/// matches "ns::" +AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, + internal::Matcher<NamespaceDecl>, InnerMatcher) { + if (Node.getAsNamespace() == NULL) + return false; + return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder); +} + } // end namespace ast_matchers } // end namespace clang |