Commit 41d9adc7 by Eric Botcazou Committed by Eric Botcazou

re PR ada/15802 (ICE at expr.c:6764 (placeholder mechanism))

	PR ada/15802
	* decl.c (same_discriminant_p): New static function.
	(gnat_to_gnu_entity) <E_Record_Type>: When there is a parent
	subtype and we have discriminants, fix up the COMPONENT_REFs
	for the discriminants to make them reference the corresponding
	fields of the parent subtype after it has been built.

From-SVN: r116981
parent 7ee51a34
2006-09-15 Eric Botcazou <ebotcazou@adacore.com>
PR ada/15802
* decl.c (same_discriminant_p): New static function.
(gnat_to_gnu_entity) <E_Record_Type>: When there is a parent
subtype and we have discriminants, fix up the COMPONENT_REFs
for the discriminants to make them reference the corresponding
fields of the parent subtype after it has been built.
2006-09-15 Roger Sayle <roger@eyesopen.com> 2006-09-15 Roger Sayle <roger@eyesopen.com>
PR ada/18817 PR ada/18817
......
...@@ -90,6 +90,7 @@ static tree elaborate_expression_1 (Node_Id, Entity_Id, tree, tree, ...@@ -90,6 +90,7 @@ static tree elaborate_expression_1 (Node_Id, Entity_Id, tree, tree,
bool, bool); bool, bool);
static tree make_packable_type (tree); static tree make_packable_type (tree);
static tree gnat_to_gnu_field (Entity_Id, tree, int, bool); static tree gnat_to_gnu_field (Entity_Id, tree, int, bool);
static bool same_discriminant_p (Entity_Id, Entity_Id);
static void components_to_record (tree, Node_Id, tree, int, bool, tree *, static void components_to_record (tree, Node_Id, tree, int, bool, tree *,
bool, bool, bool, bool); bool, bool, bool, bool);
static int compare_field_bitpos (const PTR, const PTR); static int compare_field_bitpos (const PTR, const PTR);
...@@ -2429,16 +2430,18 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -2429,16 +2430,18 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
this record has rep clauses, force the position to zero. */ this record has rep clauses, force the position to zero. */
if (Present (Parent_Subtype (gnat_entity))) if (Present (Parent_Subtype (gnat_entity)))
{ {
Entity_Id gnat_parent = Parent_Subtype (gnat_entity);
tree gnu_parent; tree gnu_parent;
/* A major complexity here is that the parent subtype will /* A major complexity here is that the parent subtype will
reference our discriminants. But those must reference reference our discriminants in its Discriminant_Constraint
the parent component of this record. So here we will list. But those must reference the parent component of this
initialize each of those components to a COMPONENT_REF. record which is of the parent subtype we have not built yet!
The first operand of that COMPONENT_REF is another To break the circle we first build a dummy COMPONENT_REF which
COMPONENT_REF which will be filled in below, once represents the "get to the parent" operation and initialize
the parent type can be safely built. */ each of those discriminants to a COMPONENT_REF of the above
dummy parent referencing the corresponding discrimant of the
base type of the parent subtype. */
gnu_get_parent = build3 (COMPONENT_REF, void_type_node, gnu_get_parent = build3 (COMPONENT_REF, void_type_node,
build0 (PLACEHOLDER_EXPR, gnu_type), build0 (PLACEHOLDER_EXPR, gnu_type),
build_decl (FIELD_DECL, NULL_TREE, build_decl (FIELD_DECL, NULL_TREE,
...@@ -2460,8 +2463,35 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -2460,8 +2463,35 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
NULL_TREE), NULL_TREE),
true); true);
gnu_parent = gnat_to_gnu_type (Parent_Subtype (gnat_entity)); /* Then we build the parent subtype. */
gnu_parent = gnat_to_gnu_type (gnat_parent);
/* Finally we fix up both kinds of twisted COMPONENT_REF we have
initially built. The discriminants must reference the fields
of the parent subtype and not those of its base type for the
placeholder machinery to properly work. */
if (Has_Discriminants (gnat_entity))
for (gnat_field = First_Stored_Discriminant (gnat_entity);
Present (gnat_field);
gnat_field = Next_Stored_Discriminant (gnat_field))
if (Present (Corresponding_Discriminant (gnat_field)))
{
Entity_Id field = Empty;
for (field = First_Stored_Discriminant (gnat_parent);
Present (field);
field = Next_Stored_Discriminant (field))
if (same_discriminant_p (gnat_field, field))
break;
gcc_assert (Present (field));
TREE_OPERAND (get_gnu_tree (gnat_field), 1)
= gnat_to_gnu_field_decl (field);
}
/* The "get to the parent" COMPONENT_REF must be given its
proper type... */
TREE_TYPE (gnu_get_parent) = gnu_parent;
/* ...and reference the _parent field of this record. */
gnu_field_list gnu_field_list
= create_field_decl (get_identifier = create_field_decl (get_identifier
(Get_Name_String (Name_uParent)), (Get_Name_String (Name_uParent)),
...@@ -2469,8 +2499,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -2469,8 +2499,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
has_rep ? TYPE_SIZE (gnu_parent) : 0, has_rep ? TYPE_SIZE (gnu_parent) : 0,
has_rep ? bitsize_zero_node : 0, 1); has_rep ? bitsize_zero_node : 0, 1);
DECL_INTERNAL_P (gnu_field_list) = 1; DECL_INTERNAL_P (gnu_field_list) = 1;
TREE_TYPE (gnu_get_parent) = gnu_parent;
TREE_OPERAND (gnu_get_parent, 1) = gnu_field_list; TREE_OPERAND (gnu_get_parent, 1) = gnu_field_list;
} }
...@@ -4291,6 +4319,21 @@ gnat_to_gnu_field_decl (Entity_Id gnat_entity) ...@@ -4291,6 +4319,21 @@ gnat_to_gnu_field_decl (Entity_Id gnat_entity)
return gnu_field; return gnu_field;
} }
/* Return true if DISCR1 and DISCR2 represent the same discriminant. */
static
bool same_discriminant_p (Entity_Id discr1, Entity_Id discr2)
{
while (Present (Corresponding_Discriminant (discr1)))
discr1 = Corresponding_Discriminant (discr1);
while (Present (Corresponding_Discriminant (discr2)))
discr2 = Corresponding_Discriminant (discr2);
return
Original_Record_Component (discr1) == Original_Record_Component (discr2);
}
/* Given GNAT_ENTITY, elaborate all expressions that are required to /* Given GNAT_ENTITY, elaborate all expressions that are required to
be elaborated at the point of its definition, but do nothing else. */ be elaborated at the point of its definition, but do nothing else. */
......
2006-09-15 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/specs/double_record_extension1.ads: New test.
* gnat.dg/specs/double_record_extension2.ads: Likewise.
2006-09-15 Paul Thomas <pault@gcc.gnu.org> 2006-09-15 Paul Thomas <pault@gcc.gnu.org>
PR fortran/29051 PR fortran/29051
package double_record_extension1 is
type T1(n: natural) is tagged record
s1: string (1..n);
end record;
type T2(j,k: natural) is new T1(j) with record
s2: string (1..k);
end record;
type T3 is new T2 (10, 10) with null record;
end double_record_extension1;
package double_record_extension2 is
type Base_Message_Type (Num_Bytes : Positive) is tagged record
Data_Block : String (1..Num_Bytes);
end record;
type Extended_Message_Type (Num_Bytes1 : Positive; Num_Bytes2 : Positive) is new Base_Message_Type (Num_Bytes1) with record
A: String (1..Num_Bytes2);
end record;
type Final_Message_Type is new Extended_Message_Type with record
B : Integer;
end record;
end double_record_extension2;
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