From 350792ffaed9b3506582b471bf133459d7ea64ab Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 12 Apr 2017 07:35:49 +0000 Subject: [PATCH] re PR target/79671 (mapnik miscompilation on armv7hl since r235622) 2017-04-12 Richard Biener Bernd Edlinger 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 From-SVN: r246866 --- gcc/ChangeLog | 18 ++++++++++++++++++ gcc/alias.c | 8 ++++++++ gcc/cp/ChangeLog | 7 +++++++ gcc/cp/tree.c | 8 ++++++++ gcc/lto-streamer-out.c | 2 ++ gcc/lto/ChangeLog | 6 ++++++ gcc/lto/lto.c | 2 ++ gcc/stor-layout.c | 10 ++++++++++ gcc/testsuite/ChangeLog | 8 ++++++++ gcc/testsuite/g++.dg/lto/pr79671_0.C | 26 ++++++++++++++++++++++++++ gcc/testsuite/g++.dg/lto/pr79671_1.c | 5 +++++ gcc/testsuite/g++.dg/torture/pr79671.C | 25 +++++++++++++++++++++++++ gcc/tree-core.h | 4 +++- gcc/tree-streamer-in.c | 2 ++ gcc/tree-streamer-out.c | 2 ++ gcc/tree.h | 7 +++++++ 16 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/lto/pr79671_0.C create mode 100644 gcc/testsuite/g++.dg/lto/pr79671_1.c create mode 100644 gcc/testsuite/g++.dg/torture/pr79671.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f96256bfac9..91a3e45c784 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2017-04-12 Richard Biener + Bernd Edlinger + + 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 PR sanitizer/80349 diff --git a/gcc/alias.c b/gcc/alias.c index cc31ee0e261..efd89ce1679 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -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 (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. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 80247bf6845..9997825e805 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2017-04-12 Richard Biener + Bernd Edlinger + + 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 PR c++/80294 - ICE with constexpr and inheritance. diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index acb9b8eef05..2edd5671c08 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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; diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 82a0cd60dec..b96b9df63b7 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -1143,6 +1143,8 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map *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)); diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index d308c255ad0..d24dd0cfa0f 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,9 @@ +2017-04-12 Richard Biener + Bernd Edlinger + + PR middle-end/79671 + * lto.c (compare_tree_sccs_1): Compare TYPE_TYPELESS_STORAGE. + 2017-02-14 Martin Liska * lto.c (do_stream_out): Free LTO file filename string. diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 99d58cff4d4..a7d5e450ea0 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -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); diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index d0beebf0686..10e9a324940 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bf315d3696e..115e1233dc0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2017-04-12 Richard Biener + Bernd Edlinger + + 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 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 index 00000000000..a55a57fd79a --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/pr79671_0.C @@ -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 (&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 index 00000000000..934cb2d63f5 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/pr79671_1.c @@ -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 index 00000000000..94605851ff1 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr79671.C @@ -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 (&y); + asm volatile ("" : "=r" (q) : "r" (q)); + return q->i; +} + +int main() +{ + if (foo() != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 2b1759efcb1..a646ecb5c95 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -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; diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c index 3496df5deb9..f0099c05032 100644 --- a/gcc/tree-streamer-in.c +++ b/gcc/tree-streamer-in.c @@ -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 diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c index 0ee2abe8f19..5cf90449341 100644 --- a/gcc/tree-streamer-out.c +++ b/gcc/tree-streamer-out.c @@ -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)); } diff --git a/gcc/tree.h b/gcc/tree.h index aa137e4132b..50a674bf0fe 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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) -- 2.30.2