OSDN Git Service

* decl.c (gnat_to_gnu_entity): Use pointers to dummy nodes, rather
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 10 Jun 2007 18:36:40 +0000 (18:36 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 10 Jun 2007 18:36:40 +0000 (18:36 +0000)
than to void, for the fields when making a new fat pointer type.
(gnat_substitute_in_type): Now substitute_in_type.
* gigi.h (gnat_substitute_in_type): Likewise.
* trans.c (gnat_gimplify_expr): Remove COMPONENT_REF kludge.
* utils.c (update_pointer_to): Update fat pointers by updating the
dummy node pointers used for the fields.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125602 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/ChangeLog
gcc/ada/decl.c
gcc/ada/gigi.h
gcc/ada/trans.c
gcc/ada/utils.c

index 04cd1d7..7acbf44 100644 (file)
@@ -1,3 +1,13 @@
+2007-06-10  Duncan Sands  <baldrick@free.fr>
+
+       * decl.c (gnat_to_gnu_entity): Use pointers to dummy nodes, rather
+       than to void, for the fields when making a new fat pointer type.
+       (gnat_substitute_in_type): Now substitute_in_type.
+       * gigi.h (gnat_substitute_in_type): Likewise.
+       * trans.c (gnat_gimplify_expr): Remove COMPONENT_REF kludge.
+       * utils.c (update_pointer_to): Update fat pointers by updating the
+       dummy node pointers used for the fields.
+
 2007-06-06  Thomas Quinot  <quinot@adacore.com>
            Bob Duff  <duff@adacore.com>
 
index 1efc9fd..86a8dd7 100644 (file)
@@ -3041,13 +3041,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
             && ! Is_Constrained (gnat_desig_rep));
 
        /* If we are pointing to an incomplete type whose completion is an
-          unconstrained array, make a fat pointer type instead of a pointer
-          to VOID.  The two types in our fields will be pointers to VOID and
-          will be replaced in update_pointer_to.  Similarly, if the type
-          itself is a dummy type or an unconstrained array.  Also make
-          a dummy TYPE_OBJECT_RECORD_TYPE in case we have any thin
-          pointers to it.  */
-
+          unconstrained array, make a fat pointer type.  The two types in our
+          fields will be pointers to dummy nodes and will be replaced in
+          update_pointer_to.  Similarly, if the type itself is a dummy type or
+          an unconstrained array.  Also make a dummy TYPE_OBJECT_RECORD_TYPE
+          in case we have any thin pointers to it.  */
        if (is_unconstrained_array
            && (Present (gnat_desig_full)
                || (present_gnu_tree (gnat_desig_equiv)
@@ -3075,6 +3073,21 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
            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_equiv),
+                                        "XUB");
+               TYPE_DUMMY_P (gnu_template_type) = 1;
+
+               TYPE_NAME (gnu_array_type)
+                 = concat_id_with_name (get_entity_name (gnat_desig_equiv),
+                                        "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;
@@ -3084,10 +3097,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
                  = 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_ptr_template,
                                                gnu_type, 0, 0, 0, 0));
 
                /* Make sure we can place this into a register.  */
@@ -6846,14 +6859,13 @@ compatible_signatures_p (tree ftype1, tree ftype2)
   return 1;
 }
 \f
-/* Given a type T, a FIELD_DECL F, and a replacement value R, return a new type
-   with all size expressions that contain F updated by replacing F with R.
-   This is identical to GCC's substitute_in_type except that it knows about
-   TYPE_INDEX_TYPE.  If F is NULL_TREE, always make a new RECORD_TYPE, even if
+/* Given a type T, a FIELD_DECL F, and a replacement value R, return a new
+   type with all size expressions that contain F updated by replacing F
+   with R.  If F is NULL_TREE, always make a new RECORD_TYPE, even if
    nothing has changed.  */
 
 tree
-gnat_substitute_in_type (tree t, tree f, tree r)
+substitute_in_type (tree t, tree f, tree r)
 {
   tree new = t;
   tree tem;
@@ -6875,7 +6887,7 @@ gnat_substitute_in_type (tree t, tree f, tree r)
          new = build_range_type (TREE_TYPE (t), low, high);
          if (TYPE_INDEX_TYPE (t))
            SET_TYPE_INDEX_TYPE
-             (new, gnat_substitute_in_type (TYPE_INDEX_TYPE (t), f, r));
+             (new, substitute_in_type (TYPE_INDEX_TYPE (t), f, r));
          return new;
        }
 
