On 04/05/17 23:02, Bernd Edlinger wrote: > On 04/05/17 19:22, Bernd Edlinger wrote: >> On 04/05/17 18:08, Jakub Jelinek wrote: >> >> Yes, exactly. I really want to reach the deadline for gcc-7. >> Fixing the name is certainly the most important first step, >> and if everybody agrees on "typeless_storage", for the name >> I can start with adjusting the name, and look into how >> to use a spare type-flag that should be a mechanical change. >> > > Jakub, I just renamed the attribute and reworked the patch > as you suggested, reg-testing is not yet completed, but > it looks good so far. I also added a few more tests. >
Aehm, sorry, actually I ran into a problem with the latest patch version, where I tried to convert the TYPE_ATTRIBUTE into a TYPE_FLAG here: https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00254.html That is for instance with g++.dg/cpp1z/init-statement6.C an internal error: "same canonical type node for different types" happened, and I was not able to fix it immediately. Although I would have liked it better this way, I think this can be fixed separately, unless someone sees an obvious thinko in the previous version. So in the moment I restored the typeless_storage as an ordinary TYPE_ATTRIBUTE, but at least it bootstraps and causes no test regressions, as always with languages=all,ada,go,obj-c++ Thanks Bernd.
Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 246678) +++ gcc/doc/extend.texi (working copy) @@ -6656,6 +6656,36 @@ @option{-fstrict-aliasing}, which is on by default at @option{-O2} or above. +@item typeless_storage +@cindex @code{typeless_storage} type attribute +In the context of section 6.5 paragraph 6 of the C11 standard, +an object of this type behaves as if it has no declared type. +In the context of section 6.5 paragraph 7 of the C11 standard, +an object or a pointer if this type behaves as if it were a +character type. +This attribute is similar to the @code{may_alias} attribute, +except that it is not restricted to pointers. + +Example of use: + +@smallexample +typedef int __attribute__((__typeless_storage__)) int_a; + +int +main (void) +@{ + int_a a = 0x12345678; + short *b = (short *) &a; + + b[1] = 0; + + if (a == 0x12345678) + abort(); + + exit(0); +@} +@end smallexample + @item packed @cindex @code{packed} type attribute This attribute, attached to @code{struct} or @code{union} type Index: gcc/alias.c =================================================================== --- gcc/alias.c (revision 246678) +++ gcc/alias.c (working copy) @@ -879,6 +879,10 @@ get_alias_set (tree t) t = TREE_TYPE (t); } + /* Honor the typeless_storage type attribute. */ + if (lookup_attribute ("typeless_storage", TYPE_ATTRIBUTES (t))) + return 0; + /* Variant qualifiers don't affect the alias set, so get the main variant. */ t = TYPE_MAIN_VARIANT (t); @@ -1234,7 +1238,9 @@ record_component_aliases (tree type) /* VECTOR_TYPE and ARRAY_TYPE share the alias set with their element type and that type has to be normalized to void *, too, in the case it is a pointer. */ - while (!canonical_type_used_p (t) && !POINTER_TYPE_P (t)) + while (!canonical_type_used_p (t) && !POINTER_TYPE_P (t) + && !lookup_attribute ("typeless_storage", + TYPE_ATTRIBUTES (t))) { gcc_checking_assert (TYPE_STRUCTURAL_EQUALITY_P (t)); t = TREE_TYPE (t); Index: gcc/tree.c =================================================================== --- gcc/tree.c (revision 246678) +++ gcc/tree.c (working copy) @@ -8041,7 +8041,8 @@ build_pointer_type_for_mode (tree to_type, machine /* If the pointed-to type has the may_alias attribute set, force a TYPE_REF_CAN_ALIAS_ALL pointer to be generated. */ - if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type))) + if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)) + || lookup_attribute ("typeless_storage", TYPE_ATTRIBUTES (to_type))) can_alias_all = true; /* In some cases, languages will have things that aren't a POINTER_TYPE @@ -8110,7 +8111,8 @@ build_reference_type_for_mode (tree to_type, machi /* If the pointed-to type has the may_alias attribute set, force a TYPE_REF_CAN_ALIAS_ALL pointer to be generated. */ - if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type))) + if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)) + || lookup_attribute ("typeless_storage", TYPE_ATTRIBUTES (to_type))) can_alias_all = true; /* In some cases, languages will have things that aren't a REFERENCE_TYPE Index: gcc/c-family/c-attribs.c =================================================================== --- gcc/c-family/c-attribs.c (revision 246678) +++ gcc/c-family/c-attribs.c (working copy) @@ -265,6 +265,7 @@ const struct attribute_spec c_common_attribute_tab { "nothrow", 0, 0, true, false, false, handle_nothrow_attribute, false }, { "may_alias", 0, 0, false, true, false, NULL, false }, + { "typeless_storage", 0, 0, false, true, false, NULL, false }, { "cleanup", 1, 1, true, false, false, handle_cleanup_attribute, false }, { "warn_unused_result", 0, 0, false, true, true, Index: gcc/cp/class.c =================================================================== --- gcc/cp/class.c (revision 246678) +++ gcc/cp/class.c (working copy) @@ -2083,7 +2082,8 @@ fixup_attribute_variants (tree t) tree attrs = TYPE_ATTRIBUTES (t); unsigned align = TYPE_ALIGN (t); bool user_align = TYPE_USER_ALIGN (t); - bool may_alias = lookup_attribute ("may_alias", attrs); + bool may_alias = lookup_attribute ("may_alias", attrs) + || lookup_attribute ("typeless_storage", attrs); if (may_alias) fixup_may_alias (t); @@ -7345,6 +7346,15 @@ finish_struct_1 (tree t) the class or perform any other required target modifications. */ targetm.cxx.adjust_class_at_definition (t); + if (cxx_dialect >= cxx1z && cxx_type_contains_byte_buffer (t) + && !lookup_attribute ("typeless_storage", TYPE_ATTRIBUTES (t))) + { + TYPE_ATTRIBUTES (t) + = tree_cons (get_identifier ("typeless_storage"), + NULL_TREE, TYPE_ATTRIBUTES (t)); + fixup_attribute_variants (t); + } + maybe_suppress_debug_info (t); if (flag_vtable_verify) Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h (revision 246678) +++ gcc/cp/cp-tree.h (working copy) @@ -6858,6 +6858,7 @@ extern tree finish_binary_fold_expr (tree extern void require_complete_eh_spec_types (tree, tree); extern void cxx_incomplete_type_diagnostic (location_t, const_tree, const_tree, diagnostic_t); +extern bool cxx_type_contains_byte_buffer (tree); inline void cxx_incomplete_type_diagnostic (const_tree value, const_tree type, diagnostic_t diag_kind) Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 246678) +++ gcc/cp/decl.c (working copy) @@ -14081,10 +14081,15 @@ start_enum (tree name, tree enumtype, tree underly enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current); /* std::byte aliases anything. */ - if (enumtype != error_mark_node + if (cxx_dialect >= cxx1z + && enumtype != error_mark_node && TYPE_CONTEXT (enumtype) == std_node - && !strcmp ("byte", TYPE_NAME_STRING (enumtype))) - TYPE_ALIAS_SET (enumtype) = 0; + && !strcmp ("byte", TYPE_NAME_STRING (enumtype)) + && !lookup_attribute ("typeless_storage", + TYPE_ATTRIBUTES (enumtype))) + TYPE_ATTRIBUTES (enumtype) + = tree_cons (get_identifier ("typeless_storage"), + NULL_TREE, TYPE_ATTRIBUTES (enumtype)); } else enumtype = xref_tag (enum_type, name, /*tag_scope=*/ts_current, Index: gcc/cp/pt.c =================================================================== --- gcc/cp/pt.c (revision 246678) +++ gcc/cp/pt.c (working copy) @@ -8851,9 +8851,10 @@ lookup_template_class_1 (tree d1, tree arglist, tr if (OVERLOAD_TYPE_P (t) && !DECL_ALIAS_TEMPLATE_P (gen_tmpl)) { - static const char *tags[] = {"abi_tag", "may_alias"}; + static const char *tags[] = {"abi_tag", "may_alias", + "typeless_storage"}; - for (unsigned ix = 0; ix != 2; ix++) + for (unsigned ix = 0; ix < sizeof (tags) / sizeof (tags[0]); ix++) { tree attributes = lookup_attribute (tags[ix], TYPE_ATTRIBUTES (template_type)); Index: gcc/cp/typeck2.c =================================================================== --- gcc/cp/typeck2.c (revision 246678) +++ gcc/cp/typeck2.c (working copy) @@ -2234,5 +2234,29 @@ require_complete_eh_spec_types (tree fntype, tree } } +/* True iff type either is or contains a byte buffer (which can be used for + storing any trivially copyable type). */ + +bool +cxx_type_contains_byte_buffer (tree type) +{ + if (TREE_CODE (type) == ARRAY_TYPE + && (cxx_type_contains_byte_buffer (TREE_TYPE (type)) + || TREE_TYPE (type) == unsigned_char_type_node + || (TREE_CODE (TREE_TYPE (type)) == ENUMERAL_TYPE + && TYPE_CONTEXT (TREE_TYPE (type)) == std_node + && !strcmp ("byte", TYPE_NAME_STRING (TREE_TYPE (type)))))) + return true; + + if (CLASS_TYPE_P (type)) + for (tree field = next_initializable_field (TYPE_FIELDS (type)); + field; + field = next_initializable_field (DECL_CHAIN (field))) + if (cxx_type_contains_byte_buffer (TREE_TYPE (field))) + return true; + + return false; +} + #include "gt-cp-typeck2.h" Index: gcc/testsuite/c-c++-common/attr-typeless-storage-1.c =================================================================== --- gcc/testsuite/c-c++-common/attr-typeless-storage-1.c (revision 0) +++ gcc/testsuite/c-c++-common/attr-typeless-storage-1.c (working copy) @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wall" } */ + +typedef int T __attribute__((typeless_storage)); + +extern T t, v; +extern T *p; +extern int *p; + +extern int *p2; +extern T *p2; + +void fn1 (T); +void fn1 (int); + +void fn2 (int); +void fn2 (T); + +/* Ensure that the composite types have typeless_storage. */ +void +f (long *i) +{ + *i = *(__typeof (*p) *) &p; + asm ("" : : "r" (*p)); + *i = *(__typeof (*p2) *) &p2; + asm ("" : : "r" (*p2)); + t = v; + asm ("" : : "r" (t)); +} Index: gcc/testsuite/c-c++-common/attr-typeless-storage-2.c =================================================================== --- gcc/testsuite/c-c++-common/attr-typeless-storage-2.c (revision 0) +++ gcc/testsuite/c-c++-common/attr-typeless-storage-2.c (working copy) @@ -0,0 +1,17 @@ +/* We used to reject this because types differentiating only in + TYPE_REF_CAN_ALIAS_ALL were deemed incompatible. */ +/* { dg-do compile } */ + +struct sockaddr; +struct sockaddr *f (void); + +struct __attribute__((typeless_storage)) sockaddr { int j; }; +struct sockaddr * +f (void) +{ + return +#ifndef __cplusplus + (void *) +#endif + 0; +} Index: gcc/testsuite/gcc.c-torture/execute/typeless-storage-1.c =================================================================== --- gcc/testsuite/gcc.c-torture/execute/typeless-storage-1.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/typeless-storage-1.c (working copy) @@ -0,0 +1,20 @@ +/* Tests that the typeless_storage attribute works as expected. */ + +extern void abort(void); +extern void exit(int); + +typedef int __attribute__((__typeless_storage__)) int_a; + +int +main (void) +{ + int_a a = 0x12345678; + short *b = (short *) &a; + + b[1] = 0; + + if (a == 0x12345678) + abort(); + + exit(0); +}