diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -7188,6 +7188,18 @@ +
Matches the result value expression of a GNU statement expression. + +Given + ({int *Ptr; *Ptr;}); +hasFinalExpr(unaryOperator()) + matches '({int *Ptr; *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 @@ -6729,6 +6729,24 @@ return false; } +/// Matches the result value expression of a GNU statement expression. +/// +/// Given +/// \code +/// ({int *Ptr; *Ptr;}); +/// \endcode +/// hasFinalExpr(unaryOperator()) +/// matches '({int *Ptr; *Ptr;})' +/// with unaryOperator() +/// matching '*Ptr' +AST_MATCHER_P(StmtExpr, hasFinalExpr, internal::Matcher, InnerMatcher) { + if (const CompoundStmt *CS = Node.getSubStmt()) { + if (const auto *E = dyn_cast_or_null (CS->body_back())) + return InnerMatcher.matches(*E, Finder, Builder); + } + return false; +} + /// Matches CUDA kernel call expression. /// /// Example matches, 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 @@ -3006,6 +3006,13 @@ EXPECT_FALSE(matches("void F() { return; }", RetVal)); } +TEST(StatementMatcher, hasFinalExpr) { + StatementMatcher RetVal = stmtExpr(hasFinalExpr(binaryOperator())); + EXPECT_TRUE(matches("void F() { ({int a, b; a + b;}); }", RetVal)); + EXPECT_FALSE(matches("void F() { ({int a; a;}); }", RetVal)); + EXPECT_FALSE(matches("void F() { ({int a;}); }", RetVal)); +} + TEST(StatementMatcher, ForFunction) { const auto CppString1 = "struct PosVec {"