diff options
| -rw-r--r-- | gcc/ada/ChangeLog | 10 | ||||
| -rw-r--r-- | gcc/ada/decl.c | 52 | ||||
| -rw-r--r-- | gcc/ada/gigi.h | 10 | ||||
| -rw-r--r-- | gcc/ada/trans.c | 13 | ||||
| -rw-r--r-- | gcc/ada/utils.c | 81 | 
5 files changed, 82 insertions, 84 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 04cd1d7..7acbf44 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -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> diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c index 1efc9fd..86a8dd7 100644 --- a/gcc/ada/decl.c +++ b/gcc/ada/decl.c @@ -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;  } -/* 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; diff --git a/gcc/ada/gigi.h b/gcc/ada/gigi.h index a42c123..d210c61 100644 --- a/gcc/ada/gigi.h +++ b/gcc/ada/gigi.h @@ -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.  */ diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c index 438b149..54ab608 100644 --- a/gcc/ada/trans.c +++ b/gcc/ada/trans.c @@ -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: diff --git a/gcc/ada/utils.c b/gcc/ada/utils.c index 69d4a88..a8a673c 100644 --- a/gcc/ada/utils.c +++ b/gcc/ada/utils.c @@ -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;  | 
