Duncan Sands - [Ada PATCH] don't modify record fields in update_pointer_to (original) (raw)

This is the mail archive of the gcc-patches@gcc.gnu.orgmailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

When an unconstrained array type is frozen, update_pointer_to updates the fat pointer type for the old, dummy, type and makes it point to the new type. It does this by overwriting the old pointer type's fields (a fat pointer is a record) with the fields from the new fat pointer. This leads to trouble, since the original fields may have been used already, for example in a COMPONENT_REF or a CONSTRUCTOR: after the update, the field argument of the component reference is no longer a field of the type being referenced! (The field argument is a field from the original fat pointer type; that field has been overwritten in the type with a field from the new fat pointer type). There is a workaround for this in trans.c (removed in this patch). Similarly for a constructor: the constructor elements are not fields of the type being constructed! You can get away with this in mainline gcc, because it simply doesn't notice, however this instantly caused trouble in my port of the Ada f-e to LLVM. This patch changes update_pointer_to so as to not replace fields: instead it uses update_pointer_to (simple pointer case) to update the pointer types used in the fields. For this to work, the dummy fat pointer fields are changed from being void pointers into pointers to dummy nodes.

This passes bootstrap and acats and gnat deja-gnu testing.

Please let me know what you think.

Best wishes,

Duncan.

Index: gcc.fsf.master/gcc/ada/decl.c

--- gcc.fsf.master.orig/gcc/ada/decl.c 2007-02-19 16:32:37.000000000 +0100 +++ gcc.fsf.master/gcc/ada/decl.c 2007-02-21 13:40:21.000000000 +0100 @@ -3050,6 +3050,21 @@ gnu_type = TYPE_POINTER_TO (gnu_old); if (!gnu_type) { + tree gnu_template_type = make_node (ENUMERAL_TYPE); + tree gnu_ptr_template = build_pointer_type (gnu_template_type); + tree gnu_array_type = make_node (ENUMERAL_TYPE); + tree gnu_ptr_array = build_pointer_type (gnu_array_type); + + TYPE_NAME (gnu_template_type) + = concat_id_with_name (get_entity_name (gnat_desig_type), + "XUB"); + TYPE_DUMMY_P (gnu_template_type) = 1; + + TYPE_NAME (gnu_array_type) + = concat_id_with_name (get_entity_name (gnat_desig_type), + "XUA"); + TYPE_DUMMY_P (gnu_array_type) = 1; + gnu_type = make_node (RECORD_TYPE); SET_TYPE_UNCONSTRAINED_ARRAY (gnu_type, gnu_old); TYPE_POINTER_TO (gnu_old) = gnu_type; @@ -3059,11 +3074,11 @@ = chainon (chainon (NULL_TREE, create_field_decl (get_identifier ("P_ARRAY"), - ptr_void_type_node, gnu_type, - 0, 0, 0, 0)), + gnu_ptr_array, gnu_type, + 0, 0, 0, 0)), create_field_decl (get_identifier ("P_BOUNDS"), - ptr_void_type_node, - gnu_type, 0, 0, 0, 0)); + gnu_ptr_template, + gnu_type, 0, 0, 0, 0)); /* Make sure we can place this into a register. */ TYPE_ALIGN (gnu_type) Index: gcc.fsf.master/gcc/ada/trans.c

--- gcc.fsf.master.orig/gcc/ada/trans.c 2007-02-19 16:32:37.000000000 +0100 +++ gcc.fsf.master/gcc/ada/trans.c 2007-02-21 13:40:21.000000000 +0100 @@ -4846,19 +4846,6 @@ return GS_ALL_DONE; } - return GS_UNHANDLED;

Index: gcc.fsf.master/gcc/ada/utils.c

--- gcc.fsf.master.orig/gcc/ada/utils.c 2007-02-19 16:32:37.000000000 +0100 +++ gcc.fsf.master/gcc/ada/utils.c 2007-02-21 13:40:21.000000000 +0100 @@ -2935,19 +2935,15 @@ else { tree new_obj_rec = TYPE_OBJECT_RECORD_TYPE (new_type); - tree ptr_temp_type; + tree array_field = TYPE_FIELDS (ptr); + tree bounds_field = TREE_CHAIN (TYPE_FIELDS (ptr)); + tree new_ptr = TYPE_POINTER_TO (new_type); tree new_ref; tree var; - SET_DECL_ORIGINAL_FIELD (TYPE_FIELDS (ptr), - TYPE_FIELDS (TYPE_POINTER_TO (new_type))); - SET_DECL_ORIGINAL_FIELD (TREE_CHAIN (TYPE_FIELDS (ptr)), - TREE_CHAIN (TYPE_FIELDS - (TYPE_POINTER_TO (new_type))));

@@ -2955,25 +2951,22 @@ ??? This is now the only use of gnat_substitute_in_type, which is now a very "heavy" routine to do this, so it should be replaced at some point. / - ptr_temp_type = TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (ptr))); - new_ref = build3 (COMPONENT_REF, ptr_temp_type, + new_ref = build3 (COMPONENT_REF, TREE_TYPE (bounds_field), build0 (PLACEHOLDER_EXPR, ptr), - TREE_CHAIN (TYPE_FIELDS (ptr)), NULL_TREE); + bounds_field, NULL_TREE); + + update_pointer_to + (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (new_ptr))), + gnat_substitute_in_type (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (new_ptr))), + TREE_CHAIN (TYPE_FIELDS (new_ptr)), new_ref)); update_pointer_to - (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (ptr))), - gnat_substitute_in_type (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (ptr))), - TREE_CHAIN (TYPE_FIELDS (ptr)), new_ref)); + (TREE_TYPE (TREE_TYPE (array_field)), + TREE_TYPE (TREE_TYPE (TYPE_FIELDS (new_ptr)))); for (var = TYPE_MAIN_VARIANT (ptr); var; var = TYPE_NEXT_VARIANT (var)) - { SET_TYPE_UNCONSTRAINED_ARRAY (var, new_type); - / This may seem a bit gross, in particular wrt DECL_CONTEXT, but - actually is in keeping with what build_qualified_type does. */ - TYPE_FIELDS (var) = TYPE_FIELDS (ptr); - }

   TYPE_POINTER_TO (new_type) = TYPE_REFERENCE_TO (new_type)
 = TREE_TYPE (new_type) = ptr;

@@ -2983,13 +2976,12 @@

   update_pointer_to (TYPE_OBJECT_RECORD_TYPE (old_type), new_obj_rec);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]