diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -463,6 +463,10 @@ #define _LIBCPP_HAS_OBJC_ARC_WEAK #endif +#if __has_extension(blocks) +# define _LIBCPP_HAS_OBJC_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 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -1016,11 +1016,17 @@ // is_scalar +template struct __is_block : false_type {}; +#if defined(_LIBCPP_HAS_OBJC_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 --- /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 --- /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; +}