Re: [RFC] Proposal for tagged_by attribute to describe union discriminators

Richard Biener via Gcc <[email protected]> Tue, 28 Jul 2026 08:31:37 +0200
Newsgroups gmane.comp.gcc.devel
Message-ID <CAFiYyc1uc_jF+Qhu9tq3V8acOLz2ZRUP8yrK5rzc3oKgUDmNJw@mail.gmail.com>
On Tue, Jul 28, 2026 at 1:20=E2=80=AFAM Ashton Warner via Gcc <[email protected].=
org> wrote:
>
> On Thu, Jul 16, 2026 at 09:59:26AM +0200, Martin Uecker wrote:
> > Am Donnerstag, dem 16.07.2026 um 09:17 +1200 schrieb Ashton Warner via =
Gcc:
> > > Hello,
> > >
> > > I would like to discuss the possibility of adding a GCC attribute for
> > > describing tagged unions (discriminated unions) to improve static
> > > analysis diagnostics.
> > >
> > > The motivation is to allow programmers to explicitly describe a
> > > relationship between an enum discriminator and a union member. C has =
a
> > > common pattern of representing variants using a struct containing an
> > > enum and a union:
> > >
> > > enum num_type {
> > >   T_INT,
> > >   T_FLOAT,
> > > };
> > >
> > > struct number {
> > >   enum num_type type;
> > >
> > >   union {
> > >     int ival;
> > >     float fval;
> > >   };
> > > };
> > >
> > > I propose the GCC attribute __attribute__((tagged_by(...))) with the
> > > following syntax:
> > >
> > > tagged_by(discriminator, mapping-list)
> > >
> > > where:
> > >
> > > - discriminator is an identifier
> > > - mapping-list is a comma-separated list of one or more mappings.
> > > - Each mapping has the form:
> > >     (enumerator, union-member)
> > >
> > > For example:
> > >
> > > struct number {
> > >   enum num_type type;
> > >
> > >   union {
> > >     int ival;
> > >     float fval;
> > >   } __attribute__((tagged_by(type,
> > >     (T_INT, ival),
> > >     (T_FLOAT, fval)
> > >   )));
> > > };
> > >
> > > The mapping is intentionally explicit rather than inferred from the
> > > declaration order of enum values and union members. This avoids
> > > changing the meaning of the attribute if either the enum or union
> > > members are reordered.
> > >
> > > The attribute does not change the representation or runtime behaviour
> > > of the union. It provides additional information that GCC can use for
> > > diagnostics and static analysis.
> > >
> > > For example:
> > >
> > > struct number n;
> > >
> > > n.type =3D T_INT;
> > > n.fval =3D 1.0f;
> > >
> > > could produce a diagnostic because fval is not the member associated
> > > with the current discriminator value.
> > >
> > > The implementation should diagnose invalid mappings, such as an
> > > enumerator that is not part of the discriminator's enum type or a
> > > member that does not exist in the union.
> > >
> > > The attribute is intended to provide semantic information in a simila=
r
> > > way to existing attributes such as counted_by, where the compiler is
> > > given information about a relationship that already exists in the
> > > program.
> > >
> >
> > I agree with this proposal.  There is an existing enhancement
> > request: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D112840
> >
> > I like an attribute on the member more than the attribute on the
> > union type.
> >
> > > Open questions:
> > >
> > > - How should enumerators without an associated union member be
> > >   represented? One possibility is allowing a mapping without a member=
,
> > >   for example (T_UNKNOWN), to explicitly indicate that an enumerator
> > >   represents a valid discriminator state with no active union member.
> > >   Enumerators that are not mentioned in the attribute could then be
> > >   diagnosed.
> > > - Should diagnostics based on this attribute be implemented as part o=
f
> > >   existing warning infrastructure, -fanalyzer, or another analysis
> > >   pass?
> > > - Could this information be useful to future runtime checking tools?
> >
> > Yes, I think this would be useful for checking at run-time similar
> > to sanitizers.  This would be easy to implement.
> >
> > > - Are there existing GCC mechanisms that overlap with this
> > >   functionality?
> > > - Are there additional constraints or semantics that would be needed
> > >   for GCC to implement this attribute?
> >
> > The issue similar to counted_by are the exact semantics for when
> > the constraints are in effect relative to when the members are
> > accessed / changed.
> >
> > Martin
>
>
> > I agree with this proposal.  There is an existing enhancement
> > request: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D112840
> >
> > I like an attribute on the member more than the attribute on the
> > union type.
>
> This proposal looks interesting and more readable than my initial
> proposal. The one semantics that is missing from this proposal is a
> system to allow the user to be notified when a union field does not
> contain a tag, or when there is no field for a given enum value.
>
> Would an attribute that enables warning on these issues be achievable?
>
> An example of this attribute
>
> struct number {
>   enum num_type type;
>
>   union {
>     int ival __attribute__((guard(.type =3D=3D T_INT));

I also think that attributes on the individual fields are better, but possi=
bly
combined with an attribute on the union?

   union {
      int ival __attribute__(tag_value(T_INT));
      float fval __attribute__((tag_value(T_FLOAT));
   } __attribute__((tagged_by(type)));

?

In principle the QUAL_UNION facility would allow having different
tag members for different fields or even complex combined expressions
or constants.  Do we want/need

  union {
      int ival __attribute__(tag_value(T_INT));
      float fval __attribute__(tag_value(T_FLOAT));
      char pad[sizeof(union)] __attribute__((tag_default));
   } __attribute__((tagged_by(type)));

aka a fallback active element?  For QUAL_UNION it would be the
last member with a true qualifier.  The behavior when no field
is active isn't explicitly documented but you could read it to be
that the union is empty then.

>     float fval;
>   } __attribute__((warn_untagged));
> };
>
> Warning: union <anonymous> member 'fval' is untagged. <warn_untagged>
>
>
> Another example showing unused enum field
>
> struct number {
>   enum num_type type;
>
>   union {
>     int ival __attribute__((guard(.type =3D=3D T_INT));
>   } __attribute__((warn_untagged(enum num_type, T_UNKNOWN)));
> };
>
> Warning: union <anonymous> missing enum value 'T_FLOAT'. <warn_untagged>
>
>
> The above showing a warn_untagged that ignores the T_UNKNOWN value.
>
> The only issue I have with my current proposed syntax for warn_untagged
> would be that it would be complex with the syntax of the guard attribute
>
> Ashton