]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* alias.h (record_alias_subset): Declare.
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 10 Feb 2009 22:52:51 +0000 (22:52 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 10 Feb 2009 22:52:51 +0000 (22:52 +0000)
* alias.c (record_alias_subset): Make global.
ada/
* gcc-interface/decl.c (enum alias_set_op): New enumeration.
(copy_alias_set): Rename into...
(relate_alias_sets): ...this.  Add third parameter OP.  Retrieve the
underlying array of unconstrained arrays for the new type as well.
If the old and new alias sets don't conflict, make one a subset of
the other as per the OP parameter.
(gnat_to_gnu_entity): Adjust calls to copy_alias_set.
<E_Record_Type>: Do not copy the alias set for derived types.
For all types, make the alias set of derived types a superset of
that of their parent type.
(make_aligning_type): Adjust calls to copy_alias_set.
(make_packable_type): Likewise.
* gcc-interface/trans.c (gnat_to_gnu)<N_Validate_Unchecked_Conversion>:
Check for alias set conflict instead of strict equality to issue the
warning.

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

gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/gcc-interface/decl.c
gcc/ada/gcc-interface/trans.c
gcc/alias.c
gcc/alias.h
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/aliasing3.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/aliasing3_pkg.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/aliasing3_pkg.ads [new file with mode: 0644]

index 32d9ad2e7066cc8296aac5f8a606f6f4aa9d160c..ed15ef60a225dcd437cee3780ddc14a7c4523caa 100644 (file)
@@ -1,3 +1,8 @@
+2009-02-10  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * alias.h (record_alias_subset): Declare.
+       * alias.c (record_alias_subset): Make global.
+
 2009-02-10  Nick Clifton  <nickc@redhat.com>
 
        * tree-parloops.c: Change license to GPLv3.
index 6a65f22a135e8cda7734f0b6fe373c9604a9f93a..1422cc3366a46b24dfafe8eb1acb4aba09e6c323 100644 (file)
@@ -1,3 +1,22 @@
+2009-02-10  Olivier Hainque  <hainque@adacore.com>
+            Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc-interface/decl.c (enum alias_set_op): New enumeration.
+       (copy_alias_set): Rename into...
+       (relate_alias_sets): ...this.  Add third parameter OP.  Retrieve the
+       underlying array of unconstrained arrays for the new type as well.
+       If the old and new alias sets don't conflict, make one a subset of
+       the other as per the OP parameter.
+       (gnat_to_gnu_entity): Adjust calls to copy_alias_set.
+       <E_Record_Type>: Do not copy the alias set for derived types.
+       For all types, make the alias set of derived types a superset of
+       that of their parent type.
+       (make_aligning_type): Adjust calls to copy_alias_set.
+       (make_packable_type): Likewise.
+       * gcc-interface/trans.c (gnat_to_gnu)<N_Validate_Unchecked_Conversion>:
+       Check for alias set conflict instead of strict equality to issue the
+       warning.
+
 2009-02-09  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc-interface/decl.c (gnat_to_gnu_entity) <E_String_Literal_Subtype>:
index e86c2f93145fb16d0620882f83dd0f08da30929c..981b4518cb750e18c3ecda23af26693a24e11922 100644 (file)
@@ -115,7 +115,15 @@ static VEC (tree,heap) *defer_finalize_list;
 static GTY ((if_marked ("tree_int_map_marked_p"),
             param_is (struct tree_int_map))) htab_t annotate_value_cache;
 
-static void copy_alias_set (tree, tree);
+enum alias_set_op
+{
+  ALIAS_SET_COPY,
+  ALIAS_SET_SUBSET,
+  ALIAS_SET_SUPERSET
+};
+
+static void relate_alias_sets (tree, tree, enum alias_set_op);
+
 static tree substitution_list (Entity_Id, Entity_Id, tree, bool);
 static bool allocatable_size_p (tree, bool);
 static void prepend_one_attribute_to (struct attrib **,
@@ -1632,7 +1640,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
       /* Inherit our alias set from what we're a subtype of.  Subtypes
         are not different types and a pointer can designate any instance
         within a subtype hierarchy.  */
-      copy_alias_set (gnu_type, TREE_TYPE (gnu_type));
+      relate_alias_sets (gnu_type, TREE_TYPE (gnu_type), ALIAS_SET_COPY);
 
       /* If the type we are dealing with is to represent a packed array,
         we need to have the bits left justified on big-endian targets
@@ -1674,7 +1682,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
          TYPE_JUSTIFIED_MODULAR_P (gnu_type) = 1;
          SET_TYPE_ADA_SIZE (gnu_type, bitsize_int (esize));
 
-         copy_alias_set (gnu_type, gnu_field_type);
+         relate_alias_sets (gnu_type, gnu_field_type, ALIAS_SET_COPY);
        }
 
       /* If the type we are dealing with has got a smaller alignment than the
@@ -1709,7 +1717,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
          TYPE_IS_PADDING_P (gnu_type) = 1;
          SET_TYPE_ADA_SIZE (gnu_type, bitsize_int (esize));
 
-         copy_alias_set (gnu_type, gnu_field_type);
+         relate_alias_sets (gnu_type, gnu_field_type, ALIAS_SET_COPY);
        }
 
       /* Otherwise reset the alignment lest we computed it above.  */
@@ -1784,7 +1792,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
 
        /* Inherit our alias set from what we're a subtype of, as for
           integer subtypes.  */
-       copy_alias_set (gnu_type, TREE_TYPE (gnu_type));
+       relate_alias_sets (gnu_type, TREE_TYPE (gnu_type), ALIAS_SET_COPY);
       }
     break;
 
@@ -2477,7 +2485,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
 
          /* Set our alias set to that of our base type.  This gives all
             array subtypes the same alias set.  */
-         copy_alias_set (gnu_type, gnu_base_type);
+         relate_alias_sets (gnu_type, gnu_base_type, ALIAS_SET_COPY);
        }
 
       /* If this is a packed type, make this type the same as the packed
@@ -2617,7 +2625,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
                              gnu_index_type);
        if (array_type_has_nonaliased_component (gnat_entity, gnu_type))
          TYPE_NONALIASED_COMPONENT (gnu_type) = 1;
-       copy_alias_set (gnu_type, gnu_string_type);
+       relate_alias_sets (gnu_type, gnu_string_type, ALIAS_SET_COPY);
       }
       break;
 
@@ -2880,14 +2888,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
        if (Is_Tagged_Type (gnat_entity) || Is_Limited_Record (gnat_entity))
          SET_TYPE_MODE (gnu_type, BLKmode);
 
-       /* If this is a derived type, we must make the alias set of this type
-          the same as that of the type we are derived from.  We assume here
-          that the other type is already frozen.  */
-       if (Etype (gnat_entity) != gnat_entity
-           && !(Is_Private_Type (Etype (gnat_entity))
-                && Full_View (Etype (gnat_entity)) == gnat_entity))
-         copy_alias_set (gnu_type, gnat_to_gnu_type (Etype (gnat_entity)));
-
        /* Fill in locations of fields.  */
        annotate_rep (gnat_entity, gnu_type);
 
