[clang] d930ed1 - Disallow use of __has_c_attribute in C++ mode.

James Y Knight via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 28 10:49:20 PST 2020


On Fri, Feb 28, 2020 at 11:42 AM Arthur O'Dwyer <arthur.j.odwyer at gmail.com>
wrote:

> On Fri, Feb 28, 2020 at 11:23 AM James Y Knight via cfe-commits <
> cfe-commits at lists.llvm.org> wrote:
>
>> On Fri, Feb 28, 2020 at 10:05 AM Aaron Ballman <aaron at aaronballman.com>
>> wrote:
>>
>>> On Thu, Feb 27, 2020 at 6:04 PM James Y Knight <jyknight at google.com>
>>> wrote:
>>> >
>>> > But, even with all that, I'm not sure why we shouldn't implement both
>>> __has_cpp_attribute AND __has_c_attribute in C++ mode?
>>> >
>>> > The subset of C attributes which retain their C-defined semantics in
>>> C++ (which, hopefully, is all of them, but doesn't need to be) should
>>> return the appropriate C-standard date with which the (C++ mode)
>>> implementation is compatible. That is, in -std=c++11, we may have
>>> __has_cpp_attribute(deprecated) == 201309, while
>>> __has_c_attribute(deprecated) == 2020XXYY.
>>>
>>> If I'm understanding you properly, then I think that this leads to
>>> some strange (to me, at least) behavior. We have some attributes that
>>> are C only attributes, some attributes that are C++ only, but most of
>>> the attributes are supported in both C and C++ with the same
>>> semantics. For the attributes that are in both C and C++, what you
>>> suggest makes sense. For the attributes that exist only in one
>>> language, I'm less convinced. It would be weird for
>>> __has_c_attribute(gnu::transparent_union) (which is a C-only
>>> attribute) to report true in C and false in C++ because we do support
>>> that C attribute.
>>
>>
>> That doesn't seem strange to me at all. it will correctly report that we
>> do not support the C attribute *in the current compilation context*.
>> These builtins should always be reporting whether the attribute feature is
>> usable in the current compilation mode, not whether it might theoretically
>> be usable with some other different set of compiler flags.
>>
>> It'd be the same if we decide to only support C++74's [[frobnlezotz]]
>> attribute when you compile code with the -std=c++74 flag. We should then
>> return 0 from __has_cpp_attribute(frobnlezotz) when the code is compiled
>> with -std=c++42.
>>
>
> That's an argument to support only `__has_attribute`, right?  The compiler
> is never in both C and C++ modes simultaneously.  Furthermore, if it is in
> C mode, then it doesn't know what to return for `__has_cpp_attribute`
> because it doesn't know if it's "not in C++42 mode" or "not in C++74 mode."
> :)  Likewise, when in C++ mode, it doesn't know which C mode it's not-in.
>

No -- the return value should depend on whether the attribute (as
implemented in the current compilation mode) is compatible with the
specification for that attribute in C (__has_c_attribute) or C++
(__has_cpp_attribute).

This is a feature-test -- not "what standards-version am I building under".
Yes, compiling in a C++ standards version mode doesn't put you "in" any C
standards mode. But, if the attribute implements the semantics specified by
C, we should report it as supported, and report the correct "version"
return value for what we've implemented.

Another thing that might seem weird is if we have a situation where C had
>> standardized actually-incompatible behavior vs C++ for the same attribute
>> name. [...]
>> That sort of incompatibility would be quite unfortunate, and I do hope we
>> never need to do that. But if we do need to do it, I believe the above
>> reporting of it makes sense and provides users with the ability to
>> more-easily write C code that is portable to C++, even in the face of such
>> unfortunate incompatibilities.
>>
>
> This is a very strong reason to support only `__has_attribute`, and not
> prematurely bifurcate it into language-specific flags.  Remember, the first
> mover has the responsibility of setting precedent.  If Clang takes the lead
> in simplicity and user-friendliness, the Standards Committee will look at
> that and say, "Ah, vendors seem to be doing a single flag," and standardize
> that, and they'll know never to let the two languages' attributes get
> significantly out of sync because that would cause headaches for vendors.
> On the other hand, if Clang goes out of its way to support "unfortunate
> incompatibilities," that will give license to the Standards Committee to *create
> and exploit* unfortunate incompatibilities.
>

This would not be an effective lever to prevent incompatibilities. If the C
standards committee decided to ignore its current policy against
introducing incompatible features, there is no way that using the same name
for feature-detection would stop them from doing so.

Furthermore, the C++ standards committee has already considered a proposal
to switch to a single name, and after consideration, voted not to do so. If
there was a good reason why that decision was *wrong*, I'd be very much in
favor of pushing back again. But I don't see any such reason to consider it
wrong. There are other possible alternatives this could have been done, but
this way is not wrong.

I recommend that Clang should support `__has_attribute` as the fundamental
> syntactic primitive.  Code intended to be portable between C and C++ should
> use `__has_attribute`.
> If WG21 happens to standardize the name `__has_cpp_attribute`, then Clang
> should add `__has_cpp_attribute` as a synonym for `__has_attribute`.
>

WG21 already decided to stay with __has_cpp_attribute. In any case, we
cannot use __has_attribute, because we already used that name for GNU-style
attribute detection.


> If you unwisely go the premature-bifurcation route and add
> __has_cpp_attribute and __has_c_attribute as non-synonyms, I encourage you
> to think about the other language front-ends, e.g. Objective-C. Will you
> add __has_objc_attribute, __has_objcxx_attribute, etc.?
>

No, I would not add those, because there is no point. Those will also use
__has_c_attribute and/or __has_cpp_attribute. Objective-C doesn't have a
standards body, so everything beyond the C or C++ standards is
compiler-extensions, and there's no possible benefit for
__has_objc_attribute.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200228/cf47334c/attachment-0001.html>


More information about the cfe-commits mailing list