]> granicus.if.org Git - clang/commitdiff
[CFG] Fix CFG for statement-expressions in return values.
authorArtem Dergachev <artem.dergachev@gmail.com>
Thu, 29 Aug 2019 20:37:28 +0000 (20:37 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Thu, 29 Aug 2019 20:37:28 +0000 (20:37 +0000)
We're building the CFG from bottom to top, so when the return-value expression
has a non-trivial CFG on its own, we need to continue building from the entry
to the return-value expression CFG rather than from the block to which
we've just appended the return statement.

Fixes a false positive warning "control may reach end of non-void function".

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@370406 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/CFG.cpp
test/Analysis/cfg.cpp
test/Sema/return.c

index e4ed0f86b918afd5de796a39ee184af6c369a506..fb835d43680a01f806d9a9ff2fc5b45056371eea 100644 (file)
@@ -2994,9 +2994,8 @@ CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) {
 
   // Visit children
   if (ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) {
-    Expr *O = RS->getRetValue();
-    if (O)
-      Visit(O, AddStmtChoice::AlwaysAdd, /*ExternallyDestructed=*/true);
+    if (Expr *O = RS->getRetValue())
+      return Visit(O, AddStmtChoice::AlwaysAdd, /*ExternallyDestructed=*/true);
     return Block;
   } else { // co_return
     return VisitChildren(S);
index 74f4d50f25dfc26c5894dee2140162889f1e1dea..9b0203e99efe972f58af5ba1dad53be67b8bf24e 100644 (file)
@@ -499,6 +499,54 @@ void foo() {
 } // end namespace pr37688_deleted_union_destructor
 
 
+namespace return_statement_expression {
+int unknown();
+
+// CHECK-LABEL: int foo()
+// CHECK:       [B6 (ENTRY)]
+// CHECK-NEXT:    Succs (1): B5
+// CHECK:       [B1]
+// CHECK-NEXT:    1: 0
+// CHECK-NEXT:    2: return [B1.1];
+// CHECK-NEXT:    Preds (1): B5
+// CHECK-NEXT:    Succs (1): B0
+// CHECK:       [B2]
+// CHECK-NEXT:    1: 0
+// CHECK-NEXT:    2: ({ ... ; [B2.1] })
+// CHECK-NEXT:    3: return [B2.2];
+// CHECK-NEXT:    Preds (1): B4
+// CHECK-NEXT:    Succs (1): B0
+// FIXME: Why do we have [B3] at all?
+// CHECK:       [B3]
+// CHECK-NEXT:    Succs (1): B4
+// CHECK:       [B4]
+// CHECK-NEXT:    1: 0
+// CHECK-NEXT:    2: [B4.1] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT:    T: while [B4.2]
+// CHECK-NEXT:    Preds (2): B3 B5
+// CHECK-NEXT:    Succs (2): NULL B2
+// CHECK:       [B5]
+// CHECK-NEXT:    1: unknown
+// CHECK-NEXT:    2: [B5.1] (ImplicitCastExpr, FunctionToPointerDecay, int (*)(void))
+// CHECK-NEXT:    3: [B5.2]()
+// CHECK-NEXT:    4: [B5.3] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT:    T: if [B5.4]
+// CHECK-NEXT:    Preds (1): B6
+// CHECK-NEXT:    Succs (2): B4 B1
+// CHECK:       [B0 (EXIT)]
+// CHECK-NEXT:    Preds (2): B1 B2
+int foo() {
+  if (unknown())
+    return ({
+      while (0)
+        ;
+      0;
+    });
+  else
+    return 0;
+}
+} // namespace statement_expression_in_return
+
 // CHECK-LABEL: template<> int *PR18472<int>()
 // CHECK: [B2 (ENTRY)]
 // CHECK-NEXT:   Succs (1): B1
@@ -522,4 +570,3 @@ template <class T> T *PR18472() {
 void PR18472_helper() {
   PR18472<int>();
 }
-
index debf5ab55f5b5b0530f173df730ee7bdbb0d1717..68c2251c463303f82decdb9a8cac5b214df101fc 100644 (file)
@@ -328,3 +328,14 @@ int sizeof_long() {
   if (sizeof(long) == 8)
     return 2;
 } // no-warning
+
+int return_statement_expression() {
+  if (unknown())
+    return ({
+      while (0)
+        ;
+      0;
+    });
+  else
+    return 0;
+} // no-warning (used to be "control may reach end of non-void function")