From: Louis Dionne Date: Tue, 21 Jan 2020 20:39:43 +0000 (-0800) Subject: [libc++] Make sure std::is_scalar returns true for block types X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=8ae404a2f6ba553368498870c2b3e39484a6312d;p=android-x86%2Fexternal-llvm-project.git [libc++] Make sure std::is_scalar returns true for block types Summary: The compiler already treats them as scalar types, so the library should too. Furthermore, this allows blocks to be used in more places, for example in std::optional, which requires an object type. rdar://problem/57892832 Reviewers: dexonsmith, EricWF, mclow.lists Differential Revision: https://reviews.llvm.org/D72708 --- diff --git a/libcxx/include/__config b/libcxx/include/__config index 84cd46bcc02..77700098281 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -463,6 +463,10 @@ typedef __char32_t char32_t; #define _LIBCPP_HAS_OBJC_ARC_WEAK #endif +#if __has_extension(blocks) +# define _LIBCPP_HAS_EXTENSION_BLOCKS +#endif + #if !(__has_feature(cxx_relaxed_constexpr)) #define _LIBCPP_HAS_NO_CXX14_CONSTEXPR #endif diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index c0c3934afcc..f8ee5648d35 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -1016,11 +1016,17 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_fundamental_v // is_scalar +template struct __is_block : false_type {}; +#if defined(_LIBCPP_HAS_EXTENSION_BLOCKS) +template struct __is_block<_Rp (^)(_Args...)> : true_type {}; +#endif + template struct _LIBCPP_TEMPLATE_VIS is_scalar : public integral_constant::value || is_member_pointer<_Tp>::value || is_pointer<_Tp>::value || __is_nullptr_t<_Tp>::value || + __is_block<_Tp>::value || is_enum<_Tp>::value > {}; template <> struct _LIBCPP_TEMPLATE_VIS is_scalar : public true_type {}; diff --git a/libcxx/test/libcxx/type_traits/is_scalar.objc.pass.mm b/libcxx/test/libcxx/type_traits/is_scalar.objc.pass.mm new file mode 100644 index 00000000000..1f7ffec8efd --- /dev/null +++ b/libcxx/test/libcxx/type_traits/is_scalar.objc.pass.mm @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++98, c++03 + +// + +// std::is_scalar + +// Make sure we report that blocks are scalar types. + +#include +#include + +struct Foo { }; +template struct Arg { }; + +static_assert(std::is_scalar::value, ""); +static_assert(std::is_scalar::value, ""); +static_assert(std::is_scalar)>::value, ""); +static_assert(std::is_scalar, Arg<1>)>::value, ""); +static_assert(std::is_scalar, Arg<1>, Arg<2>)>::value, ""); +static_assert(std::is_scalar::value, ""); +static_assert(std::is_scalar::value, ""); +static_assert(std::is_scalar)>::value, ""); +static_assert(std::is_scalar, Arg<1>)>::value, ""); +static_assert(std::is_scalar, Arg<1>, Arg<2>)>::value, ""); + + +int main(int, char**) { + std::optional)> opt; (void)opt; + return 0; +} diff --git a/libcxx/test/libcxx/utilities/optional/block.objc.pass.mm b/libcxx/test/libcxx/utilities/optional/block.objc.pass.mm new file mode 100644 index 00000000000..8d2722bf853 --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/block.objc.pass.mm @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// This test makes sure that we can create a `std::optional` containing +// an Objective-C++ block. + +#include +#include + +int main(int, char**) +{ + using Block = void (^)(void); + std::optional block; + assert(!block); + + return 0; +}