diff options
Diffstat (limited to 'include/clang/ASTMatchers')
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchFinder.h | 29 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchers.h | 1445 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchersInternal.h | 621 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchersMacros.h | 65 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTTypeTraits.h | 209 |
5 files changed, 1963 insertions, 406 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h index dd237ee..30b4050 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -85,7 +85,14 @@ public: class MatchCallback { public: virtual ~MatchCallback(); + + /// \brief Called on every match by the \c MatchFinder. virtual void run(const MatchResult &Result) = 0; + + /// \brief Called at the start of each translation unit. + /// + /// Optionally override to do per translation unit tasks. + virtual void onStartOfTranslationUnit() {} }; /// \brief Called when parsing is finished. Intended for testing only. @@ -112,11 +119,24 @@ public: MatchCallback *Action); void addMatcher(const StatementMatcher &NodeMatch, MatchCallback *Action); + void addMatcher(const NestedNameSpecifierMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const TypeLocMatcher &NodeMatch, + MatchCallback *Action); /// @} /// \brief Creates a clang ASTConsumer that finds all matches. clang::ASTConsumer *newASTConsumer(); + /// \brief Finds all matches on the given \c Node. + /// + /// @{ + void findAll(const Decl &Node, ASTContext &Context); + void findAll(const Stmt &Node, ASTContext &Context); + /// @} + /// \brief Registers a callback to notify the end of parsing. /// /// The provided closure is called after parsing is done, before the AST is @@ -125,11 +145,10 @@ public: void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); private: - /// \brief The MatchCallback*'s will be called every time the - /// UntypedBaseMatcher matches on the AST. - std::vector< std::pair< - const internal::UntypedBaseMatcher*, - MatchCallback*> > Triggers; + /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called + /// when it matches. + std::vector<std::pair<const internal::DynTypedMatcher*, MatchCallback*> > + MatcherCallbackPairs; /// \brief Called when parsing is done. ParsingDoneTestCallback *ParsingDone; 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 diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index 3f55685..e5365ff 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -39,7 +39,11 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/Type.h" +#include "clang/ASTMatchers/ASTTypeTraits.h" #include "llvm/ADT/VariadicFunction.h" +#include "llvm/Support/type_traits.h" #include <map> #include <string> #include <vector> @@ -57,6 +61,45 @@ class BoundNodes; namespace internal { class BoundNodesTreeBuilder; +/// \brief Internal version of BoundNodes. Holds all the bound nodes. +class BoundNodesMap { +public: + /// \brief Adds \c Node to the map with key \c ID. + /// + /// The node's base type should be in NodeBaseType or it will be unaccessible. + template <typename T> + void addNode(StringRef ID, const T* Node) { + NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node); + } + void addNode(StringRef ID, ast_type_traits::DynTypedNode Node) { + NodeMap[ID] = Node; + } + + /// \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. + template <typename T> + const T *getNodeAs(StringRef ID) const { + IDToNodeMap::const_iterator It = NodeMap.find(ID); + if (It == NodeMap.end()) { + return NULL; + } + return It->second.get<T>(); + } + + /// \brief Copies all ID/Node pairs to BoundNodesTreeBuilder \c Builder. + void copyTo(BoundNodesTreeBuilder *Builder) const; + + /// \brief Copies all ID/Node pairs to BoundNodesMap \c Other. + void copyTo(BoundNodesMap *Other) const; + +private: + /// \brief A map from IDs to the bound nodes. + typedef std::map<std::string, ast_type_traits::DynTypedNode> IDToNodeMap; + + IDToNodeMap NodeMap; +}; /// \brief A tree of bound nodes in match results. /// @@ -84,11 +127,10 @@ public: BoundNodesTree(); /// \brief Create a BoundNodesTree from pre-filled maps of bindings. - BoundNodesTree(const std::map<std::string, const Decl*>& DeclBindings, - const std::map<std::string, const Stmt*>& StmtBindings, + BoundNodesTree(const BoundNodesMap& Bindings, const std::vector<BoundNodesTree> RecursiveBindings); - /// \brief Adds all bound nodes to bound_nodes_builder. + /// \brief Adds all bound nodes to \c Builder. void copyTo(BoundNodesTreeBuilder* Builder) const; /// \brief Visits all matches that this BoundNodesTree represents. @@ -99,17 +141,12 @@ public: private: void visitMatchesRecursively( Visitor* ResultVistior, - std::map<std::string, const Decl*> DeclBindings, - std::map<std::string, const Stmt*> StmtBindings); - - template <typename T> - void copyBindingsTo(const T& bindings, BoundNodesTreeBuilder* Builder) const; + const BoundNodesMap& AggregatedBindings); // FIXME: Find out whether we want to use different data structures here - // first benchmarks indicate that it doesn't matter though. - std::map<std::string, const Decl*> DeclBindings; - std::map<std::string, const Stmt*> StmtBindings; + BoundNodesMap Bindings; std::vector<BoundNodesTree> RecursiveBindings; }; @@ -123,12 +160,13 @@ public: BoundNodesTreeBuilder(); /// \brief Add a binding from an id to a node. - /// - /// FIXME: Add overloads for all AST base types. - /// @{ - void setBinding(const std::string &Id, const Decl *Node); - void setBinding(const std::string &Id, const Stmt *Node); - /// @} + template <typename T> + void setBinding(const std::string &Id, const T *Node) { + Bindings.addNode(Id, Node); + } + void setBinding(const std::string &Id, ast_type_traits::DynTypedNode Node) { + Bindings.addNode(Id, Node); + } /// \brief Adds a branch in the tree. void addMatch(const BoundNodesTree& Bindings); @@ -137,11 +175,10 @@ public: BoundNodesTree build() const; private: - BoundNodesTreeBuilder(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT - void operator=(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT + BoundNodesTreeBuilder(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION; + void operator=(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION; - std::map<std::string, const Decl*> DeclBindings; - std::map<std::string, const Stmt*> StmtBindings; + BoundNodesMap Bindings; std::vector<BoundNodesTree> RecursiveBindings; }; @@ -169,7 +206,8 @@ public: BoundNodesTreeBuilder *Builder) const = 0; }; -/// \brief Interface for matchers that only evaluate properties on a single node. +/// \brief Interface for matchers that only evaluate properties on a single +/// node. template <typename T> class SingleNodeMatcherInterface : public MatcherInterface<T> { public: @@ -187,6 +225,24 @@ private: } }; +/// \brief Base class for all matchers that works on a \c DynTypedNode. +/// +/// Matcher implementations will check whether the \c DynTypedNode is +/// convertible into the respecitve types and then do the actual match +/// on the actual node, or return false if it is not convertible. +class DynTypedMatcher { +public: + virtual ~DynTypedMatcher() {} + + /// \brief Returns true if the matcher matches the given \c DynNode. + virtual bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const = 0; + + /// \brief Returns a unique ID for the matcher. + virtual uint64_t getID() const = 0; +}; + /// \brief Wrapper of a MatcherInterface<T> *that allows copying. /// /// A Matcher<Base> can be used anywhere a Matcher<Derived> is @@ -196,12 +252,32 @@ private: /// operator rather than a type hierarchy to be able to templatize the /// type hierarchy instead of spelling it out. template <typename T> -class Matcher { +class Matcher : public DynTypedMatcher { public: /// \brief Takes ownership of the provided implementation pointer. explicit Matcher(MatcherInterface<T> *Implementation) : Implementation(Implementation) {} + /// \brief Implicitly converts \c Other to a Matcher<T>. + /// + /// Requires \c T to be derived from \c From. + template <typename From> + Matcher(const Matcher<From> &Other, + typename llvm::enable_if_c< + llvm::is_base_of<From, T>::value && + !llvm::is_same<From, T>::value >::type* = 0) + : Implementation(new ImplicitCastMatcher<From>(Other)) {} + + /// \brief Implicitly converts \c Matcher<Type> to \c Matcher<QualType>. + /// + /// The resulting matcher is not strict, i.e. ignores qualifiers. + template <typename TypeT> + Matcher(const Matcher<TypeT> &Other, + typename llvm::enable_if_c< + llvm::is_same<T, QualType>::value && + llvm::is_same<TypeT, Type>::value >::type* = 0) + : Implementation(new TypeToQualType<TypeT>(Other)) {} + /// \brief Forwards the call to the underlying MatcherInterface<T> pointer. bool matches(const T &Node, ASTMatchFinder *Finder, @@ -209,14 +285,6 @@ public: return Implementation->matches(Node, Finder, Builder); } - /// \brief Implicitly converts this object to a Matcher<Derived>. - /// - /// Requires Derived to be derived from T. - template <typename Derived> - operator Matcher<Derived>() const { - return Matcher<Derived>(new ImplicitCastMatcher<Derived>(*this)); - } - /// \brief Returns an ID that uniquely identifies the matcher. uint64_t getID() const { /// FIXME: Document the requirements this imposes on matcher @@ -224,23 +292,55 @@ public: return reinterpret_cast<uint64_t>(Implementation.getPtr()); } + /// \brief Returns whether the matcher matches on the given \c DynNode. + virtual bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + const T *Node = DynNode.get<T>(); + if (!Node) return false; + return matches(*Node, Finder, Builder); + } + + /// \brief Allows the conversion of a \c Matcher<Type> to a \c + /// Matcher<QualType>. + /// + /// Depending on the constructor argument, the matcher is either strict, i.e. + /// does only matches in the absence of qualifiers, or not, i.e. simply + /// ignores any qualifiers. + template <typename TypeT> + class TypeToQualType : public MatcherInterface<QualType> { + public: + TypeToQualType(const Matcher<TypeT> &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const QualType &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + if (Node.isNull()) + return false; + return InnerMatcher.matches(*Node, Finder, Builder); + } + private: + const Matcher<TypeT> InnerMatcher; + }; + private: - /// \brief Allows conversion from Matcher<T> to Matcher<Derived> if Derived - /// is derived from T. - template <typename Derived> - class ImplicitCastMatcher : public MatcherInterface<Derived> { + /// \brief Allows conversion from Matcher<Base> to Matcher<T> if T + /// is derived from Base. + template <typename Base> + class ImplicitCastMatcher : public MatcherInterface<T> { public: - explicit ImplicitCastMatcher(const Matcher<T> &From) + explicit ImplicitCastMatcher(const Matcher<Base> &From) : From(From) {} - virtual bool matches(const Derived &Node, + virtual bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return From.matches(Node, Finder, Builder); } private: - const Matcher<T> From; + const Matcher<Base> From; }; llvm::IntrusiveRefCntPtr< MatcherInterface<T> > Implementation; @@ -280,18 +380,14 @@ private: /// FIXME: Add other ways to convert... if (Node.isNull()) return false; - CXXRecordDecl *NodeAsRecordDecl = Node->getAsCXXRecordDecl(); - return NodeAsRecordDecl != NULL && - InnerMatcher.matches(*NodeAsRecordDecl, Finder, Builder); + return matchesDecl(Node->getAsCXXRecordDecl(), Finder, Builder); } /// \brief Extracts the Decl of the callee of a CallExpr and returns whether /// the inner matcher matches on it. bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - const Decl *NodeAsDecl = Node.getCalleeDecl(); - return NodeAsDecl != NULL && - InnerMatcher.matches(*NodeAsDecl, Finder, Builder); + return matchesDecl(Node.getCalleeDecl(), Finder, Builder); } /// \brief Extracts the Decl of the constructor call and returns whether the @@ -299,96 +395,63 @@ private: bool matchesSpecialized(const CXXConstructExpr &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - const Decl *NodeAsDecl = Node.getConstructor(); - return NodeAsDecl != NULL && - InnerMatcher.matches(*NodeAsDecl, Finder, Builder); + return matchesDecl(Node.getConstructor(), Finder, Builder); + } + + /// \brief Extracts the \c ValueDecl a \c MemberExpr refers to and returns + /// whether the inner matcher matches on it. + bool matchesSpecialized(const MemberExpr &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesDecl(Node.getMemberDecl(), Finder, Builder); + } + + /// \brief Returns whether the inner matcher \c Node. Returns false if \c Node + /// is \c NULL. + bool matchesDecl(const Decl *Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Node != NULL && InnerMatcher.matches(*Node, Finder, Builder); } const Matcher<Decl> InnerMatcher; }; /// \brief IsBaseType<T>::value is true if T is a "base" type in the AST -/// node class hierarchies (i.e. if T is Decl, Stmt, or QualType). +/// node class hierarchies. template <typename T> struct IsBaseType { static const bool value = (llvm::is_same<T, Decl>::value || llvm::is_same<T, Stmt>::value || llvm::is_same<T, QualType>::value || + llvm::is_same<T, Type>::value || + llvm::is_same<T, TypeLoc>::value || + llvm::is_same<T, NestedNameSpecifier>::value || + llvm::is_same<T, NestedNameSpecifierLoc>::value || llvm::is_same<T, CXXCtorInitializer>::value); }; template <typename T> const bool IsBaseType<T>::value; -/// \brief Interface that can match any AST base node type and contains default -/// implementations returning false. -class UntypedBaseMatcher : public llvm::RefCountedBaseVPTR { -public: - virtual ~UntypedBaseMatcher() {} - - virtual bool matches(const Decl &DeclNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const QualType &TypeNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const Stmt &StmtNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const CXXCtorInitializer &CtorInitNode, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - - /// \brief Returns a unique ID for the matcher. - virtual uint64_t getID() const = 0; -}; - -/// \brief An UntypedBaseMatcher that overwrites the Matches(...) method for -/// node type T. T must be an AST base type. -template <typename T> -class TypedBaseMatcher : public UntypedBaseMatcher { - TOOLING_COMPILE_ASSERT(IsBaseType<T>::value, - typed_base_matcher_can_only_be_used_with_base_type); -public: - explicit TypedBaseMatcher(const Matcher<T> &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - using UntypedBaseMatcher::matches; - /// \brief Implements UntypedBaseMatcher::Matches. - /// - /// Since T is guaranteed to be a "base" AST node type, this method is - /// guaranteed to override one of the matches() methods from - /// UntypedBaseMatcher. - virtual bool matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return InnerMatcher.matches(Node, Finder, Builder); - } - - /// \brief Implements UntypedBaseMatcher::getID. - virtual uint64_t getID() const { - return InnerMatcher.getID(); - } - -private: - Matcher<T> InnerMatcher; -}; - /// \brief Interface that allows matchers to traverse the AST. /// FIXME: Find a better name. /// -/// This provides two entry methods for each base node type in the AST: -/// - matchesChildOf: +/// This provides three entry methods for each base node type in the AST: +/// - \c matchesChildOf: /// Matches a matcher on every child node of the given node. Returns true /// if at least one child node could be matched. -/// - matchesDescendantOf: +/// - \c matchesDescendantOf: /// Matches a matcher on all descendant nodes of the given node. Returns true /// if at least one descendant matched. +/// - \c matchesAncestorOf: +/// Matches a matcher on all ancestors of the given node. Returns true if +/// at least one ancestor matched. +/// +/// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal. +/// In the future, we wan to implement this for all nodes for which it makes +/// sense. In the case of matchesAncestorOf, we'll want to implement it for +/// all nodes, as all nodes have ancestors. class ASTMatchFinder { public: /// \brief Defines how we descend a level in the AST when we pass @@ -408,6 +471,14 @@ public: BK_All }; + /// \brief Defines which ancestors are considered for a match. + enum AncestorMatchMode { + /// All ancestors. + AMM_All, + /// Direct parent only. + AMM_ParentOnly + }; + virtual ~ASTMatchFinder() {} /// \brief Returns true if the given class is directly or indirectly derived @@ -418,26 +489,70 @@ public: const Matcher<NamedDecl> &Base, BoundNodesTreeBuilder *Builder) = 0; - // FIXME: Implement for other base nodes. - virtual bool matchesChildOf(const Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesTreeBuilder *Builder, - TraversalKind Traverse, - BindKind Bind) = 0; - virtual bool matchesChildOf(const Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, + template <typename T> + bool matchesChildOf(const T &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + TraversalKind Traverse, + BindKind Bind) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of<Decl, T>::value || + llvm::is_base_of<Stmt, T>::value || + llvm::is_base_of<NestedNameSpecifier, T>::value || + llvm::is_base_of<NestedNameSpecifierLoc, T>::value || + llvm::is_base_of<TypeLoc, T>::value || + llvm::is_base_of<QualType, T>::value), + unsupported_type_for_recursive_matching); + return matchesChildOf(ast_type_traits::DynTypedNode::create(Node), + Matcher, Builder, Traverse, Bind); + } + + template <typename T> + bool matchesDescendantOf(const T &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + BindKind Bind) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of<Decl, T>::value || + llvm::is_base_of<Stmt, T>::value || + llvm::is_base_of<NestedNameSpecifier, T>::value || + llvm::is_base_of<NestedNameSpecifierLoc, T>::value || + llvm::is_base_of<TypeLoc, T>::value || + llvm::is_base_of<QualType, T>::value), + unsupported_type_for_recursive_matching); + return matchesDescendantOf(ast_type_traits::DynTypedNode::create(Node), + Matcher, Builder, Bind); + } + + // FIXME: Implement support for BindKind. + template <typename T> + bool matchesAncestorOf(const T &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + AncestorMatchMode MatchMode) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<Decl, T>::value || + llvm::is_base_of<Stmt, T>::value), + only_Decl_or_Stmt_allowed_for_recursive_matching); + return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node), + Matcher, Builder, MatchMode); + } + +protected: + virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, TraversalKind Traverse, BindKind Bind) = 0; - virtual bool matchesDescendantOf(const Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesTreeBuilder *Builder, - BindKind Bind) = 0; - virtual bool matchesDescendantOf(const Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, + virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, BindKind Bind) = 0; + + virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, + BoundNodesTreeBuilder *Builder, + AncestorMatchMode MatchMode) = 0; }; /// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by @@ -606,9 +721,6 @@ public: /// The returned matcher is equivalent to this matcher, but will /// bind the matched node on a match. Matcher<T> bind(StringRef ID) const { - TOOLING_COMPILE_ASSERT((llvm::is_base_of<Stmt, T>::value || - llvm::is_base_of<Decl, T>::value), - trying_to_bind_unsupported_node_type__only_decl_and_stmt_supported); return Matcher<T>(new IdMatcher<T>(ID, *this)); } }; @@ -635,7 +747,7 @@ public: } private: - const TypedBaseMatcher<ChildT> ChildMatcher; + const Matcher<ChildT> ChildMatcher; }; /// \brief Matches nodes of type T that have child nodes of type ChildT for @@ -661,7 +773,7 @@ class ForEachMatcher : public MatcherInterface<T> { } private: - const TypedBaseMatcher<ChildT> ChildMatcher; + const Matcher<ChildT> ChildMatcher; }; /// \brief Matches nodes of type T if the given Matcher<T> does not match. @@ -733,6 +845,20 @@ private: const Matcher<T> InnertMatcher2; }; +/// \brief Creates a Matcher<T> that matches if all inner matchers match. +template<typename T> +BindableMatcher<T> makeAllOfComposite( + ArrayRef<const Matcher<T> *> InnerMatchers) { + if (InnerMatchers.empty()) + return BindableMatcher<T>(new TrueMatcher<T>); + MatcherInterface<T> *InnerMatcher = new TrueMatcher<T>; + for (int i = InnerMatchers.size() - 1; i >= 0; --i) { + InnerMatcher = new AllOfMatcher<T, Matcher<T>, Matcher<T> >( + *InnerMatchers[i], makeMatcher(InnerMatcher)); + } + return BindableMatcher<T>(InnerMatcher); +} + /// \brief Creates a Matcher<T> that matches if /// T is dyn_cast'able into InnerT and all inner matchers match. /// @@ -742,17 +868,8 @@ private: template<typename T, typename InnerT> BindableMatcher<T> makeDynCastAllOfComposite( ArrayRef<const Matcher<InnerT> *> InnerMatchers) { - if (InnerMatchers.empty()) { - Matcher<InnerT> InnerMatcher = makeMatcher(new TrueMatcher<InnerT>); - return BindableMatcher<T>(new DynCastMatcher<T, InnerT>(InnerMatcher)); - } - Matcher<InnerT> InnerMatcher = *InnerMatchers.back(); - for (int i = InnerMatchers.size() - 2; i >= 0; --i) { - InnerMatcher = makeMatcher( - new AllOfMatcher<InnerT, Matcher<InnerT>, Matcher<InnerT> >( - *InnerMatchers[i], InnerMatcher)); - } - return BindableMatcher<T>(new DynCastMatcher<T, InnerT>(InnerMatcher)); + return BindableMatcher<T>(new DynCastMatcher<T, InnerT>( + makeAllOfComposite(InnerMatchers))); } /// \brief Matches nodes of type T that have at least one descendant node of @@ -775,7 +892,53 @@ public: } private: - const TypedBaseMatcher<DescendantT> DescendantMatcher; + const Matcher<DescendantT> DescendantMatcher; +}; + +/// \brief Matches nodes of type \c T that have a parent node of type \c ParentT +/// for which the given inner matcher matches. +/// +/// \c ParentT must be an AST base type. +template <typename T, typename ParentT> +class HasParentMatcher : public MatcherInterface<T> { + TOOLING_COMPILE_ASSERT(IsBaseType<ParentT>::value, + has_parent_only_accepts_base_type_matcher); +public: + explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher) + : ParentMatcher(ParentMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Finder->matchesAncestorOf( + Node, ParentMatcher, Builder, ASTMatchFinder::AMM_ParentOnly); + } + + private: + const Matcher<ParentT> ParentMatcher; +}; + +/// \brief Matches nodes of type \c T that have at least one ancestor node of +/// type \c AncestorT for which the given inner matcher matches. +/// +/// \c AncestorT must be an AST base type. +template <typename T, typename AncestorT> +class HasAncestorMatcher : public MatcherInterface<T> { + TOOLING_COMPILE_ASSERT(IsBaseType<AncestorT>::value, + has_ancestor_only_accepts_base_type_matcher); +public: + explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher) + : AncestorMatcher(AncestorMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Finder->matchesAncestorOf( + Node, AncestorMatcher, Builder, ASTMatchFinder::AMM_All); + } + + private: + const Matcher<AncestorT> AncestorMatcher; }; /// \brief Matches nodes of type T that have at least one descendant node of @@ -801,7 +964,7 @@ class ForEachDescendantMatcher : public MatcherInterface<T> { } private: - const TypedBaseMatcher<DescendantT> DescendantMatcher; + const Matcher<DescendantT> DescendantMatcher; }; /// \brief Matches on nodes that have a getValue() method if getValue() equals @@ -858,6 +1021,22 @@ class IsTemplateInstantiationMatcher : public MatcherInterface<T> { } }; +/// \brief Matches on explicit template specializations for FunctionDecl, +/// VarDecl or CXXRecordDecl nodes. +template <typename T> +class IsExplicitTemplateSpecializationMatcher : public MatcherInterface<T> { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, T>::value) || + (llvm::is_base_of<VarDecl, T>::value) || + (llvm::is_base_of<CXXRecordDecl, T>::value), + requires_getTemplateSpecializationKind_method); + public: + virtual bool matches(const T& Node, + ASTMatchFinder* Finder, + BoundNodesTreeBuilder* Builder) const { + return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization); + } +}; + class IsArrowMatcher : public SingleNodeMatcherInterface<MemberExpr> { public: virtual bool matchesNode(const MemberExpr &Node) const { @@ -894,6 +1073,166 @@ public: VariadicDynCastAllOfMatcher() {} }; +/// \brief A \c VariadicAllOfMatcher<T> object is a variadic functor that takes +/// a number of \c Matcher<T> and returns a \c Matcher<T> that matches \c T +/// nodes that are matched by all of the given matchers. +/// +/// For example: +/// const VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier; +/// Creates a functor nestedNameSpecifier(...) that creates a +/// \c Matcher<NestedNameSpecifier> given a variable number of arguments of type +/// \c Matcher<NestedNameSpecifier>. +/// The returned matcher matches if all given matchers match. +template <typename T> +class VariadicAllOfMatcher : public llvm::VariadicFunction< + BindableMatcher<T>, Matcher<T>, + makeAllOfComposite<T> > { +public: + VariadicAllOfMatcher() {} +}; + +/// \brief Matches nodes of type \c TLoc for which the inner +/// \c Matcher<T> matches. +template <typename TLoc, typename T> +class LocMatcher : public MatcherInterface<TLoc> { +public: + explicit LocMatcher(const Matcher<T> &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const TLoc &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + if (!Node) + return false; + return InnerMatcher.matches(*extract(Node), Finder, Builder); + } + +private: + const NestedNameSpecifier *extract(const NestedNameSpecifierLoc &Loc) const { + return Loc.getNestedNameSpecifier(); + } + + const Matcher<T> InnerMatcher; +}; + +/// \brief Matches \c NestedNameSpecifiers with a prefix matching another +/// \c Matcher<NestedNameSpecifier>. +class NestedNameSpecifierPrefixMatcher + : public MatcherInterface<NestedNameSpecifier> { +public: + explicit NestedNameSpecifierPrefixMatcher( + const Matcher<NestedNameSpecifier> &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const NestedNameSpecifier &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + NestedNameSpecifier *NextNode = Node.getPrefix(); + if (NextNode == NULL) + return false; + return InnerMatcher.matches(*NextNode, Finder, Builder); + } + +private: + const Matcher<NestedNameSpecifier> InnerMatcher; +}; + +/// \brief Matches \c NestedNameSpecifierLocs with a prefix matching another +/// \c Matcher<NestedNameSpecifierLoc>. +class NestedNameSpecifierLocPrefixMatcher + : public MatcherInterface<NestedNameSpecifierLoc> { +public: + explicit NestedNameSpecifierLocPrefixMatcher( + const Matcher<NestedNameSpecifierLoc> &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const NestedNameSpecifierLoc &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + NestedNameSpecifierLoc NextNode = Node.getPrefix(); + if (!NextNode) + return false; + return InnerMatcher.matches(NextNode, Finder, Builder); + } + +private: + const Matcher<NestedNameSpecifierLoc> InnerMatcher; +}; + +/// \brief Matches \c TypeLocs based on an inner matcher matching a certain +/// \c QualType. +/// +/// Used to implement the \c loc() matcher. +class TypeLocTypeMatcher : public MatcherInterface<TypeLoc> { +public: + explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const TypeLoc &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + if (!Node) + return false; + return InnerMatcher.matches(Node.getType(), Finder, Builder); + } + +private: + const Matcher<QualType> InnerMatcher; +}; + +/// \brief Matches nodes of type \c T for which the inner matcher matches on a +/// another node of type \c T that can be reached using a given traverse +/// function. +template <typename T> +class TypeTraverseMatcher : public MatcherInterface<T> { +public: + explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher, + QualType (T::*TraverseFunction)() const) + : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + QualType NextNode = (Node.*TraverseFunction)(); + if (NextNode.isNull()) + return false; + return InnerMatcher.matches(NextNode, Finder, Builder); + } + +private: + const Matcher<QualType> InnerMatcher; + QualType (T::*TraverseFunction)() const; +}; + +/// \brief Matches nodes of type \c T in a ..Loc hierarchy, for which the inner +/// matcher matches on a another node of type \c T that can be reached using a +/// given traverse function. +template <typename T> +class TypeLocTraverseMatcher : public MatcherInterface<T> { +public: + explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher, + TypeLoc (T::*TraverseFunction)() const) + : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + TypeLoc NextNode = (Node.*TraverseFunction)(); + if (!NextNode) + return false; + return InnerMatcher.matches(NextNode, Finder, Builder); + } + +private: + const Matcher<TypeLoc> InnerMatcher; + TypeLoc (T::*TraverseFunction)() const; +}; + +template <typename T, typename InnerT> +T makeTypeAllOfComposite(ArrayRef<const Matcher<InnerT> *> InnerMatchers) { + return T(makeAllOfComposite<InnerT>(InnerMatchers)); +} + } // end namespace internal } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h index c68534a..953abc2 100644 --- a/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -221,4 +221,69 @@ const NodeType &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const +/// \brief Creates a variadic matcher for both a specific \c Type as well as +/// the corresponding \c TypeLoc. +#define AST_TYPE_MATCHER(NodeType, MatcherName) \ + const internal::VariadicDynCastAllOfMatcher<Type, NodeType> MatcherName; \ + const internal::VariadicDynCastAllOfMatcher<TypeLoc, \ + NodeType##Loc> MatcherName##Loc + +/// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines +/// the matcher \c MatcherName that can be used to traverse from one \c Type +/// to another. +/// +/// For a specific \c SpecificType, the traversal is done using +/// \c SpecificType::FunctionName. The existance of such a function determines +/// whether a corresponding matcher can be used on \c SpecificType. +#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) \ +class Polymorphic##MatcherName##TypeMatcher { \ +public: \ + Polymorphic##MatcherName##TypeMatcher( \ + const internal::Matcher<QualType> &InnerMatcher) \ + : InnerMatcher(InnerMatcher) {} \ + template <typename T> operator internal::Matcher<T>() { \ + return internal::Matcher<T>(new internal::TypeTraverseMatcher<T>( \ + InnerMatcher, &T::FunctionName)); \ + } \ +private: \ + const internal::Matcher<QualType> InnerMatcher; \ +}; \ +class Variadic##MatcherName##TypeTraverseMatcher \ + : public llvm::VariadicFunction< \ + Polymorphic##MatcherName##TypeMatcher, \ + internal::Matcher<QualType>, \ + internal::makeTypeAllOfComposite< \ + Polymorphic##MatcherName##TypeMatcher, QualType> > { \ +public: \ + Variadic##MatcherName##TypeTraverseMatcher() {} \ +}; \ +const Variadic##MatcherName##TypeTraverseMatcher MatcherName + +/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works +/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs. +#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) \ +class Polymorphic##MatcherName##TypeLocMatcher { \ +public: \ + Polymorphic##MatcherName##TypeLocMatcher( \ + const internal::Matcher<TypeLoc> &InnerMatcher) \ + : InnerMatcher(InnerMatcher) {} \ + template <typename T> operator internal::Matcher<T>() { \ + return internal::Matcher<T>(new internal::TypeLocTraverseMatcher<T>( \ + InnerMatcher, &T::FunctionName##Loc)); \ + } \ +private: \ + const internal::Matcher<TypeLoc> InnerMatcher; \ +}; \ +class Variadic##MatcherName##TypeLocTraverseMatcher \ + : public llvm::VariadicFunction< \ + Polymorphic##MatcherName##TypeLocMatcher, \ + internal::Matcher<TypeLoc>, \ + internal::makeTypeAllOfComposite< \ + Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \ +public: \ + Variadic##MatcherName##TypeLocTraverseMatcher() {} \ +}; \ +const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \ +AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type) + #endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H diff --git a/include/clang/ASTMatchers/ASTTypeTraits.h b/include/clang/ASTMatchers/ASTTypeTraits.h new file mode 100644 index 0000000..bda53ea --- /dev/null +++ b/include/clang/ASTMatchers/ASTTypeTraits.h @@ -0,0 +1,209 @@ +//===--- ASTMatchersTypeTraits.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Provides a dynamically typed node container that can be used to store +// an AST base node at runtime in the same storage in a type safe way. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H +#define LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H + +#include "clang/AST/Decl.h" +#include "clang/AST/Stmt.h" +#include "llvm/Support/AlignOf.h" + +namespace clang { +namespace ast_type_traits { + +/// \brief A dynamically typed AST node container. +/// +/// Stores an AST node in a type safe way. This allows writing code that +/// works with different kinds of AST nodes, despite the fact that they don't +/// have a common base class. +/// +/// Use \c create(Node) to create a \c DynTypedNode from an AST node, +/// and \c get<T>() to retrieve the node as type T if the types match. +/// +/// See \c NodeTypeTag for which node base types are currently supported; +/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of +/// the supported base types. +class DynTypedNode { +public: + /// \brief Creates a \c DynTypedNode from \c Node. + template <typename T> + static DynTypedNode create(const T &Node) { + return BaseConverter<T>::create(Node); + } + + /// \brief Retrieve the stored node as type \c T. + /// + /// Returns NULL if the stored node does not have a type that is + /// convertible to \c T. + /// + /// For types that have identity via their pointer in the AST + /// (like \c Stmt and \c Decl) the returned pointer points to the + /// referenced AST node. + /// For other types (like \c QualType) the value is stored directly + /// in the \c DynTypedNode, and the returned pointer points at + /// the storage inside DynTypedNode. For those nodes, do not + /// use the pointer outside the scope of the DynTypedNode. + template <typename T> + const T *get() const { + return BaseConverter<T>::get(Tag, Storage.buffer); + } + + /// \brief Returns a pointer that identifies the stored AST node. + /// + /// Note that this is not supported by all AST nodes. For AST nodes + /// that don't have a pointer-defined identity inside the AST, this + /// method returns NULL. + const void *getMemoizationData() const; + +private: + /// \brief Takes care of converting from and to \c T. + template <typename T, typename EnablerT = void> struct BaseConverter; + + /// \brief Supported base node types. + enum NodeTypeTag { + NT_Decl, + NT_Stmt, + NT_NestedNameSpecifier, + NT_NestedNameSpecifierLoc, + NT_QualType, + NT_Type, + NT_TypeLoc + } Tag; + + /// \brief Stores the data of the node. + /// + /// Note that we can store \c Decls and \c Stmts by pointer as they are + /// guaranteed to be unique pointers pointing to dedicated storage in the + /// AST. \c QualTypes on the other hand do not have storage or unique + /// pointers and thus need to be stored by value. + llvm::AlignedCharArrayUnion<Decl*, QualType, TypeLoc, NestedNameSpecifierLoc> + Storage; +}; + +// FIXME: Pull out abstraction for the following. +template<typename T> struct DynTypedNode::BaseConverter<T, + typename llvm::enable_if<llvm::is_base_of<Decl, T> >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Decl) + return dyn_cast<T>(*reinterpret_cast<Decl*const*>(Storage)); + return NULL; + } + static DynTypedNode create(const Decl &Node) { + DynTypedNode Result; + Result.Tag = NT_Decl; + new (Result.Storage.buffer) const Decl*(&Node); + return Result; + } +}; +template<typename T> struct DynTypedNode::BaseConverter<T, + typename llvm::enable_if<llvm::is_base_of<Stmt, T> >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Stmt) + return dyn_cast<T>(*reinterpret_cast<Stmt*const*>(Storage)); + return NULL; + } + static DynTypedNode create(const Stmt &Node) { + DynTypedNode Result; + Result.Tag = NT_Stmt; + new (Result.Storage.buffer) const Stmt*(&Node); + return Result; + } +}; +template<typename T> struct DynTypedNode::BaseConverter<T, + typename llvm::enable_if<llvm::is_base_of<Type, T> >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Type) + return dyn_cast<T>(*reinterpret_cast<Type*const*>(Storage)); + return NULL; + } + static DynTypedNode create(const Type &Node) { + DynTypedNode Result; + Result.Tag = NT_Type; + new (Result.Storage.buffer) const Type*(&Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter<NestedNameSpecifier, void> { + static const NestedNameSpecifier *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_NestedNameSpecifier) + return *reinterpret_cast<NestedNameSpecifier*const*>(Storage); + return NULL; + } + static DynTypedNode create(const NestedNameSpecifier &Node) { + DynTypedNode Result; + Result.Tag = NT_NestedNameSpecifier; + new (Result.Storage.buffer) const NestedNameSpecifier*(&Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter<NestedNameSpecifierLoc, void> { + static const NestedNameSpecifierLoc *get(NodeTypeTag Tag, + const char Storage[]) { + if (Tag == NT_NestedNameSpecifierLoc) + return reinterpret_cast<const NestedNameSpecifierLoc*>(Storage); + return NULL; + } + static DynTypedNode create(const NestedNameSpecifierLoc &Node) { + DynTypedNode Result; + Result.Tag = NT_NestedNameSpecifierLoc; + new (Result.Storage.buffer) NestedNameSpecifierLoc(Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter<QualType, void> { + static const QualType *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_QualType) + return reinterpret_cast<const QualType*>(Storage); + return NULL; + } + static DynTypedNode create(const QualType &Node) { + DynTypedNode Result; + Result.Tag = NT_QualType; + new (Result.Storage.buffer) QualType(Node); + return Result; + } +}; +template<> struct DynTypedNode::BaseConverter<TypeLoc, void> { + static const TypeLoc *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_TypeLoc) + return reinterpret_cast<const TypeLoc*>(Storage); + return NULL; + } + static DynTypedNode create(const TypeLoc &Node) { + DynTypedNode Result; + Result.Tag = NT_TypeLoc; + new (Result.Storage.buffer) TypeLoc(Node); + return Result; + } +}; +// The only operation we allow on unsupported types is \c get. +// This allows to conveniently use \c DynTypedNode when having an arbitrary +// AST node that is not supported, but prevents misuse - a user cannot create +// a DynTypedNode from arbitrary types. +template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter { + static const T *get(NodeTypeTag Tag, const char Storage[]) { return NULL; } +}; + +inline const void *DynTypedNode::getMemoizationData() const { + switch (Tag) { + case NT_Decl: return BaseConverter<Decl>::get(Tag, Storage.buffer); + case NT_Stmt: return BaseConverter<Stmt>::get(Tag, Storage.buffer); + default: return NULL; + }; +} + +} // end namespace ast_type_traits +} // end namespace clang + +#endif // LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H |