@@ -6902,7 +6914,7 @@ gnat_substitute_in_type (tree t, tree f, tree r)
       return t;
 
     case COMPLEX_TYPE:
-      tem = gnat_substitute_in_type (TREE_TYPE (t), f, r);
+      tem = substitute_in_type (TREE_TYPE (t), f, r);
       if (tem == TREE_TYPE (t))
        return t;
 
@@ -6917,8 +6929,8 @@ gnat_substitute_in_type (tree t, tree f, tree r)
 
     case ARRAY_TYPE:
       {
-       tree component = gnat_substitute_in_type (TREE_TYPE (t), f, r);
-       tree domain = gnat_substitute_in_type (TYPE_DOMAIN (t), f, r);
+       tree component = substitute_in_type (TREE_TYPE (t), f, r);
+       tree domain = substitute_in_type (TYPE_DOMAIN (t), f, r);
 
        if (component == TREE_TYPE (t) && domain == TYPE_DOMAIN (t))
          return t;
@@ -6968,7 +6980,7 @@ gnat_substitute_in_type (tree t, tree f, tree r)
            tree new_field = copy_node (field);
 
            TREE_TYPE (new_field)
-             = gnat_substitute_in_type (TREE_TYPE (new_field), f, r);
+             = substitute_in_type (TREE_TYPE (new_field), f, r);
 
            if (DECL_HAS_REP_P (field) && !DECL_INTERNAL_P (field))
              field_has_rep = true;
index a42c123..d210c61 100644 (file)
@@ -160,11 +160,11 @@ extern tree maybe_pad_type (tree type, tree size, unsigned int align,
    the value passed against the list of choices.  */
 extern tree choices_to_gnu (tree operand, Node_Id choices);
 
-/* Given a type T, a FIELD_DECL F, and a replacement value R,
-   return a new type with all size expressions that contain F
-   updated by replacing F with R.  This is identical to GCC's
-   substitute_in_type except that it knows about TYPE_INDEX_TYPE.  */
-extern tree gnat_substitute_in_type (tree t, tree f, tree r);
+/* Given a type T, a FIELD_DECL F, and a replacement value R, return a new
+   type with all size expressions that contain F updated by replacing F
+   with R.  If F is NULL_TREE, always make a new RECORD_TYPE, even if
+   nothing has changed.  */
+extern tree substitute_in_type (tree t, tree f, tree r);
 
 /* Return the "RM size" of GNU_TYPE.  This is the actual number of bits
    needed to represent the object.  */
index 438b149..54ab608 100644 (file)
@@ -5201,19 +5201,6 @@ gnat_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
          return GS_ALL_DONE;
        }
 
-      return GS_UNHANDLED;
-
-    case COMPONENT_REF:
-      /* We have a kludge here.  If the FIELD_DECL is from a fat pointer and is
-        from an early dummy type, replace it with the proper FIELD_DECL.  */
-      if (TYPE_FAT_POINTER_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))
-         && DECL_ORIGINAL_FIELD (TREE_OPERAND (*expr_p, 1)))
-       {
-         TREE_OPERAND (*expr_p, 1)
-           = DECL_ORIGINAL_FIELD (TREE_OPERAND (*expr_p, 1));
-         return GS_OK;
-       }
-
       /* ... fall through ... */
 
     default:
