[RFC] Enable C++11/C2x attributes in all standard modes as an extension and remove `-fdouble-square-bracket-attributes`

Currently, C++11/C2x attributes (I’ll just call them C++ attributes) can be enabled via -fdouble-square-bracket-attributes in all language modes. This flag was introduced in 606093a, but seems to be basically unused in the wild [1].

A problem with this approach is that libraries cannot rely on the extension actually being present, so it’s not really possible to make use of the extension for them. It’s also basically impossible to disabling C++ attributes in C++11 and later, since every major standard library makes wide use of C++ attributes. While this is not a problem for C currently, this will most likely become one in the future.

That the flag is basically never used would suggest that it’s a good idea to just remove it, but I think the better thing to do would be to enable the extension unconditionally. Doing this will not break any users, since it’s a conforming extension and anybody who uses the flag to enable C++ attributes currently just gets them instead. This also allows libraries like libc++ to rely on the C++ attribute syntax being available, making it possible to simplify some code. Making C++ attributes available in all language modes simplifies the clang code a bit as well, since the language mode doesn’t have to be checked anymore. Another benefit is that diagnostics are better because a warning that you’re using an extension is emitted instead of complaining about unexpected tokens.

This would also allow Clang to stop using the GNU attribute syntax for newly introduced attributes, making it easier to distinguish between Clang and GCC extensions, and allowing access to clang statement attributes like [[clang::always_inline]] which are currently not possible use in C++03/before C2x.

The implementation of this can be seen in ⚙ D151683 [clang] Enable C++11-style attributes in all language modes.

[1] context:global -fdouble-… - Sourcegraph

CC @AaronBallman @erichkeane


Libraries still cannot rely on the extension because nobody implements this as an extension in all language modes (at least, last time I checked). Updating __cpp_attributes will help library folks in C++ know whether the extension is supported or not, as that’s standardized. But what’s the plan for C folks (we don’t have standardized feature testing macros in C)? I think we could probably add a __has_extension entry for C, analogous to __has_extension(cxx_attributes). WDYT?

I’m in support of this idea. I think we should enable the extension unconditionally for Clang 17 with a release note mentioning that -fdouble-square-bracket-attributes will be removed in Clang 18 just as a kindness to users with proprietary code bases that might be using it.

Eh, not quite. New attributes added to Clang should be using the Clang spelling, which includes both a GNU- and a C+±style spelling. There are still a few cases where we only expose the attribute as a GNU spelling or under a different vendor namespace with a C+±style spelling, but those are one-offs.

I’m a bit confused what you mean. If we implement it unconditionally in all language modes, libraries will be able to rely on it being present (assuming the library only supports clang).

I think it would be a good idea to get FTMs in C, but for the time being, __has_externsion(cxx_attributes) sounds good.

That’s fine with me. We should probably also mention there that the flag doesn’t do anything anymore?

This was more of a possible path forward anyways, but what exactly would prevent us from not adding new GNU spellings (other than cases where it’s not possible to implement a given attribute with a C+±style spelling)? It seems like a good idea to me to avoid claiming meaning for attributes which aren’t actually available in GCC.

Sorry, that was probably me being biased. :slight_smile: When I hear “library”, I assume it means “portable across multiple compilers” by default.

For C++ that works, but we should add c_attributes for the C variant (if only because __has_c_attribute and __has_cpp_attribute are separate, alas).

Yup, that’s a good idea!

__attribute__ no longer means “supported by GCC” (and hasn’t for quite a few years); we’ve diverged in our support for both the syntactic locations where the attribute specifier can be used and in what attributes we support. However, it is still a shared namespace between multiple compilers and so we make efforts not to give a significantly different meaning to an attribute that already exists with that name in GCC (as opposed to slight semantic differences, which do come up from time to time).

Ah OK. That makes sense. Although, any library that supports clang and MSVC would also benefit from this, since (AFAIK) MSVC only supports C++14-and-later. NVC++ and ICC also support C++ attributes in C++03: Compiler Explorer

Right. Do you think we should add __has_extension(c_attributes) and __has_extension(cxx_attributes) for C and C++ respectively, or is the FTM for C++ enough?

I get that __attribute__ doesn’t mean “supported by GCC”, but why does clang want to add clang-specific attributes in that namespace? I simply don’t see the benefit of adding an attribute spelling if it’s not portable to any other compiler anyways.

We already have __has_extension(cxx_attributes), so we’d just need the C variant: Compiler Explorer

Sometimes we’re forced to due to syntactic requirements. As an example, enable_if and diagnose_if need to be GNU attributes because there’s no way to add them as a declaration attribute that can refer to function parameters. Sometimes it’s because we’re forced to due to third party specifications (like some CUDA attributes). That’s really the two big reasons why.