@@ -3003,7 +3003,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
              TYPE_SIZE_UNIT (gnu_type) = TYPE_SIZE_UNIT (gnu_base_type);
              SET_TYPE_ADA_SIZE (gnu_type, TYPE_ADA_SIZE (gnu_base_type));
              TYPE_ALIGN (gnu_type) = TYPE_ALIGN (gnu_base_type);
-             copy_alias_set (gnu_type, gnu_base_type);
+             relate_alias_sets (gnu_type, gnu_base_type, ALIAS_SET_COPY);
 
              if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type)))
                for (gnu_temp = gnu_subst_list;
@@ -4531,6 +4531,49 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
     {
       gnu_type = TREE_TYPE (gnu_decl);
 
+      /* 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.
+
+        The option chosen is to make the alias set of the derived type a
+        superset of that of its parent type.  It trivially fulfills the
+        simple requirement for the Integer derivation example above, and
+        the component case as well by superset transitivity:
+
+                  superset      superset
+               R ----------> D ----------> T
+
+        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);
+       }
+
       /* Back-annotate the Alignment of the type if not already in the
         tree.  Likewise for sizes.  */
       if (Unknown_Alignment (gnat_entity))
@@ -5158,11 +5201,16 @@ mark_out_of_scope (Entity_Id gnat_entity)
     }
 }
 \f
-/* Set the alias set of GNU_NEW_TYPE to be that of GNU_OLD_TYPE.  If this
-   is a multi-dimensional array type, do this recursively.  */
+/* Relate the alias sets of GNU_NEW_TYPE and GNU_OLD_TYPE according to OP.
+   If this is a multi-dimensional array type, do this recursively.
+
+   OP may be
+   - ALIAS_SET_COPY:     the new set is made a copy of the old one.
+   - ALIAS_SET_SUPERSET: the new set is made a superset of the old one.
+   - ALIAS_SET_SUBSET:   the new set is made a subset of the old one.  */
 
 static void
