Hi klimek, Added a new narrowing matcher: hasMethod which aplies a matcher to a CXXRecordDecl's methods until a match is made or there are no more methods.
Enhanced hasOverloadedOperatorName to work on CXXOperatorCallExpr as well as CXXMethodDecl. Updated tests and docs. http://llvm-reviews.chandlerc.com/D494 Files: docs/LibASTMatchersReference.html include/clang/ASTMatchers/ASTMatchers.h include/clang/ASTMatchers/ASTMatchersInternal.h unittests/ASTMatchers/ASTMatchersTest.cpp
Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -1393,17 +1393,43 @@ </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasOverloadedOperatorName0')"><a name="hasOverloadedOperatorName0Anchor">hasOverloadedOperatorName</a></td><td>std::string Name</td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>></td><td class="name" onclick="toggle('hasOverloadedOperatorName0')"><a name="hasOverloadedOperatorName0Anchor">hasOverloadedOperatorName</a></td><td>StringRef Name</td></tr> <tr><td colspan="4" class="doc" id="hasOverloadedOperatorName0"><pre>Matches overloaded operator names. Matches overloaded operator names specified in strings without the -"operator" prefix, such as "<<", for OverloadedOperatorCall's. +"operator" prefix: e.g. "<<". -Example matches a << b - (matcher == operatorCallExpr(hasOverloadedOperatorName("<<"))) - a << b; - c && d; assuming both operator<< - and operator&& are overloaded somewhere. +Given: + class A { int operator*(); }; + const A &operator<<(const A &a, const A &b); + A a; + a << a; <-- This matches + +operatorCallExpr(hasOverloadedOperatorName("<<"))) matches the specified +line and recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches +the declaration of A. + +Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>> +</pre></td></tr> + + +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasOverloadedOperatorName1')"><a name="hasOverloadedOperatorName1Anchor">hasOverloadedOperatorName</a></td><td>StringRef Name</td></tr> +<tr><td colspan="4" class="doc" id="hasOverloadedOperatorName1"><pre>Matches overloaded operator names. + +Matches overloaded operator names specified in strings without the +"operator" prefix: e.g. "<<". + +Given: + class A { int operator*(); }; + const A &operator<<(const A &a, const A &b); + A a; + a << a; <-- This matches + +operatorCallExpr(hasOverloadedOperatorName("<<"))) matches the specified +line and recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches +the declaration of A. + +Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>> </pre></td></tr> @@ -2230,6 +2256,18 @@ </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasMethod0')"><a name="hasMethod0Anchor">hasMethod</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasMethod0"><pre>Matches the first method of a class or struct that satisfies InnerMatcher. + +Given: + class A { void func(); }; + class B { void member(); }; + +recordDecl(hasMethod(hasName("func"))) matches the declaration of A +but not B. +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('isDerivedFrom0')"><a name="isDerivedFrom0Anchor">isDerivedFrom</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>> Base</td></tr> <tr><td colspan="4" class="doc" id="isDerivedFrom0"><pre>Matches C++ classes that are directly or indirectly derived from a class matching Base. Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -1384,18 +1384,26 @@ /// \brief Matches overloaded operator names. /// /// Matches overloaded operator names specified in strings without the -/// "operator" prefix, such as "<<", for OverloadedOperatorCall's. +/// "operator" prefix: e.g. "<<". /// -/// Example matches a << b -/// (matcher == operatorCallExpr(hasOverloadedOperatorName("<<"))) +/// Given: /// \code -/// a << b; -/// c && d; // assuming both operator<< -/// // and operator&& are overloaded somewhere. +/// class A { int operator*(); }; +/// const A &operator<<(const A &a, const A &b); +/// A a; +/// a << a; // <-- This matches /// \endcode -AST_MATCHER_P(CXXOperatorCallExpr, - hasOverloadedOperatorName, std::string, Name) { - return getOperatorSpelling(Node.getOperator()) == Name; +/// +/// \c operatorCallExpr(hasOverloadedOperatorName("<<"))) matches the specified +/// line and \c recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches +/// the declaration of \c A. +/// +/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl> +inline internal::PolymorphicMatcherWithParam1< + internal::HasOverloadedOperatorNameMatcher, StringRef> +hasOverloadedOperatorName(const StringRef Name) { + return internal::PolymorphicMatcherWithParam1< + internal::HasOverloadedOperatorNameMatcher, StringRef>(Name); } /// \brief Matches C++ classes that are directly or indirectly derived from @@ -1445,6 +1453,27 @@ return isSameOrDerivedFrom(hasName(BaseName)); } +/// \brief Matches the first method of a class or struct that satisfies \c +/// InnerMatcher. +/// +/// Given: +/// \code +/// class A { void func(); }; +/// class B { void member(); }; +/// \code +/// +/// \c recordDecl(hasMethod(hasName("func"))) matches the declaration of \c A +/// but not \c B. +AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>, + InnerMatcher) { + for (CXXRecordDecl::method_iterator I = Node.method_begin(), + E = Node.method_end(); + I != E; ++I) + if (InnerMatcher.matches(**I, Finder, Builder)) + return true; + return false; +} + /// \brief Matches AST nodes that have child AST nodes that match the /// provided matcher. /// Index: include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- include/clang/ASTMatchers/ASTMatchersInternal.h +++ include/clang/ASTMatchers/ASTMatchersInternal.h @@ -370,6 +370,40 @@ static bool const value = sizeof(f<Derived>(0)) == 2; }; +// \brief Matches overloaded operators with a specific name. +// +// The type argument ArgT is not used by this matcher but is used by +// PolymorphicMatcherWithParam1 and should be StringRef. +template <typename T, typename ArgT> +class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> { +public: + explicit HasOverloadedOperatorNameMatcher(const StringRef Name) + : SingleNodeMatcherInterface<T>(), Name(Name) {} + + virtual bool matchesNode(const T &Node) const { + return matchesSpecialized(Node); + } + LLVM_OVERRIDE; + +private: + + /// \brief CXXOperatorCallExpr exist only for calls to overloaded operators + /// so this function returns true if the call is to an operator of the given + /// name. + bool matchesSpecialized(const CXXOperatorCallExpr &Node) const { + return getOperatorSpelling(Node.getOperator()) == Name; + } + + /// \brief Returns true only if CXXMethodDecl represents an overloaded + /// operator and has the given operator name. + bool matchesSpecialized(const CXXMethodDecl &Node) const { + return Node.isOverloadedOperator() && + getOperatorSpelling(Node.getOverloadedOperator()) == Name; + } + + std::string Name; +}; + /// \brief Matches declarations for QualType and CallExpr. /// /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but Index: unittests/ASTMatchers/ASTMatchersTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTest.cpp +++ unittests/ASTMatchers/ASTMatchersTest.cpp @@ -313,6 +313,13 @@ recordDecl(isDerivedFrom(recordDecl(hasName("X")).bind("test"))))); } +TEST(DeclarationMatcher, hasMethod) { + EXPECT_TRUE(matches("class A { void func(); };", + recordDecl(hasMethod(hasName("func"))))); + EXPECT_TRUE(notMatches("class A { void func(); };", + recordDecl(hasMethod(isPublic())))); +} + TEST(DeclarationMatcher, ClassDerivedFromDependentTemplateSpecialization) { EXPECT_TRUE(matches( "template <typename T> struct A {" @@ -1022,6 +1029,12 @@ "bool operator&&(Y x, Y y) { return true; }; " "Y a; Y b; bool c = a && b;", OpCallLessLess)); + DeclarationMatcher ClassWithOpStar = + recordDecl(hasMethod(hasOverloadedOperatorName("*"))); + EXPECT_TRUE(matches("class Y { int operator*(); };", + ClassWithOpStar)); + EXPECT_TRUE(notMatches("class Y { void myOperator(); };", + ClassWithOpStar)) ; } TEST(Matcher, NestedOverloadedOperatorCalls) {
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
