aboutsummaryrefslogtreecommitdiff
path: root/gcc/flow.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>2000-10-05 23:01:27 -0700
committerRichard Henderson <rth@gcc.gnu.org>2000-10-05 23:01:27 -0700
commitb313a0fe15d7f5953f87141c49786a8eccb90683 (patch)
tree2a84a351f2dd9e081499cea34c0929d359328dd0 /gcc/flow.c
parent63c16fc50c5cf446269da98919ccc7016bd4498f (diff)
downloadgcc-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.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/gcc/flow.c b/gcc/flow.c
index b913c6e..52eed8d 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -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