Am Dienstag, dem 02.06.2026 um 10:29 +0200 schrieb Richard Biener:
> On Mon, 25 May 2026, Martin Uecker wrote:
> 
> > 
> > 
> > Any comments about this?  
> > 
> > The fix would need to be backported to 15 and 16.
> > 
> > Martin
> > 
> > Am Montag, dem 11.05.2026 um 18:20 +0200 schrieb Martin Uecker:
> > > So, annoyingly, I got this wrong.
> > > 
> > > Bootstrapped and regression tested on x86_64.
> > > 
> > > Best,
> > > Martin
> > > 
> > > 
> > >     c23: fix TBAA error for function returning structure [PR125252]
> > >     
> > >     To fix PR122572 we globbed pointers to structure or union types nested
> > >     within other structure or union types to a void pointer when computing
> > >     the TYPE_CANONICAL.  But when doing this for function return types 
> > > this
> > >     then leads to wrong aliasing decisions, because for some reason 
> > > function
> > >     derivation behaves differently than pointer and array derivation.  
> > > Instead
> > >     of globbing to void, replace the nested structure or union type with 
> > > an
> > >     incomplete type instead.
> > >     
> > >             PR c/124252
> > >     
> > >     gcc/c/ChangeLog:
> > >     
> > >             * c-typeck.cc (ptr_to_tagged_member): Return type of member.
> > >             (c_type_canonical): Use incomplete type.
> > >     
> > >     gcc/testsuite/ChangeLog:
> > >     
> > >             * gcc.dg/pr125252.c
> > > 
> > > diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
> > > index 6195d179543..3ffeed73d8c 100644
> > > --- a/gcc/c/c-typeck.cc
> > > +++ b/gcc/c/c-typeck.cc
> > > @@ -579,8 +579,9 @@ c_reconstruct_complex_type (tree type, tree bottom)
> > >  
> > >  /* Helper function for c_canonical_type.  Check whether FIELD
> > >     contains a pointer to a structure or union with tag,
> > > -   possibly nested in other type derivations.  */
> > > -static bool
> > > +   possibly nested in other type derivations, and return the
> > > +   type of this nested structure or union.  */
> > > +static tree
> > >  ptr_to_tagged_member (tree field)
> > >  {
> > >    gcc_assert (FIELD_DECL == TREE_CODE (field));
> > > @@ -598,17 +599,17 @@ ptr_to_tagged_member (tree field)
> > >    if (ptr_seen
> > >        && RECORD_OR_UNION_TYPE_P (type)
> > >        && NULL_TREE != c_type_tag (type))
> > > -    return true;
> > > +    return type;
> > >  
> > > -  return false;
> > > +  return NULL_TREE;
> > >  }
> > >  
> > >  /* For a record or union type, make necessary adaptations so that the
> > >     type can be used as TYPE_CANONICAL.
> > >  
> > >     If the TYPE contains a pointer (possibly nested in other type
> > > -   derivations) to a structure or union as a member, create a copy
> > > -   and change such pointers to void pointers.  Otherwise, the middle-end
> > > +   derivations) to a structure or union as a member, create a copy and
> > > +   change the nested type to an incomplete type.  Otherwise, the 
> > > middle-end
> > >     gets confused when recording component aliases in the case where we
> > >     have formed equivalency classes that include types for which these
> > >     member pointers end up pointing to other structure or unions types
> > > @@ -635,9 +636,15 @@ c_type_canonical (tree type)
> > >    for (tree x = TYPE_FIELDS (type); x; x = DECL_CHAIN (x))
> > >      {
> > >        tree f = copy_node (x);
> > > -      if (ptr_to_tagged_member (x))
> > > - TREE_TYPE (f) = c_reconstruct_complex_type (TREE_TYPE (x),
> > > -                                             ptr_type_node);
> > > +      if (tree m = ptr_to_tagged_member (x))
> 
> I'm not sure how this constrains 'm', so does
> 
> > > + {
> > > +   tree new_node = make_node (TREE_CODE (m));
> 
> this possibly lose some important bits of 'm' that you do not set below?
> 
> Other than that it looks consistent on what you do (and you understand
> it better than me).  I usually do not want to get into approving
> C language frontend changes though ...

Removing information is the point.  While my understanding of 
what the middle-end does gets better it is still possible that
I miss something, but I do not see what other information might
be important here.

I also noticed now that the original fix was buggy also because
it should have used void_type_node instead of ptr_type_node
above, so I could try whether this is also sufficient to fix the
problem with the original fix. But using an incomplete type is
closer to what one wants.

Martin

> 
> Richard.
> 
> > > +   TYPE_NAME (new_node) = TYPE_NAME (m);
> > > +   SET_TYPE_STRUCTURAL_EQUALITY (new_node);
> > > +   new_node = qualify_type (new_node, m);
> > > +   TREE_TYPE (f) = c_reconstruct_complex_type (TREE_TYPE (x),
> > > +                                               new_node);
> > > + }
> > >        *fields = f;
> > >        fields = &DECL_CHAIN (f);
> > >      }
> > > diff --git a/gcc/testsuite/gcc.dg/pr125252.c 
> > > b/gcc/testsuite/gcc.dg/pr125252.c
> > > new file mode 100644
> > > index 00000000000..4e27fa15978
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.dg/pr125252.c
> > > @@ -0,0 +1,36 @@
> > > +/* { dg-do run } */
> > > +/* { dg-options "-std=gnu23 -O2" } */
> > > +
> > > +
> > > +int k;
> > > +struct S {};
> > > +
> > > +#define T struct S
> > > +
> > > +T *get_sender () {
> > > +  k = 1;
> > > +  return (void *)0;
> > > +}
> > > +
> > > +T *get_cc () { }
> > > +
> > > +void test () {
> > > +        struct {
> > > +                T *(*get_header) (void);
> > > +        } reply_to_map[] = {
> > > +                { get_sender },
> > > +                { get_cc },
> > > +        };
> > > +
> > > +        for (int i = 0; i < 2; i++) {
> > > +                asm ("" ::"r"(reply_to_map[i].get_header ()));
> > > +        }
> > > +}
> > > +
> > > +int main() {
> > > +        test ();
> > > +
> > > +        if (k != 1)
> > > +            __builtin_abort();
> > > +}
> > > +
> > 

Reply via email to