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) {