[ASTMatchers] Make hasOverloadedOperatorName also match freestanding overloads.
Freestanding overloads are represented as FunctionDecls in the AST, make the matcher also match them. Differential Revision: http://reviews.llvm.org/D4493 llvm-svn: 212940
This commit is contained in:
parent
8e254166e1
commit
09514492cc
|
@ -1542,14 +1542,14 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
|
||||||
/// line and \c recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches
|
/// line and \c recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches
|
||||||
/// the declaration of \c A.
|
/// the declaration of \c A.
|
||||||
///
|
///
|
||||||
/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl>
|
/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl>
|
||||||
inline internal::PolymorphicMatcherWithParam1<
|
inline internal::PolymorphicMatcherWithParam1<
|
||||||
internal::HasOverloadedOperatorNameMatcher, StringRef,
|
internal::HasOverloadedOperatorNameMatcher, StringRef,
|
||||||
AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>
|
AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>
|
||||||
hasOverloadedOperatorName(const StringRef Name) {
|
hasOverloadedOperatorName(const StringRef Name) {
|
||||||
return internal::PolymorphicMatcherWithParam1<
|
return internal::PolymorphicMatcherWithParam1<
|
||||||
internal::HasOverloadedOperatorNameMatcher, StringRef,
|
internal::HasOverloadedOperatorNameMatcher, StringRef,
|
||||||
AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>(
|
AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>(
|
||||||
Name);
|
Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -517,7 +517,7 @@ template <typename T> struct has_getDecl {
|
||||||
template <typename T, typename ArgT>
|
template <typename T, typename ArgT>
|
||||||
class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
|
class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
|
||||||
static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
|
static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
|
||||||
std::is_same<T, CXXMethodDecl>::value,
|
std::is_base_of<FunctionDecl, T>::value,
|
||||||
"unsupported class for matcher");
|
"unsupported class for matcher");
|
||||||
static_assert(std::is_same<ArgT, StringRef>::value,
|
static_assert(std::is_same<ArgT, StringRef>::value,
|
||||||
"argument type must be StringRef");
|
"argument type must be StringRef");
|
||||||
|
@ -541,7 +541,7 @@ private:
|
||||||
|
|
||||||
/// \brief Returns true only if CXXMethodDecl represents an overloaded
|
/// \brief Returns true only if CXXMethodDecl represents an overloaded
|
||||||
/// operator and has the given operator name.
|
/// operator and has the given operator name.
|
||||||
bool matchesSpecialized(const CXXMethodDecl &Node) const {
|
bool matchesSpecialized(const FunctionDecl &Node) const {
|
||||||
return Node.isOverloadedOperator() &&
|
return Node.isOverloadedOperator() &&
|
||||||
getOperatorSpelling(Node.getOverloadedOperator()) == Name;
|
getOperatorSpelling(Node.getOverloadedOperator()) == Name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1095,12 +1095,19 @@ TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) {
|
||||||
"bool operator&&(Y x, Y y) { return true; }; "
|
"bool operator&&(Y x, Y y) { return true; }; "
|
||||||
"Y a; Y b; bool c = a && b;",
|
"Y a; Y b; bool c = a && b;",
|
||||||
OpCallLessLess));
|
OpCallLessLess));
|
||||||
|
StatementMatcher OpStarCall =
|
||||||
|
operatorCallExpr(hasOverloadedOperatorName("*"));
|
||||||
|
EXPECT_TRUE(matches("class Y; int operator*(Y &); void f(Y &y) { *y; }",
|
||||||
|
OpStarCall));
|
||||||
DeclarationMatcher ClassWithOpStar =
|
DeclarationMatcher ClassWithOpStar =
|
||||||
recordDecl(hasMethod(hasOverloadedOperatorName("*")));
|
recordDecl(hasMethod(hasOverloadedOperatorName("*")));
|
||||||
EXPECT_TRUE(matches("class Y { int operator*(); };",
|
EXPECT_TRUE(matches("class Y { int operator*(); };",
|
||||||
ClassWithOpStar));
|
ClassWithOpStar));
|
||||||
EXPECT_TRUE(notMatches("class Y { void myOperator(); };",
|
EXPECT_TRUE(notMatches("class Y { void myOperator(); };",
|
||||||
ClassWithOpStar)) ;
|
ClassWithOpStar)) ;
|
||||||
|
DeclarationMatcher AnyOpStar = functionDecl(hasOverloadedOperatorName("*"));
|
||||||
|
EXPECT_TRUE(matches("class Y; int operator*(Y &);", AnyOpStar));
|
||||||
|
EXPECT_TRUE(matches("class Y { int operator*(); };", AnyOpStar));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Matcher, NestedOverloadedOperatorCalls) {
|
TEST(Matcher, NestedOverloadedOperatorCalls) {
|
||||||
|
|
Loading…
Reference in New Issue