* [Ada] Fix internal error on double renaming of private constant
@ 2022-09-06 7:16 Marc Poulhiès
0 siblings, 0 replies; only message in thread
From: Marc Poulhiès @ 2022-09-06 7:16 UTC (permalink / raw)
To: gcc-patches; +Cc: Eric Botcazou
[-- Attachment #1: Type: text/plain, Size: 439 bytes --]
The first renaming uses the type of the full view of the constant but not
the second, which introduces problematic view conversions downstream.
Tested on x86_64-pc-linux-gnu, committed on trunk
gcc/ada/
* gcc-interface/trans.cc (Full_View_Of_Private_Constant): New
function returning the Full_View of a private constant, after
looking through a chain of renamings, if any.
(Identifier_to_gnu): Call it on the entity. Small cleanup.
[-- Attachment #2: patch.diff --]
[-- Type: text/x-diff, Size: 4722 bytes --]
diff --git a/gcc/ada/gcc-interface/trans.cc b/gcc/ada/gcc-interface/trans.cc
--- a/gcc/ada/gcc-interface/trans.cc
+++ b/gcc/ada/gcc-interface/trans.cc
@@ -1088,6 +1088,28 @@ Gigi_Types_Compatible (Entity_Id type, Entity_Id def_type)
return false;
}
+/* Return the full view of a private constant E, or of a renaming thereof, if
+ its type has discriminants, and Empty otherwise. */
+
+static Entity_Id
+Full_View_Of_Private_Constant (Entity_Id E)
+{
+ while (Present (Renamed_Object (E)) && Is_Entity_Name (Renamed_Object (E)))
+ E = Entity (Renamed_Object (E));
+
+ if (Ekind (E) != E_Constant || No (Full_View (E)))
+ return Empty;
+
+ const Entity_Id T = Etype (E);
+
+ if (Is_Private_Type (T)
+ && (Has_Unknown_Discriminants (T)
+ || (Present (Full_View (T)) && Has_Discriminants (Full_View (T)))))
+ return Full_View (E);
+
+ return Empty;
+}
+
/* Subroutine of gnat_to_gnu to translate GNAT_NODE, an N_Identifier, to a GCC
tree, which is returned. GNU_RESULT_TYPE_P is a pointer to where we should
place the result type. */
@@ -1095,21 +1117,19 @@ Gigi_Types_Compatible (Entity_Id type, Entity_Id def_type)
static tree
Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
{
- /* The entity of GNAT_NODE and its type. */
- Node_Id gnat_entity = (Nkind (gnat_node) == N_Defining_Identifier
- || Nkind (gnat_node) == N_Defining_Operator_Symbol)
- ? gnat_node : Entity (gnat_node);
- Node_Id gnat_entity_type = Etype (gnat_entity);
+ Entity_Id gnat_entity = (Nkind (gnat_node) == N_Defining_Identifier
+ || Nkind (gnat_node) == N_Defining_Operator_Symbol)
+ ? gnat_node : Entity (gnat_node);
+ Entity_Id gnat_result_type;
+ tree gnu_result, gnu_result_type;
/* If GNAT_NODE is a constant, whether we should use the initialization
value instead of the constant entity, typically for scalars with an
address clause when the parent doesn't require an lvalue. */
- bool use_constant_initializer = false;
+ bool use_constant_initializer;
/* Whether we should require an lvalue for GNAT_NODE. Needed in
specific circumstances only, so evaluated lazily. < 0 means
unknown, > 0 means known true, 0 means known false. */
- int require_lvalue = -1;
- Entity_Id gnat_result_type;
- tree gnu_result, gnu_result_type;
+ int require_lvalue;
/* If the Etype of this node is not the same as that of the Entity, then
something went wrong, probably in generic instantiation. However, this
@@ -1118,25 +1138,17 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
may have been changed to a subtype by Exp_Ch3.Adjust_Discriminants. */
gcc_assert (!Is_Object (gnat_entity)
|| Ekind (gnat_entity) == E_Discriminant
- || Etype (gnat_node) == gnat_entity_type
- || Gigi_Types_Compatible (Etype (gnat_node), gnat_entity_type));
+ || Etype (gnat_node) == Etype (gnat_entity)
+ || Gigi_Types_Compatible (Etype (gnat_node),
+ Etype (gnat_entity)));
- /* If this is a reference to a deferred constant whose partial view is an
+ /* If this is a reference to a deferred constant whose partial view is of
unconstrained private type, the proper type is on the full view of the
- constant, not on the full view of the type, which may be unconstrained.
-
- This may be a reference to a type, for example in the prefix of the
- attribute Position, generated for dispatching code (see Make_DT in
- exp_disp,adb). In that case we need the type itself, not is parent,
- in particular if it is a derived type */
- if (Ekind (gnat_entity) == E_Constant
- && Is_Private_Type (gnat_entity_type)
- && (Has_Unknown_Discriminants (gnat_entity_type)
- || (Present (Full_View (gnat_entity_type))
- && Has_Discriminants (Full_View (gnat_entity_type))))
- && Present (Full_View (gnat_entity)))
+ constant, not on the full view of the type which may be unconstrained. */
+ const Entity_Id gnat_full_view = Full_View_Of_Private_Constant (gnat_entity);
+ if (Present (gnat_full_view))
{
- gnat_entity = Full_View (gnat_entity);
+ gnat_entity = gnat_full_view;
gnat_result_type = Etype (gnat_entity);
}
else
@@ -1184,7 +1196,13 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
= lvalue_required_p (gnat_node, gnu_result_type, true, false);
use_constant_initializer = !require_lvalue;
}
+ else
+ {
+ require_lvalue = -1;
+ use_constant_initializer = false;
+ }
+ /* Fetch the initialization value of a constant if requested. */
if (use_constant_initializer)
{
/* If this is a deferred constant, the initializer is attached to
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-09-06 7:16 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-06 7:16 [Ada] Fix internal error on double renaming of private constant Marc Poulhiès
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).