diff --git a/docs/FeatureTestMacroTable.rst b/docs/FeatureTestMacroTable.rst index d900497eb..4d3b0799a 100644 --- a/docs/FeatureTestMacroTable.rst +++ b/docs/FeatureTestMacroTable.rst @@ -188,7 +188,7 @@ Status ------------------------------------------------- ----------------- ``__cpp_lib_generic_unordered_lookup`` *unimplemented* ------------------------------------------------- ----------------- - ``__cpp_lib_is_constant_evaluated`` *unimplemented* + ``__cpp_lib_is_constant_evaluated`` ``201811L`` ------------------------------------------------- ----------------- ``__cpp_lib_list_remove_return_type`` *unimplemented* ------------------------------------------------- ----------------- diff --git a/include/__config b/include/__config index ead522520..0488093aa 100644 --- a/include/__config +++ b/include/__config @@ -1257,6 +1257,10 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container( #define _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF #endif +#if !__has_builtin(__builtin_is_constant_evaluated) && _GNUC_VER < 900 +#define _LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED +#endif + #if !defined(_LIBCPP_HAS_NO_OFF_T_FUNCTIONS) # if defined(_LIBCPP_MSVCRT) || defined(_NEWLIB_VERSION) # define _LIBCPP_HAS_NO_OFF_T_FUNCTIONS diff --git a/include/type_traits b/include/type_traits index 43faf275c..657162952 100644 --- a/include/type_traits +++ b/include/type_traits @@ -4876,6 +4876,13 @@ enum class endian }; #endif +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED) +_LIBCPP_INLINE_VISIBILITY +inline constexpr bool is_constant_evaluated() noexcept { + return __builtin_is_constant_evaluated(); +} +#endif + _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 diff --git a/include/version b/include/version index 1037ee5df..948f64512 100644 --- a/include/version +++ b/include/version @@ -222,7 +222,9 @@ __cpp_lib_void_t 201411L // # define __cpp_lib_destroying_delete 201806L # define __cpp_lib_erase_if 201811L // # define __cpp_lib_generic_unordered_lookup 201811L -// # define __cpp_lib_is_constant_evaluated 201811L +# if !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED) +# define __cpp_lib_is_constant_evaluated 201811L +# endif // # define __cpp_lib_list_remove_return_type 201806L // # define __cpp_lib_ranges 201811L // # define __cpp_lib_three_way_comparison 201711L diff --git a/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp index 7e8b3de35..29e76b36e 100644 --- a/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp +++ b/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp @@ -315,16 +315,16 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) +# if TEST_HAS_BUILTIN(__builtin_is_constant_evaluated) || TEST_GCC_VER >= 900 # ifndef __cpp_lib_is_constant_evaluated # error "__cpp_lib_is_constant_evaluated should be defined in c++2a" # endif # if __cpp_lib_is_constant_evaluated != 201811L # error "__cpp_lib_is_constant_evaluated should have the value 201811L in c++2a" # endif -# else // _LIBCPP_VERSION +# else # ifdef __cpp_lib_is_constant_evaluated -# error "__cpp_lib_is_constant_evaluated should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_is_constant_evaluated should not be defined when TEST_HAS_BUILTIN(__builtin_is_constant_evaluated) || TEST_GCC_VER >= 900 is not defined!" # endif # endif diff --git a/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp index b85d42d00..7735a13db 100644 --- a/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -1798,16 +1798,16 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) +# if TEST_HAS_BUILTIN(__builtin_is_constant_evaluated) || TEST_GCC_VER >= 900 # ifndef __cpp_lib_is_constant_evaluated # error "__cpp_lib_is_constant_evaluated should be defined in c++2a" # endif # if __cpp_lib_is_constant_evaluated != 201811L # error "__cpp_lib_is_constant_evaluated should have the value 201811L in c++2a" # endif -# else // _LIBCPP_VERSION +# else # ifdef __cpp_lib_is_constant_evaluated -# error "__cpp_lib_is_constant_evaluated should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_is_constant_evaluated should not be defined when TEST_HAS_BUILTIN(__builtin_is_constant_evaluated) || TEST_GCC_VER >= 900 is not defined!" # endif # endif diff --git a/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.fail.cpp b/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.fail.cpp new file mode 100644 index 000000000..c139233b8 --- /dev/null +++ b/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.fail.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// + + +#include +#include + +#include "test_macros.h" + +int main(int, char**) +{ +#ifndef __cpp_lib_is_constant_evaluated + // expected-error@+1 {{no member named 'is_constant_evaluated' in namespace 'std'}} + bool b = std::is_constant_evaluated(); +#else + // expected-error@+1 {{static_assert failed}} + static_assert(!std::is_constant_evaluated(), ""); +#endif + return 0; +} diff --git a/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.pass.cpp b/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.pass.cpp new file mode 100644 index 000000000..4dc796e95 --- /dev/null +++ b/test/std/utilities/meta/meta.const.eval/is_constant_evaluated.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++17 + +// + +// constexpr bool is_constant_evaluated() noexcept; // C++20 + +#include +#include + +#include "test_macros.h" + +#ifndef __cpp_lib_is_constant_evaluated +#if TEST_HAS_BUILTIN(__builtin_is_constant_evaluated) +# error __cpp_lib_is_constant_evaluated should be defined +#endif +#endif + +template struct InTemplate {}; + +int main(int, char**) +{ +#ifdef __cpp_lib_is_constant_evaluated + // Test the signature + { + ASSERT_SAME_TYPE(decltype(std::is_constant_evaluated()), bool); + ASSERT_NOEXCEPT(std::is_constant_evaluated()); + constexpr bool p = std::is_constant_evaluated(); + assert(p); + } + // Test the return value of the builtin for basic sanity only. It's the + // compilers job to test tho builtin for correctness. + { + static_assert(std::is_constant_evaluated(), ""); + bool p = std::is_constant_evaluated(); + assert(!p); + ASSERT_SAME_TYPE(InTemplate, InTemplate); + static int local_static = std::is_constant_evaluated() ? 42 : -1; + assert(local_static == 42); + } +#endif + return 0; +} diff --git a/utils/generate_feature_test_macro_components.py b/utils/generate_feature_test_macro_components.py index c11846ec6..ed015876a 100755 --- a/utils/generate_feature_test_macro_components.py +++ b/utils/generate_feature_test_macro_components.py @@ -525,7 +525,8 @@ feature_test_macros = sorted([ add_version_header(x) for x in [ "c++2a": 201811L, }, "headers": ["type_traits"], - "unimplemented": True, + "depends": "TEST_HAS_BUILTIN(__builtin_is_constant_evaluated) || TEST_GCC_VER >= 900", + "internal_depends": "!defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)", }, {"name": "__cpp_lib_list_remove_return_type", "values": { diff --git a/www/cxx2a_status.html b/www/cxx2a_status.html index 0adc0e18e..e6f544497 100644 --- a/www/cxx2a_status.html +++ b/www/cxx2a_status.html @@ -113,7 +113,7 @@ P0482R6CWGchar8_t: A type for UTF-8 characters and stringsSan Diego P0487R1LWGFixing operator>>(basic_istream&, CharT*) (LWG 2499)San DiegoComplete8.0 P0591R4LWGUtility functions to implement uses-allocator constructionSan Diego - P0595R2CWGP0595R2 std::is_constant_evaluated()San Diego + P0595R2CWGP0595R2 std::is_constant_evaluated()San DiegoComplete9.0 P0602R4LWGvariant and optional should propagate copy/move trivialitySan DiegoComplete8.0 P0608R3LWGA sane variant converting constructorSan Diego P0655R1LWGvisit<R>: Explicit Return Type for visitSan Diego