njames93 created this revision.
njames93 added reviewers: aaron.ballman, klimek.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Extend hasReturnValue to match the last statement in a gnu statement expression 
if the last statement is an expression.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D76196

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ 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) {
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ 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<Expr>(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
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ 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<Expr>,
-              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<Expr>, InnerMatcher) {
+  const Expr *Ret = internal::getReturnValue(Node);
+  return Ret && InnerMatcher.matches(*Ret, Finder, Builder);
 }
 
 /// Matches CUDA kernel call expression.
Index: clang/docs/LibASTMatchersReference.html
===================================================================
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -7164,14 +7164,20 @@
 
 
 <tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ReturnStmt.html";>ReturnStmt</a>&gt;</td><td class="name" onclick="toggle('hasReturnValue0')"><a name="hasReturnValue0Anchor">hasReturnValue</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasReturnValue0"><pre>Matches the return value expression of a return statement
+<tr><td colspan="4" class="doc" id="hasReturnValue0"><pre>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'
 </pre></td></tr>
 
 
@@ -7188,6 +7194,24 @@
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1StmtExpr.html";>StmtExpr</a>&gt;</td><td class="name" onclick="toggle('hasReturnValue1')"><a name="hasReturnValue1Anchor">hasReturnValue</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasReturnValue1"><pre>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'
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt</a>&gt;</td><td class="name" onclick="toggle('alignOfExpr0')"><a name="alignOfExpr0Anchor">alignOfExpr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html";>UnaryExprOrTypeTraitExpr</a>&gt;  InnerMatcher</td></tr>
 <tr><td colspan="4" class="doc" id="alignOfExpr0"><pre>Same as unaryExprOrTypeTraitExpr, but only matching
 alignof.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to