Commit f778c049 by Eric Botcazou Committed by Eric Botcazou

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
parent ea814c66
2012-07-25 Eric Botcazou <ebotcazou@adacore.com> 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 * expr.c (expand_expr_real_1): Do not expand operand #1 and #2
of BIT_FIELD_REF for ignored results. of BIT_FIELD_REF for ignored results.
* fold-const.c (fold_ternary_loc) <BIT_FIELD_REF>: Check that the * fold-const.c (fold_ternary_loc) <BIT_FIELD_REF>: Check that the
......
...@@ -76,6 +76,7 @@ struct lower_data ...@@ -76,6 +76,7 @@ struct lower_data
static void lower_stmt (gimple_stmt_iterator *, 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_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_gimple_return (gimple_stmt_iterator *, struct lower_data *);
static void lower_builtin_setjmp (gimple_stmt_iterator *); static void lower_builtin_setjmp (gimple_stmt_iterator *);
...@@ -373,31 +374,28 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data) ...@@ -373,31 +374,28 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
return; return;
case GIMPLE_TRY: case GIMPLE_TRY:
{ if (gimple_try_kind (stmt) == GIMPLE_TRY_CATCH)
bool try_cannot_fallthru; lower_try_catch (gsi, data);
lower_sequence (gimple_try_eval_ptr (stmt), data); else
try_cannot_fallthru = data->cannot_fallthru; {
data->cannot_fallthru = false; /* It must be a GIMPLE_TRY_FINALLY. */
lower_sequence (gimple_try_cleanup_ptr (stmt), data); bool cannot_fallthru;
/* See gimple_stmt_may_fallthru for the rationale. */ lower_sequence (gimple_try_eval_ptr (stmt), data);
if (gimple_try_kind (stmt) == GIMPLE_TRY_FINALLY) cannot_fallthru = data->cannot_fallthru;
{
data->cannot_fallthru |= try_cannot_fallthru; /* The finally clause is always executed after the try clause,
gsi_next (gsi); so if it does not fall through, then the try-finally will not
return; 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
break; whole try-finally will only fall through if both the try
clause and the finally clause fall through. */
case GIMPLE_CATCH: data->cannot_fallthru = false;
data->cannot_fallthru = false; lower_sequence (gimple_try_cleanup_ptr (stmt), data);
lower_sequence (gimple_catch_handler_ptr (stmt), data); data->cannot_fallthru |= cannot_fallthru;
break; gsi_next (gsi);
}
case GIMPLE_EH_FILTER: return;
data->cannot_fallthru = false;
lower_sequence (gimple_eh_filter_failure_ptr (stmt), data);
break;
case GIMPLE_EH_ELSE: case GIMPLE_EH_ELSE:
lower_sequence (gimple_eh_else_n_body_ptr (stmt), data); 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) ...@@ -520,6 +518,67 @@ lower_gimple_bind (gimple_stmt_iterator *gsi, struct lower_data *data)
gsi_remove (gsi, false); 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. /* Try to determine whether a TRY_CATCH expression can fall through.
This is a subroutine of block_may_fallthru. */ This is a subroutine of block_may_fallthru. */
......
2012-07-25 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/noreturn5.ad[sb]: New test.
2012-07-25 Sandra Loosemore <sandra@codesourcery.com> 2012-07-25 Sandra Loosemore <sandra@codesourcery.com>
Paul Brook <paul@codesourcery.com> Paul Brook <paul@codesourcery.com>
......
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;
-- { dg-do compile }
package Noreturn5 is
procedure Proc (Arg_Line : Wide_String; Keep_Going : Boolean);
pragma No_Return (Proc);
end Noreturn5;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment