aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/cp-gimplify.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2013-11-22 21:07:31 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2013-11-22 21:07:31 +0100
commit0a508bb66b6056dd7a7cd7a689daa1b1dfff6863 (patch)
tree27f73f1a16fc3ef2b2d49ac81210b2c02c06ba3f /gcc/cp/cp-gimplify.c
parent59b36ecf239ba0164f55a2ac2cd37154d7963dd9 (diff)
downloadgcc-0a508bb66b6056dd7a7cd7a689daa1b1dfff6863.zip
gcc-0a508bb66b6056dd7a7cd7a689daa1b1dfff6863.tar.gz
gcc-0a508bb66b6056dd7a7cd7a689daa1b1dfff6863.tar.bz2
ubsan.c (ubsan_source_location): Don't crash on unknown locations.
* ubsan.c (ubsan_source_location): Don't crash on unknown locations. (ubsan_pass): Ignore clobber stmts. * sanitizer.def (BUILT_IN_UBSAN_HANDLE_MISSING_RETURN): New built-in. * opts.c (common_handle_option): Add -fsanitize=return. * flag-types.h (enum sanitize_code): Add SANITIZE_RETURN and or it into SANITIZE_UNDEFINED. c-family/ * c-ubsan.h (ubsan_instrument_return): New prototype. * c-ubsan.c (ubsan_instrument_return): New function. cp/ * cp-gimplify.c: Include target.h and c-family/c-ubsan.h. (cp_ubsan_maybe_instrument_return): New function. (cp_genericize): Call it if -fsanitize=return. testsuite/ * g++.dg/ubsan/return-1.C: New test. * g++.dg/ubsan/return-2.C: New test. From-SVN: r205283
Diffstat (limited to 'gcc/cp/cp-gimplify.c')
-rw-r--r--gcc/cp/cp-gimplify.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 176dbc3..b1270a1 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -39,6 +39,8 @@ along with GCC; see the file COPYING3. If not see
#include "hashtab.h"
#include "flags.h"
#include "splay-tree.h"
+#include "target.h"
+#include "c-family/c-ubsan.h"
/* Forward declarations. */
@@ -1178,6 +1180,59 @@ cp_genericize_tree (tree* t_p)
wtd.bind_expr_stack.release ();
}
+/* If a function that should end with a return in non-void
+ function doesn't obviously end with return, add ubsan
+ instrmentation code to verify it at runtime. */
+
+static void
+cp_ubsan_maybe_instrument_return (tree fndecl)
+{
+ if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
+ || DECL_CONSTRUCTOR_P (fndecl)
+ || DECL_DESTRUCTOR_P (fndecl)
+ || !targetm.warn_func_return (fndecl))
+ return;
+
+ tree t = DECL_SAVED_TREE (fndecl);
+ while (t)
+ {
+ switch (TREE_CODE (t))
+ {
+ case BIND_EXPR:
+ t = BIND_EXPR_BODY (t);
+ continue;
+ case TRY_FINALLY_EXPR:
+ t = TREE_OPERAND (t, 0);
+ continue;
+ case STATEMENT_LIST:
+ {
+ tree_stmt_iterator i = tsi_last (t);
+ if (!tsi_end_p (i))
+ {
+ t = tsi_stmt (i);
+ continue;
+ }
+ }
+ break;
+ case RETURN_EXPR:
+ return;
+ default:
+ break;
+ }
+ break;
+ }
+ 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_stmt_iterator i = tsi_last (BIND_EXPR_BODY (t));
+ t = ubsan_instrument_return (DECL_SOURCE_LOCATION (fndecl));
+ tsi_link_after (&i, t, TSI_NEW_STMT);
+ }
+}
+
void
cp_genericize (tree fndecl)
{
@@ -1240,6 +1295,9 @@ cp_genericize (tree fndecl)
walk_tree's hash functionality. */
cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
+ if (flag_sanitize & SANITIZE_RETURN)
+ cp_ubsan_maybe_instrument_return (fndecl);
+
/* Do everything else. */
c_genericize (fndecl);