Commit 4ec7c4ec by Eric Botcazou Committed by Arnaud Charlet

trans.c (assoc_to_constructor): Make sure Corresponding_Discriminant is only…

trans.c (assoc_to_constructor): Make sure Corresponding_Discriminant is only called on discriminants.

2017-05-02  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc-interface/trans.c (assoc_to_constructor): Make sure
	Corresponding_Discriminant is only called on discriminants.
	Skip the saving of the result only for them.
	(gnat_to_gnu) <N_Selected_Component>: Likewise.
	<N_Unchecked_Type_Conversion>: Translate the result type first.
	(gigi): Set TREE_NOTHROW on Begin_Handler.
	(stmt_list_cannot_raise_p): New predicate.
	(Exception_Handler_to_gnu_gcc): Emit a simple final call instead of
	a cleanup if the statements of the handler cannot raise.
	(process_freeze_entity): Use Is_Record_Type.
	(process_type): Likewise.

From-SVN: r247484
parent 52e0a9f7
2017-05-02 Eric Botcazou <ebotcazou@adacore.com> 2017-05-02 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/trans.c (assoc_to_constructor): Make sure
Corresponding_Discriminant is only called on discriminants.
Skip the saving of the result only for them.
(gnat_to_gnu) <N_Selected_Component>: Likewise.
<N_Unchecked_Type_Conversion>: Translate the result type first.
(gigi): Set TREE_NOTHROW on Begin_Handler.
(stmt_list_cannot_raise_p): New predicate.
(Exception_Handler_to_gnu_gcc): Emit a simple final call instead of
a cleanup if the statements of the handler cannot raise.
(process_freeze_entity): Use Is_Record_Type.
(process_type): Likewise.
2017-05-02 Eric Botcazou <ebotcazou@adacore.com>
* einfo.ads (Corresponding_Record_Component): New alias * einfo.ads (Corresponding_Record_Component): New alias
for Node21 used for E_Component and E_Discriminant. for Node21 used for E_Component and E_Discriminant.
* einfo.adb (Corresponding_Record_Component): New function. * einfo.adb (Corresponding_Record_Component): New function.
......
...@@ -516,6 +516,8 @@ gigi (Node_Id gnat_root, ...@@ -516,6 +516,8 @@ gigi (Node_Id gnat_root,
= create_subprog_decl (get_identifier ("__gnat_begin_handler"), NULL_TREE, = create_subprog_decl (get_identifier ("__gnat_begin_handler"), NULL_TREE,
ftype, NULL_TREE, ftype, NULL_TREE,
is_disabled, true, true, true, false, NULL, Empty); is_disabled, true, true, true, false, NULL, Empty);
/* __gnat_begin_handler is a dummy procedure. */
TREE_NOTHROW (begin_handler_decl) = 1;
end_handler_decl end_handler_decl
= create_subprog_decl (get_identifier ("__gnat_end_handler"), NULL_TREE, = create_subprog_decl (get_identifier ("__gnat_end_handler"), NULL_TREE,
...@@ -5256,6 +5258,36 @@ Exception_Handler_to_gnu_fe_sjlj (Node_Id gnat_node) ...@@ -5256,6 +5258,36 @@ Exception_Handler_to_gnu_fe_sjlj (Node_Id gnat_node)
return build3 (COND_EXPR, void_type_node, gnu_choice, gnu_body, NULL_TREE); return build3 (COND_EXPR, void_type_node, gnu_choice, gnu_body, NULL_TREE);
} }
/* Return true if no statement in GNAT_LIST can alter the control flow. */
static bool
stmt_list_cannot_alter_control_flow_p (List_Id gnat_list)
{
if (No (gnat_list))
return true;
/* This is very conservative, we reject everything except for simple
assignments between identifiers or literals. */
for (Node_Id gnat_node = First (gnat_list);
Present (gnat_node);
gnat_node = Next (gnat_node))
{
if (Nkind (gnat_node) != N_Assignment_Statement)
return false;
if (Nkind (Name (gnat_node)) != N_Identifier)
return false;
Node_Kind nkind = Nkind (Expression (gnat_node));
if (nkind != N_Identifier
&& nkind != N_Integer_Literal
&& nkind != N_Real_Literal)
return false;
}
return true;
}
/* Subroutine of gnat_to_gnu to translate gnat_node, an N_Exception_Handler, /* Subroutine of gnat_to_gnu to translate gnat_node, an N_Exception_Handler,
to a GCC tree, which is returned. This is the variant for GCC exception to a GCC tree, which is returned. This is the variant for GCC exception
schemes. */ schemes. */
...@@ -5264,16 +5296,15 @@ static tree ...@@ -5264,16 +5296,15 @@ static tree
Exception_Handler_to_gnu_gcc (Node_Id gnat_node) Exception_Handler_to_gnu_gcc (Node_Id gnat_node)
{ {
tree gnu_etypes_list = NULL_TREE; tree gnu_etypes_list = NULL_TREE;
tree gnu_current_exc_ptr, prev_gnu_incoming_exc_ptr;
Node_Id gnat_temp;
/* We build a TREE_LIST of nodes representing what exception types this /* We build a TREE_LIST of nodes representing what exception types this
handler can catch, with special cases for others and all others cases. handler can catch, with special cases for others and all others cases.
Each exception type is actually identified by a pointer to the exception Each exception type is actually identified by a pointer to the exception
id, or to a dummy object for "others" and "all others". */ id, or to a dummy object for "others" and "all others". */
for (gnat_temp = First (Exception_Choices (gnat_node)); for (Node_Id gnat_temp = First (Exception_Choices (gnat_node));
gnat_temp; gnat_temp = Next (gnat_temp)) gnat_temp;
gnat_temp = Next (gnat_temp))
{ {
tree gnu_expr, gnu_etype; tree gnu_expr, gnu_etype;
...@@ -5329,10 +5360,10 @@ Exception_Handler_to_gnu_gcc (Node_Id gnat_node) ...@@ -5329,10 +5360,10 @@ Exception_Handler_to_gnu_gcc (Node_Id gnat_node)
We use a local variable to retrieve the incoming value at handler entry We use a local variable to retrieve the incoming value at handler entry
time, and reuse it to feed the end_handler hook's argument at exit. */ time, and reuse it to feed the end_handler hook's argument at exit. */
gnu_current_exc_ptr tree gnu_current_exc_ptr
= build_call_expr (builtin_decl_explicit (BUILT_IN_EH_POINTER), = build_call_expr (builtin_decl_explicit (BUILT_IN_EH_POINTER),
1, integer_zero_node); 1, integer_zero_node);
prev_gnu_incoming_exc_ptr = gnu_incoming_exc_ptr; tree prev_gnu_incoming_exc_ptr = gnu_incoming_exc_ptr;
gnu_incoming_exc_ptr gnu_incoming_exc_ptr
= create_var_decl (get_identifier ("EXPTR"), NULL_TREE, = create_var_decl (get_identifier ("EXPTR"), NULL_TREE,
ptr_type_node, gnu_current_exc_ptr, ptr_type_node, gnu_current_exc_ptr,
...@@ -5355,11 +5386,16 @@ Exception_Handler_to_gnu_gcc (Node_Id gnat_node) ...@@ -5355,11 +5386,16 @@ Exception_Handler_to_gnu_gcc (Node_Id gnat_node)
gnu_incoming_exc_ptr)); gnu_incoming_exc_ptr));
} }
add_stmt_list (Statements (gnat_node));
/* We don't have an End_Label at hand to set the location of the cleanup /* We don't have an End_Label at hand to set the location of the cleanup
actions, so we use that of the exception handler itself instead. */ actions, so we use that of the exception handler itself instead. */
add_cleanup (build_call_n_expr (end_handler_decl, 1, gnu_incoming_exc_ptr), tree stmt = build_call_n_expr (end_handler_decl, 1, gnu_incoming_exc_ptr);
gnat_node); if (stmt_list_cannot_alter_control_flow_p (Statements (gnat_node)))
add_stmt_list (Statements (gnat_node)); add_stmt_with_node (stmt, gnat_node);
else
add_cleanup (stmt, gnat_node);
gnat_poplevel (); gnat_poplevel ();
gnu_incoming_exc_ptr = prev_gnu_incoming_exc_ptr; gnu_incoming_exc_ptr = prev_gnu_incoming_exc_ptr;
...@@ -6370,16 +6406,22 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -6370,16 +6406,22 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_prefix = maybe_implicit_deref (gnu_prefix); gnu_prefix = maybe_implicit_deref (gnu_prefix);
/* For discriminant references in tagged types always substitute the /* gnat_to_gnu_entity does not save the GNU tree made for renamed
corresponding discriminant as the actual selected component. */ discriminants so avoid making recursive calls on each reference
if (Is_Tagged_Type (Underlying_Type (Etype (gnat_prefix)))) to them by following the appropriate link directly here. */
while (Present (Corresponding_Discriminant (gnat_field))) if (Ekind (gnat_field) == E_Discriminant)
gnat_field = Corresponding_Discriminant (gnat_field); {
/* For discriminant references in tagged types always substitute
/* For discriminant references of untagged types always substitute the the corresponding discriminant as the actual component. */
corresponding stored discriminant. */ if (Is_Tagged_Type (Underlying_Type (Etype (gnat_prefix))))
else if (Present (Corresponding_Discriminant (gnat_field))) while (Present (Corresponding_Discriminant (gnat_field)))
gnat_field = Original_Record_Component (gnat_field); gnat_field = Corresponding_Discriminant (gnat_field);
/* For discriminant references in untagged types always substitute
the corresponding stored discriminant. */
else if (Present (Corresponding_Discriminant (gnat_field)))
gnat_field = Original_Record_Component (gnat_field);
}
/* Handle extracting the real or imaginary part of a complex. /* Handle extracting the real or imaginary part of a complex.
The real part is the first field and the imaginary the last. */ The real part is the first field and the imaginary the last. */
...@@ -6515,6 +6557,7 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -6515,6 +6557,7 @@ gnat_to_gnu (Node_Id gnat_node)
break; break;
case N_Unchecked_Type_Conversion: case N_Unchecked_Type_Conversion:
gnu_result_type = get_unpadded_type (Etype (gnat_node));
gnu_expr = maybe_character_value (gnat_to_gnu (Expression (gnat_node))); gnu_expr = maybe_character_value (gnat_to_gnu (Expression (gnat_node)));
/* Skip further processing if the conversion is deemed a no-op. */ /* Skip further processing if the conversion is deemed a no-op. */
...@@ -6525,8 +6568,6 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -6525,8 +6568,6 @@ gnat_to_gnu (Node_Id gnat_node)
break; break;
} }
gnu_result_type = get_unpadded_type (Etype (gnat_node));
/* If the result is a pointer type, see if we are improperly /* If the result is a pointer type, see if we are improperly
converting to a stricter alignment. */ converting to a stricter alignment. */
if (STRICT_ALIGNMENT && POINTER_TYPE_P (gnu_result_type) if (STRICT_ALIGNMENT && POINTER_TYPE_P (gnu_result_type)
...@@ -8666,7 +8707,7 @@ process_freeze_entity (Node_Id gnat_node) ...@@ -8666,7 +8707,7 @@ process_freeze_entity (Node_Id gnat_node)
&& TYPE_IS_DUMMY_P (TREE_TYPE (gnu_old)))) && TYPE_IS_DUMMY_P (TREE_TYPE (gnu_old))))
{ {
gcc_assert (Is_Concurrent_Type (gnat_entity) gcc_assert (Is_Concurrent_Type (gnat_entity)
|| (IN (kind, Record_Kind) || (Is_Record_Type (gnat_entity)
&& Is_Concurrent_Record_Type (gnat_entity))); && Is_Concurrent_Record_Type (gnat_entity)));
return; return;
} }
...@@ -9600,7 +9641,7 @@ process_type (Entity_Id gnat_entity) ...@@ -9600,7 +9641,7 @@ process_type (Entity_Id gnat_entity)
/* If this is a record type corresponding to a task or protected type /* If this is a record type corresponding to a task or protected type
that is a completion of an incomplete type, perform a similar update that is a completion of an incomplete type, perform a similar update
on the type. ??? Including protected types here is a guess. */ on the type. ??? Including protected types here is a guess. */
if (IN (Ekind (gnat_entity), Record_Kind) if (Is_Record_Type (gnat_entity)
&& Is_Concurrent_Record_Type (gnat_entity) && Is_Concurrent_Record_Type (gnat_entity)
&& present_gnu_tree (Corresponding_Concurrent_Type (gnat_entity))) && present_gnu_tree (Corresponding_Concurrent_Type (gnat_entity)))
{ {
...@@ -9641,15 +9682,16 @@ assoc_to_constructor (Entity_Id gnat_entity, Node_Id gnat_assoc, tree gnu_type) ...@@ -9641,15 +9682,16 @@ assoc_to_constructor (Entity_Id gnat_entity, Node_Id gnat_assoc, tree gnu_type)
in every record component association. */ in every record component association. */
gcc_assert (No (Next (gnat_field))); gcc_assert (No (Next (gnat_field)));
/* Ignore fields that have Corresponding_Discriminants since we'll /* Ignore discriminants that have Corresponding_Discriminants in tagged
be setting that field in the parent. */ types since we'll be setting those fields in the parent subtype. */
if (Present (Corresponding_Discriminant (Entity (gnat_field))) if (Ekind (Entity (gnat_field)) == E_Discriminant
&& Present (Corresponding_Discriminant (Entity (gnat_field)))
&& Is_Tagged_Type (Scope (Entity (gnat_field)))) && Is_Tagged_Type (Scope (Entity (gnat_field))))
continue; continue;
/* Also ignore discriminants of Unchecked_Unions. */ /* Also ignore discriminants of Unchecked_Unions. */
if (Is_Unchecked_Union (gnat_entity) if (Ekind (Entity (gnat_field)) == E_Discriminant
&& Ekind (Entity (gnat_field)) == E_Discriminant) && Is_Unchecked_Union (gnat_entity))
continue; continue;
/* Before assigning a value in an aggregate make sure range checks /* Before assigning a value in an aggregate make sure range checks
......
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