]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR sanitizer/81212 (-Wreturn-type is disabled when used together with...
authorJakub Jelinek <jakub@redhat.com>
Mon, 25 Jun 2018 16:57:59 +0000 (18:57 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 25 Jun 2018 16:57:59 +0000 (18:57 +0200)
Backported from mainline
2017-12-02  Jakub Jelinek  <jakub@redhat.com>

PR c++/81212
* tree-cfg.c (pass_warn_function_return::execute): Handle
__builtin_ubsan_handle_missing_return like __builtin_unreachable
with BUILTINS_LOCATION.

* g++.dg/ubsan/pr81212.C: New test.

From-SVN: r262042

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ubsan/pr81212.C [new file with mode: 0644]
gcc/tree-cfg.c

index 310eda8082d809bb2e045e68556a44cddd31952b..e961c0e34222ecf40b36834a3b0906cbfdbe0c16 100644 (file)
@@ -3,6 +3,11 @@
        Backported from mainline
        2017-12-02  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c++/81212
+       * tree-cfg.c (pass_warn_function_return::execute): Handle
+       __builtin_ubsan_handle_missing_return like __builtin_unreachable
+       with BUILTINS_LOCATION.
+
        PR target/78643
        PR target/80583
        * expr.c (get_inner_reference): If DECL_MODE of a non-bitfield
index 204fea0c8f8a66cedf396784d1c6bb7a01e8fc4d..67023267d1b317b0bfadbfabbeb9d7738f45d4b5 100644 (file)
@@ -3,6 +3,9 @@
        Backported from mainline
        2017-12-02  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c++/81212
+       * g++.dg/ubsan/pr81212.C: New test.
+
        PR target/78643
        PR target/80583
        * gcc.target/i386/pr80583.c: New test.
diff --git a/gcc/testsuite/g++.dg/ubsan/pr81212.C b/gcc/testsuite/g++.dg/ubsan/pr81212.C
new file mode 100644 (file)
index 0000000..ce92a07
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/81212
+// { dg-do compile }
+// { dg-options "-Wreturn-type -fsanitize=return" }
+
+struct S
+{
+  S (void *);
+  void *s;
+};
+
+S
+foo (bool x, void *y)
+{
+  if (x)
+    return S (y);
+}      // { dg-warning "control reaches end of non-void function" }
index 380f6898db75da019b49d8ec5f83ca3164b89277..983fd704f6bcfc4d5a71c013985587d1574fdd33 100644 (file)
@@ -8752,7 +8752,6 @@ pass_warn_function_return::execute (function *fun)
      without returning a value.  */
   else if (warn_return_type
           && !TREE_NO_WARNING (fun->decl)
-          && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (fun)->preds) > 0
           && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fun->decl))))
     {
       FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (fun)->preds)
@@ -8766,11 +8765,40 @@ pass_warn_function_return::execute (function *fun)
              location = gimple_location (last);
              if (location == UNKNOWN_LOCATION)
                location = fun->function_end_locus;
-             warning_at (location, OPT_Wreturn_type, "control reaches end of non-void function");
+             warning_at (location, OPT_Wreturn_type,
+                         "control reaches end of non-void function");
              TREE_NO_WARNING (fun->decl) = 1;
              break;
            }
        }
+      /* -fsanitize=return turns fallthrough from the end of non-void function
+        into __builtin___ubsan_handle_missing_return () call.
+        Recognize those too.  */
+      basic_block bb;
+      if (!TREE_NO_WARNING (fun->decl) && (flag_sanitize & SANITIZE_RETURN))
+       FOR_EACH_BB_FN (bb, fun)
+         if (EDGE_COUNT (bb->succs) == 0)
+           {
+             gimple *last = last_stmt (bb);
+             const enum built_in_function ubsan_missing_ret
+               = BUILT_IN_UBSAN_HANDLE_MISSING_RETURN;
+             if (last && gimple_call_builtin_p (last, ubsan_missing_ret))
+               {
+                 gimple_stmt_iterator gsi = gsi_for_stmt (last);
+                 gsi_prev_nondebug (&gsi);
+                 gimple *prev = gsi_stmt (gsi);
+                 if (prev == NULL)
+                   location = UNKNOWN_LOCATION;
+                 else
+                   location = gimple_location (prev);
+                 if (LOCATION_LOCUS (location) == UNKNOWN_LOCATION)
+                   location = fun->function_end_locus;
+                 warning_at (location, OPT_Wreturn_type,
+                             "control reaches end of non-void function");
+                 TREE_NO_WARNING (fun->decl) = 1;
+                 break;
+               }
+           }
     }
   return 0;
 }