<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Feb 28, 2020 at 11:42 AM Arthur O'Dwyer <<a href="mailto:arthur.j.odwyer@gmail.com">arthur.j.odwyer@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">On Fri, Feb 28, 2020 at 11:23 AM James Y Knight via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">On Fri, Feb 28, 2020 at 10:05 AM Aaron Ballman <<a href="mailto:aaron@aaronballman.com" target="_blank">aaron@aaronballman.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Thu, Feb 27, 2020 at 6:04 PM James Y Knight <<a href="mailto:jyknight@google.com" target="_blank">jyknight@google.com</a>> wrote:<br>
><br>
> 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?<br>
><br>
> 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.<br>
<br>
If I'm understanding you properly, then I think that this leads to<br>
some strange (to me, at least) behavior. We have some attributes that<br>
are C only attributes, some attributes that are C++ only, but most of<br>
the attributes are supported in both C and C++ with the same<br>
semantics. For the attributes that are in both C and C++, what you<br>
suggest makes sense. For the attributes that exist only in one<br>
language, I'm less convinced. It would be weird for<br>
__has_c_attribute(gnu::transparent_union) (which is a C-only<br>
attribute) to report true in C and false in C++ because we do support<br>
that C attribute.</blockquote><div><br></div><div>That doesn't seem strange to me at all. it will correctly report that we do not support the C attribute <i>in the current compilation context</i>. 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.</div><div><br></div><div>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.</div></div></div></blockquote><div><br></div><div>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.</div></div></div></blockquote><div><br></div><div>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).</div><div><br></div><div>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.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div>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. [...]</div><div>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.</div></div></div></blockquote><div><br></div><div>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 <i>create and exploit</i> unfortunate incompatibilities.</div></div></div></blockquote><div><br></div><div>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.</div><div><br></div><div>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 <i>wrong</i>, 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.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div>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`.</div><div>If WG21 happens to standardize the name `__has_cpp_attribute`, then Clang should add `__has_cpp_attribute` as a synonym for `__has_attribute`.</div></div></div></blockquote><div><br></div><div>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.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div>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.?<br></div></div></div></blockquote><div><br></div><div>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.</div></div></div>