diff --git a/libcxx/docs/Cxx2bStatusPaperStatus.csv b/libcxx/docs/Cxx2bStatusPaperStatus.csv --- a/libcxx/docs/Cxx2bStatusPaperStatus.csv +++ b/libcxx/docs/Cxx2bStatusPaperStatus.csv @@ -1,6 +1,6 @@ "Paper #","Group","Paper Name","Meeting","Status","First released version" "`P0881R7 `__","LWG","A Proposal to add stacktrace library","Autumn 2020","","" "`P0943R6 `__","LWG","Support C atomics in C++","Autumn 2020","","" -"`P1048R1 `__","LWG","A proposal for a type trait to detect scoped enumerations","Autumn 2020","","" +"`P1048R1 `__","LWG","A proposal for a type trait to detect scoped enumerations","Autumn 2020","|Complete|","12.0" "`P1679R3 `__","LWG","string contains function","Autumn 2020","","" "","","","","","" diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -292,7 +292,7 @@ ------------------------------------------------- ----------------- **C++ 2b** ------------------------------------------------------------------- - ``__cpp_lib_is_scoped_enum`` *unimplemented* + ``__cpp_lib_is_scoped_enum`` ``202011L`` ------------------------------------------------- ----------------- ``__cpp_lib_stacktrace`` *unimplemented* ------------------------------------------------- ----------------- diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -51,6 +51,7 @@ template struct is_arithmetic; template struct is_fundamental; template struct is_member_pointer; + template struct is_scoped_enum; // C++2b template struct is_scalar; template struct is_object; template struct is_compound; @@ -284,6 +285,8 @@ = is_compound::value; // C++17 template inline constexpr bool is_member_pointer_v = is_member_pointer::value; // C++17 + template inline constexpr bool is_scoped_enum_v + = is_scoped_enum::value; // C++2b // See C++14 20.10.4.3, type properties template inline constexpr bool is_const_v @@ -4177,6 +4180,25 @@ #endif // _LIBCPP_CXX03_LANG +// is_scoped_enum [meta.unary.prop] + +#if _LIBCPP_STD_VER > 20 +template > +struct __is_scoped_enum_helper : false_type {}; + +template +struct __is_scoped_enum_helper<_Tp, true> + : public bool_constant > > {}; + +template +struct _LIBCPP_TEMPLATE_VIS is_scoped_enum + : public __is_scoped_enum_helper<_Tp> {}; + +template +_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_scoped_enum_v = + is_scoped_enum<_Tp>::value; +#endif + #if _LIBCPP_STD_VER > 14 template diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -355,7 +355,7 @@ #endif #if _LIBCPP_STD_VER > 20 -// # define __cpp_lib_is_scoped_enum 202011L +# define __cpp_lib_is_scoped_enum 202011L // # define __cpp_lib_stacktrace 202011L // # define __cpp_lib_stdatomic_h 202011L // # define __cpp_lib_string_contains 202011L diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp @@ -638,17 +638,11 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_is_scoped_enum -# error "__cpp_lib_is_scoped_enum should be defined in c++2b" -# endif -# if __cpp_lib_is_scoped_enum != 202011L -# error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_is_scoped_enum -# error "__cpp_lib_is_scoped_enum should not be defined because it is unimplemented in libc++!" -# endif +#ifndef __cpp_lib_is_scoped_enum +#error "__cpp_lib_is_scoped_enum should be defined in c++2b" +#endif +#if __cpp_lib_is_scoped_enum != 202011L +#error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b" # endif # ifndef __cpp_lib_is_swappable diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -3983,17 +3983,11 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_is_scoped_enum -# error "__cpp_lib_is_scoped_enum should be defined in c++2b" -# endif -# if __cpp_lib_is_scoped_enum != 202011L -# error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_is_scoped_enum -# error "__cpp_lib_is_scoped_enum should not be defined because it is unimplemented in libc++!" -# endif +#ifndef __cpp_lib_is_scoped_enum +#error "__cpp_lib_is_scoped_enum should be defined in c++2b" +#endif +#if __cpp_lib_is_scoped_enum != 202011L +#error "__cpp_lib_is_scoped_enum should have the value 202011L in c++2b" # endif # ifndef __cpp_lib_is_swappable diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_scoped_enum.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_scoped_enum.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_scoped_enum.pass.cpp @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// 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++03, c++11, c++14, c++17, c++2a + +// type_traits + +// is_scoped_enum // C++2b + +#include +#include // for std::nullptr_t +#include "test_macros.h" + +template +void test_positive() { + static_assert(std::is_scoped_enum::value); + static_assert(std::is_scoped_enum::value); + static_assert(std::is_scoped_enum::value); + static_assert(std::is_scoped_enum::value); + + static_assert(std::is_scoped_enum_v); + static_assert(std::is_scoped_enum_v); + static_assert(std::is_scoped_enum_v); + static_assert(std::is_scoped_enum_v); +} + +template +void test_negative() { + static_assert(!std::is_scoped_enum::value); + static_assert(!std::is_scoped_enum::value); + static_assert(!std::is_scoped_enum::value); + static_assert(!std::is_scoped_enum::value); + + static_assert(!std::is_scoped_enum_v); + static_assert(!std::is_scoped_enum_v); + static_assert(!std::is_scoped_enum_v); + static_assert(!std::is_scoped_enum_v); +} + +class Empty {}; + +class NotEmpty { + virtual ~NotEmpty(); +}; + +union Union {}; + +struct bit_zero { + int : 0; +}; + +class Abstract { + virtual ~Abstract() = 0; +}; + +enum Enum { zero, one }; +enum class CEnum1 { zero, one }; +enum class CEnum2; +enum class CEnum3 : short; +struct incomplete_type; + +using FunctionPtr = void (*)(); +using FunctionType = void(); + +struct TestMembers { + static int static_method(int) { return 0; } + int method() { return 0; } + + enum E1 { m_zero, m_one }; + enum class CE1; +}; + +void func1(); +int func2(int); + +int main(int, char**) { + test_positive(); + test_positive(); + test_positive(); + test_positive(); + + test_negative(); + test_negative(); + + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + test_negative(); + + return 0; +} diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -368,7 +368,6 @@ "name": "__cpp_lib_is_scoped_enum", "values": { "c++2b": 202011 }, "headers": ["type_traits"], - "unimplemented": True, }, { "name": "__cpp_lib_is_swappable", "values": { "c++17": 201603 },