diff mbox

Add a new type attribute always_alias (PR79671)

Message ID AM4PR0701MB216292327A207737064C3CA3E40A0@AM4PR0701MB2162.eurprd07.prod.outlook.com
State New
Headers show

Commit Message

Bernd Edlinger April 5, 2017, 9:46 a.m. UTC
Hi,

this is related to the P1 codegen bug PR79671:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79671

Therefore I would like to add this now although
the trunk is already at in stage 4.

I propose to add a new type attribute always_alias that
works like may_alias but unlike may_alias it should
also make instances alias anything.  It is also exposed
in C/C++ as __attribute__((always_alias)).

For C++17 the FE automatically introduces this attribute
at std::byte and all class/struct/union which contain
either a std::byte array or an unsigned char array.

Note that the patch [1] needs to be applied as well,
because otherwise the new attribute will trip several
failures in the libstdc++ testsuite.


Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?


Thanks
Bernd.


[1] https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00189.html
gcc
2017-04-05  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* doc/extend.texi: Document the always_alias type attribute.
	* alias.c (get_alias_set): Honor the always_alias attribute.
	(record_component_aliases): Don't ignore the always_alias attribute.
	* tree.c (build_pointer_type_for_mode,
	build_reference_type_for_mode): Add the always_alias attribute.

gcc/c-family
2017-04-05  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* c-attribs.c (c_common_attribute_tab): Add the always_alias attribute.

gcc/cp
2017-04-05  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* class.c (fixup_attribute_variants): Add the always_alias attribute.
	(finish_struct_1): Add an always_alias attribute if required by C++17.
	* decl.c (start_enum): Likewise.
	* pt.c (lookup_template_class_1): Add the always_alias attribute.
	* typeck2.c (cxx_type_contains_byte_buffer): New function.
	* cp-tree.h (cxx_type_contains_byte_buffer): Declare.

Comments

Jakub Jelinek April 5, 2017, 1:28 p.m. UTC | #1
On Wed, Apr 05, 2017 at 09:46:09AM +0000, Bernd Edlinger wrote:
> this is related to the P1 codegen bug PR79671:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79671
> 
> Therefore I would like to add this now although
> the trunk is already at in stage 4.
> 
> I propose to add a new type attribute always_alias that
> works like may_alias but unlike may_alias it should
> also make instances alias anything.  It is also exposed
> in C/C++ as __attribute__((always_alias)).

I have just two small comments, for review IMHO want agreement
between Jason and Richard on this.

One thing is whether it is a good idea to keep this info in the IL
as an attribute, especially when you add it automatically in the
C++ FE.  I see e.g. 25 spare bits in tree_type_common.  Don't say we
need to waste them, but I'd say in C++ unsigned char arrays are fairly
common and thus not having to create the attribute for them each time
and look it up might be beneficial.

Also, wonder if you need to mark all types containing such arrays,
if you couldn't just set that flag in C++ on unsigned char/std::byte
arrays (and on anything with that attribute), have that imply alias set
0 on it and then let the rest of alias machinery handle aggregate types
containing such fields.

	Jakub
Florian Weimer April 5, 2017, 2:50 p.m. UTC | #2
On 04/05/2017 11:46 AM, Bernd Edlinger wrote:
> +@item always_alias
> +@cindex @code{always_alias} type attribute
> +Same as @code{may_alias}, but additionally applies to instances of
> +types with this attribute.

As a GCC user, I have to say that this doesn't really explain what the 
attribute does.  The C standard does not define what an “instance” of a 
type is.

Thanks,
Florian
Richard Biener April 5, 2017, 3:20 p.m. UTC | #3
On April 5, 2017 3:28:32 PM GMT+02:00, Jakub Jelinek <jakub@redhat.com> wrote:
>On Wed, Apr 05, 2017 at 09:46:09AM +0000, Bernd Edlinger wrote:
>> this is related to the P1 codegen bug PR79671:
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79671
>> 
>> Therefore I would like to add this now although
>> the trunk is already at in stage 4.
>> 
>> I propose to add a new type attribute always_alias that
>> works like may_alias but unlike may_alias it should
>> also make instances alias anything.  It is also exposed
>> in C/C++ as __attribute__((always_alias)).
>
>I have just two small comments, for review IMHO want agreement
>between Jason and Richard on this.
>
>One thing is whether it is a good idea to keep this info in the IL
>as an attribute, especially when you add it automatically in the
>C++ FE.  I see e.g. 25 spare bits in tree_type_common.  Don't say we
>need to waste them, but I'd say in C++ unsigned char arrays are fairly
>common and thus not having to create the attribute for them each time
>and look it up might be beneficial.

