Author: Marek Kurdej Date: 2021-01-12T17:08:20+01:00 New Revision: 1f1250151f222ba391d05dcc173f4b6c65d05ca2
URL: https://github.com/llvm/llvm-project/commit/1f1250151f222ba391d05dcc173f4b6c65d05ca2 DIFF: https://github.com/llvm/llvm-project/commit/1f1250151f222ba391d05dcc173f4b6c65d05ca2.diff LOG: [libc++] [C++2b] [P1048] Add is_scoped_enum and is_scoped_enum_v. * https://wg21.link/p1048 Reviewed By: ldionne, #libc Differential Revision: https://reviews.llvm.org/D94409 Added: libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_scoped_enum.pass.cpp Modified: libcxx/docs/Cxx2bStatusPaperStatus.csv libcxx/docs/FeatureTestMacroTable.rst libcxx/include/type_traits libcxx/include/version libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp libcxx/utils/generate_feature_test_macro_components.py Removed: ################################################################################ diff --git a/libcxx/docs/Cxx2bStatusPaperStatus.csv b/libcxx/docs/Cxx2bStatusPaperStatus.csv index c79509528add..f5c893fdbd48 100644 --- a/libcxx/docs/Cxx2bStatusPaperStatus.csv +++ b/libcxx/docs/Cxx2bStatusPaperStatus.csv @@ -1,6 +1,6 @@ "Paper #","Group","Paper Name","Meeting","Status","First released version" "`P0881R7 <https://wg21.link/P0881R7>`__","LWG","A Proposal to add stacktrace library","Autumn 2020","","" "`P0943R6 <https://wg21.link/P0943R6>`__","LWG","Support C atomics in C++","Autumn 2020","","" -"`P1048R1 <https://wg21.link/P1048R1>`__","LWG","A proposal for a type trait to detect scoped enumerations","Autumn 2020","","" +"`P1048R1 <https://wg21.link/P1048R1>`__","LWG","A proposal for a type trait to detect scoped enumerations","Autumn 2020","|Complete|","12.0" "`P1679R3 <https://wg21.link/P1679R3>`__","LWG","string contains function","Autumn 2020","","" "","","","","","" diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 99fb4e790c7d..8221bbe2a4af 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -292,7 +292,7 @@ Status ------------------------------------------------- ----------------- **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 index 99b2a8f9f025..48884eab8e86 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -51,6 +51,7 @@ namespace std template <class T> struct is_arithmetic; template <class T> struct is_fundamental; template <class T> struct is_member_pointer; + template <class T> struct is_scoped_enum; // C++2b template <class T> struct is_scalar; template <class T> struct is_object; template <class T> struct is_compound; @@ -284,6 +285,8 @@ namespace std = is_compound<T>::value; // C++17 template <class T> inline constexpr bool is_member_pointer_v = is_member_pointer<T>::value; // C++17 + template <class T> inline constexpr bool is_scoped_enum_v + = is_scoped_enum<T>::value; // C++2b // See C++14 20.10.4.3, type properties template <class T> inline constexpr bool is_const_v @@ -4177,6 +4180,25 @@ struct __has_operator_addressof #endif // _LIBCPP_CXX03_LANG +// is_scoped_enum [meta.unary.prop] + +#if _LIBCPP_STD_VER > 20 +template <class _Tp, bool = is_enum_v<_Tp> > +struct __is_scoped_enum_helper : false_type {}; + +template <class _Tp> +struct __is_scoped_enum_helper<_Tp, true> + : public bool_constant<!is_convertible_v<_Tp, underlying_type_t<_Tp> > > {}; + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_scoped_enum + : public __is_scoped_enum_helper<_Tp> {}; + +template <class _Tp> +_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_scoped_enum_v = + is_scoped_enum<_Tp>::value; +#endif + #if _LIBCPP_STD_VER > 14 template <class... _Args> diff --git a/libcxx/include/version b/libcxx/include/version index 3920b69a601c..9e5fc81da44e 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -355,7 +355,7 @@ __cpp_lib_void_t 201411L <type_traits> #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 index 04c6aaa81fd7..41bc22f6a330 100644 --- 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 index 664c8fe75839..3ff920c3a489 100644 --- 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 index 000000000000..ad50755a00cd --- /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 <type_traits> +#include <cstddef> // for std::nullptr_t +#include "test_macros.h" + +template <class T> +void test_positive() { + static_assert(std::is_scoped_enum<T>::value); + static_assert(std::is_scoped_enum<const T>::value); + static_assert(std::is_scoped_enum<volatile T>::value); + static_assert(std::is_scoped_enum<const volatile T>::value); + + static_assert(std::is_scoped_enum_v<T>); + static_assert(std::is_scoped_enum_v<const T>); + static_assert(std::is_scoped_enum_v<volatile T>); + static_assert(std::is_scoped_enum_v<const volatile T>); +} + +template <class T> +void test_negative() { + static_assert(!std::is_scoped_enum<T>::value); + static_assert(!std::is_scoped_enum<const T>::value); + static_assert(!std::is_scoped_enum<volatile T>::value); + static_assert(!std::is_scoped_enum<const volatile T>::value); + + static_assert(!std::is_scoped_enum_v<T>); + static_assert(!std::is_scoped_enum_v<const T>); + static_assert(!std::is_scoped_enum_v<volatile T>); + static_assert(!std::is_scoped_enum_v<const volatile T>); +} + +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<CEnum1>(); + test_positive<CEnum2>(); + test_positive<CEnum3>(); + test_positive<TestMembers::CE1>(); + + test_negative<Enum>(); + test_negative<TestMembers::E1>(); + + test_negative<std::nullptr_t>(); + test_negative<void>(); + test_negative<int>(); + test_negative<int&>(); + test_negative<int&&>(); + test_negative<int*>(); + test_negative<double>(); + test_negative<const int*>(); + test_negative<char[3]>(); + test_negative<char[]>(); + test_negative<Union>(); + test_negative<Empty>(); + test_negative<bit_zero>(); + test_negative<NotEmpty>(); + test_negative<Abstract>(); + test_negative<FunctionPtr>(); + test_negative<FunctionType>(); + test_negative<incomplete_type>(); + test_negative<int TestMembers::*>(); + test_negative<void (TestMembers::*)()>(); + + test_negative<decltype(func1)>(); + test_negative<decltype(&func1)>(); + test_negative<decltype(func2)>(); + test_negative<decltype(&func2)>(); + test_negative<decltype(TestMembers::static_method)>(); + test_negative<decltype(&TestMembers::static_method)>(); + test_negative<decltype(&TestMembers::method)>(); + + return 0; +} diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index daa40f2a15ac..c08771fc056c 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -368,7 +368,6 @@ def add_version_header(tc): "name": "__cpp_lib_is_scoped_enum", "values": { "c++2b": 202011 }, "headers": ["type_traits"], - "unimplemented": True, }, { "name": "__cpp_lib_is_swappable", "values": { "c++17": 201603 }, _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits