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 @@ Matcher<ReturnStmt>hasReturnValueMatcher<Expr> InnerMatcher -
Matches the return value expression of a return statement
+
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'
 
@@ -7188,6 +7194,24 @@
+Matcher<StmtExpr>hasReturnValueMatcher<Expr> InnerMatcher +
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'
+
+ + Matcher<Stmt>alignOfExprMatcher<UnaryExprOrTypeTraitExpr> InnerMatcher
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) {