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();
> > > +}
> > > +
> >