This is the mail archive of the gcc-patches@gcc.gnu.org mailing 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]

[Ada] Fix latent aliasing bug with composite derived types


We have a special circuitry in gigi to deal with derived types and aliasing:

      /* If this is a derived type, relate its alias set to that of its parent
         to avoid troubles when a call to an inherited primitive is inlined in
         a context where a derived object is accessed.  The inlined code works
         on the parent view so the resulting code may access the same object
         using both the parent and the derived alias sets, which thus have to
         conflict.  As the same issue arises with component references, the
         parent alias set also has to conflict with composite types enclosing
         derived components.  For instance, if we have:

            type D is new T;
            type R is record
               Component : D;
            end record;

         we want T to conflict with both D and R, in addition to R being a
         superset of D by record/component construction.

         One way to achieve this is to perform an alias set copy from the
         parent to the derived type.  This is not quite appropriate, though,
         as we don't want separate derived types to conflict with each other:

            type I1 is new Integer;
            type I2 is new Integer;

         We want I1 and I2 to both conflict with Integer but we do not want
         I1 to conflict with I2, and an alias set copy on derivation would
         have that effect.


It isn't strong enough for composite types because you're allowed to convert 
between independently derived types:

   subtype Real is Long_Float;

   type Tuple3 is array (0..2) of Real;
   type Point3 is new Tuple3;
   type Vector3 is new Tuple3;

   procedure F (V : Vector3);

   PMax : Point3;

   F (Vector3 (PMax))

and this is translated into a VIEW_CONVERT_EXPR:

   F (pack07__real[3] &) &VIEW_CONVERT_EXPR<pack07__real[3]>(pmax)

and then gimplified into:

   pmax.0 = (pack07__real[3] *) &pmax;
   F (pmax.0);

i.e. a blatant case of type punning, the problem being that the alias sets 
don't conflict by virtue of the aforementioned reasoning.

Fixed thusly, tested on i586-suse-linux, applied on the mainline.


2009-10-29  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc-interface/decl.c (array_type_has_nonaliased_component): Swap
	parameters and rewrite comments.  For a derived type, return the
	setting of its parent type.
	(gnat_to_gnu_entity): Do an alias set copy for derived types if they
	are composite.  Adjust calls to above function.


-- 
Eric Botcazou
Index: gcc-interface/decl.c
===================================================================
--- gcc-interface/decl.c	(revision 153644)
+++ gcc-interface/decl.c	(working copy)
@@ -135,7 +135,7 @@ static tree gnat_to_gnu_param (Entity_Id
 			       bool *);
 static tree gnat_to_gnu_field (Entity_Id, tree, int, bool, bool);
 static bool same_discriminant_p (Entity_Id, Entity_Id);
-static bool array_type_has_nonaliased_component (Entity_Id, tree);
+static bool array_type_has_nonaliased_component (tree, Entity_Id);
 static bool compile_time_known_address_p (Node_Id);
 static bool cannot_be_superflat_p (Node_Id);
 static void components_to_record (tree, Node_Id, tree, int, bool, tree *,
@@ -1963,7 +1963,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
 	  {
 	    tem = build_array_type (tem, gnu_index_types[index]);
 	    TYPE_MULTI_ARRAY_P (tem) = (index > 0);
-	    if (array_type_has_nonaliased_component (gnat_entity, tem))
+	    if (array_type_has_nonaliased_component (tem, gnat_entity))
 	      TYPE_NONALIASED_COMPONENT (tem) = 1;
 	  }
 
@@ -2312,7 +2312,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
 	    {
 	      gnu_type = build_array_type (gnu_type, gnu_index_types[index]);
 	      TYPE_MULTI_ARRAY_P (gnu_type) = (index > 0);
-	      if (array_type_has_nonaliased_component (gnat_entity, gnu_type))
+	      if (array_type_has_nonaliased_component (gnu_type, gnat_entity))
 		TYPE_NONALIASED_COMPONENT (gnu_type) = 1;
 	    }
 
@@ -2563,7 +2563,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
 	gnu_type
 	  = build_array_type (gnat_to_gnu_type (Component_Type (gnat_entity)),
 			      gnu_index_type);
-	if (array_type_has_nonaliased_component (gnat_entity, gnu_type))
+	if (array_type_has_nonaliased_component (gnu_type, gnat_entity))
 	  TYPE_NONALIASED_COMPONENT (gnu_type) = 1;
 	relate_alias_sets (gnu_type, gnu_string_type, ALIAS_SET_COPY);
       }
@@ -4602,11 +4602,38 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
 		   superset      superset
 		R ----------> D ----------> T
 
+	 However, for composite types, conversions between derived types are
+	 translated into VIEW_CONVERT_EXPRs so a sequence like:
+
+	    type Comp1 is new Comp;
+	    type Comp2 is new Comp;
+	    procedure Proc (C : Comp1);
+
+	    C : Comp2;
+	    Proc (Comp1 (C));
+
+	 is translated into:
+
+	    C : Comp2;
+	    Proc ((Comp1 &) &VIEW_CONVERT_EXPR <Comp1> (C));
+
+	 and gimplified into:
+
+	    C : Comp2;
+	    Comp1 *C.0;
+	    C.0 = (Comp1 *) &C;
+	    Proc (C.0);
+
+	 i.e. generates code involving type punning.  Therefore, Comp1 needs
+	 to conflict with Comp2 and an alias set copy is required.
+
 	 The language rules ensure the parent type is already frozen here.  */
       if (Is_Derived_Type (gnat_entity))
 	{
 	  tree gnu_parent_type = gnat_to_gnu_type (Etype (gnat_entity));
-	  relate_alias_sets (gnu_type, gnu_parent_type, ALIAS_SET_SUPERSET);
+	  relate_alias_sets (gnu_type, gnu_parent_type,
+			     Is_Composite_Type (gnat_entity)
+			     ? ALIAS_SET_COPY : ALIAS_SET_SUPERSET);
 	}
 
       /* Back-annotate the Alignment of the type if not already in the
@@ -5254,21 +5281,38 @@ same_discriminant_p (Entity_Id discr1, E
     Original_Record_Component (discr1) == Original_Record_Component (discr2);
 }
 
-/* Return true if the array type specified by GNAT_TYPE and GNU_TYPE has
-   a non-aliased component in the back-end sense.  */
+/* Return true if the array type GNU_TYPE, which represents a dimension of
+   GNAT_TYPE, has a non-aliased component in the back-end sense.  */
 
 static bool