Agreed.

>Also, wonder if you need to mark all types containing such arrays,
>if you couldn't just set that flag in C++ on unsigned char/std::byte
>arrays (and on anything with that attribute), have that imply alias set
>0 on it and then let the rest of alias machinery handle aggregate types
>containing such fields.

Yes, I expected it to work like this (didn't look at the patch yet).

Richard.

>	Jakub
Richard Biener April 5, 2017, 3:23 p.m. UTC | #4
On April 5, 2017 4:50:32 PM GMT+02:00, Florian Weimer <fweimer@redhat.com> wrote:
>On 04/05/2017 11:46 AM, Bernd Edlinger wrote:
>> +@item always_alias
>> +@cindex @code{always_alias} type attribute
>> +Same as @code{may_alias}, but additionally applies to instances of
>> +types with this attribute.
>
>As a GCC user, I have to say that this doesn't really explain what the 
>attribute does.  The C standard does not define what an “instance” of a
>
>type is.

I don't like the name.  I'd name it 'typeless_storage' and document that when storage is accessed with a type with this attribute it it behaves like a character type with respect to semantics.

Richard.

>
>Thanks,
>Florian
Bernd Edlinger April 5, 2017, 3:27 p.m. UTC | #5
On 04/05/17 15:28, Jakub Jelinek wrote:
> On Wed, Apr 05, 2017 at 09:46:09AM +0000, Bernd Edlinger wrote:
>> this is related to the P1 codegen bug PR79671:
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79671
>>
>> Therefore I would like to add this now although
>> the trunk is already at in stage 4.
>>
>> I propose to add a new type attribute always_alias that
>> works like may_alias but unlike may_alias it should
>> also make instances alias anything.  It is also exposed
>> in C/C++ as __attribute__((always_alias)).
>
> I have just two small comments, for review IMHO want agreement
> between Jason and Richard on this.
>
> One thing is whether it is a good idea to keep this info in the IL
> as an attribute, especially when you add it automatically in the
> C++ FE.  I see e.g. 25 spare bits in tree_type_common.  Don't say we
> need to waste them, but I'd say in C++ unsigned char arrays are fairly
> common and thus not having to create the attribute for them each time
> and look it up might be beneficial.
>

Yes, but it is not clear if it will be available in LTO, for instance
we used to stream TYPE_ALIAS_SET == 0 information to let frontends mark
types that are opaque for TBAA.  This however did not work as intended,
because TYPE_ALIAS_SET == 0 was regularly lost in type merging.

But streaming an attribute works seamless, and is not lost in type
merging AFAICT.

> Also, wonder if you need to mark all types containing such arrays,
> if you couldn't just set that flag in C++ on unsigned char/std::byte
> arrays (and on anything with that attribute), have that imply alias set
> 0 on it and then let the rest of alias machinery handle aggregate types
> containing such fields.
>

Actually I set the flag only on C++ code with std::byte and
struct/union with embedded unsigned char or std::byte arrays,
but not on char arrays for instance, so I hope that it will
not pessimize the codegen too much.  The attribute does not
propagate from normal std::byte to the enclosing structure.

With LTO it is impossible to know which -std= option was used
and all C and C++ code is merged together.  So I was trying hard
to fin a way how it can work without breaking LTO.


Bernd.
Jakub Jelinek April 5, 2017, 3:29 p.m. UTC | #6
On Wed, Apr 05, 2017 at 03:27:20PM +0000, Bernd Edlinger wrote:
> Yes, but it is not clear if it will be available in LTO, for instance
> we used to stream TYPE_ALIAS_SET == 0 information to let frontends mark
> types that are opaque for TBAA.  This however did not work as intended,
> because TYPE_ALIAS_SET == 0 was regularly lost in type merging.
> 
> But streaming an attribute works seamless, and is not lost in type
> merging AFAICT.

Streaming flags on types works seamlessly too, if you add the 2-3x one-liner
changes in the streamer.  Just look at some other type flag and do the same
thing.

	Jakub
Bernd Edlinger April 5, 2017, 3:38 p.m. UTC | #7
On 04/05/17 17:23, Richard Biener wrote:
> On April 5, 2017 4:50:32 PM GMT+02:00, Florian Weimer <fweimer@redhat.com> wrote:

>> On 04/05/2017 11:46 AM, Bernd Edlinger wrote:

>>> +@item always_alias

>>> +@cindex @code{always_alias} type attribute

>>> +Same as @code{may_alias}, but additionally applies to instances of

>>> +types with this attribute.

>>

>> As a GCC user, I have to say that this doesn't really explain what the

>> attribute does.  The C standard does not define what an “instance” of a

>>

>> type is.

>

> I don't like the name.  I'd name it 'typeless_storage' and document that when storage is accessed with a type with this attribute it it behaves like a character type with respect to semantics.

>


you mean you like to name it __attribute__((typeless_storage)) ?

I wanted to say it behaves mostly like __attribute__((may_alias))
except that may_alias only has an effect on pointers and references
but not when accessing an object directly, (I hope you know what
I mean).


Bernd.


> Richard.

>

>>

>> Thanks,

>> Florian

>
Jonathan Wakely April 5, 2017, 4:03 p.m. UTC | #8
On 05/04/17 15:38 +0000, Bernd Edlinger wrote:
>On 04/05/17 17:23, Richard Biener wrote:
>> On April 5, 2017 4:50:32 PM GMT+02:00, Florian Weimer <fweimer@redhat.com> wrote:
>>> On 04/05/2017 11:46 AM, Bernd Edlinger wrote:
>>>> +@item always_alias
>>>> +@cindex @code{always_alias} type attribute
>>>> +Same as @code{may_alias}, but additionally applies to instances of
>>>> +types with this attribute.
>>>
>>> As a GCC user, I have to say that this doesn't really explain what the
>>> attribute does.  The C standard does not define what an “instance” of a
>>>
>>> type is.

Agreed.


>> I don't like the name.  I'd name it 'typeless_storage' and document that when storage is accessed with a type with this attribute it it behaves like a character type with respect to semantics.
>>
>
>you mean you like to name it __attribute__((typeless_storage)) ?
>
>I wanted to say it behaves mostly like __attribute__((may_alias))
>except that may_alias only has an effect on pointers and references
>but not when accessing an object directly, (I hope you know what
>I mean).

And may_alias is not a very helpful name either.

I much prefer Richi's suggestion of typeless_storage.

But I'm not convinced we need the attribute at all. If a struct
containing an array of std::byte or unsigned char has the property
already then that's good. I don't think we need a non-portable way to
make other types behave the same. If you can change the code to use a
new GCC attribute then you can change the code to use an array of
unsigned char, and be portable.
Jakub Jelinek April 5, 2017, 4:08 p.m. UTC | #9
On Wed, Apr 05, 2017 at 05:03:33PM +0100, Jonathan Wakely wrote:
> > I wanted to say it behaves mostly like __attribute__((may_alias))
> > except that may_alias only has an effect on pointers and references
> > but not when accessing an object directly, (I hope you know what
> > I mean).
> 
> And may_alias is not a very helpful name either.
> 
> I much prefer Richi's suggestion of typeless_storage.
> 
> But I'm not convinced we need the attribute at all. If a struct
> containing an array of std::byte or unsigned char has the property
> already then that's good. I don't think we need a non-portable way to
> make other types behave the same. If you can change the code to use a
> new GCC attribute then you can change the code to use an array of
> unsigned char, and be portable.

It will only work that way in C++ though, so if you want to achieve
the same in C, which doesn't have any special case for unsigned char
arrays nor std::byte, you need an attribute.

	Jakub
Bernd Edlinger April 5, 2017, 5:22 p.m. UTC | #10
On 04/05/17 18:08, Jakub Jelinek wrote:
> On Wed, Apr 05, 2017 at 05:03:33PM +0100, Jonathan Wakely wrote:
>>> I wanted to say it behaves mostly like __attribute__((may_alias))
>>> except that may_alias only has an effect on pointers and references
>>> but not when accessing an object directly, (I hope you know what
>>> I mean).
>>
>> And may_alias is not a very helpful name either.
>>
>> I much prefer Richi's suggestion of typeless_storage.
>>
>> But I'm not convinced we need the attribute at all. If a struct
>> containing an array of std::byte or unsigned char has the property
>> already then that's good. I don't think we need a non-portable way to
>> make other types behave the same. If you can change the code to use a
>> new GCC attribute then you can change the code to use an array of
>> unsigned char, and be portable.
>
> It will only work that way in C++ though, so if you want to achieve
> the same in C, which doesn't have any special case for unsigned char
> arrays nor std::byte, you need an attribute.
>

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.


Bernd.
Bernd Edlinger April 5, 2017, 5:41 p.m. UTC | #11
On 04/05/17 17:20, Richard Biener wrote:
>> Also, wonder if you need to mark all types containing such arrays,

>> if you couldn't just set that flag in C++ on unsigned char/std::byte

>> arrays (and on anything with that attribute), have that imply alias set

>> 0 on it and then let the rest of alias machinery handle aggregate types

>> containing such fields.

>

> Yes, I expected it to work like this (didn't look at the patch yet).

>


I want to allow *only* what the C++ standard requires or what Jason says
of course :), and not a single bit more, because it suppresses otherwise
correct optimizations.

So a struct with a std::byte member is not alias_set 0,
only the std::byte itself is, but an array of std::byte
is itself typeless_storage, and makes the whole structure
also typeless_storage, but that is not the usual way how
the alias machinery works, where such an attribute would not
propagate.  Currently I think the C++ FE can do the propagation
when the type is declared.  I would not imply that with the
typeless_storage attribute, because may_alias does not do that
either.


Bernd.
Jason Merrill April 5, 2017, 8:17 p.m. UTC | #12
On Wed, Apr 5, 2017 at 1:41 PM, Bernd Edlinger
<bernd.edlinger@hotmail.de> wrote:
> On 04/05/17 17:20, Richard Biener wrote:
>>> Also, wonder if you need to mark all types containing such arrays,
>>> if you couldn't just set that flag in C++ on unsigned char/std::byte
>>> arrays (and on anything with that attribute), have that imply alias set
>>> 0 on it and then let the rest of alias machinery handle aggregate types
>>> containing such fields.
>>
>> Yes, I expected it to work like this (didn't look at the patch yet).

My impression is that this is how GCC 6 worked, but GCC 7 decides to
ignore alias set 0 members.  Is that right?

> I want to allow *only* what the C++ standard requires or what Jason says
> of course :), and not a single bit more, because it suppresses otherwise
> correct optimizations.
>
> So a struct with a std::byte member is not alias_set 0,
> only the std::byte itself is, but an array of std::byte
> is itself typeless_storage, and makes the whole structure
> also typeless_storage

Well, only the array member, not the whole structure, but it may make
sense for GCC to treat the whole structure as such internally.

Jason
Bernd Edlinger April 5, 2017, 8:46 p.m. UTC | #13
On 04/05/17 22:17, Jason Merrill wrote:
> On Wed, Apr 5, 2017 at 1:41 PM, Bernd Edlinger

> <bernd.edlinger@hotmail.de> wrote:

>> On 04/05/17 17:20, Richard Biener wrote:

>>>> Also, wonder if you need to mark all types containing such arrays,

>>>> if you couldn't just set that flag in C++ on unsigned char/std::byte

>>>> arrays (and on anything with that attribute), have that imply alias set

>>>> 0 on it and then let the rest of alias machinery handle aggregate types

>>>> containing such fields.

>>>

>>> Yes, I expected it to work like this (didn't look at the patch yet).

>

> My impression is that this is how GCC 6 worked, but GCC 7 decides to

> ignore alias set 0 members.  Is that right?

>


This is how I always thought it worked, until Jakub pointed out that
it is documented differently:

@item may_alias
@cindex @code{may_alias} type attribute
Accesses through pointers to types with this attribute are not subject
to type-based alias analysis, but are instead assumed to be able to 
alias any other type of objects.
In the context of section 6.5 paragraph 7 of the C99 standard,
an lvalue expression dereferencing such a pointer is treated like
having a character type.

=> So nobody said anything about accesses without pointers.



>> I want to allow *only* what the C++ standard requires or what Jason says

>> of course :), and not a single bit more, because it suppresses otherwise

>> correct optimizations.

>>

>> So a struct with a std::byte member is not alias_set 0,

>> only the std::byte itself is, but an array of std::byte

>> is itself typeless_storage, and makes the whole structure

>> also typeless_storage

>

> Well, only the array member, not the whole structure, but it may make

> sense for GCC to treat the whole structure as such internally.

>



Yes, that is only as close as I can get in the moment.

It does the same as may_alias but additionally objects
declared with that type have alias set 0, I just don't
know if I have yet found the right words so that it can
be understood.  Based on the feedback I have now written:

+@item typeless_storage
+@cindex @code{typeless_storage} type attribute
+An object declared with a type with this attribute behaves like a
+character type with respect to aliasing semantics.



Bernd.
Pedro Alves April 5, 2017, 10:54 p.m. UTC | #14
On 04/05/2017 09:46 PM, Bernd Edlinger wrote:

> It does the same as may_alias but additionally objects
> declared with that type have alias set 0, I just don't
> know if I have yet found the right words so that it can
> be understood.  Based on the feedback I have now written:
> 
> +@item typeless_storage
> +@cindex @code{typeless_storage} type attribute
> +An object declared with a type with this attribute behaves like a
> +character type with respect to aliasing semantics.

I think including an example of what becomes valid with
such types but wouldn't be valid both without any
attribute and also with may_alias would help.

Thanks,
Pedro Alves
Richard Biener April 6, 2017, 7:23 a.m. UTC | #15
On Wed, 5 Apr 2017, Jason Merrill wrote:

> On Wed, Apr 5, 2017 at 1:41 PM, Bernd Edlinger
> <bernd.edlinger@hotmail.de> wrote:
> > On 04/05/17 17:20, Richard Biener wrote:
> >>> Also, wonder if you need to mark all types containing such arrays,
> >>> if you couldn't just set that flag in C++ on unsigned char/std::byte
> >>> arrays (and on anything with that attribute), have that imply alias set
> >>> 0 on it and then let the rest of alias machinery handle aggregate types
> >>> containing such fields.
> >>
> >> Yes, I expected it to work like this (didn't look at the patch yet).
> 
> My impression is that this is how GCC 6 worked, but GCC 7 decides to
> ignore alias set 0 members.  Is that right?

Yes, in GCC 6 an access via an aggregate type that had an alias-set zero
member was using alias-set zero.

So we'd re-instantiate that behavior for aggregates containing
a type marked with the proposed new flag.

> > I want to allow *only* what the C++ standard requires or what Jason says
> > of course :), and not a single bit more, because it suppresses otherwise
> > correct optimizations.
> >
> > So a struct with a std::byte member is not alias_set 0,
> > only the std::byte itself is, but an array of std::byte
> > is itself typeless_storage, and makes the whole structure
> > also typeless_storage
> 
> Well, only the array member, not the whole structure, but it may make
> sense for GCC to treat the whole structure as such internally.

Yes, it's the easiest way to implement the required behavior.  But
I wouldn't document it that way but clearly state that only the
marked member behaves so but that for the purpose of accesses via
a container type the standards access rules apply as if the member
is accessed with a character type.

Richard.
Jonathan Wakely April 6, 2017, 10:08 a.m. UTC | #16
On 05/04/17 20:46 +0000, Bernd Edlinger wrote:
>It does the same as may_alias but additionally objects
>declared with that type have alias set 0, I just don't
>know if I have yet found the right words so that it can
>be understood.  Based on the feedback I have now written:
>
>+@item typeless_storage
>+@cindex @code{typeless_storage} type attribute
>+An object declared with a type with this attribute behaves like a
>+character type with respect to aliasing semantics.

This says that an object behaves like a type, which is a category
error. Don't you mean that a type declared with this attribute behaves
like a character type w.r.t aliasing semantics?

Or an object of a type with this attribute behaves like an object of
character type w.r.t aliasing semantics.
diff mbox

Patch

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 always_alias type attribute.  */
+  if (lookup_attribute ("always_alias", 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 ("always_alias",
+					     TYPE_ATTRIBUTES (t)))
 		  {
 		    gcc_checking_assert (TYPE_STRUCTURAL_EQUALITY_P (t));
 		    t = TREE_TYPE (t);
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 },
+  { "always_alias",	      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 ("always_alias", 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 ("always_alias", TYPE_ATTRIBUTES (t)))
+    {
+      TYPE_ATTRIBUTES (t)
+	= tree_cons (get_identifier ("always_alias"),
+		     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 ("always_alias",
+				    TYPE_ATTRIBUTES (enumtype)))
+	    TYPE_ATTRIBUTES (enumtype)
+	      = tree_cons (get_identifier ("always_alias"),
+			   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,9 @@  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", "always_alias"};
 
-	  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/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 246678)
+++ gcc/doc/extend.texi	(working copy)
@@ -6656,6 +6656,11 @@  declaration, the above program would abort when co
 @option{-fstrict-aliasing}, which is on by default at @option{-O2} or
 above.
 
+@item always_alias
+@cindex @code{always_alias} type attribute
+Same as @code{may_alias}, but additionally applies to instances of
+types with this attribute.
+
 @item packed
 @cindex @code{packed} type attribute
 This attribute, attached to @code{struct} or @code{union} type
Index: gcc/testsuite/c-c++-common/attr-always-alias-1.c
===================================================================
--- gcc/testsuite/c-c++-common/attr-always-alias-1.c	(revision 0)
+++ gcc/testsuite/c-c++-common/attr-always-alias-1.c	(working copy)
@@ -0,0 +1,29 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall" } */
+
+typedef int T __attribute__((always_alias));
+
+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 always_alias.  */
+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/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 ("always_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 (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type))
+      || lookup_attribute ("always_alias", TYPE_ATTRIBUTES (to_type)))
     can_alias_all = true;
 
   /* In some cases, languages will have things that aren't a REFERENCE_TYPE