https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65892

--- Comment #32 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to James Kuyper Jr. from comment #31)
> (In reply to rguent...@suse.de from comment #29)
> > On Thu, 19 Apr 2018, jameskuyper at verizon dot net wrote:
> ...
> > > The relevant wording is "anywhere that a declaration of the completed 
> > > type of
> > > the union is visible.", so it's unambiguously the type, not the object, 
> > > which
> > > must be visible. A declaration of the completed type can be visible 
> > > without any
> > > objects of that type being visible, and that's sufficient for this rule to
> > > apply.
> > > 
> > > > ...  Must the access be performed
> > > > using the union object, or just the union type, or neither?
> > > 
> > > It says only that "it is permitted to inspect the common initial part"; it
> > > imposes no restrictions on how the inspection may be performed. Clearly,
> > > inspection through an lvalue of the union's type must be permitted, but 
> > > it is
> > > also permitted to use the more indirect methods which are the subject of 
> > > this
> > > bug report, simply because the standard says nothing to restrict the 
> > > permission
> > > it grants to the more direct cases.
> > 
> > Note I repeatedly said this part of the standard is just stupid.
> 
> As a judgement call, I reserve the right to disagree with you on that point,
> particularly if that judgement was based primarily on the following
> misconception:
> 
> > ...  It makes
> > most if not all type-based alias analysis useless.
> 
> How could that be true? It only applies to pairs of struct types that are
> the types of members of the same union, it only applies within the scope of
> a completed definition of that union's type, and it doesn't apply if the
> implementation can prove to itself that the two objects in question are not
> actually members of the same union object. It seems to me that the need to
> take this rule into consideration would come up pretty infrequently.

Elsewhere you said that "inspect the common initial part" needs to allow
accesses that do not make the union object visible.  So consider

struct A { int i; float f; };
struct B { int i; double e; };
union { struct A a; struct B b; };

struct B b;
struct A a;

int foo1 (struct A *p)
{
  return p->i; // GCC considers this to not alias 'b', but only 'a'
}

int foo2 (int *p)
{
  return *p; // GCC considers this to alias 'b' and 'a'
}

float foo3 (float *p)
{
  return *p; // GCC considers this to alias only 'a'
}

I guess foo3 is not allowed since 6.5.2.3p6 doesn't allow any type punning
since it only covers the common initial sequence.  We are too strict with
foo1 I guess, with our current implementation I can't see to make that
work without making *p alias 'b' as well.

Now consider

struct C { int i; };
union { struct A a; struct C; };

struct A a;
struct C c;

void foo (struct C *p)
{
  *p = c;
}

do we need to consider this to assign to 'a'?  As far as I read the
standard yes.  We don't handle that, and as I said above this would
mean C and A to have the same alias-set which means now float *
also aliases objects of type B and double * objects of type A.
It doesn't make float * alias double * of course, so it's not all
bets are off but it means that for a program using C++-like
inheritance via unions (like GCC for example does) you mostly
give up on TBAA.

> Code which relies upon this feature to implement a C-style approximation to
> inheritance has been fairly common, which is precisely why the C committee
> decided to create this rule, to make sure such code had well-defined
> behavior.
> 
> > Which means I'll refuse any patches implementing it in a way that affects
> > default behavior.  A clean patch (I really can't think of any clean 
> > approach besides forcing -fno-strict-aliasing!) with some extra flag
> > (well, just use -fno-strict-aliasing ...) would be fine with me.
> 
> I can understanding not making this the default behavior if you feel that
> way; I only use gcc in fully standard-conforming mode, anyway, so that
> doesn't matter to me. However, personally, I would prefer it if gcc's
> fully-conforming mode took full advantage of all the optimization
> opportunities legitimately enabled by 6.5p7 (which does not include
> opportunities revoked by 6.5.2.3p6).

As the examples above show and probably because of the limited TBAA
implementation in GCC honoring 6.5.2.3p6 comes at a cost.  I'm not
sure why 6.5.2.3p6 is necessary given 6.5.2.3p3 points to the footnote
95 which allows to do the inspection under the type-punning umbrella
if the access is made through the union type.

Reply via email to