summaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r--gcc/tree-cfg.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index a7c7348ed29..ae1cdb33f53 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -9077,13 +9077,29 @@ pass_warn_function_return::execute (function *fun)
&& EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (fun)->preds) > 0)
{
location = UNKNOWN_LOCATION;
- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (fun)->preds)
+ for (ei = ei_start (EXIT_BLOCK_PTR_FOR_FN (fun)->preds);
+ (e = ei_safe_edge (ei)); )
{
last = last_stmt (e->src);
if ((gimple_code (last) == GIMPLE_RETURN
|| gimple_call_builtin_p (last, BUILT_IN_RETURN))
- && (location = gimple_location (last)) != UNKNOWN_LOCATION)
+ && location == UNKNOWN_LOCATION
+ && (location = gimple_location (last)) != UNKNOWN_LOCATION
+ && !optimize)
break;
+ /* When optimizing, replace return stmts in noreturn functions
+ with __builtin_unreachable () call. */
+ if (optimize && gimple_code (last) == GIMPLE_RETURN)
+ {
+ tree fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
+ gimple *new_stmt = gimple_build_call (fndecl, 0);
+ gimple_set_location (new_stmt, gimple_location (last));
+ gimple_stmt_iterator gsi = gsi_for_stmt (last);
+ gsi_replace (&gsi, new_stmt, true);
+ remove_edge (e);
+ }
+ else
+ ei_next (&ei);
}
if (location == UNKNOWN_LOCATION)
location = cfun->function_end_locus;