Date: Tue, 10 Feb 2026 17:13:30 +0100
On 10/02/2026 16:21, Alejandro Colomar wrote:
> Hi David,
>
> On 2026-02-10T15:47:12+0100, David Brown wrote:
> [...]
>>>> [[comp::attr]]
>>>> Ignorable or non-ignorable according to the implementation (with the
>>>> recommendation that it is ignorable by default but that the compiler provide
>>>> a flag to make it non-ignorable).
>>>>
>>>> [[[comp::attr]]]
>>>> Non-ignorable. If a compiler cannot support this in the manner intended by
>>>> the "comp" compiler, it is a fatal error.
>>>>
>>>> [[(comp::attr)]]
>>>> Ignorable. Compilers are encouraged to provide a warning if they are the
>>>> owner of the "comp" namespace and do not recognise "attr".
>>>>
>>>> [[[comp1::attr1 || comp2::attr2 || ... ]]]
>>>> Non-ignorable. Compilers must support and apply one of these attributes,
>>>> but may choose which. If they cannot support any, it is a fatal error. For
>>>> example, [[[gnu::always_inline || msvc::forceinline]]]
>>>>
>>
>> You did not comment on this syntax, which I think is the most significant
>> new idea in my post. Do you like this idea, or do you have a better
>> alternative?
>
> That feature exists:
>
> #if __has_c_attribute(gnu::packed)
> # define PACKED gnu::packed
> #else if __has_c_attribute(foo::packed)
> # define PACKED foo::packed
> #else
> # error "No support for a packed attribute"
> #endif
>
> [[PACKED]] void f(void);
>
> I agree that || would be nice for this. I'd make it
>
> [[gnu::packed || foo::packed]]
>
> without a third '['
>
(The third [ was for consistency with user indication that the attribute
should not be ignorable, but that's an orthogonal point.)
>>
>>>> [[(comp1::attr1 || comp2::attr2 || ... )]]
>>>> The compiler can apply its choice of one of these attributes, but can ignore
>>>> them all.
>>>
>>> I think it's a bad idea to allow programmers to decide about the
>>> ignorability of language features. Ignorability of a feature should be
>>> part of the feature itself. What would it mean to do
>>>
>>> [[(gnu::packed)]]
>>>
>>> ? That's an ABI-breaking attribute, and ignoring it will result in
>>> bugs.
>>>
>>
>> We can't legislate against programmers doing something stupid! And we
>> certainly should not limit their abilities to make useful choices just
>> because some people might do something silly - at least not when it requires
>> an active choice such as this syntax requires. We should of course try to
>> reduce the risk of accidental mistakes (which is a big reason, IMHO, that
>> making "[[no_discard]]" ignorable is a terrible mistake - an accidental
>> misspelling of a language feature should result in an error message, not be
>> quietly discarded).
>>
>> But I think it would be fine for both the C++ standard and compiler
>> documentation for namespace attributes to say that certain attributes cannot
>> be ignored. If that applied to "gnu::packed", then "[[(gnu::packed)]]"
>> would be an error. But programmers should be allowed to mark an attribute
>> like "gnu::cold" as ignorable because it does not affect the semantics of
>> the program in any way.
>>
>>> I prefer keeping all vendor attributes non-ignorable, and close the door
>>> to ignorable vendor attributes. Then, if we want standard non-ignorable
>>> ones, let's just specify a standard "vendor"; that could be the empty
>>> prefix ::, or maybe std::.
>>>
>>
>> There are lots of vendor attributes that can be used today, and that would
>> be safe to ignore. I prefer to say that if an attribute is not ignorable
>> (either because the user has used [[[ ]]], or because the it is documented
>> as never ignorable) then it cannot be ignored by /any/ compiler. That
>> requirement puts a lot of pressure on compiler implementations, and I think
>> it is best to relieve that pressure by allowing attributes to be ignorable
>> when the user knows that is safe.
>
> That feature exists:
>
> #if __has_c_attribute(gnu::cold)
> # define COLD gnu::cold
> #else
> # define COLD
> #endif
>
> [[COLD]] void f(void);
>
> I don't see a need for a new spelling.
> I don't see a need to ignorable attributes.
>
>
> Cheers,
> Alex
>
While that is all true, it defeats the point of attributes (at least
non-standard attributes) in the first place. After all, why support
[[gnu::cold]] or [[msvc::cold_func]] (if that existed) format when you
could have simply written :
#if defined(__GNUC__)
# define COLD __attribute__((cold))
#elif defined(_MSC_VER)
# define COLD _declspec(cold_func)
#else
# define COLD
#endif
COLD void f(void);
Compiler-check conditional compilation and conditional macro definitions
are horrible. Conditional compilation and macro definitions based on
feature checks are marginally less horrible, but only marginally so.
Both can be very useful, but you don't want to have to use them except
in rare and unusual cases. It is far better to be able to write :
[[gnu::cold, msvc::cold_func]] void f(void);
and skip the pre-processor stuff. Even better, IMHO, would be to be
able to write :
[[[gnu::cold || msvc::cold_func]]] void f(void);
and know that the compiler will complain if it can't make the function
cold in one way or the other.
Good language syntax decisions make it easy to write common constructs,
middle-of-the-road convenience for rare constructs, and don't care if it
is awkward or verbose for very niche cases. We want keywords for things
people want often, attributes for things that turn up occasionally, and
can leave ugly conditional compilation for rarities or when compiler
developments are ahead of language standardisation.
> Hi David,
>
> On 2026-02-10T15:47:12+0100, David Brown wrote:
> [...]
>>>> [[comp::attr]]
>>>> Ignorable or non-ignorable according to the implementation (with the
>>>> recommendation that it is ignorable by default but that the compiler provide
>>>> a flag to make it non-ignorable).
>>>>
>>>> [[[comp::attr]]]
>>>> Non-ignorable. If a compiler cannot support this in the manner intended by
>>>> the "comp" compiler, it is a fatal error.
>>>>
>>>> [[(comp::attr)]]
>>>> Ignorable. Compilers are encouraged to provide a warning if they are the
>>>> owner of the "comp" namespace and do not recognise "attr".
>>>>
>>>> [[[comp1::attr1 || comp2::attr2 || ... ]]]
>>>> Non-ignorable. Compilers must support and apply one of these attributes,
>>>> but may choose which. If they cannot support any, it is a fatal error. For
>>>> example, [[[gnu::always_inline || msvc::forceinline]]]
>>>>
>>
>> You did not comment on this syntax, which I think is the most significant
>> new idea in my post. Do you like this idea, or do you have a better
>> alternative?
>
> That feature exists:
>
> #if __has_c_attribute(gnu::packed)
> # define PACKED gnu::packed
> #else if __has_c_attribute(foo::packed)
> # define PACKED foo::packed
> #else
> # error "No support for a packed attribute"
> #endif
>
> [[PACKED]] void f(void);
>
> I agree that || would be nice for this. I'd make it
>
> [[gnu::packed || foo::packed]]
>
> without a third '['
>
(The third [ was for consistency with user indication that the attribute
should not be ignorable, but that's an orthogonal point.)
>>
>>>> [[(comp1::attr1 || comp2::attr2 || ... )]]
>>>> The compiler can apply its choice of one of these attributes, but can ignore
>>>> them all.
>>>
>>> I think it's a bad idea to allow programmers to decide about the
>>> ignorability of language features. Ignorability of a feature should be
>>> part of the feature itself. What would it mean to do
>>>
>>> [[(gnu::packed)]]
>>>
>>> ? That's an ABI-breaking attribute, and ignoring it will result in
>>> bugs.
>>>
>>
>> We can't legislate against programmers doing something stupid! And we
>> certainly should not limit their abilities to make useful choices just
>> because some people might do something silly - at least not when it requires
>> an active choice such as this syntax requires. We should of course try to
>> reduce the risk of accidental mistakes (which is a big reason, IMHO, that
>> making "[[no_discard]]" ignorable is a terrible mistake - an accidental
>> misspelling of a language feature should result in an error message, not be
>> quietly discarded).
>>
>> But I think it would be fine for both the C++ standard and compiler
>> documentation for namespace attributes to say that certain attributes cannot
>> be ignored. If that applied to "gnu::packed", then "[[(gnu::packed)]]"
>> would be an error. But programmers should be allowed to mark an attribute
>> like "gnu::cold" as ignorable because it does not affect the semantics of
>> the program in any way.
>>
>>> I prefer keeping all vendor attributes non-ignorable, and close the door
>>> to ignorable vendor attributes. Then, if we want standard non-ignorable
>>> ones, let's just specify a standard "vendor"; that could be the empty
>>> prefix ::, or maybe std::.
>>>
>>
>> There are lots of vendor attributes that can be used today, and that would
>> be safe to ignore. I prefer to say that if an attribute is not ignorable
>> (either because the user has used [[[ ]]], or because the it is documented
>> as never ignorable) then it cannot be ignored by /any/ compiler. That
>> requirement puts a lot of pressure on compiler implementations, and I think
>> it is best to relieve that pressure by allowing attributes to be ignorable
>> when the user knows that is safe.
>
> That feature exists:
>
> #if __has_c_attribute(gnu::cold)
> # define COLD gnu::cold
> #else
> # define COLD
> #endif
>
> [[COLD]] void f(void);
>
> I don't see a need for a new spelling.
> I don't see a need to ignorable attributes.
>
>
> Cheers,
> Alex
>
While that is all true, it defeats the point of attributes (at least
non-standard attributes) in the first place. After all, why support
[[gnu::cold]] or [[msvc::cold_func]] (if that existed) format when you
could have simply written :
#if defined(__GNUC__)
# define COLD __attribute__((cold))
#elif defined(_MSC_VER)
# define COLD _declspec(cold_func)
#else
# define COLD
#endif
COLD void f(void);
Compiler-check conditional compilation and conditional macro definitions
are horrible. Conditional compilation and macro definitions based on
feature checks are marginally less horrible, but only marginally so.
Both can be very useful, but you don't want to have to use them except
in rare and unusual cases. It is far better to be able to write :
[[gnu::cold, msvc::cold_func]] void f(void);
and skip the pre-processor stuff. Even better, IMHO, would be to be
able to write :
[[[gnu::cold || msvc::cold_func]]] void f(void);
and know that the compiler will complain if it can't make the function
cold in one way or the other.
Good language syntax decisions make it easy to write common constructs,
middle-of-the-road convenience for rare constructs, and don't care if it
is awkward or verbose for very niche cases. We want keywords for things
people want often, attributes for things that turn up occasionally, and
can leave ugly conditional compilation for rarities or when compiler
developments are ahead of language standardisation.
Received on 2026-02-10 16:13:36
