[cfe-dev] Keyword warnings in libc++'s type_traits and other headers

Alp Toker alp at nuanti.com
Mon Dec 23 17:28:34 PST 2013


On 24/12/2013 00:29, Marshall Clow wrote:
> On Dec 23, 2013, at 1:16 PM, Howard Hinnant <howard.hinnant at gmail.com 
> <mailto:howard.hinnant at gmail.com>> wrote:
>>
>> Two further questions:
>>
>> 1. Do these keywords come with __has_feature tests (like __is_class 
>> does)?  If not, they should.
>>
>> 2.  If they do come with __has_feature tests, how about libc++ doing 
>> the same thing it does for is_class et al.?
>>
>> #if !__has_feature(is_void)
>>
>> template <class _Tp> struct __is_void       : public false_type {};
>> template <>          struct __is_void<void> : public true_type {};
>>
>> #endif  // !__has_feature(is_void)
>>
>> template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY is_void
>>    : public __is_void<typename remove_cv<_Tp>::type> {};
>>
>> That way we don't need major surgery.  We avoid the conflict if it 
>> exists.  And we take advantage of the compiler intrinsic if it exists.
>
> This sounds good to me, but I think it’ll be a bit more involved than 
> that:
>
> #if !__has_feature(is_void)

Hi Marshall,

A feature definition was never added for these trait intrinsics 
unfortunately. I'll look into it.

>
> template <class _Tp> struct __is_void       : public false_type {};
> template <>          struct __is_void<void> : public true_type {};
>
> template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY is_void
>    : public __is_void<typename remove_cv<_Tp>::type> {};

This would still conflict with the keyword in current clang versions and 
other compilers that don't have a quality __has_feature() implementation.

To reiterate, you'll do well to avoid the __is_* prefix entirely 
regardless of whether you can feature-test for individual availability 
of the keywords.

I'll try to illustrate this in a different way, taking clang out of the 
picture for a minute. None of these structures extracted from libc++ 
will compile with MSVC 2013:


|struct __is_nothrow_constructible {}||;||
||testvc.cpp(8) : error C2332: 'struct' : missing tag name||
||||
||struct __is_nothrow_assignable||{}||;||
||testvc.cpp(8) : error C2332: 'struct' : missing tag name||
||||
||struct __is_constructible {}||;||
||testvc.cpp(8) : error C2332: 'struct' : missing tag name|


It's a fact of life that there many compiler-defined keywords littering 
the __is_* namespace and most of them are undocumented. Trying to use 
them as identifiers or type names is a parse error.

You /could/ try to continue using the __is_* names that are known not to 
conflict today, but it's a quixotic solution that'll break every time a 
new compiler point-release adds new built-in trait primitives.


>
> #else
>
> template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY is_void
>    : public integral_constant<bool, __is_void(typename 
> remove_cv<_Tp>::type)>;
>
> #endif  // !__has_feature(is_void)

This part will work.

I'd actually recommend keeping the production-quality library 
implementations in libc++ instead of switching wholesale to the clang 
intrinsics. Many of our intrinsics are there for compatibility and 
haven't been fully tested in a production environment.

If you just s/__is_/__libcpp_is_/ to avoid the keywords you'll gain 
compatibility with other modern compilers, silence the extension 
warnings and help us set a schedule for removing the GNU compatibility 
hack in the parser.

After that we can start to look at offering optimized type traits by 
coordinating more closely, but it's not the immediate issue at hand.

Alp.


-- 
http://www.nuanti.com
the browser experts

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20131224/d9cc7aef/attachment.html>


More information about the cfe-dev mailing list