Skip to content

Commit 60e5ecd

Browse files
authored
[ASTMatchers] Fix matching CXXOperatorCallExpr of -> (#139994)
The `->` operator does not have a corresponding `UnaryOperatorKind`, and so was unsupported by the `hasOperatorName` and `hasUnaryOperand` matchers. Instead of trying to determine the equivalent unary or binary operator and then deriving the opcode string, we consult `OperatorKinds.def` directly (through `getOperatorSpelling`). For `hasUnaryOperand` support, we special case the arrow operator specifically.
1 parent e9cba3c commit 60e5ecd

File tree

2 files changed

+28
-21
lines changed

2 files changed

+28
-21
lines changed

clang/include/clang/ASTMatchers/ASTMatchersInternal.h

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,8 +2161,10 @@ inline const Expr *getSubExpr(const NodeType &Node) {
21612161
template <>
21622162
inline const Expr *
21632163
getSubExpr<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) {
2164-
if (!internal::equivalentUnaryOperator(Node))
2164+
if (!internal::equivalentUnaryOperator(Node) &&
2165+
Node.getOperator() != OO_Arrow) {
21652166
return nullptr;
2167+
}
21662168
return Node.getArg(0);
21672169
}
21682170

@@ -2223,14 +2225,9 @@ inline StringRef getOpName(const CXXRewrittenBinaryOperator &Node) {
22232225
return Node.getOpcodeStr();
22242226
}
22252227
inline std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
2226-
auto optBinaryOpcode = equivalentBinaryOperator(Node);
2227-
if (!optBinaryOpcode) {
2228-
auto optUnaryOpcode = equivalentUnaryOperator(Node);
2229-
if (!optUnaryOpcode)
2230-
return std::nullopt;
2231-
return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
2232-
}
2233-
return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
2228+
if (const char *Str = getOperatorSpelling(Node.getOperator()))
2229+
return Str;
2230+
return std::nullopt;
22342231
}
22352232
inline StringRef getOpName(const CXXFoldExpr &Node) {
22362233
return BinaryOperator::getOpcodeStr(Node.getOperator());
@@ -2271,14 +2268,9 @@ class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
22712268
return Node.getOpcodeStr();
22722269
}
22732270
static std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
2274-
auto optBinaryOpcode = equivalentBinaryOperator(Node);
2275-
if (!optBinaryOpcode) {
2276-
auto optUnaryOpcode = equivalentUnaryOperator(Node);
2277-
if (!optUnaryOpcode)
2278-
return std::nullopt;
2279-
return UnaryOperator::getOpcodeStr(*optUnaryOpcode);
2280-
}
2281-
return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
2271+
if (const char *Str = getOperatorSpelling(Node.getOperator()))
2272+
return Str;
2273+
return std::nullopt;
22822274
}
22832275

22842276
std::vector<std::string> Names;

clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2025,21 +2025,36 @@ void plusIntOperator()
20252025
hasOperatorName("+"), hasUnaryOperand(expr())))));
20262026

20272027
Code = R"cpp(
2028-
struct HasOpArrow
2028+
struct S {
2029+
void foo(int);
2030+
};
2031+
struct HasOpStar
20292032
{
20302033
int& operator*();
20312034
};
2032-
void foo()
2035+
struct HasOpArrow
20332036
{
2034-
HasOpArrow s1;
2035-
*s1;
2037+
S* operator->();
2038+
};
2039+
void hasOpStarMem(HasOpStar s)
2040+
{
2041+
*s;
2042+
}
2043+
void hasOpArrowMem(HasOpArrow a)
2044+
{
2045+
a->foo(42);
20362046
}
20372047
)cpp";
20382048

20392049
EXPECT_TRUE(
20402050
matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
20412051
cxxOperatorCallExpr(hasOperatorName("*"),
20422052
hasUnaryOperand(expr())))));
2053+
EXPECT_TRUE(matches(
2054+
Code, traverse(TK_IgnoreUnlessSpelledInSource,
2055+
cxxOperatorCallExpr(hasOperatorName("->"),
2056+
hasUnaryOperand(declRefExpr(
2057+
to(varDecl(hasName("a")))))))));
20432058
}
20442059

20452060
TEST(Matcher, UnaryOperatorTypes) {

0 commit comments

Comments
 (0)