On 04/07/17 08:54, Richard Biener wrote: > On Thu, 6 Apr 2017, Bernd Edlinger wrote: >> I think get_alias_set(t) will return 0 for typeless_storage >> types, and therefore has_zero_child will be set anyway. >> I think both mean the same thing in the end, but it depends on >> what typeless_storage should actually mean, and we have >> not yet the same idea about it. > > But has_zero_child does not do what we like it to because otherwise > in the PR using the char[] array member would have worked! > > has_zero_child doesn't do that on purpose of course, but this means > returing alias-set zero for the typeless storage _member_ doesn't > suffice. >
I see you have a certain idea how to solve the C++17 issue. And yes, I apologize, if I tried to pee on your tree :) What you propose is I think the following: The C++ FE sets TYPE_TYPELESS_STORAGE a std::byte and on "unsigned char" if the language dialect is cxx17 and the TBAA makes all the rest. What I propose is as follows: The TYPE_TYPELESS_STORAGE is a generic attribute, it can be set on any type, and in the TBAA the attribute does not squirrel around at all. If it is on a type, then all DECLs with this type get the alias set 0. If it is on a member of a struct that does not mean more than if the struct has a char member this it sets has_zero_child, which I do not want to mean anything else than before. The C++ FE does the business logic here, in deciding where to distribute the TYPE_TYPELESS_STORAGE flags. in this example class A { class B { std::byte x[5]; } b; }; std::byte, class B, and class A would get the TYPE_TYPELESS_STORAGE flag set by the C++FE if the language dialect is cxx17 or above, so that you can place anything into any object of class A and class B, and of type std::byte. but in this example class B { std::byte x; }; only std::byte would get the TYPE_TYPELESS_STORAGE flag, so you can not put anyting into an object of class B, just on an object of std::byte. >> >> I wanted to be able to declare a int __attribute__((typeless_storage)) >> as in the test case, and the sample in the spec. And that >> information is not in the TYPE_MAIN_VARIANT. Therefore I look for >> typeless_storage before "t = TYPE_MAIN_VARIANT (t)". > > As I said I believe this is a useless feature. If you want something > typeless then the underlying type doesn't matter so we can as well > force it to be an array of char. Makes our live simpler. And > even makes the code portable to compilers that treat arrays of char > conservatively. > I just learned that the C11 standard does not guarantee that, and also an array of char does not provide the necessary alignment per se, at least without alignment attributes. >> >> See cxx_type_contains_byte_buffer: this function looks recursively into >> structures and unions, and returns the information if the beast >> contains an array of unsigned char or std::byte. > > But with a properly designed middle-end feature that's not needed. > > There's technically no reason to pessimize TBAA for anything but > the typeless storage member of a structure. > Yes, it is just a matter of taste. And if you want the middle end to be flexible here or if everything should work without user intervention. >>> >>> @@ -1491,6 +1491,7 @@ struct GTY(()) tree_type_common { >>> unsigned needs_constructing_flag : 1; >>> unsigned transparent_aggr_flag : 1; >>> unsigned restrict_flag : 1; >>> + unsigned typeless_storage_flag : 1; >>> unsigned contains_placeholder_bits : 2; >>> >>> ENUM_BITFIELD(machine_mode) mode : 8; >>> >>> bits are grouped in groups of 8 bits, this breaks it. >>> >> >> Oh..., does this explain the problems that I had with this version??? > > No, just "cosmetics". > >>> @@ -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 (TYPE_TYPELESS_STORAGE (to_type) >>> + || lookup_attribute ("may_alias", 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 (TYPE_TYPELESS_STORAGE (to_type) >>> + || lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type))) >>> can_alias_all = true; >>> >>> /* In some cases, languages will have things that aren't a >>> >>> not needed. >>> >> >> You mean, because the get_alias_set (to_type) will be 0 anyways, >> and can_alias_all wont change the semantic? > > Well, typeless_storage and may_alias are something different. If > you require the above then your implementation of typeless_storage > is broken. > You are right, the hunk above is actually unnecessary. > Richard. > >> >> Bernd. >> >>> +/* Nonzero if the type should behave like a character type >>> + with respect to aliasing sementics. */ >>> +#define TYPE_TYPELESS_STORAGE(NODE) \ >>> + (TYPE_CHECK (NODE)->type_common.typeless_storage_flag) >>> >>> ARRAY_TYPE_CHECK (NODE)-> >>> >>> Richard. >>> >> >> >