re PR target/79671 (mapnik miscompilation on armv7hl since r235622)
authorRichard Biener <rguenther@suse.de>
Wed, 12 Apr 2017 07:35:49 +0000 (07:35 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 12 Apr 2017 07:35:49 +0000 (07:35 +0000)
2017-04-12  Richard Biener  <rguenther@suse.de>
Bernd Edlinger  <bernd.edlinger@hotmail.de>

PR middle-end/79671
* alias.c (component_uses_parent_alias_set_from): Handle
TYPE_TYPELESS_STORAGE.
(get_alias_set): Likewise.
* tree-core.h (tree_type_common): Add typeless_storage flag.
* tree.h (TYPE_TYPELESS_STORAGE): New macro.
* stor-layout.c (place_union_field): Set TYPE_TYPELESS_STORAGE
for types containing members with TYPE_TYPELESS_STORAGE.
(place_field): Likewise.
(layout_type): Likewise for ARRAY_TYPE.
* lto-streamer-out.c (hash_tree): Hash TYPE_TYPELESS_STORAGE.
* tree-streamer-in.c (unpack_ts_type_common_value_fields): Stream
TYPE_TYPELESS_STORAGE.
* tree-streamer-out.c (pack_ts_type_common_value_fields): Likewise.

lto/
* lto.c (compare_tree_sccs_1): Compare TYPE_TYPELESS_STORAGE.

cp/
* tree.c (build_cplus_array_type): Set TYPE_TYPELESS_STORAGE
for arrays of character or std::byte type.

* g++.dg/torture/pr79671.C: New testcase.
* g++.dg/lto/pr79671_0.C: Likewise.
* g++.dg/lto/pr79671_1.c: Likewise.

Co-Authored-By: Bernd Edlinger <bernd.edlinger@hotmail.de>
From-SVN: r246866

16 files changed:
gcc/ChangeLog
gcc/alias.c
gcc/cp/ChangeLog
gcc/cp/tree.c
gcc/lto-streamer-out.c
gcc/lto/ChangeLog
gcc/lto/lto.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lto/pr79671_0.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lto/pr79671_1.c [new file with mode: 0644]
gcc/testsuite/g++.dg/torture/pr79671.C [new file with mode: 0644]
gcc/tree-core.h
gcc/tree-streamer-in.c
gcc/tree-streamer-out.c
gcc/tree.h

index f96256bfac997e7c708af9d060dfc7971b1403d9..91a3e45c7841e1959b4c422e3cac36deb5e92bbc 100644 (file)
@@ -1,3 +1,21 @@
+2017-04-12  Richard Biener  <rguenther@suse.de>
+       Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       PR middle-end/79671
+       * alias.c (component_uses_parent_alias_set_from): Handle
+       TYPE_TYPELESS_STORAGE.
+       (get_alias_set): Likewise.
+       * tree-core.h (tree_type_common): Add typeless_storage flag.
+       * tree.h (TYPE_TYPELESS_STORAGE): New macro.
+       * stor-layout.c (place_union_field): Set TYPE_TYPELESS_STORAGE
+       for types containing members with TYPE_TYPELESS_STORAGE.
+       (place_field): Likewise.
+       (layout_type): Likewise for ARRAY_TYPE.
+       * lto-streamer-out.c (hash_tree): Hash TYPE_TYPELESS_STORAGE.
+       * tree-streamer-in.c (unpack_ts_type_common_value_fields): Stream
+       TYPE_TYPELESS_STORAGE.
+       * tree-streamer-out.c (pack_ts_type_common_value_fields): Likewise.
+
 2017-04-12  Jakub Jelinek  <jakub@redhat.com>
 
        PR sanitizer/80349
index cc31ee0e261724813c851012f86688b4a19006d6..efd89ce1679aff088dc3df20bac7b84d3727274f 100644 (file)
@@ -613,6 +613,10 @@ component_uses_parent_alias_set_from (const_tree t)
 {
   const_tree found = NULL_TREE;
 
+  if (AGGREGATE_TYPE_P (TREE_TYPE (t))
+      && TYPE_TYPELESS_STORAGE (TREE_TYPE (t)))
+    return const_cast <tree> (t);
+
   while (handled_component_p (t))
     {
       switch (TREE_CODE (t))
@@ -883,6 +887,10 @@ get_alias_set (tree t)
      variant.  */
   t = TYPE_MAIN_VARIANT (t);
 
+  if (AGGREGATE_TYPE_P (t)
+      && TYPE_TYPELESS_STORAGE (t))
+    return 0;
+
   /* Always use the canonical type as well.  If this is a type that
      requires structural comparisons to identify compatible types
      use alias set zero.  */
index 80247bf684518b8ac265462cdd7e255b22006409..9997825e8057db33325cf09199a5d65181ec5c47 100644 (file)
@@ -1,3 +1,10 @@
+2017-04-12  Richard Biener  <rguenther@suse.de>
+       Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       PR middle-end/79671
+       * tree.c (build_cplus_array_type): Set TYPE_TYPELESS_STORAGE
+       for arrays of character or std::byte type.
+
 2017-04-11  Jason Merrill  <jason@redhat.com>
 
        PR c++/80294 - ICE with constexpr and inheritance.
index acb9b8eef0529888c383a579e173d810ff23d475..2edd5671c08f5564d8d6ae4bdcb2b9b7e6c473c5 100644 (file)
@@ -949,6 +949,13 @@ build_cplus_array_type (tree elt_type, tree index_type)
   else
     {
       t = build_array_type (elt_type, index_type);
+      if (elt_type == unsigned_char_type_node
+         || elt_type == signed_char_type_node
+         || elt_type == char_type_node
+         || (TREE_CODE (elt_type) == ENUMERAL_TYPE
+             && TYPE_CONTEXT (elt_type) == std_node
+             && !strcmp ("byte", TYPE_NAME_STRING (elt_type))))
+       TYPE_TYPELESS_STORAGE (t) = 1;
     }
 
   /* Now check whether we already have this array variant.  */
@@ -972,6 +979,7 @@ build_cplus_array_type (tree elt_type, tree index_type)
                 as it will overwrite alignment etc. of all variants.  */
              TYPE_SIZE (t) = TYPE_SIZE (m);
              TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (m);
+             TYPE_TYPELESS_STORAGE (t) = TYPE_TYPELESS_STORAGE (m);
            }
 
          TYPE_MAIN_VARIANT (t) = m;
index 82a0cd60dec8facc71e846bd63583ba3ec0ebbb7..b96b9df63b75dcdbaa493e47fb1e32f798980c6a 100644 (file)
@@ -1143,6 +1143,8 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
        }
       else if (code == ARRAY_TYPE)
        hstate.add_flag (TYPE_NONALIASED_COMPONENT (t));
+      if (AGGREGATE_TYPE_P (t))
+       hstate.add_flag (TYPE_TYPELESS_STORAGE (t));
       hstate.commit_flag ();
       hstate.add_int (TYPE_PRECISION (t));
       hstate.add_int (TYPE_ALIGN (t));
index d308c255ad0429fff7c14f1932d35dc5b3388f0a..d24dd0cfa0f43f54b2cddc48e122e1e450969af1 100644 (file)
@@ -1,3 +1,9 @@
+2017-04-12  Richard Biener  <rguenther@suse.de>
+       Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       PR middle-end/79671
+       * lto.c (compare_tree_sccs_1): Compare TYPE_TYPELESS_STORAGE.
+
 2017-02-14  Martin Liska  <mliska@suse.cz>
 
        * lto.c (do_stream_out): Free LTO file filename string.
index 99d58cff4d42e9fa92eebef8151f18e7623e00e7..a7d5e450ea0b0ae025dca03a660210a1b1fd0f45 100644 (file)
@@ -1162,6 +1162,8 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
        }
       else if (code == ARRAY_TYPE)
        compare_values (TYPE_NONALIASED_COMPONENT);
