diff options
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r-- | gcc/tree-cfg.c | 20 |
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; |