Hi!

As the testcases show, we actually instrument -fsanitize=return only if
the DECL_SAVED_TREE (fndecl) is a BIND_EXPR with STATEMENT_LIST as its
BIND_EXPR_BODY (plus tests that it actually needs such an instrumentation).
The return-{4,5}.C tests show that it isn't always the case, sometimes we
have just a STATEMENT_LIST without BIND_EXPR around it (for empty
functions), sometimes BIND_EXPR_BODY is a single statement, not a
STATEMENT_LIST.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2016-09-27  Jakub Jelinek  <ja...@redhat.com>

        PR c++/77722
        * cp-gimplify.c (cp_ubsan_maybe_instrument_return): Instrument also
        functions that have just a STATEMENT_LIST instead of BIND_EXPR, or
        BIND_EXPR with some statement rather than STATEMENT_LIST as body.

        * g++.dg/ubsan/return-4.C: New test.
        * g++.dg/ubsan/return-5.C: New test.
        * g++.dg/ubsan/return-6.C: New test.

--- gcc/cp/cp-gimplify.c.jj     2016-08-12 17:33:42.000000000 +0200
+++ gcc/cp/cp-gimplify.c        2016-09-26 09:37:30.679543731 +0200
@@ -1570,14 +1570,22 @@ cp_ubsan_maybe_instrument_return (tree f
     }
   if (t == NULL_TREE)
     return;
-  t = DECL_SAVED_TREE (fndecl);
-  if (TREE_CODE (t) == BIND_EXPR
-      && TREE_CODE (BIND_EXPR_BODY (t)) == STATEMENT_LIST)
+  tree *p = &DECL_SAVED_TREE (fndecl);
+  if (TREE_CODE (*p) == BIND_EXPR)
+    p = &BIND_EXPR_BODY (*p);
+  t = ubsan_instrument_return (DECL_SOURCE_LOCATION (fndecl));
+  if (TREE_CODE (*p) == STATEMENT_LIST)
     {
-      tree_stmt_iterator i = tsi_last (BIND_EXPR_BODY (t));
-      t = ubsan_instrument_return (DECL_SOURCE_LOCATION (fndecl));
+      tree_stmt_iterator i = tsi_last (*p);
       tsi_link_after (&i, t, TSI_NEW_STMT);
     }
+  else
+    {
+      tree list = NULL_TREE;
+      append_to_statement_list_force (*p, &list);
+      append_to_statement_list (t, &list);
+      *p = list;
+    }
 }
 
 void
--- gcc/testsuite/g++.dg/ubsan/return-4.C.jj    2016-09-26 09:42:45.306503657 
+0200
+++ gcc/testsuite/g++.dg/ubsan/return-4.C       2016-09-26 09:54:08.778728718 
+0200
@@ -0,0 +1,18 @@
+// PR c++/77722
+// { dg-do run }
+// { dg-options "-fsanitize=return -w" }
+// { dg-shouldfail "ubsan" }
+
+int
+foo ()
+{
+}
+
+int
+main ()
+{
+  foo ();
+  return 0;
+}
+
+// { dg-output "execution reached the end of a value-returning function 
without returning a value" }
--- gcc/testsuite/g++.dg/ubsan/return-5.C.jj    2016-09-26 09:53:37.135134983 
+0200
+++ gcc/testsuite/g++.dg/ubsan/return-5.C       2016-09-26 09:54:03.273799395 
+0200
@@ -0,0 +1,19 @@
+// PR c++/77722
+// { dg-do run }
+// { dg-options "-fsanitize=return -w" }
+// { dg-shouldfail "ubsan" }
+
+int
+foo ()
+{
+  int a = 5;
+}
+
+int
+main ()
+{
+  foo ();
+  return 0;
+}
+
+// { dg-output "execution reached the end of a value-returning function 
without returning a value" }
--- gcc/testsuite/g++.dg/ubsan/return-6.C.jj    2016-09-26 09:53:40.024097892 
+0200
+++ gcc/testsuite/g++.dg/ubsan/return-6.C       2016-09-26 09:54:14.327657477 
+0200
@@ -0,0 +1,20 @@
+// PR c++/77722
+// { dg-do run }
+// { dg-options "-fsanitize=return -w" }
+// { dg-shouldfail "ubsan" }
+
+int
+foo ()
+{
+  int a = 5;
+  int b = 5;
+}
+
+int
+main ()
+{
+  foo ();
+  return 0;
+}
+
+// { dg-output "execution reached the end of a value-returning function 
without returning a value" }

        Jakub

Reply via email to