+      if (AGGREGATE_TYPE_P (t1))
+       compare_values (TYPE_TYPELESS_STORAGE);
       compare_values (TYPE_PACKED);
       compare_values (TYPE_RESTRICT);
       compare_values (TYPE_USER_ALIGN);
index d0beebf06868545442f2b6431ae034a04252db8c..10e9a324940f4ab5f62a0808c6c09e8e6e9f4c77 100644 (file)
@@ -1091,6 +1091,10 @@ place_union_field (record_layout_info rli, tree field)
   if (TREE_CODE (TREE_TYPE (field)) == ERROR_MARK)
     return;
 
+  if (AGGREGATE_TYPE_P (TREE_TYPE (field))
+      && TYPE_TYPELESS_STORAGE (TREE_TYPE (field)))
+    TYPE_TYPELESS_STORAGE (rli->t) = 1;
+
   /* We assume the union's size will be a multiple of a byte so we don't
      bother with BITPOS.  */
   if (TREE_CODE (rli->t) == UNION_TYPE)
@@ -1168,6 +1172,10 @@ place_field (record_layout_info rli, tree field)
       return;
     }
 
+  if (AGGREGATE_TYPE_P (type)
+      && TYPE_TYPELESS_STORAGE (type))
+    TYPE_TYPELESS_STORAGE (rli->t) = 1;
+
   /* Work out the known alignment so far.  Note that A & (-A) is the
      value of the least-significant bit in A that is one.  */
   if (! integer_zerop (rli->bitpos))
