diff options
Diffstat (limited to 'gcc/cp/cp-gimplify.c')
-rw-r--r-- | gcc/cp/cp-gimplify.c | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index e2629464dd9..b1270a187f1 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -28,12 +28,19 @@ along with GCC; see the file COPYING3. If not see #include "cp-tree.h" #include "c-family/c-common.h" #include "tree-iterator.h" +#include "pointer-set.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "hashtab.h" -#include "pointer-set.h" #include "flags.h" #include "splay-tree.h" +#include "target.h" +#include "c-family/c-ubsan.h" /* Forward declarations. */ @@ -1173,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) { @@ -1235,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); |