diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -7164,14 +7164,20 @@
Matches the return value expression of a return statement +@@ -7188,6 +7194,24 @@ Matches the return value expression of a return statement or GNU statement +expression. Given + auto i = ({foo(); *ptr;}) return a + b; hasReturnValue(binaryOperator()) matches 'return a + b' with binaryOperator() matching 'a + b' +hasReturnValue(unaryOperator()) + matches ({foo(); *ptr;}) +with unaryOperator() + matching '*ptr'
Matches the return value expression of a return statement or GNU statement
+expression.
+
+Given
+ auto i = ({foo(); *ptr;})
+ return a + b;
+hasReturnValue(binaryOperator())
+ matches 'return a + b'
+with binaryOperator()
+ matching 'a + b'
+hasReturnValue(unaryOperator())
+ matches ({foo(); *ptr;})
+with unaryOperator()
+ matching '*ptr'
+Same as unaryExprOrTypeTraitExpr, but only matching
alignof.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -6712,21 +6712,27 @@
return false;
}
-/// Matches the return value expression of a return statement
+/// Matches the return value expression of a return statement or GNU statement
+/// expression.
///
/// Given
/// \code
+/// auto i = ({foo(); *ptr;})
/// return a + b;
/// \endcode
/// hasReturnValue(binaryOperator())
/// matches 'return a + b'
/// with binaryOperator()
/// matching 'a + b'
-AST_MATCHER_P(ReturnStmt, hasReturnValue, internal::Matcher,
- InnerMatcher) {
- if (const auto *RetValue = Node.getRetValue())
- return InnerMatcher.matches(*RetValue, Finder, Builder);
- return false;
+/// hasReturnValue(unaryOperator())
+/// matches ({foo(); *ptr;})
+/// with unaryOperator()
+/// matching '*ptr'
+AST_POLYMORPHIC_MATCHER_P(hasReturnValue,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(ReturnStmt, StmtExpr),
+ internal::Matcher, InnerMatcher) {
+ const Expr *Ret = internal::getReturnValue(Node);
+ return Ret && InnerMatcher.matches(*Ret, Finder, Builder);
}
/// Matches CUDA kernel call expression.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1852,6 +1852,17 @@
return Node.getSubStmt();
}
+inline const Expr *getReturnValue(const ReturnStmt &Node) {
+ return Node.getRetValue();
+}
+
+inline const Expr *getReturnValue(const StmtExpr &Node) {
+ const CompoundStmt *CS = Node.getSubStmt();
+ if (!CS)
+ return nullptr;
+ return llvm::dyn_cast_or_null(CS->body_back());
+}
+
/// If \p Loc is (transitively) expanded from macro \p MacroName, returns the
/// location (in the chain of expansions) at which \p MacroName was
/// expanded. Since the macro may have been expanded inside a series of
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -3004,6 +3004,10 @@
EXPECT_TRUE(matches("int F() { int a, b; return a + b; }", RetVal));
EXPECT_FALSE(matches("int F() { int a; return a; }", RetVal));
EXPECT_FALSE(matches("void F() { return; }", RetVal));
+ StatementMatcher RetStmtExprVal = stmtExpr(hasReturnValue(binaryOperator()));
+ EXPECT_TRUE(matches("void F() { ({int a, b; a + b;}); }", RetStmtExprVal));
+ EXPECT_FALSE(matches("void F() { ({int a; a;}); }", RetStmtExprVal));
+ EXPECT_FALSE(matches("void F() { ({int a;}); }", RetStmtExprVal));
}
TEST(StatementMatcher, ForFunction) {