@@ -2340,6 +2348,8 @@ layout_type (tree type)
                SET_TYPE_MODE (type, BLKmode);
              }
          }
+       if (AGGREGATE_TYPE_P (element))
+         TYPE_TYPELESS_STORAGE (type) = TYPE_TYPELESS_STORAGE (element);
        /* When the element size is constant, check that it is at least as
           large as the element alignment.  */
        if (TYPE_SIZE_UNIT (element)
index bf315d3696e54e84eced4a78b065666e80d2dc1e..115e1233dc00547a0055d314c5f550fe3210a48f 100644 (file)
@@ -1,3 +1,11 @@
+2017-04-12  Richard Biener  <rguenther@suse.de>
+       Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       PR middle-end/79671
+       * g++.dg/torture/pr79671.C: New testcase.
+       * g++.dg/lto/pr79671_0.C: Likewise.
+       * g++.dg/lto/pr79671_1.c: Likewise.
+
 2017-04-12  Jakub Jelinek  <jakub@redhat.com>
 
        PR sanitizer/80349
diff --git a/gcc/testsuite/g++.dg/lto/pr79671_0.C b/gcc/testsuite/g++.dg/lto/pr79671_0.C
new file mode 100644 (file)
index 0000000..a55a57f
--- /dev/null
@@ -0,0 +1,26 @@
+// { dg-lto-do run }
+
+void *operator new(__SIZE_TYPE__, void *p2) { return p2; }
+struct B { B(int i_) : i(i_) {} int i; };
+struct X
+{
+  unsigned char buf[sizeof (B)];
+};
+
+int __attribute__((noinline)) foo()
+{
+  X x alignas (B), y alignas (B);
+  new (&x) B (0);
+  y = x;
+  B *q = reinterpret_cast <B *>(&y);
+  asm volatile ("" : "=r" (q) : "r" (q));
+  return q->i;
+}
+extern "C" void bar ();
+int main()
+{
+  if (foo() != 0)
+    __builtin_abort ();
+  bar ();
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lto/pr79671_1.c b/gcc/testsuite/g++.dg/lto/pr79671_1.c
new file mode 100644 (file)
index 0000000..934cb2d
--- /dev/null
@@ -0,0 +1,5 @@
+struct X
+{
+  unsigned char buf[sizeof (int)];
+};
+void bar () { struct X x; *(volatile char *)x.buf = 1; }
diff --git a/gcc/testsuite/g++.dg/torture/pr79671.C b/gcc/testsuite/g++.dg/torture/pr79671.C
new file mode 100644 (file)
index 0000000..9460585
--- /dev/null
@@ -0,0 +1,25 @@
+// { dg-do run }
+
+void *operator new(__SIZE_TYPE__, void *p2) { return p2; }
+struct B { B(int i_) : i(i_) {} int i; };
+struct X
+{
+  unsigned char buf[sizeof (B)];
+};
+
+int __attribute__((noinline)) foo()
+{
+  X x alignas(B), y alignas(B);
+  new (&x) B (0);
+  y = x;
+  B *q = reinterpret_cast <B *>(&y);
+  asm volatile ("" : "=r" (q) : "r" (q));
+  return q->i;
+}
+
+int main()
+{
+  if (foo() != 0)
+    __builtin_abort ();
+  return 0;
+}
index 2b1759efcb182bf57b80033a4cc7f1af4dbf22eb..a646ecb5c951869fa8bfa3af11c524414c0c6c3b 100644 (file)
@@ -1511,7 +1511,9 @@ struct GTY(()) tree_type_common {
      so we need to store the value 32 (not 31, as we need the zero
      as well), hence six bits.  */
   unsigned align : 6;
-  unsigned spare : 25;
+  unsigned typeless_storage : 1;
+  unsigned spare : 24;
+
   alias_set_type alias_set;
   tree pointer_to;
   tree reference_to;
index 3496df5deb979ca258a9f6ee74b22788fabb6a8a..f0099c050325b87fe55b6de91cc8d9d4cef628a5 100644 (file)
@@ -376,6 +376,8 @@ unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
     }
   else if (TREE_CODE (expr) == ARRAY_TYPE)
     TYPE_NONALIASED_COMPONENT (expr) = (unsigned) bp_unpack_value (bp, 1);
+  if (AGGREGATE_TYPE_P (expr))
+    TYPE_TYPELESS_STORAGE (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_PRECISION (expr) = bp_unpack_var_len_unsigned (bp);
   SET_TYPE_ALIGN (expr, bp_unpack_var_len_unsigned (bp));
 #ifdef ACCEL_COMPILER
index 0ee2abe8f19fb39cc48de77283687bf29d8ad13b..5cf904493410e78ed08b2034089473d2e25c9afd 100644 (file)
@@ -328,6 +328,8 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
     }
   else if (TREE_CODE (expr) == ARRAY_TYPE)
     bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1);
+  if (AGGREGATE_TYPE_P (expr))
+    bp_pack_value (bp, TYPE_TYPELESS_STORAGE (expr), 1);
   bp_pack_var_len_unsigned (bp, TYPE_PRECISION (expr));
   bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr));
 }
index aa137e4132bb5c5ca3f397a51b475307c7ab91b6..50a674bf0fef6d216ce9d704e3b5e9e0b952c950 100644 (file)
@@ -2035,6 +2035,13 @@ extern machine_mode element_mode (const_tree t);
 #define TYPE_NONALIASED_COMPONENT(NODE) \
   (ARRAY_TYPE_CHECK (NODE)->type_common.transparent_aggr_flag)
 
+/* For an ARRAY_TYPE, a RECORD_TYPE, a UNION_TYPE or a QUAL_UNION_TYPE
+   whether the array is typeless storage or the type contains a member
+   with this flag set.  Such types are excempt from type-based alias
+   analysis.  */
+#define TYPE_TYPELESS_STORAGE(NODE) \
+  (TREE_CHECK4 (NODE, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, ARRAY_TYPE)->type_common.typeless_storage)
+
 /* Indicated that objects of this type should be laid out in as
    compact a way as possible.  */
 #define TYPE_PACKED(NODE) (TYPE_CHECK (NODE)->base.u.bits.packed_flag)