aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2017-11-06 10:02:15 +0100
committerMartin Liska <marxin@gcc.gnu.org>2017-11-06 09:02:15 +0000
commit1b6fa695ab5e6f6fd57ed9264b336f06f440125b (patch)
tree34f2706dd509a58f25ed69fda30793e918703da2 /gcc/cp
parent3232f0521cda16efeff012f65bc4d0b15d02a7e2 (diff)
downloadgcc-1b6fa695ab5e6f6fd57ed9264b336f06f440125b.zip
gcc-1b6fa695ab5e6f6fd57ed9264b336f06f440125b.tar.gz
gcc-1b6fa695ab5e6f6fd57ed9264b336f06f440125b.tar.bz2
Instrument function exit with __builtin_unreachable in C++
2017-11-06 Martin Liska <mliska@suse.cz> PR middle-end/82404 * c-opts.c (c_common_post_options): Set -Wreturn-type for C++ FE. * c.opt: Set default value of warn_return_type. 2017-11-06 Martin Liska <mliska@suse.cz> PR middle-end/82404 * constexpr.c (cxx_eval_builtin_function_call): Handle __builtin_unreachable call. (get_function_named_in_call): Declare function earlier. (constexpr_fn_retval): Skip __builtin_unreachable. * cp-gimplify.c (cp_ubsan_maybe_instrument_return): Rename to ... (cp_maybe_instrument_return): ... this. (cp_genericize): Call the function unconditionally. 2017-11-06 Martin Liska <mliska@suse.cz> PR middle-end/82404 * options.c (gfc_post_options): Set default value of -Wreturn-type to false. From-SVN: r254437
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/constexpr.c52
-rw-r--r--gcc/cp/cp-gimplify.c20
3 files changed, 61 insertions, 23 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 590e322..bb90b5a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2017-11-06 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/82404
+ * constexpr.c (cxx_eval_builtin_function_call): Handle
+ __builtin_unreachable call.
+ (get_function_named_in_call): Declare function earlier.
+ (constexpr_fn_retval): Skip __builtin_unreachable.
+ * cp-gimplify.c (cp_ubsan_maybe_instrument_return): Rename to
+ ...
+ (cp_maybe_instrument_return): ... this.
+ (cp_genericize): Call the function unconditionally.
+
2017-11-03 Nathan Sidwell <nathan@acm.org>
PR c++/82710
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 483f731..670aae2 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -628,6 +628,20 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
return error_mark_node;
}
+/* We have an expression tree T that represents a call, either CALL_EXPR
+ or AGGR_INIT_EXPR. If the call is lexically to a named function,
+ retrun the _DECL for that function. */
+
+static tree
+get_function_named_in_call (tree t)
+{
+ tree fun = cp_get_callee (t);
+ if (fun && TREE_CODE (fun) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fun, 0)) == FUNCTION_DECL)
+ fun = TREE_OPERAND (fun, 0);
+ return fun;
+}
+
/* Subroutine of register_constexpr_fundef. BODY is the body of a function
declared to be constexpr, or a sub-statement thereof. Returns the
return value if suitable, error_mark_node for a statement not allowed in
@@ -682,6 +696,15 @@ constexpr_fn_retval (tree body)
case USING_STMT:
return NULL_TREE;
+ case CALL_EXPR:
+ {
+ tree fun = get_function_named_in_call (body);
+ if (fun != NULL_TREE
+ && DECL_FUNCTION_CODE (fun) == BUILT_IN_UNREACHABLE)
+ return NULL_TREE;
+ }
+ /* Fallthru. */
+
default:
return error_mark_node;
}
@@ -1098,20 +1121,6 @@ save_fundef_copy (tree fun, tree copy)
}
/* We have an expression tree T that represents a call, either CALL_EXPR
- or AGGR_INIT_EXPR. If the call is lexically to a named function,
- retrun the _DECL for that function. */
-
-static tree
-get_function_named_in_call (tree t)
-{
- tree fun = cp_get_callee (t);
- if (fun && TREE_CODE (fun) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (fun, 0)) == FUNCTION_DECL)
- fun = TREE_OPERAND (fun, 0);
- return fun;
-}
-
-/* We have an expression tree T that represents a call, either CALL_EXPR
or AGGR_INIT_EXPR. Return the Nth argument. */
static inline tree
@@ -1180,9 +1189,18 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
{
if (!*non_constant_p && !ctx->quiet)
{
- new_call = build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
- CALL_EXPR_FN (t), nargs, args);
- error ("%q+E is not a constant expression", new_call);
+ /* Do not allow__builtin_unreachable in constexpr function.
+ The __builtin_unreachable call with BUILTINS_LOCATION
+ comes from cp_maybe_instrument_return. */
+ if (DECL_FUNCTION_CODE (fun) == BUILT_IN_UNREACHABLE
+ && EXPR_LOCATION (t) == BUILTINS_LOCATION)
+ error ("constexpr call flows off the end of the function");
+ else
+ {
+ new_call = build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
+ CALL_EXPR_FN (t), nargs, args);
+ error ("%q+E is not a constant expression", new_call);
+ }
}
*non_constant_p = true;
return t;
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 262485a..014c1ee 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1556,10 +1556,11 @@ cp_genericize_tree (tree* t_p, bool handle_invisiref_parm_p)
/* If a function that should end with a return in non-void
function doesn't obviously end with return, add ubsan
- instrumentation code to verify it at runtime. */
+ instrumentation code to verify it at runtime. If -fsanitize=return
+ is not enabled, instrument __builtin_unreachable. */
static void
-cp_ubsan_maybe_instrument_return (tree fndecl)
+cp_maybe_instrument_return (tree fndecl)
{
if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
|| DECL_CONSTRUCTOR_P (fndecl)
@@ -1600,7 +1601,16 @@ cp_ubsan_maybe_instrument_return (tree fndecl)
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));
+
+ location_t loc = DECL_SOURCE_LOCATION (fndecl);
+ if (sanitize_flags_p (SANITIZE_RETURN, fndecl))
+ t = ubsan_instrument_return (loc);
+ else
+ {
+ tree fndecl = builtin_decl_explicit (BUILT_IN_UNREACHABLE);
+ t = build_call_expr_loc (BUILTINS_LOCATION, fndecl, 0);
+ }
+
append_to_statement_list (t, p);
}
@@ -1674,9 +1684,7 @@ cp_genericize (tree fndecl)
walk_tree's hash functionality. */
cp_genericize_tree (&DECL_SAVED_TREE (fndecl), true);
- if (sanitize_flags_p (SANITIZE_RETURN)
- && current_function_decl != NULL_TREE)
- cp_ubsan_maybe_instrument_return (fndecl);
+ cp_maybe_instrument_return (fndecl);
/* Do everything else. */
c_genericize (fndecl);