-array_type_has_nonaliased_component (Entity_Id gnat_type, tree gnu_type)
+array_type_has_nonaliased_component (tree gnu_type, Entity_Id gnat_type)
 {
-  /* If the type below this is a multi-array type, then
-     this does not have aliased components.  */
+  /* If the array type is not the innermost dimension of the GNAT type,
+     then it has a non-aliased component.  */
   if (TREE_CODE (TREE_TYPE (gnu_type)) == ARRAY_TYPE
       && TYPE_MULTI_ARRAY_P (TREE_TYPE (gnu_type)))
     return true;
 
+  /* If the array type has an aliased component in the front-end sense,
+     then it also has an aliased component in the back-end sense.  */
   if (Has_Aliased_Components (gnat_type))
     return false;
 
+  /* If this is a derived type, then it has a non-aliased component if
+     and only if its parent type also has one.  */
+  if (Is_Derived_Type (gnat_type))
+    {
+      tree gnu_parent_type = gnat_to_gnu_type (Etype (gnat_type));
+      int index;
+      if (TREE_CODE (gnu_parent_type) == UNCONSTRAINED_ARRAY_TYPE)
+	gnu_parent_type
+	  = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_parent_type))));
+      for (index = Number_Dimensions (gnat_type) - 1; index > 0; index--)
+	gnu_parent_type = TREE_TYPE (gnu_parent_type);
+      return TYPE_NONALIASED_COMPONENT (gnu_parent_type);
+    }
+
+  /* Otherwise, rely exclusively on properties of the element type.  */
   return type_for_nonaliased_component_p (TREE_TYPE (gnu_type));
 }
 

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