-copy_alias_set (tree gnu_new_type, tree gnu_old_type)
+relate_alias_sets (tree gnu_new_type, tree gnu_old_type, enum alias_set_op op)
 {
   /* Remove any padding from GNU_OLD_TYPE.  It doesn't matter in the case
      of a one-dimensional array, since the padding has the same alias set
@@ -5173,30 +5221,60 @@ copy_alias_set (tree gnu_new_type, tree gnu_old_type)
             || TYPE_IS_PADDING_P (gnu_old_type)))
     gnu_old_type = TREE_TYPE (TYPE_FIELDS (gnu_old_type));
 
-  /* We need to be careful here in case GNU_OLD_TYPE is an unconstrained
-     array.  In that case, it doesn't have the same shape as GNU_NEW_TYPE,
-     so we need to go down to what does.  */
+  /* Unconstrained array types are deemed incomplete and would thus be given
+     alias set 0.  Retrieve the underlying array type.  */
   if (TREE_CODE (gnu_old_type) == UNCONSTRAINED_ARRAY_TYPE)
     gnu_old_type
       = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_old_type))));
+  if (TREE_CODE (gnu_new_type) == UNCONSTRAINED_ARRAY_TYPE)
+    gnu_new_type
+      = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (gnu_new_type))));
 
   if (TREE_CODE (gnu_new_type) == ARRAY_TYPE
       && TREE_CODE (TREE_TYPE (gnu_new_type)) == ARRAY_TYPE
       && TYPE_MULTI_ARRAY_P (TREE_TYPE (gnu_new_type)))
-    copy_alias_set (TREE_TYPE (gnu_new_type), TREE_TYPE (gnu_old_type));
+    relate_alias_sets (TREE_TYPE (gnu_new_type), TREE_TYPE (gnu_old_type), op);
 
-  /* The alias set shouldn't be copied between array types with different
-     aliasing settings because this can break the aliasing relationship
-     between the array type and its element type.  */
+  switch (op)
+    {
+    case ALIAS_SET_COPY:
+      /* The alias set shouldn't be copied between array types with different
+        aliasing settings because this can break the aliasing relationship
+        between the array type and its element type.  */
 #ifndef ENABLE_CHECKING
-  if (flag_strict_aliasing)
+      if (flag_strict_aliasing)
 #endif
-    gcc_assert (!(TREE_CODE (gnu_new_type) == ARRAY_TYPE
-                 && TREE_CODE (gnu_old_type) == ARRAY_TYPE
-                 && TYPE_NONALIASED_COMPONENT (gnu_new_type)
-                    != TYPE_NONALIASED_COMPONENT (gnu_old_type)));
+       gcc_assert (!(TREE_CODE (gnu_new_type) == ARRAY_TYPE
+                     && TREE_CODE (gnu_old_type) == ARRAY_TYPE
+                     && TYPE_NONALIASED_COMPONENT (gnu_new_type)
+                        != TYPE_NONALIASED_COMPONENT (gnu_old_type)));
+
+      TYPE_ALIAS_SET (gnu_new_type) = get_alias_set (gnu_old_type);
+      break;
+
+    case ALIAS_SET_SUBSET:
+    case ALIAS_SET_SUPERSET:
+      {
+       alias_set_type old_set = get_alias_set (gnu_old_type);
+       alias_set_type new_set = get_alias_set (gnu_new_type);
+
+       /* Do nothing if the alias sets conflict.  This ensures that we
+          never call record_alias_subset several times for the same pair
+          or at all for alias set 0.  */
+       if (!alias_sets_conflict_p (old_set, new_set))
+         {
+           if (op == ALIAS_SET_SUBSET)
+             record_alias_subset (old_set, new_set);
+           else
+             record_alias_subset (new_set, old_set);
+         }
+      }
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
 
-  TYPE_ALIAS_SET (gnu_new_type) = get_alias_set (gnu_old_type);
   record_component_aliases (gnu_new_type);
 }
 \f
@@ -5600,7 +5678,7 @@ make_aligning_type (tree type, unsigned int align, tree size,
 
   SET_TYPE_MODE (record_type, BLKmode);
 
-  copy_alias_set (record_type, type);
+  relate_alias_sets (record_type, type, ALIAS_SET_COPY);
   return record_type;
 }
 \f
@@ -5722,7 +5800,7 @@ make_packable_type (tree type, bool in_record)
     }
 
   finish_record_type (new_type, nreverse (field_list), 2, true);
-  copy_alias_set (new_type, type);
+  relate_alias_sets (new_type, type, ALIAS_SET_COPY);
 
   /* If this is a padding record, we never want to make the size smaller
      than what was specified.  For QUAL_UNION_TYPE, also copy the size.  */
index 51d20d26e1d1d386a74eaf9cd8fa780b43a745d8..17433e90d309f619e3918fe184f11d08eec1ebaf 100644 (file)
@@ -4940,8 +4940,9 @@ gnat_to_gnu (Node_Id gnat_node)
                        != TYPE_DUMMY_P (gnu_target_desig_type))
                    || (TYPE_DUMMY_P (gnu_source_desig_type)
                        && gnu_source_desig_type != gnu_target_desig_type)
