diff options
author | Richard Henderson <rth@cygnus.com> | 2000-10-05 23:01:27 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2000-10-05 23:01:27 -0700 |
commit | b313a0fe15d7f5953f87141c49786a8eccb90683 (patch) | |
tree | 2a84a351f2dd9e081499cea34c0929d359328dd0 /gcc/flow.c | |
parent | 63c16fc50c5cf446269da98919ccc7016bd4498f (diff) | |
download | gcc-b313a0fe15d7f5953f87141c49786a8eccb90683.zip gcc-b313a0fe15d7f5953f87141c49786a8eccb90683.tar.gz gcc-b313a0fe15d7f5953f87141c49786a8eccb90683.tar.bz2 |
c-decl.c (warn_missing_noreturn): Remove.
* c-decl.c (warn_missing_noreturn): Remove.
(c_expand_body): Don't set or check can_reach_end.
* c-tree.h (warn_missing_noreturn): Move ...
* flags.h: ... here.
(can_reach_end): Remove.
* flow.c (check_function_return_warnings): New.
(make_edges): No edge to exit for noreturn sibcalls.
* function.c (expand_function_end): Save the return value
clobber instruction.
(mark_function_status): Mark it.
* function.h (struct function): Add x_clobber_return_insn.
* jump.c (can_reach_end): Remove.
(calculate_can_reach_end): Remove.
(jump_optimize_1): Don't call it.
* output.h (check_function_return_warnings): Declare.
* toplev.c (warn_missing_noreturn): Move from c-decl.c
(rest_of_compilation): Call check_function_return_warnings.
From-SVN: r36750
Diffstat (limited to 'gcc/flow.c')
-rw-r--r-- | gcc/flow.c | 44 |
1 files changed, 42 insertions, 2 deletions
@@ -511,6 +511,43 @@ find_basic_blocks (f, nregs, file) #endif } +void +check_function_return_warnings () +{ + if (warn_missing_noreturn + && !TREE_THIS_VOLATILE (cfun->decl) + && EXIT_BLOCK_PTR->pred == NULL) + warning ("function might be possible candidate for attribute `noreturn'"); + + /* If we have a path to EXIT, then we do return. */ + if (TREE_THIS_VOLATILE (cfun->decl) + && EXIT_BLOCK_PTR->pred != NULL) + warning ("`noreturn' function does return"); + + /* If the clobber_return_insn appears in some basic block, then we + do reach the end without returning a value. */ + else if (warn_return_type + && cfun->x_clobber_return_insn != NULL + && EXIT_BLOCK_PTR->pred != NULL) + { + int max_uid = get_max_uid (); + + /* If clobber_return_insn was excised by jump1, then renumber_insns + can make max_uid smaller than the number still recorded in our rtx. + That's fine, since this is a quick way of verifying that the insn + is no longer in the chain. */ + if (INSN_UID (cfun->x_clobber_return_insn) < max_uid) + { + /* Recompute insn->block mapping, since the initial mapping is + set before we delete unreachable blocks. */ + compute_bb_for_insn (max_uid); + + if (BLOCK_FOR_INSN (cfun->x_clobber_return_insn) != NULL) + warning ("control reaches end of non-void function"); + } + } +} + /* Count the basic blocks of the function. */ static int @@ -1115,8 +1152,11 @@ make_edges (label_value_list) wouldn't have created the sibling call in the first place. */ if (code == CALL_INSN && SIBLING_CALL_P (insn)) - make_edge (edge_cache, bb, EXIT_BLOCK_PTR, - EDGE_ABNORMAL | EDGE_ABNORMAL_CALL); + { + if (! find_reg_note (insn, REG_NORETURN, NULL_RTX)) + make_edge (edge_cache, bb, EXIT_BLOCK_PTR, + EDGE_ABNORMAL | EDGE_ABNORMAL_CALL); + } else /* If this is a CALL_INSN, then mark it as reaching the active EH |