On 7/8/26 3:29 PM, Jakub Jelinek wrote:
On Wed, Jul 08, 2026 at 08:27:12PM +0200, Jakub Jelinek wrote:
On Wed, Jul 08, 2026 at 02:08:38PM -0400, Jason Merrill wrote:
--- gcc/testsuite/g++.dg/cpp0x/attr-trivial_abi8.C.jj 2026-07-08
18:49:01.145455196 +0200
+++ gcc/testsuite/g++.dg/cpp0x/attr-trivial_abi8.C 2026-07-08
18:49:23.583166926 +0200
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++11 } }
+
+#if __has_cpp_attribute (clang::trivial_abi) != 1
+#error
+#endif
+#if __has_cpp_attribute (gnu::trivial_abi) != 0
+#error
+#endif
+#if __has_cpp_attribute (trivial_abi) != 1
+#error
+#endif
This answer seems clearly wrong, since [[trivial_abi]] doesn't work. I'd
prefer expecting 0 and xfail.
I know, but unfortunately __has_cpp_attribute and __has_attribute
behave identically in C++.
In C __has_attribute (identifier) tests __attribute__((identifier))
or [[identifier]] support and __has_c_attribute (identifier)
tests [[identifier]] only and both with scoped attributes test
[[scope::identifier]].
But I'm not sure it isn't too late to change this when both C++ forms
behaved the same way since GCC 5.1, so 11 years in the wild.
I expect that the vast majority of uses distinguish properly between the
two forms, i.e. __has_attribute for __attribute__(()) and
__has_cpp_attribute for [[]]].
A quick look at grep.app seems to support this; the only incorrect uses
I see are in the GCC testsuite (and this patch would add more).
And the behavior above violates https://eel.is/c++draft/cpp.cond#5 . Of
course the standard doesn't say anything about the __has_attribute
extension.
As a transition measure we could warn about using the wrong __has for an
attribute.
There is a way to differentiate what can be accepted as [[identifier]]
even in C++, if __has_cpp_attribute results in 1, it is the __attribute__
form, if it is >= 2 (or >= 200809, there is nothing in between), then
it is [[identifer]].
And it is even documented like that.
The special operator @code{__has_cpp_attribute (@var{operand})} may be used
in @samp{#if} and @samp{#elif} expressions in C++ code to test whether
the attribute referenced by its @var{operand} is recognized by GCC.
@code{__has_cpp_attribute (@var{operand})} is equivalent to
@code{__has_attribute (@var{operand})} except that when @var{operand}
designates a supported standard attribute it evaluates to an integer
constant of the form @code{YYYYMM} indicating the year and month when
the attribute was first introduced into the C++ standard.
The "except that when @var{operand} ... " part is misleading because
__has_attribute behaves exactly like that too.
Looking at clang++, that behaves differently, doesn't allow scoped
attributes in __has_attribute at all (just __has_cpp_attribute and
__has_c_attribute) and __has_cpp_attribute (trivial_abi) is 0
and __has_attribute (trivial_abi) is 1.
Yes, that's the behavior I would expect.
And for this patch I'm just asking that we not test for the wrong answer.
Jason