gimple-low.c (lower_try_catch): New function.

* gimple-low.c (lower_try_catch): New function.
	(lower_stmt) <GIMPLE_TRY>: Use it to lower GIMPLE_TRY_CATCH.
	<GIMPLE_CATCH>: Delete.
	<GIMPLE_EH_FILTER>: Likewise.

From-SVN: r189865
This commit is contained in:
Eric Botcazou 2012-07-25 19:57:51 +00:00 committed by Eric Botcazou
parent ea814c6675
commit f778c049cd
5 changed files with 132 additions and 24 deletions

View file

@ -1,3 +1,10 @@
2012-07-25 Eric Botcazou <ebotcazou@adacore.com>
* gimple-low.c (lower_try_catch): New function.
(lower_stmt) <GIMPLE_TRY>: Use it to lower GIMPLE_TRY_CATCH.
<GIMPLE_CATCH>: Delete.
<GIMPLE_EH_FILTER>: Likewise.
2012-07-25 Eric Botcazou <ebotcazou@adacore.com>
* expr.c (expand_expr_real_1): Do not expand operand #1 and #2

View file

@ -76,6 +76,7 @@ struct lower_data
static void lower_stmt (gimple_stmt_iterator *, struct lower_data *);
static void lower_gimple_bind (gimple_stmt_iterator *, struct lower_data *);
static void lower_try_catch (gimple_stmt_iterator *, struct lower_data *);
static void lower_gimple_return (gimple_stmt_iterator *, struct lower_data *);
static void lower_builtin_setjmp (gimple_stmt_iterator *);
@ -373,31 +374,28 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
return;
case GIMPLE_TRY:
{
bool try_cannot_fallthru;
lower_sequence (gimple_try_eval_ptr (stmt), data);
try_cannot_fallthru = data->cannot_fallthru;
data->cannot_fallthru = false;
lower_sequence (gimple_try_cleanup_ptr (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;
if (gimple_try_kind (stmt) == GIMPLE_TRY_CATCH)
lower_try_catch (gsi, data);
else
{
/* It must be a GIMPLE_TRY_FINALLY. */
bool cannot_fallthru;
lower_sequence (gimple_try_eval_ptr (stmt), data);
cannot_fallthru = data->cannot_fallthru;
case GIMPLE_CATCH:
data->cannot_fallthru = false;
lower_sequence (gimple_catch_handler_ptr (stmt), data);
break;
case GIMPLE_EH_FILTER:
data->cannot_fallthru = false;
lower_sequence (gimple_eh_filter_failure_ptr (stmt), data);
break;
/* The finally clause is always executed after the try clause,
so if it does not fall through, then the try-finally will not
fall through. Otherwise, if the try clause does not fall
through, then when the finally clause falls through it will
resume execution wherever the try clause was going. So the
whole try-finally will only fall through if both the try
clause and the finally clause fall through. */
data->cannot_fallthru = false;
lower_sequence (gimple_try_cleanup_ptr (stmt), data);
data->cannot_fallthru |= cannot_fallthru;
gsi_next (gsi);
}
return;
case GIMPLE_EH_ELSE:
lower_sequence (gimple_eh_else_n_body_ptr (stmt), data);
@ -520,6 +518,67 @@ lower_gimple_bind (gimple_stmt_iterator *gsi, struct lower_data *data)
gsi_remove (gsi, false);
}
/* Same as above, but for a GIMPLE_TRY_CATCH. */
static void
lower_try_catch (gimple_stmt_iterator *gsi, struct lower_data *data)
{
bool cannot_fallthru;
gimple stmt = gsi_stmt (*gsi);
gimple_stmt_iterator i;
/* We don't handle GIMPLE_TRY_FINALLY. */
gcc_assert (gimple_try_kind (stmt) == GIMPLE_TRY_CATCH);
lower_sequence (gimple_try_eval_ptr (stmt), data);
cannot_fallthru = data->cannot_fallthru;
i = gsi_start (*gimple_try_cleanup_ptr (stmt));
switch (gimple_code (gsi_stmt (i)))
{
case GIMPLE_CATCH:
/* We expect to see a sequence of GIMPLE_CATCH stmts, each with a
catch expression and a body. The whole try/catch may fall
through iff any of the catch bodies falls through. */
for (; !gsi_end_p (i); gsi_next (&i))
{
data->cannot_fallthru = false;
lower_sequence (gimple_catch_handler_ptr (gsi_stmt (i)), data);
if (!data->cannot_fallthru)
cannot_fallthru = false;
}
break;
case GIMPLE_EH_FILTER:
/* The exception filter expression only matters if there is an
exception. If the exception does not match EH_FILTER_TYPES,
we will execute EH_FILTER_FAILURE, and we will fall through
if that falls through. If the exception does match
EH_FILTER_TYPES, the stack unwinder will continue up the
stack, so we will not fall through. We don't know whether we
will throw an exception which matches EH_FILTER_TYPES or not,
so we just ignore EH_FILTER_TYPES and assume that we might
throw an exception which doesn't match. */
data->cannot_fallthru = false;
lower_sequence (gimple_eh_filter_failure_ptr (gsi_stmt (i)), data);
if (!data->cannot_fallthru)
cannot_fallthru = false;
break;
default:
/* This case represents statements to be executed when an
exception occurs. Those statements are implicitly followed
by a GIMPLE_RESX to resume execution after the exception. So
in this case the try/catch never falls through. */
data->cannot_fallthru = false;
lower_sequence (gimple_try_cleanup_ptr (stmt), data);
break;
}
data->cannot_fallthru = cannot_fallthru;
gsi_next (gsi);
}
/* Try to determine whether a TRY_CATCH expression can fall through.
This is a subroutine of block_may_fallthru. */

View file

@ -1,3 +1,7 @@
2012-07-25 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/noreturn5.ad[sb]: New test.
2012-07-25 Sandra Loosemore <sandra@codesourcery.com>
Paul Brook <paul@codesourcery.com>

View file

@ -0,0 +1,30 @@
with Ada.Characters.Handling; use Ada.Characters.Handling;
with GNAT.OS_Lib; use GNAT.OS_Lib;
with Text_IO; use Text_IO;
package body Noreturn5 is
procedure Proc (Arg_Line : Wide_String; Keep_Going : Boolean) is
begin
Put (To_String (Arg_Line));
if Keep_Going then
raise Constraint_Error;
else
OS_Exit (1);
end if;
exception
when Constraint_Error =>
raise;
when others =>
if Keep_Going then
raise Constraint_Error;
else
OS_Exit (1);
end if;
end;
end Noreturn5;

View file

@ -0,0 +1,8 @@
-- { dg-do compile }
package Noreturn5 is
procedure Proc (Arg_Line : Wide_String; Keep_Going : Boolean);
pragma No_Return (Proc);
end Noreturn5;