diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchers.h | 64 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchersInternal.h | 38 |
2 files changed, 93 insertions, 9 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 4e369523e8..c5ebd3c450 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -1384,18 +1384,26 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { /// \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 @@ inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom( 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. /// @@ -1786,6 +1815,23 @@ AST_MATCHER_P(QualType, references, internal::Matcher<QualType>, InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); } +/// \brief Matches QualTypes whose canonical type matches InnerMatcher. +/// +/// Given: +/// \code +/// typedef int &int_ref; +/// int a; +/// int_ref b = a; +/// \code +/// +/// \c varDecl(hasType(qualType(referenceType()))))) will not match the +/// declaration of b but \c +/// varDecl(hasType(qualType(hasCanonicalType(referenceType())))))) does. +AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher<QualType>, + InnerMatcher) { + return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder); +} + /// \brief Overloaded to match the referenced type's declaration. inline internal::Matcher<QualType> references( const internal::Matcher<Decl> &InnerMatcher) { diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index f309794034..30691ad8f9 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -370,6 +370,44 @@ template <typename T> struct has_getDecl { 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> { + TOOLING_COMPILE_ASSERT((llvm::is_same<T, CXXOperatorCallExpr>::value || + llvm::is_same<T, CXXMethodDecl>::value), + unsupported_class_for_matcher); + TOOLING_COMPILE_ASSERT((llvm::is_same<ArgT, StringRef>::value), + argument_type_must_be_StringRef); +public: + explicit HasOverloadedOperatorNameMatcher(const StringRef Name) + : SingleNodeMatcherInterface<T>(), Name(Name) {} + + virtual bool matchesNode(const T &Node) const LLVM_OVERRIDE { + return matchesSpecialized(Node); + } + +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 |