-                   || (get_alias_set (gnu_source_desig_type)
-                       != get_alias_set (gnu_target_desig_type))))
+                   || !alias_sets_conflict_p
+                       (get_alias_set (gnu_source_desig_type),
+                        get_alias_set (gnu_target_desig_type))))
              {
                post_error_ne
                  ("?possible aliasing problem for type&",
@@ -4973,8 +4974,9 @@ gnat_to_gnu (Node_Id gnat_node)
                        != TYPE_DUMMY_P (gnu_target_array_type))
                    || (TYPE_DUMMY_P (gnu_source_array_type)
                        && gnu_source_array_type != gnu_target_array_type)
-                   || (get_alias_set (gnu_source_array_type)
-                       != get_alias_set (gnu_target_array_type))))
+                   || !alias_sets_conflict_p
+                       (get_alias_set (gnu_source_array_type),
+                        get_alias_set (gnu_target_array_type))))
              {
                post_error_ne
                  ("?possible aliasing problem for type&",
index 13c94bc6dff0c0dcf66517dc2051cb1356e0f1f0..d8d8e3f290dd03e2ed066f84091ff913a018361c 100644 (file)
@@ -167,7 +167,6 @@ static rtx adjust_offset_for_component_ref (tree, rtx);
 static int write_dependence_p (const_rtx, const_rtx, int);
 
 static void memory_modified_1 (rtx, const_rtx, void *);
-static void record_alias_subset (alias_set_type, alias_set_type);
 
 /* Set up all info needed to perform alias analysis on memory references.  */
 
@@ -735,7 +734,7 @@ new_alias_set (void)
    It is illegal for SUPERSET to be zero; everything is implicitly a
    subset of alias set zero.  */
 
-static void
+void
 record_alias_subset (alias_set_type superset, alias_set_type subset)
 {
   alias_set_entry superset_entry;
index 3492d7ee6ca6a66b827d5650c7b657fe36155fb8..dd197f0a68ab5e33f0fc99cf2473d2873e206230 100644 (file)
@@ -36,6 +36,7 @@ extern alias_set_type get_varargs_alias_set (void);
 extern alias_set_type get_frame_alias_set (void);
 extern bool component_uses_parent_alias_set (const_tree);
 extern bool alias_set_subset_of (alias_set_type, alias_set_type);
+extern void record_alias_subset (alias_set_type, alias_set_type);
 extern void record_component_aliases (tree);
 extern int alias_sets_conflict_p (alias_set_type, alias_set_type);
 extern int alias_sets_must_conflict_p (alias_set_type, alias_set_type);
index fedb4c60da298c5373da9ca14c4fb154d4de043e..d9a63e073be36c16873c86bfc4e88984cde3919e 100644 (file)
@@ -1,3 +1,8 @@
+2009-02-10  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/aliasing3.adb: New test.
+       * gnat.dg/aliasing3_pkg.ad[sb]: New helper.
+
 2009-02-10  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/34397
diff --git a/gcc/testsuite/gnat.dg/aliasing3.adb b/gcc/testsuite/gnat.dg/aliasing3.adb
new file mode 100644 (file)
index 0000000..916821c
--- /dev/null
@@ -0,0 +1,10 @@
+-- { dg-do run }
+-- { dg-options "-O2 -gnatn" }
+
+with Aliasing3_Pkg; use Aliasing3_Pkg;
+
+procedure Aliasing3 is
+begin
+  Pointer.A(1) := 5;
+  Test (Block.A);
+end;
diff --git a/gcc/testsuite/gnat.dg/aliasing3_pkg.adb b/gcc/testsuite/gnat.dg/aliasing3_pkg.adb
new file mode 100644 (file)
index 0000000..73c1e3e
--- /dev/null
@@ -0,0 +1,10 @@
+package body Aliasing3_Pkg is
+
+  procedure Test (A : Arr) is
+  begin
+    if A(1) /= 5 then
+      raise Program_Error;
+    end if;
+  end;
+
+end Aliasing3_Pkg;
diff --git a/gcc/testsuite/gnat.dg/aliasing3_pkg.ads b/gcc/testsuite/gnat.dg/aliasing3_pkg.ads
new file mode 100644 (file)
index 0000000..4704a7c
--- /dev/null
@@ -0,0 +1,19 @@
+package Aliasing3_Pkg is
+
+  type Arr is array (1..3) of Integer;
+
+  procedure Test (A : Arr);
+  pragma Inline (Test);
+
+  type My_Arr is new Arr;
+
+  type Rec is record
+    A : My_Arr;
+  end record;
+
+  type Ptr is access all Rec;
+
+  Block : aliased Rec;
+  Pointer : Ptr := Block'Access;
+
+end Aliasing3_Pkg;