Add std::is_constant_evaluated.

Clang recently added __builtin_is_constant_evaluated() and GCC 9.0
has it as well.

This patch adds support for it in libc++.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@359119 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/docs/FeatureTestMacroTable.rst b/docs/FeatureTestMacroTable.rst
index d900497..4d3b079 100644
--- a/docs/FeatureTestMacroTable.rst
+++ b/docs/FeatureTestMacroTable.rst
@@ -188,7 +188,7 @@
     ------------------------------------------------- -----------------
     ``__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 ead5225..0488093 100644
--- a/include/__config
+++ b/include/__config
@@ -1257,6 +1257,10 @@
 #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 43faf27..6571629 100644
--- a/include/type_traits
+++ b/include/type_traits
@@ -4876,6 +4876,13 @@
 };
 #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 1037ee5..948f645 100644
--- a/include/version
+++ b/include/version
@@ -222,7 +222,9 @@
 // # 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 7e8b3de..29e76b3 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 b85d42d..7735a13 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 0000000..c139233
--- /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
+
+// <type_traits>
+
+
+#include <type_traits>
+#include <cassert>
+
+#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 0000000..4dc796e
--- /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
+
+// <type_traits>
+
+// constexpr bool is_constant_evaluated() noexcept; // C++20
+
+#include <type_traits>
+#include <cassert>
+
+#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 <bool> 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<std::is_constant_evaluated()>, InTemplate<true>);
+    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 c11846e..ed01587 100755
--- a/utils/generate_feature_test_macro_components.py
+++ b/utils/generate_feature_test_macro_components.py
@@ -525,7 +525,8 @@
      "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 0adc0e1..e6f5444 100644
--- a/www/cxx2a_status.html
+++ b/www/cxx2a_status.html
@@ -113,7 +113,7 @@
 	<tr><td><a href="https://wg21.link/P0482R6">P0482R6</a></td><td>CWG</td><td>char8_t: A type for UTF-8 characters and strings</td><td>San Diego</td><td><i> </i></td><td></td></tr>
 	<tr><td><a href="https://wg21.link/P0487R1">P0487R1</a></td><td>LWG</td><td>Fixing operator&gt;&gt;(basic_istream&amp;, CharT*) (LWG 2499)</td><td>San Diego</td><td>Complete</td><td>8.0</td></tr>
 	<tr><td><a href="https://wg21.link/P0591R4">P0591R4</a></td><td>LWG</td><td>Utility functions to implement uses-allocator construction</td><td>San Diego</td><td><i> </i></td><td></td></tr>
-	<tr><td><a href="https://wg21.link/P0595R2">P0595R2</a></td><td>CWG</td><td>P0595R2 std::is_constant_evaluated()</td><td>San Diego</td><td><i> </i></td><td></td></tr>
+	<tr><td><a href="https://wg21.link/P0595R2">P0595R2</a></td><td>CWG</td><td>P0595R2 std::is_constant_evaluated()</td><td>San Diego</td><td>Complete</td><td>9.0</td></tr>
 	<tr><td><a href="https://wg21.link/P0602R4">P0602R4</a></td><td>LWG</td><td>variant and optional should propagate copy/move triviality</td><td>San Diego</td><td>Complete</td><td>8.0</td></tr>
 	<tr><td><a href="https://wg21.link/P0608R3">P0608R3</a></td><td>LWG</td><td>A sane variant converting constructor</td><td>San Diego</td><td><i> </i></td><td></td></tr>
 	<tr><td><a href="https://wg21.link/P0655R1">P0655R1</a></td><td>LWG</td><td>visit&lt;R&gt;: Explicit Return Type for visit</td><td>San Diego</td><td><i> </i></td><td></td></tr>