On Mon, Jan 5, 2026 at 9:00 AM Alejandro Colomar <[email protected]> wrote:
>
> Hi Aaron,
>
> On Mon, Jan 05, 2026 at 08:24:16AM -0500, Aaron Ballman wrote:
> > Back from vacation, a few comments below.
>
> Thanks!
>
> > On Wed, Dec 17, 2025 at 6:04 PM Alejandro Colomar <[email protected]> wrote:
> [...]
> > > > > [[fallthrough]] is an *aberration*.
> > > >
> > > > lol
> > > >
> > > > > It should have never been an
> > > > > attribute, because, as you see, it doesn't attribute anything.
> > > >
> > > > It is an attribute-declaration. See 6.7.1p1 and p10. This was done to
> > > > make the grammar a bit easier to understand, in C++ it's attributing a
> > > > null statement instead.
> > >
> > > Neither of them are good, indeed. That's a consequence of trying to fit
> > > an attribute into what really is a statement.
> >
> > Attributes can be applied to statements, so I fail to see what the
> > issue is here?
>
> That was part of the ad-hoc fitting process I'm critizising. Before
> [[fallthrough]], no other attributes could attribute a statement, right?
No *standard* attributes in C, yes. There are vendor attributes which
do (clang::musttail, etc) as well as C++ standard attributes which do
(likely, unlikely). Statement attributes have been a part of this
feature since day one.
> There was no prior art in any implementations before WG21 did that,
> I also suspect. Committee inventions tend to be bad, and this is no
> exception.
This is incorrect.
> > > > > fallthrough is a jump statement misusing the syntax of an attribute.
> > > >
> > > > Incorrect. It is not a jump statement, it has no semantic effect. See
> > > > 6.7.13.6
> > >
> > > It is not defined by the standard to be a jump statement, but we could
> > > perfectly define it as such if we wanted. And it would fit much better
> > > than "an attribute to the null statement" or "an attribute declaration".
> >
> > I don't agree; when we start making non-jumps into jumps, we
> > complicate things for no benefit (for example, we then have to think
> > about every place we put constraints on jumps and targets and decide
> > what to do with these non-jumps).
>
> Could you give an example where this could go wrong?
e.g., when discussing the defer TS, we decided that you cannot jump
into or out of a defer block but can jump within one. So is this now
jumping out of a defer block?
defer {
;
}
Obviously, it's not jumping out of a defer block but it's the kind of
thing we have start considering every time someone says "jump".
>
> > > > > It should have been 'fallthrough;', with syntax similar to 'continue;'
> > > > > et al.. What it does is best described as "jump to the next 'case'",
> > > > > with a constraint that the statement must be the last statement at the
> > > > > top-level of a 'case'.
> > > >
> > > > No, it really does not. It's a hint to the compiler saying "the
> > > > semantics of this code is intended". It's not a jump to the next case
> > > > in the same way that a semi colon is not a jump to the next statement;
> > > > it's following the flow of execution laid out by the abstract machine.
> > >
> > > It is a jump statement, just like a return statement at the end of a
> > > function that return void is a jump statement, or a continue statement
> > > at the end of a loop is a jump statement too.
> >
> > Jump statements emit branching instructions, fallthrough (and semi
> > colons) do not.
>
> This isn't true. Here's a counter-example:
>
> #include <stdio.h>
> int
> main(int argc, char *[])
> {
> switch(argc) {
> default:
> puts("foo");
> break;
> }
> puts("bar");
> return 0;
> }
>
> 'break' is a jump statement, and there's no branching instruction.
>
> That's because branching instructions are an implementation detail that
> isn't inherent to the abstract machine.
>
> A jump statement is defined as
> "A jump statement causes an unconditional jump to another place"
>
> And that's exactly what a jump statement does; no more, no less.
>
> Consider a hypothetical C dialect that decided to switch the default
> behavior of switch so that if you don't say anything you'd break out of
> the switch. Then, 'fallthrough' would --within the abstract machine--
> be clearly a jump statement, as it unconditionally jumps to a place
> where by default the code wouldn't go. The fact that when translating
> to assembly you'll use branching instructions or not is irrelevant.
>
> Admittedly, that example would be unlikely, but you could consider
> a more realistic C dialect that decided that a case without an explicit
> fallthrough or break would be a constraint violation. That is, there
> would be no natural behavior for a case, and it should always be
> explicitly requested. This is actually implemented by both GCC (and
> I suppose Clang too) as '-Wimplicit-fallthrough=5'.
>
> In the abstract machine corresponding to the '-Wimplicit-fallthrough=5'
> dialect, fallthrough is clearly a jump statement, as it jumps to a place
> that you'd otherwise not reach as part of the abstract machine.
>
> > > Both of those have no
> > > semantics, and you can remove them without consequences; the difference
> > > is that fallthrough is constrained to never have semantics.
> > >
> > > [...]
> > >
> > > > > I'm working on a proposal to fix attributes (see below) so that
> > > > > they're
> > > > > not comments anymore. Aaron seems to be okay with that proposal.
> > > >
> > > > I have no idea where you got that impression,
> > >
> > > You and I discussed it in Brno (not in the meetings, but in the
> > > corridors).
> > >
> > > > but it's not something
> > > > I'm okay with; I think your proposal is an overreach into
> > > > implementation QoI.
> > > [...]
> > >
> > > I don't understand why now you claim that you're not okay with it.
> > > Also, I don't agree that transforming UB into a constraint violation is
> > > somehow an overreach into QoI.
> >
> > I am at a loss for where the confusion came from, I've *always* been
> > adamant about the design principle that standard attributes are hints
> > to the compiler and never anything more.
>
> And I don't intend to change that with this proposal.
>
> > (Note: implementation-defined
> > attributes are not standard attributes, those are expected to do
> > anything and everything an implementation desires.) That's been a
> > principle of the feature since it was introduced into C++11. I know
> > WG21 has tried to undo that with p2552r3, but that paper didn't
> > actually change the status quo with its wording (and consequently,
> > Clang isn't changing the implementation either; we're quite happy with
> > our implementation and we have downstreams which rely on it).
>
> My proposal, as discussed with you, is to add a mandatory diagnostic
> (contraint violation) about the presence of unrecognized attributes.
> Nothing else.
And that's what I'm opposed to. :-)
>
> This indeed matches the default behavior of both GCC and Clang, and
> I expect to also match every other quality compiler.
>
> alx@devuan:~/tmp$ cat attr.c
> [[attr]]
> int
> main(void)
> {
> return 0;
> }
> alx@devuan:~/tmp$ gcc attr.c
> attr.c:1:1: warning: ‘attr’ attribute ignored [-Wattributes]
> 1 | [[attr]]
> | ^
> alx@devuan:~/tmp$ clang attr.c
> attr.c:1:3: warning: unknown attribute 'attr' ignored
> [-Wunknown-attributes]
> 1 | [[attr]]
> | ^~~~
> 1 warning generated.
>
> And in compilers that don't want to implement any attributes, it should
> be trivial to emit a diagnostic saying "Attributes are not supported".
>
> Is that okay to you?
No, for a few reasons.
1) Different vendors have different pressures and so just because
Clang and GCC decided to diagnose this case does not mean everyone
should be required to diagnose this case.
2) A constraint violation means something very different and I do not
think you want us to go down the route you're taking us -- we've
worked hard to change perception to be that a constraint violation is
an error whenever possible and not just "emit any old diagnostic".
e.g., the standard is telling you that your code is wrong. Not "I wish
you'd write it another way", but "this should not translate into
semantics for the abstract machine" kind of wrong. If you don't want
these to be errors, constraint violation is the wrong tool for the job
and recommended practice is a better way to go.
3) Attributes are useful for forward compatibility and diagnosing
unknown ones can be an annoyance to users in practice. Currently, the
only tools users have to control those diagnostics is to turn off
diagnostics for *all* unknown attributes. Clang tried designing a -W
flag that would work well to let you selectively disable diagnostics;
the idea died on the vine because it's actually challenging to design
a usable command line flag for that when you consider `-Wno-` variants
so we don't even have tools in the compiler to make your suggestion
less frustrating in practice.
~Aaron
>
> > WG21 added an attribute that was not a hint to the compiler and it has
> > been a mess that implementations are still dealing with five+ years
> > later; I do not support following down the same path for C.
> >
> > ~Aaron
>
> Have a lovely New Year!
> Alex
>
> --
> <https://www.alejandro-colomar.es>