index 69d4a88..a8a673c 100644 (file)
@@ -3160,75 +3160,64 @@ update_pointer_to (tree old_type, tree new_type)
     }
 
   /* Now deal with the unconstrained array case. In this case the "pointer"
-     is actually a RECORD_TYPE where the types of both fields are
-     pointers to void.  In that case, copy the field list from the
-     old type to the new one and update the fields' context. */
+     is actually a RECORD_TYPE where both fields are pointers to dummy nodes.
+     Turn them into pointers to the correct types using update_pointer_to.  */
   else if (TREE_CODE (ptr) != RECORD_TYPE || !TYPE_IS_FAT_POINTER_P (ptr))
     gcc_unreachable ();
 
   else
     {
       tree new_obj_rec = TYPE_OBJECT_RECORD_TYPE (new_type);
-      tree fields = TYPE_FIELDS (TYPE_POINTER_TO (new_type));
-      tree new_fields, ptr_temp_type, new_ref, bounds, var;
-
-      /* Replace contents of old pointer with those of new pointer.  */
-      new_fields = copy_node (fields);
-      TREE_CHAIN (new_fields) = copy_node (TREE_CHAIN (fields));
-
-      SET_DECL_ORIGINAL_FIELD (TYPE_FIELDS (ptr), new_fields);
-      SET_DECL_ORIGINAL_FIELD (TREE_CHAIN (TYPE_FIELDS (ptr)),
-                              TREE_CHAIN (new_fields));
-
-      TYPE_FIELDS (ptr) = new_fields;
-      DECL_CONTEXT (new_fields) = ptr;
-      DECL_CONTEXT (TREE_CHAIN (new_fields)) = ptr;
-
-      /* Rework the PLACEHOLDER_EXPR inside the reference to the template
-        bounds and update the pointers to them.
-
-        ??? 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.  */
-      bounds = TREE_TYPE (TREE_TYPE (new_fields));
-      ptr_temp_type = TREE_TYPE (TREE_CHAIN (new_fields));
-      new_ref = build3 (COMPONENT_REF, 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;
+
+      /* Make pointers to the dummy template point to the real template.  */
+      update_pointer_to
+       (TREE_TYPE (TREE_TYPE (bounds_field)),
+        TREE_TYPE (TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (new_ptr)))));
+
+      /* The references to the template bounds present in the array type
+        are made through a PLACEHOLDER_EXPR of type new_ptr.  Since we
+        are updating ptr to make it a full replacement for new_ptr as
+        pointer to new_type, we must rework the PLACEHOLDER_EXPR so as
+        to make it of type ptr.  */
+      new_ref = build3 (COMPONENT_REF, TREE_TYPE (bounds_field),
                        build0 (PLACEHOLDER_EXPR, ptr),
-                       TREE_CHAIN (new_fields), NULL_TREE);
-      update_pointer_to (bounds,
-                        gnat_substitute_in_type (bounds,
-                                                 TREE_CHAIN (fields),
-                                                 new_ref));
+                       bounds_field, NULL_TREE);
 
-      for (var = TYPE_MAIN_VARIANT (ptr); var; var = TYPE_NEXT_VARIANT (var))
-       {
-         SET_TYPE_UNCONSTRAINED_ARRAY (var, new_type);
+      /* Create the new array for the new PLACEHOLDER_EXPR and make
+        pointers to the dummy array point to it.
 
-         /* 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) = new_fields;
-       }
+        ??? This is now the only use of substitute_in_type,
+        which is a very "heavy" routine to do this, so it
+        should be replaced at some point.  */
+      update_pointer_to
+       (TREE_TYPE (TREE_TYPE (array_field)),
+        substitute_in_type (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (new_ptr))),
+                            TREE_CHAIN (TYPE_FIELDS (new_ptr)), new_ref));
 
+      /* Make ptr the pointer to new_type.  */
       TYPE_POINTER_TO (new_type) = TYPE_REFERENCE_TO (new_type)
        = TREE_TYPE (new_type) = ptr;
 
+      for (var = TYPE_MAIN_VARIANT (ptr); var; var = TYPE_NEXT_VARIANT (var))
+       SET_TYPE_UNCONSTRAINED_ARRAY (var, new_type);
+
       /* Now handle updating the allocation record, what the thin pointer
         points to.  Update all pointers from the old record into the new
-        one, update the types of the fields, and recompute the size.  */
-
+        one, update the type of the array field, and recompute the size.  */
       update_pointer_to (TYPE_OBJECT_RECORD_TYPE (old_type), new_obj_rec);
 
-      TREE_TYPE (TYPE_FIELDS (new_obj_rec))
-       = TREE_TYPE (TREE_TYPE (TREE_CHAIN (new_fields)));
-
       TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (new_obj_rec)))
-       = TREE_TYPE (TREE_TYPE (new_fields));
+       = TREE_TYPE (TREE_TYPE (array_field));
 
       /* The size recomputation needs to account for alignment constraints, so
         we let layout_type work it out.  This will reset the field offsets to
         what they would be in a regular record, so we shift them back to what
         we want them to be for a thin pointer designated type afterwards.  */
-
       DECL_SIZE (TYPE_FIELDS (new_obj_rec)) = 0;
       DECL_SIZE (TREE_CHAIN (TYPE_FIELDS (new_obj_rec))) = 0;
       TYPE_SIZE (new_obj_rec) = 0;