gimple-low.c (struct lower_data): Add cannot_fallthru field.
* gimple-low.c (struct lower_data): Add cannot_fallthru field. (lower_stmt) <GIMPLE_BIND>: Add comment. <GIMPLE_COND, GIMPLE_GOTO, GIMPLE_SWITCH>: Set cannot_fallthru to true and return. <GIMPLE_RETURN>: Remove the statement if cannot_fallthru is set. Otherwise lower it and set cannot_fallthru to true. <GIMPLE_TRY>: Update cannot_fallthru for GIMPLE_TRY_FINALLY and return. <GIMPLE_CATCH, GIMPLE_EH_FILTER>; Set cannot_fallthru to false. <GIMPLE_CALL>: Set cannot_fallthru to false for BUILT_IN_SETJMP and to true for a noreturn call. Do not remove statements. <GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TASK>: Set cannot_fallthru to false. Set cannot_fallthru to false on function exit. (gimple_stmt_may_fallthru) <GIMPLE_SWITCH>: Really return false. <GIMPLE_ASSIGN>: Remove. From-SVN: r152984
This commit is contained in:
parent
585ba38fd5
commit
a141816c42
@ -1,3 +1,20 @@
|
||||
2009-10-19 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gimple-low.c (struct lower_data): Add cannot_fallthru field.
|
||||
(lower_stmt) <GIMPLE_BIND>: Add comment.
|
||||
<GIMPLE_COND, GIMPLE_GOTO, GIMPLE_SWITCH>: Set cannot_fallthru to true
|
||||
and return.
|
||||
<GIMPLE_RETURN>: Remove the statement if cannot_fallthru is set.
|
||||
Otherwise lower it and set cannot_fallthru to true.
|
||||
<GIMPLE_TRY>: Update cannot_fallthru for GIMPLE_TRY_FINALLY and return.
|
||||
<GIMPLE_CATCH, GIMPLE_EH_FILTER>; Set cannot_fallthru to false.
|
||||
<GIMPLE_CALL>: Set cannot_fallthru to false for BUILT_IN_SETJMP and
|
||||
to true for a noreturn call. Do not remove statements.
|
||||
<GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TASK>: Set cannot_fallthru to false.
|
||||
Set cannot_fallthru to false on function exit.
|
||||
(gimple_stmt_may_fallthru) <GIMPLE_SWITCH>: Really return false.
|
||||
<GIMPLE_ASSIGN>: Remove.
|
||||
|
||||
2009-10-19 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
|
||||
|
||||
* config/s390/s390.c (s390_z10_optimize_cmp): Don't touch FP compares.
|
||||
|
@ -76,6 +76,9 @@ struct lower_data
|
||||
of the function. */
|
||||
VEC(return_statements_t,heap) *return_statements;
|
||||
|
||||
/* True if the current statement cannot fall through. */
|
||||
bool cannot_fallthru;
|
||||
|
||||
/* True if the function calls __builtin_setjmp. */
|
||||
bool calls_builtin_setjmp;
|
||||
};
|
||||
@ -317,7 +320,12 @@ lower_omp_directive (gimple_stmt_iterator *gsi, struct lower_data *data)
|
||||
}
|
||||
|
||||
|
||||
/* Lower statement GSI. DATA is passed through the recursion. */
|
||||
/* Lower statement GSI. DATA is passed through the recursion. We try to
|
||||
track the fallthruness of statements and get rid of unreachable return
|
||||
statements in order to prevent the EH lowering pass from adding useless
|
||||
edges that can cause bogus warnings to be issued later; this guess need
|
||||
not be 100% accurate, simply be conservative and reset cannot_fallthru
|
||||
to false if we don't know. */
|
||||
|
||||
static void
|
||||
lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
|
||||
@ -330,36 +338,61 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
|
||||
{
|
||||
case GIMPLE_BIND:
|
||||
lower_gimple_bind (gsi, data);
|
||||
/* Propagate fallthruness. */
|
||||
return;
|
||||
|
||||
case GIMPLE_COND:
|
||||
/* The gimplifier has already lowered this into gotos. */
|
||||
break;
|
||||
case GIMPLE_GOTO:
|
||||
case GIMPLE_SWITCH:
|
||||
data->cannot_fallthru = true;
|
||||
gsi_next (gsi);
|
||||
return;
|
||||
|
||||
case GIMPLE_RETURN:
|
||||
lower_gimple_return (gsi, data);
|
||||
if (data->cannot_fallthru)
|
||||
{
|
||||
gsi_remove (gsi, false);
|
||||
/* Propagate fallthruness. */
|
||||
}
|
||||
else
|
||||
{
|
||||
lower_gimple_return (gsi, data);
|
||||
data->cannot_fallthru = true;
|
||||
}
|
||||
return;
|
||||
|
||||
case GIMPLE_TRY:
|
||||
lower_sequence (gimple_try_eval (stmt), data);
|
||||
lower_sequence (gimple_try_cleanup (stmt), data);
|
||||
{
|
||||
bool try_cannot_fallthru;
|
||||
lower_sequence (gimple_try_eval (stmt), data);
|
||||
try_cannot_fallthru = data->cannot_fallthru;
|
||||
data->cannot_fallthru = false;
|
||||
lower_sequence (gimple_try_cleanup (stmt), data);
|
||||
/* See gimple_stmt_may_fallthru for the rationale. */
|
||||
if (gimple_try_kind (stmt) == GIMPLE_TRY_FINALLY)
|
||||
{
|
||||
data->cannot_fallthru |= try_cannot_fallthru;
|
||||
gsi_next (gsi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMPLE_CATCH:
|
||||
data->cannot_fallthru = false;
|
||||
lower_sequence (gimple_catch_handler (stmt), data);
|
||||
break;
|
||||
|
||||
case GIMPLE_EH_FILTER:
|
||||
data->cannot_fallthru = false;
|
||||
lower_sequence (gimple_eh_filter_failure (stmt), data);
|
||||
break;
|
||||
|
||||
case GIMPLE_NOP:
|
||||
case GIMPLE_ASM:
|
||||
case GIMPLE_ASSIGN:
|
||||
case GIMPLE_GOTO:
|
||||
case GIMPLE_PREDICT:
|
||||
case GIMPLE_LABEL:
|
||||
case GIMPLE_SWITCH:
|
||||
case GIMPLE_EH_MUST_NOT_THROW:
|
||||
case GIMPLE_OMP_FOR:
|
||||
case GIMPLE_OMP_SECTIONS:
|
||||
@ -383,21 +416,16 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
|
||||
&& DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
|
||||
&& DECL_FUNCTION_CODE (decl) == BUILT_IN_SETJMP)
|
||||
{
|
||||
data->calls_builtin_setjmp = true;
|
||||
lower_builtin_setjmp (gsi);
|
||||
data->cannot_fallthru = false;
|
||||
data->calls_builtin_setjmp = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/* After a noreturn call, remove a subsequent GOTO or RETURN that might
|
||||
have been mechanically added; this will prevent the EH lowering pass
|
||||
from adding useless edges and thus complicating the initial CFG. */
|
||||
if (decl && (flags_from_decl_or_type (decl) & ECF_NORETURN))
|
||||
{
|
||||
data->cannot_fallthru = true;
|
||||
gsi_next (gsi);
|
||||
if (!gsi_end_p (*gsi)
|
||||
&& (gimple_code (gsi_stmt (*gsi)) == GIMPLE_GOTO
|
||||
|| gimple_code (gsi_stmt (*gsi)) == GIMPLE_RETURN))
|
||||
gsi_remove (gsi, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -405,13 +433,16 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
|
||||
|
||||
case GIMPLE_OMP_PARALLEL:
|
||||
case GIMPLE_OMP_TASK:
|
||||
data->cannot_fallthru = false;
|
||||
lower_omp_directive (gsi, data);
|
||||
data->cannot_fallthru = false;
|
||||
return;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
data->cannot_fallthru = false;
|
||||
gsi_next (gsi);
|
||||
}
|
||||
|
||||
@ -660,9 +691,9 @@ gimple_stmt_may_fallthru (gimple stmt)
|
||||
return false;
|
||||
|
||||
case GIMPLE_SWITCH:
|
||||
/* Switch has already been lowered and represents a
|
||||
branch to a selected label and hence can not fall through. */
|
||||
return true;
|
||||
/* Switch has already been lowered and represents a branch
|
||||
to a selected label and hence can't fall through. */
|
||||
return false;
|
||||
|
||||
case GIMPLE_COND:
|
||||
/* GIMPLE_COND's are already lowered into a two-way branch. They
|
||||
@ -688,13 +719,10 @@ gimple_stmt_may_fallthru (gimple stmt)
|
||||
return (gimple_seq_may_fallthru (gimple_try_eval (stmt))
|
||||
&& gimple_seq_may_fallthru (gimple_try_cleanup (stmt)));
|
||||
|
||||
case GIMPLE_ASSIGN:
|
||||
return true;
|
||||
|
||||
case GIMPLE_CALL:
|
||||
/* Functions that do not return do not fall through. */
|
||||
return (gimple_call_flags (stmt) & ECF_NORETURN) == 0;
|
||||
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
@ -744,7 +772,7 @@ lower_gimple_return (gimple_stmt_iterator *gsi, struct lower_data *data)
|
||||
gsi_remove (gsi, false);
|
||||
}
|
||||
|
||||
/* Lower a __builtin_setjmp TSI.
|
||||
/* Lower a __builtin_setjmp GSI.
|
||||
|
||||
__builtin_setjmp is passed a pointer to an array of five words (not
|
||||
all will be used on all machines). It operates similarly to the C
|
||||
|
@ -1,3 +1,7 @@
|
||||
2009-10-19 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gnat.dg/noreturn2.ad[sb]: New test.
|
||||
|
||||
2009-10-19 Tobias Burnus <burnus@net-b.de>
|
||||
|
||||
PR fortran/41755
|
||||
|
23
gcc/testsuite/gnat.dg/noreturn2.adb
Normal file
23
gcc/testsuite/gnat.dg/noreturn2.adb
Normal file
@ -0,0 +1,23 @@
|
||||
-- { dg-do compile }
|
||||
|
||||
package body Noreturn2 is
|
||||
|
||||
procedure Raise_Exception_No_Defer (Message : String);
|
||||
pragma No_Return (Raise_Exception_No_Defer);
|
||||
|
||||
procedure Raise_From (X : Exception_Occurrence) is
|
||||
Occurrence_Message : constant String := Exception_Message (X);
|
||||
begin
|
||||
if Occurrence_Message = "$" then
|
||||
Raise_Exception_No_Defer (Occurrence_Message);
|
||||
else
|
||||
Raise_Exception_No_Defer ("::" & Occurrence_Message);
|
||||
end if;
|
||||
end;
|
||||
|
||||
procedure Raise_Exception_No_Defer (Message : String) is
|
||||
begin
|
||||
raise Program_Error;
|
||||
end;
|
||||
|
||||
end Noreturn2;
|
8
gcc/testsuite/gnat.dg/noreturn2.ads
Normal file
8
gcc/testsuite/gnat.dg/noreturn2.ads
Normal file
@ -0,0 +1,8 @@
|
||||
with Ada.Exceptions; use Ada.Exceptions;
|
||||
|
||||
package Noreturn2 is
|
||||
|
||||
procedure Raise_From (X : Exception_Occurrence);
|
||||
pragma No_Return (Raise_From);
|
||||
|
||||
end Noreturn2;
|
Loading…
Reference in New Issue
Block a user