Commit 1b6fa695 by Martin Liska Committed by Martin Liska

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
parent 3232f052
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-10-31 David Malcolm <dmalcolm@redhat.com> 2017-10-31 David Malcolm <dmalcolm@redhat.com>
* c-common.c (binary_op_error): Update for renaming of * c-common.c (binary_op_error): Update for renaming of
......
...@@ -989,6 +989,9 @@ c_common_post_options (const char **pfilename) ...@@ -989,6 +989,9 @@ c_common_post_options (const char **pfilename)
flag_extern_tls_init = 1; flag_extern_tls_init = 1;
} }
if (warn_return_type == -1)
warn_return_type = c_dialect_cxx ();
if (num_in_fnames > 1) if (num_in_fnames > 1)
error ("too many filenames given. Type %s --help for usage", error ("too many filenames given. Type %s --help for usage",
progname); progname);
......
...@@ -960,7 +960,7 @@ C++ ObjC++ Var(warn_reorder) Warning LangEnabledBy(C++ ObjC++,Wall) ...@@ -960,7 +960,7 @@ C++ ObjC++ Var(warn_reorder) Warning LangEnabledBy(C++ ObjC++,Wall)
Warn when the compiler reorders code. Warn when the compiler reorders code.
Wreturn-type Wreturn-type
C ObjC C++ ObjC++ Var(warn_return_type) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) C ObjC C++ ObjC++ Var(warn_return_type) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Init(-1)
Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++). Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++).
Wscalar-storage-order Wscalar-storage-order
......
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> 2017-11-03 Nathan Sidwell <nathan@acm.org>
PR c++/82710 PR c++/82710
......
...@@ -628,6 +628,20 @@ build_constexpr_constructor_member_initializers (tree type, tree body) ...@@ -628,6 +628,20 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
return error_mark_node; 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 /* Subroutine of register_constexpr_fundef. BODY is the body of a function
declared to be constexpr, or a sub-statement thereof. Returns the declared to be constexpr, or a sub-statement thereof. Returns the
return value if suitable, error_mark_node for a statement not allowed in return value if suitable, error_mark_node for a statement not allowed in
...@@ -682,6 +696,15 @@ constexpr_fn_retval (tree body) ...@@ -682,6 +696,15 @@ constexpr_fn_retval (tree body)
case USING_STMT: case USING_STMT:
return NULL_TREE; 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: default:
return error_mark_node; return error_mark_node;
} }
...@@ -1098,20 +1121,6 @@ save_fundef_copy (tree fun, tree copy) ...@@ -1098,20 +1121,6 @@ save_fundef_copy (tree fun, tree copy)
} }
/* We have an expression tree T that represents a call, either CALL_EXPR /* 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. */ or AGGR_INIT_EXPR. Return the Nth argument. */
static inline tree static inline tree
...@@ -1180,10 +1189,19 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, ...@@ -1180,10 +1189,19 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
{ {
if (!*non_constant_p && !ctx->quiet) if (!*non_constant_p && !ctx->quiet)
{ {
/* 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), new_call = build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
CALL_EXPR_FN (t), nargs, args); CALL_EXPR_FN (t), nargs, args);
error ("%q+E is not a constant expression", new_call); error ("%q+E is not a constant expression", new_call);
} }
}
*non_constant_p = true; *non_constant_p = true;
return t; return t;
} }
......
...@@ -1556,10 +1556,11 @@ cp_genericize_tree (tree* t_p, bool handle_invisiref_parm_p) ...@@ -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 /* If a function that should end with a return in non-void
function doesn't obviously end with return, add ubsan 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 static void
cp_ubsan_maybe_instrument_return (tree fndecl) cp_maybe_instrument_return (tree fndecl)
{ {
if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))) if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
|| DECL_CONSTRUCTOR_P (fndecl) || DECL_CONSTRUCTOR_P (fndecl)
...@@ -1600,7 +1601,16 @@ cp_ubsan_maybe_instrument_return (tree fndecl) ...@@ -1600,7 +1601,16 @@ cp_ubsan_maybe_instrument_return (tree fndecl)
tree *p = &DECL_SAVED_TREE (fndecl); tree *p = &DECL_SAVED_TREE (fndecl);
if (TREE_CODE (*p) == BIND_EXPR) if (TREE_CODE (*p) == BIND_EXPR)
p = &BIND_EXPR_BODY (*p); 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); append_to_statement_list (t, p);
} }
...@@ -1674,9 +1684,7 @@ cp_genericize (tree fndecl) ...@@ -1674,9 +1684,7 @@ cp_genericize (tree fndecl)
walk_tree's hash functionality. */ walk_tree's hash functionality. */
cp_genericize_tree (&DECL_SAVED_TREE (fndecl), true); cp_genericize_tree (&DECL_SAVED_TREE (fndecl), true);
if (sanitize_flags_p (SANITIZE_RETURN) cp_maybe_instrument_return (fndecl);
&& current_function_decl != NULL_TREE)
cp_ubsan_maybe_instrument_return (fndecl);
/* Do everything else. */ /* Do everything else. */
c_genericize (fndecl); c_genericize (fndecl);
......
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.
2017-11-05 Thomas Koenig <tkoenig@gcc.gnu.org> 2017-11-05 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/82471 PR fortran/82471
......
...@@ -435,6 +435,9 @@ gfc_post_options (const char **pfilename) ...@@ -435,6 +435,9 @@ gfc_post_options (const char **pfilename)
gfc_fatal_error ("Maximum subrecord length cannot exceed %d", gfc_fatal_error ("Maximum subrecord length cannot exceed %d",
MAX_SUBRECORD_LENGTH); MAX_SUBRECORD_LENGTH);
if (warn_return_type == -1)
warn_return_type = 0;
gfc_cpp_post_options (); gfc_cpp_post_options ();
if (gfc_option.allow_std & GFC_STD_F2008) if (gfc_option.allow_std & GFC_STD_F2008)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment