[libcxx-commits] [libcxx] 67c88e4 - [libc++] P1645 constexpr for <numeric>

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sat Nov 28 08:03:57 PST 2020


Author: Mark de Wever
Date: 2020-11-28T17:02:54+01:00
New Revision: 67c88e47bdba2578150a9034a717d6ddcace4e13

URL: https://github.com/llvm/llvm-project/commit/67c88e47bdba2578150a9034a717d6ddcace4e13
DIFF: https://github.com/llvm/llvm-project/commit/67c88e47bdba2578150a9034a717d6ddcace4e13.diff

LOG: [libc++] P1645 constexpr for <numeric>

Implements P1645: constexpr for <numeric> algorithms

Reviewed By: ldionne, #libc

Differential Revision: https://reviews.llvm.org/D90569

Added: 
    

Modified: 
    libcxx/docs/Cxx2aStatusPaperStatus.csv
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/include/numeric
    libcxx/include/version
    libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
    libcxx/test/std/numerics/numeric.ops/accumulate/accumulate.pass.cpp
    libcxx/test/std/numerics/numeric.ops/accumulate/accumulate_op.pass.cpp
    libcxx/test/std/numerics/numeric.ops/adjacent.difference/adjacent_difference.pass.cpp
    libcxx/test/std/numerics/numeric.ops/adjacent.difference/adjacent_difference_op.pass.cpp
    libcxx/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan.pass.cpp
    libcxx/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan_init_op.pass.cpp
    libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan.pass.cpp
    libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op.pass.cpp
    libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op_init.pass.cpp
    libcxx/test/std/numerics/numeric.ops/inner.product/inner_product.pass.cpp
    libcxx/test/std/numerics/numeric.ops/inner.product/inner_product_comp.pass.cpp
    libcxx/test/std/numerics/numeric.ops/numeric.iota/iota.pass.cpp
    libcxx/test/std/numerics/numeric.ops/partial.sum/partial_sum.pass.cpp
    libcxx/test/std/numerics/numeric.ops/partial.sum/partial_sum_op.pass.cpp
    libcxx/test/std/numerics/numeric.ops/reduce/reduce.pass.cpp
    libcxx/test/std/numerics/numeric.ops/reduce/reduce_init.pass.cpp
    libcxx/test/std/numerics/numeric.ops/reduce/reduce_init_op.pass.cpp
    libcxx/test/std/numerics/numeric.ops/transform.exclusive.scan/transform_exclusive_scan_init_bop_uop.pass.cpp
    libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop.pass.cpp
    libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop_init.pass.cpp
    libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_init_bop_uop.pass.cpp
    libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init.pass.cpp
    libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init_op_op.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Cxx2aStatusPaperStatus.csv b/libcxx/docs/Cxx2aStatusPaperStatus.csv
index 456ac647b7a3..793fc92be5f2 100644
--- a/libcxx/docs/Cxx2aStatusPaperStatus.csv
+++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv
@@ -138,7 +138,7 @@
 "`P1394 <https://wg21.link/P1394>`__","LWG","Range constructor for std::span","Belfast","* *",""
 "`P1456 <https://wg21.link/P1456>`__","LWG","Move-only views","Belfast","* *",""
 "`P1622 <https://wg21.link/P1622>`__","LWG","Mandating the Standard Library: Clause 32 - Thread support library","Belfast","* *",""
-"`P1645 <https://wg21.link/P1645>`__","LWG","constexpr for numeric algorithms","Belfast","* *",""
+"`P1645 <https://wg21.link/P1645>`__","LWG","constexpr for numeric algorithms","Belfast","|Complete|","12.0"
 "`P1664 <https://wg21.link/P1664>`__","LWG","reconstructible_range - a concept for putting ranges back together","Belfast","* *",""
 "`P1686 <https://wg21.link/P1686>`__","LWG","Mandating the Standard Library: Clause 27 - Time library","Belfast","* *",""
 "`P1690 <https://wg21.link/P1690>`__","LWG","Refinement Proposal for P0919 Heterogeneous lookup for unordered containers","Belfast","|Complete|","12.0"

diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 637a4849e471..aa60a033edc3 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -196,6 +196,8 @@ Status
     ------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_misc``                      *unimplemented*
     ------------------------------------------------- -----------------
+    ``__cpp_lib_constexpr_numeric``                   ``201911L``
+    ------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_swap_algorithms``           *unimplemented*
     ------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_utility``                   ``201811L``

diff  --git a/libcxx/include/numeric b/libcxx/include/numeric
index 088bd7438d2b..5c10dd3c1e67 100644
--- a/libcxx/include/numeric
+++ b/libcxx/include/numeric
@@ -17,115 +17,116 @@ namespace std
 {
 
 template <class InputIterator, class T>
-    T
+    constexpr T  // constexpr since C++20
     accumulate(InputIterator first, InputIterator last, T init);
 
 template <class InputIterator, class T, class BinaryOperation>
-    T
+    constexpr T  // constexpr since C++20
     accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op);
 
 template<class InputIterator>
-    typename iterator_traits<InputIterator>::value_type
+    constexpr typename iterator_traits<InputIterator>::value_type  // constexpr since C++20
     reduce(InputIterator first, InputIterator last);  // C++17
 
 template<class InputIterator, class T>
-    T
+    constexpr T  // constexpr since C++20
     reduce(InputIterator first, InputIterator last, T init);  // C++17
 
 template<class InputIterator, class T, class BinaryOperation>
-    T
+    constexpr T  // constexpr since C++20
     reduce(InputIterator first, InputIterator last, T init, BinaryOperation binary_op);  // C++17
 
 template <class InputIterator1, class InputIterator2, class T>
-    T
+    constexpr T  // constexpr since C++20
     inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init);
 
 template <class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2>
-    T
+    constexpr T  // constexpr since C++20
     inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2,
                   T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);
 
 
 template<class InputIterator1, class InputIterator2, class T>
-    T
+    constexpr T  // constexpr since C++20
     transform_reduce(InputIterator1 first1, InputIterator1 last1,
                      InputIterator2 first2, T init);  // C++17
 
 template<class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2>
-    T
+    constexpr T  // constexpr since C++20
     transform_reduce(InputIterator1 first1, InputIterator1 last1,
                      InputIterator2 first2, T init,
                      BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);  // C++17
 
 template<class InputIterator, class T, class BinaryOperation, class UnaryOperation>
-    T
+    constexpr T  // constexpr since C++20
     transform_reduce(InputIterator first, InputIterator last, T init,
                      BinaryOperation binary_op, UnaryOperation unary_op);  // C++17
 
 template <class InputIterator, class OutputIterator>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     partial_sum(InputIterator first, InputIterator last, OutputIterator result);
 
 template <class InputIterator, class OutputIterator, class BinaryOperation>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);
 
 template<class InputIterator, class OutputIterator, class T>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     exclusive_scan(InputIterator first, InputIterator last,
                    OutputIterator result, T init); // C++17
 
 template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     exclusive_scan(InputIterator first, InputIterator last,
                    OutputIterator result, T init, BinaryOperation binary_op); // C++17
 
 template<class InputIterator, class OutputIterator>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     inclusive_scan(InputIterator first, InputIterator last, OutputIterator result);  // C++17
 
 template<class InputIterator, class OutputIterator, class BinaryOperation>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     inclusive_scan(InputIterator first, InputIterator last,
                    OutputIterator result, BinaryOperation binary_op);  // C++17
 
 template<class InputIterator, class OutputIterator, class BinaryOperation, class T>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     inclusive_scan(InputIterator first, InputIterator last,
                    OutputIterator result, BinaryOperation binary_op, T init);  // C++17
 
 template<class InputIterator, class OutputIterator, class T,
          class BinaryOperation, class UnaryOperation>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     transform_exclusive_scan(InputIterator first, InputIterator last,
                              OutputIterator result, T init,
                              BinaryOperation binary_op, UnaryOperation unary_op);  // C++17
 
 template<class InputIterator, class OutputIterator,
          class BinaryOperation, class UnaryOperation>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     transform_inclusive_scan(InputIterator first, InputIterator last,
                              OutputIterator result,
                              BinaryOperation binary_op, UnaryOperation unary_op);  // C++17
 
 template<class InputIterator, class OutputIterator,
          class BinaryOperation, class UnaryOperation, class T>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     transform_inclusive_scan(InputIterator first, InputIterator last,
                              OutputIterator result,
                              BinaryOperation binary_op, UnaryOperation unary_op,
                              T init);  // C++17
 
 template <class InputIterator, class OutputIterator>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     adjacent_
diff erence(InputIterator first, InputIterator last, OutputIterator result);
 
 template <class InputIterator, class OutputIterator, class BinaryOperation>
-    OutputIterator
+    constexpr OutputIterator  // constexpr since C++20
     adjacent_
diff erence(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);
 
 template <class ForwardIterator, class T>
-    void iota(ForwardIterator first, ForwardIterator last, T value);
+    constexpr void  // constexpr since C++20
+    iota(ForwardIterator first, ForwardIterator last, T value);
 
 template <class M, class N>
     constexpr common_type_t<M,N> gcd(M m, N n);    // C++17
@@ -133,9 +134,11 @@ template <class M, class N>
 template <class M, class N>
     constexpr common_type_t<M,N> lcm(M m, N n);    // C++17
 
-integer         midpoint(integer a, integer b);                  // C++20
-pointer         midpoint(pointer a, pointer b);                  // C++20
-floating_point  midpoint(floating_point a, floating_point b);    // C++20
+template<class T>
+    constexpr T midpoint(T a, T b) noexcept;  // C++20
+
+template<class T>
+    constexpr T* midpoint(T* a, T* b);        // C++20
 
 }  // std
 
@@ -158,7 +161,7 @@ _LIBCPP_PUSH_MACROS
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _InputIterator, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _Tp
 accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
 {
@@ -172,7 +175,7 @@ accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
 }
 
 template <class _InputIterator, class _Tp, class _BinaryOperation>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _Tp
 accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOperation __binary_op)
 {
@@ -187,7 +190,7 @@ accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOpe
 
 #if _LIBCPP_STD_VER > 14
 template <class _InputIterator, class _Tp, class _BinaryOp>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _Tp
 reduce(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOp __b)
 {
@@ -197,7 +200,7 @@ reduce(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOp __b)
 }
 
 template <class _InputIterator, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _Tp
 reduce(_InputIterator __first, _InputIterator __last, _Tp __init)
 {
@@ -205,7 +208,7 @@ reduce(_InputIterator __first, _InputIterator __last, _Tp __init)
 }
 
 template <class _InputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 typename iterator_traits<_InputIterator>::value_type
 reduce(_InputIterator __first, _InputIterator __last)
 {
@@ -215,7 +218,7 @@ reduce(_InputIterator __first, _InputIterator __last)
 #endif
 
 template <class _InputIterator1, class _InputIterator2, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _Tp
 inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _Tp __init)
 {
@@ -229,7 +232,7 @@ inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2
 }
 
 template <class _InputIterator1, class _InputIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _Tp
 inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2,
               _Tp __init, _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2)
@@ -245,7 +248,7 @@ inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2
 
 #if _LIBCPP_STD_VER > 14
 template <class _InputIterator, class _Tp, class _BinaryOp, class _UnaryOp>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _Tp
 transform_reduce(_InputIterator __first, _InputIterator __last,
            _Tp __init,  _BinaryOp __b, _UnaryOp __u)
@@ -257,7 +260,7 @@ transform_reduce(_InputIterator __first, _InputIterator __last,
 
 template <class _InputIterator1, class _InputIterator2,
           class _Tp, class _BinaryOp1, class _BinaryOp2>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _Tp
 transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1,
                  _InputIterator2 __first2, _Tp __init,  _BinaryOp1 __b1, _BinaryOp2 __b2)
@@ -268,7 +271,7 @@ transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1,
 }
 
 template <class _InputIterator1, class _InputIterator2, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _Tp
 transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1,
                  _InputIterator2 __first2, _Tp __init)
@@ -279,7 +282,7 @@ transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1,
 #endif
 
 template <class _InputIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
 {
@@ -301,7 +304,7 @@ partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __res
 }
 
 template <class _InputIterator, class _OutputIterator, class _BinaryOperation>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __result,
               _BinaryOperation __binary_op)
@@ -325,7 +328,7 @@ partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __res
 
 #if _LIBCPP_STD_VER > 14
 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 exclusive_scan(_InputIterator __first, _InputIterator __last,
                _OutputIterator __result, _Tp __init, _BinaryOp __b)
@@ -345,7 +348,7 @@ exclusive_scan(_InputIterator __first, _InputIterator __last,
 }
 
 template <class _InputIterator, class _OutputIterator, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 exclusive_scan(_InputIterator __first, _InputIterator __last,
                _OutputIterator __result, _Tp __init)
@@ -354,6 +357,7 @@ exclusive_scan(_InputIterator __first, _InputIterator __last,
 }
 
 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp>
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
                                _OutputIterator __result, _BinaryOp __b,  _Tp __init)
 {
@@ -365,6 +369,7 @@ _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
 }
 
 template <class _InputIterator, class _OutputIterator, class _BinaryOp>
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
                                _OutputIterator __result, _BinaryOp __b)
 {
@@ -379,6 +384,7 @@ _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
 }
 
 template <class _InputIterator, class _OutputIterator>
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
                                _OutputIterator __result)
 {
@@ -387,7 +393,7 @@ _OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
 
 template <class _InputIterator, class _OutputIterator, class _Tp,
           class _BinaryOp, class _UnaryOp>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 transform_exclusive_scan(_InputIterator __first, _InputIterator __last,
                            _OutputIterator __result, _Tp __init,
@@ -408,7 +414,9 @@ transform_exclusive_scan(_InputIterator __first, _InputIterator __last,
 }
 
 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp, class _UnaryOp>
-_OutputIterator transform_inclusive_scan(_InputIterator __first, _InputIterator __last,
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_OutputIterator
+transform_inclusive_scan(_InputIterator __first, _InputIterator __last,
                            _OutputIterator __result, _BinaryOp __b, _UnaryOp __u, _Tp __init)
 {
     for (; __first != __last; ++__first, (void) ++__result) {
@@ -420,7 +428,9 @@ _OutputIterator transform_inclusive_scan(_InputIterator __first, _InputIterator
 }
 
 template <class _InputIterator, class _OutputIterator, class _BinaryOp, class _UnaryOp>
-_OutputIterator transform_inclusive_scan(_InputIterator __first, _InputIterator __last,
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_OutputIterator
+transform_inclusive_scan(_InputIterator __first, _InputIterator __last,
                                _OutputIterator __result, _BinaryOp __b, _UnaryOp __u)
 {
     if (__first != __last) {
@@ -435,7 +445,7 @@ _OutputIterator transform_inclusive_scan(_InputIterator __first, _InputIterator
 #endif
 
 template <class _InputIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 adjacent_
diff erence(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
 {
@@ -458,7 +468,7 @@ adjacent_
diff erence(_InputIterator __first, _InputIterator __last, _OutputIterat
 }
 
 template <class _InputIterator, class _OutputIterator, class _BinaryOperation>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 adjacent_
diff erence(_InputIterator __first, _InputIterator __last, _OutputIterator __result,
                       _BinaryOperation __binary_op)
@@ -482,7 +492,7 @@ adjacent_
diff erence(_InputIterator __first, _InputIterator __last, _OutputIterat
 }
 
 template <class _ForwardIterator, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 void
 iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value_)
 {

diff  --git a/libcxx/include/version b/libcxx/include/version
index 58f676548fe7..2f1fd92db406 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -48,6 +48,7 @@ __cpp_lib_concepts                                      201806L <concepts>
 __cpp_lib_constexpr_dynamic_alloc                       201907L <memory>
 __cpp_lib_constexpr_misc                                201811L <array> <functional> <iterator>
                                                                 <string_view> <tuple> <utility>
+__cpp_lib_constexpr_numeric                             201911L <numeric>
 __cpp_lib_constexpr_swap_algorithms                     201806L <algorithm>
 __cpp_lib_constexpr_utility                             201811L <utility>
 __cpp_lib_destroying_delete                             201806L <new>
@@ -254,6 +255,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 // # define __cpp_lib_concepts                             201806L
 # define __cpp_lib_constexpr_dynamic_alloc              201907L
 // # define __cpp_lib_constexpr_misc                       201811L
+# define __cpp_lib_constexpr_numeric                    201911L
 // # define __cpp_lib_constexpr_swap_algorithms            201806L
 # define __cpp_lib_constexpr_utility                    201811L
 # if _LIBCPP_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.pass.cpp
index c43d7175e1ee..881c81474eb0 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.pass.cpp
@@ -14,6 +14,7 @@
 // Test the feature test macros defined by <numeric>
 
 /*  Constant                        Value
+    __cpp_lib_constexpr_numeric     201911L [C++2a]
     __cpp_lib_gcd_lcm               201606L [C++17]
     __cpp_lib_interpolate           201902L [C++2a]
     __cpp_lib_parallel_algorithm    201603L [C++17]
@@ -24,6 +25,10 @@
 
 #if TEST_STD_VER < 14
 
+# ifdef __cpp_lib_constexpr_numeric
+#   error "__cpp_lib_constexpr_numeric should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_gcd_lcm
 #   error "__cpp_lib_gcd_lcm should not be defined before c++17"
 # endif
@@ -38,6 +43,10 @@
 
 #elif TEST_STD_VER == 14
 
+# ifdef __cpp_lib_constexpr_numeric
+#   error "__cpp_lib_constexpr_numeric should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_gcd_lcm
 #   error "__cpp_lib_gcd_lcm should not be defined before c++17"
 # endif
@@ -52,6 +61,10 @@
 
 #elif TEST_STD_VER == 17
 
+# ifdef __cpp_lib_constexpr_numeric
+#   error "__cpp_lib_constexpr_numeric should not be defined before c++2a"
+# endif
+
 # ifndef __cpp_lib_gcd_lcm
 #   error "__cpp_lib_gcd_lcm should be defined in c++17"
 # endif
@@ -78,6 +91,13 @@
 
 #elif TEST_STD_VER > 17
 
+# ifndef __cpp_lib_constexpr_numeric
+#   error "__cpp_lib_constexpr_numeric should be defined in c++2a"
+# endif
+# if __cpp_lib_constexpr_numeric != 201911L
+#   error "__cpp_lib_constexpr_numeric should have the value 201911L in c++2a"
+# endif
+
 # ifndef __cpp_lib_gcd_lcm
 #   error "__cpp_lib_gcd_lcm should be defined in c++2a"
 # endif

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 efb8416924ce..0aaef3c51122 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
@@ -42,6 +42,7 @@
     __cpp_lib_concepts                             201806L [C++2a]
     __cpp_lib_constexpr_dynamic_alloc              201907L [C++2a]
     __cpp_lib_constexpr_misc                       201811L [C++2a]
+    __cpp_lib_constexpr_numeric                    201911L [C++2a]
     __cpp_lib_constexpr_swap_algorithms            201806L [C++2a]
     __cpp_lib_constexpr_utility                    201811L [C++2a]
     __cpp_lib_destroying_delete                    201806L [C++2a]
@@ -227,6 +228,10 @@
 #   error "__cpp_lib_constexpr_misc should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_constexpr_numeric
+#   error "__cpp_lib_constexpr_numeric should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_constexpr_swap_algorithms
 #   error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a"
 # endif
@@ -619,6 +624,10 @@
 #   error "__cpp_lib_constexpr_misc should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_constexpr_numeric
+#   error "__cpp_lib_constexpr_numeric should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_constexpr_swap_algorithms
 #   error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a"
 # endif
@@ -1125,6 +1134,10 @@
 #   error "__cpp_lib_constexpr_misc should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_constexpr_numeric
+#   error "__cpp_lib_constexpr_numeric should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_constexpr_swap_algorithms
 #   error "__cpp_lib_constexpr_swap_algorithms should not be defined before c++2a"
 # endif
@@ -1910,6 +1923,13 @@
 #   endif
 # endif
 
+# ifndef __cpp_lib_constexpr_numeric
+#   error "__cpp_lib_constexpr_numeric should be defined in c++2a"
+# endif
+# if __cpp_lib_constexpr_numeric != 201911L
+#   error "__cpp_lib_constexpr_numeric should have the value 201911L in c++2a"
+# endif
+
 # if !defined(_LIBCPP_VERSION)
 #   ifndef __cpp_lib_constexpr_swap_algorithms
 #     error "__cpp_lib_constexpr_swap_algorithms should be defined in c++2a"

diff  --git a/libcxx/test/std/numerics/numeric.ops/accumulate/accumulate.pass.cpp b/libcxx/test/std/numerics/numeric.ops/accumulate/accumulate.pass.cpp
index 8513635de3e1..d491bc0394b3 100644
--- a/libcxx/test/std/numerics/numeric.ops/accumulate/accumulate.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/accumulate/accumulate.pass.cpp
@@ -7,7 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 // <numeric>
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template <InputIterator Iter, MoveConstructible T>
 //   requires HasPlus<T, Iter::reference>
 //         && HasAssign<T, HasPlus<T, Iter::reference>::result_type>
@@ -21,14 +23,14 @@
 #include "test_iterators.h"
 
 template <class Iter, class T>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter first, Iter last, T init, T x)
 {
     assert(std::accumulate(first, last, init) == x);
 }
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[] = {1, 2, 3, 4, 5, 6};
@@ -43,7 +45,8 @@ test()
     test(Iter(ia), Iter(ia+sa), 10, 31);
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test<input_iterator<const int*> >();
     test<forward_iterator<const int*> >();
@@ -51,5 +54,14 @@ int main(int, char**)
     test<random_access_iterator<const int*> >();
     test<const int*>();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/accumulate/accumulate_op.pass.cpp b/libcxx/test/std/numerics/numeric.ops/accumulate/accumulate_op.pass.cpp
index c2a430f370f7..bef328e5ba02 100644
--- a/libcxx/test/std/numerics/numeric.ops/accumulate/accumulate_op.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/accumulate/accumulate_op.pass.cpp
@@ -7,7 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 // <numeric>
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template <InputIterator Iter, MoveConstructible T,
 //           Callable<auto, const T&, Iter::reference> BinaryOperation>
 //   requires HasAssign<T, BinaryOperation::result_type>
@@ -29,25 +31,25 @@ struct rvalue_addable
     bool correctOperatorUsed = false;
 
     // make sure the predicate is passed an rvalue and an lvalue (so check that the first argument was moved)
-    rvalue_addable operator()(rvalue_addable&& r, rvalue_addable const&) {
+    constexpr rvalue_addable operator()(rvalue_addable&& r, rvalue_addable const&) {
         r.correctOperatorUsed = true;
         return std::move(r);
     }
 };
 
-rvalue_addable operator+(rvalue_addable& lhs, rvalue_addable const&)
+constexpr rvalue_addable operator+(rvalue_addable& lhs, rvalue_addable const&)
 {
     lhs.correctOperatorUsed = false;
         return lhs;
 }
 
-rvalue_addable operator+(rvalue_addable&& lhs, rvalue_addable const&)
+constexpr rvalue_addable operator+(rvalue_addable&& lhs, rvalue_addable const&)
 {
     lhs.correctOperatorUsed = true;
     return std::move(lhs);
 }
 
-void
+constexpr void
 test_use_move()
 {
     rvalue_addable arr[100];
@@ -58,7 +60,15 @@ test_use_move()
 }
 #endif // TEST_STD_VER > 17
 
+// C++20 can use string in constexpr evaluation, but both libc++ and MSVC
+// don't have the support yet. In these cases omit the constexpr test.
+// FIXME Remove constexpr string workaround introduced in D90569
+#if TEST_STD_VER > 17 && \
+	(!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
 void
+#else
+TEST_CONSTEXPR_CXX20 void
+#endif
 test_string()
 {
     std::string sa[] = {"a", "b", "c"};
@@ -67,14 +77,14 @@ test_string()
 }
 
 template <class Iter, class T>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter first, Iter last, T init, T x)
 {
     assert(std::accumulate(first, last, init, std::multiplies<T>()) == x);
 }
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[] = {1, 2, 3, 4, 5, 6};
@@ -89,7 +99,8 @@ test()
     test(Iter(ia), Iter(ia+sa), 10, 7200);
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test<input_iterator<const int*> >();
     test<forward_iterator<const int*> >();
@@ -100,7 +111,23 @@ int main(int, char**)
 #if TEST_STD_VER > 17
     test_use_move();
 #endif // TEST_STD_VER > 17
+    // C++20 can use string in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases omit the constexpr test.
+    // FIXME Remove constexpr string workaround introduced in D90569
+#if TEST_STD_VER > 17 && \
+	(!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
+	if (!std::is_constant_evaluated())
+#endif
     test_string();
 
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
     return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/adjacent.
diff erence/adjacent_
diff erence.pass.cpp b/libcxx/test/std/numerics/numeric.ops/adjacent.
diff erence/adjacent_
diff erence.pass.cpp
index 3e043e5cb8fe..f39715cfb13e 100644
--- a/libcxx/test/std/numerics/numeric.ops/adjacent.
diff erence/adjacent_
diff erence.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/adjacent.
diff erence/adjacent_
diff erence.pass.cpp
@@ -7,7 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 // <numeric>
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template <InputIterator InIter,
 //           OutputIterator<auto, const InIter::value_type&> OutIter>
 //   requires HasMinus<InIter::value_type, InIter::value_type>
@@ -25,7 +27,7 @@
 #include "test_iterators.h"
 
 template <class InIter, class OutIter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[] = {15, 10, 6, 3, 1};
@@ -46,18 +48,18 @@ class X
 {
     int i_;
 
-    X& operator=(const X&);
+    TEST_CONSTEXPR_CXX20 X& operator=(const X&);
 public:
-    explicit X(int i) : i_(i) {}
-    X(const X& x) : i_(x.i_) {}
-    X& operator=(X&& x)
+    TEST_CONSTEXPR_CXX20 explicit X(int i) : i_(i) {}
+    TEST_CONSTEXPR_CXX20 X(const X& x) : i_(x.i_) {}
+    TEST_CONSTEXPR_CXX20 X& operator=(X&& x)
     {
         i_ = x.i_;
         x.i_ = -1;
         return *this;
     }
 
-    friend X operator-(const X& x, const X& y) {return X(x.i_ - y.i_);}
+    TEST_CONSTEXPR_CXX20 friend X operator-(const X& x, const X& y) {return X(x.i_ - y.i_);}
 
     friend class Y;
 };
@@ -66,16 +68,17 @@ class Y
 {
     int i_;
 
-    Y& operator=(const Y&);
+    TEST_CONSTEXPR_CXX20 Y& operator=(const Y&);
 public:
-    explicit Y(int i) : i_(i) {}
-    Y(const Y& y) : i_(y.i_) {}
-    void operator=(const X& x) {i_ = x.i_;}
+    TEST_CONSTEXPR_CXX20 explicit Y(int i) : i_(i) {}
+    TEST_CONSTEXPR_CXX20 Y(const Y& y) : i_(y.i_) {}
+    TEST_CONSTEXPR_CXX20 void operator=(const X& x) {i_ = x.i_;}
 };
 
 #endif
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test<input_iterator<const int*>, output_iterator<int*> >();
     test<input_iterator<const int*>, forward_iterator<int*> >();
@@ -113,5 +116,14 @@ int main(int, char**)
     std::adjacent_
diff erence(x, x+3, y);
 #endif
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/adjacent.
diff erence/adjacent_
diff erence_op.pass.cpp b/libcxx/test/std/numerics/numeric.ops/adjacent.
diff erence/adjacent_
diff erence_op.pass.cpp
index f8c12abd9e2b..636d50d0f4ff 100644
--- a/libcxx/test/std/numerics/numeric.ops/adjacent.
diff erence/adjacent_
diff erence_op.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/adjacent.
diff erence/adjacent_
diff erence_op.pass.cpp
@@ -7,7 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 // <numeric>
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template <InputIterator InIter,
 //           OutputIterator<auto, const InIter::value_type&> OutIter,
 //           Callable<auto, const InIter::value_type&, const InIter::value_type&> BinaryOperation>
@@ -32,25 +34,25 @@ struct rvalue_subtractable
     bool correctOperatorUsed = false;
 
     // make sure the predicate is passed an rvalue and an lvalue (so check that the first argument was moved)
-    rvalue_subtractable operator()(rvalue_subtractable const&, rvalue_subtractable&& r) {
+    constexpr rvalue_subtractable operator()(rvalue_subtractable const&, rvalue_subtractable&& r) {
         r.correctOperatorUsed = true;
         return std::move(r);
     }
 };
 
-rvalue_subtractable operator-(rvalue_subtractable const&, rvalue_subtractable& rhs)
+constexpr rvalue_subtractable operator-(rvalue_subtractable const&, rvalue_subtractable& rhs)
 {
     rhs.correctOperatorUsed = false;
     return rhs;
 }
 
-rvalue_subtractable operator-(rvalue_subtractable const&, rvalue_subtractable&& rhs)
+constexpr rvalue_subtractable operator-(rvalue_subtractable const&, rvalue_subtractable&& rhs)
 {
     rhs.correctOperatorUsed = true;
     return std::move(rhs);
 }
 
-void
+constexpr void
 test_use_move()
 {
     const std::size_t size = 100;
@@ -65,7 +67,15 @@ test_use_move()
 }
 #endif // TEST_STD_VER > 17
 
+// C++20 can use string in constexpr evaluation, but both libc++ and MSVC
+// don't have the support yet. In these cases omit the constexpr test.
+// FIXME Remove constexpr string workaround introduced in D90569
+#if TEST_STD_VER > 17 && \
+	(!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
 void
+#else
+TEST_CONSTEXPR_CXX20 void
+#endif
 test_string()
 {
     std::string sa[] = {"a", "b", "c"};
@@ -76,7 +86,7 @@ test_string()
 }
 
 template <class InIter, class OutIter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[] = {15, 10, 6, 3, 1};
@@ -98,18 +108,18 @@ class X
 {
     int i_;
 
-    X& operator=(const X&);
+    TEST_CONSTEXPR_CXX20 X& operator=(const X&);
 public:
-    explicit X(int i) : i_(i) {}
-    X(const X& x) : i_(x.i_) {}
-    X& operator=(X&& x)
+    TEST_CONSTEXPR_CXX20 explicit X(int i) : i_(i) {}
+    TEST_CONSTEXPR_CXX20 X(const X& x) : i_(x.i_) {}
+    TEST_CONSTEXPR_CXX20 X& operator=(X&& x)
     {
         i_ = x.i_;
         x.i_ = -1;
         return *this;
     }
 
-    friend X operator-(const X& x, const X& y) {return X(x.i_ - y.i_);}
+    TEST_CONSTEXPR_CXX20 friend X operator-(const X& x, const X& y) {return X(x.i_ - y.i_);}
 
     friend class Y;
 };
@@ -118,17 +128,18 @@ class Y
 {
     int i_;
 
-    Y& operator=(const Y&);
+    TEST_CONSTEXPR_CXX20 Y& operator=(const Y&);
 public:
-    explicit Y(int i) : i_(i) {}
-    Y(const Y& y) : i_(y.i_) {}
-    void operator=(const X& x) {i_ = x.i_;}
+    TEST_CONSTEXPR_CXX20 explicit Y(int i) : i_(i) {}
+    TEST_CONSTEXPR_CXX20 Y(const Y& y) : i_(y.i_) {}
+    TEST_CONSTEXPR_CXX20 void operator=(const X& x) {i_ = x.i_;}
 };
 
 #endif
 
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test<input_iterator<const int*>, output_iterator<int*> >();
     test<input_iterator<const int*>, forward_iterator<int*> >();
@@ -169,7 +180,23 @@ int main(int, char**)
 #if TEST_STD_VER > 17
     test_use_move();
 #endif // TEST_STD_VER > 17
+    // C++20 can use string in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases omit the constexpr test.
+    // FIXME Remove constexpr string workaround introduced in D90569
+#if TEST_STD_VER > 17 && \
+	(!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
+	if (!std::is_constant_evaluated())
+#endif
     test_string();
 
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
     return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan.pass.cpp b/libcxx/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan.pass.cpp
index a4b7da0e1479..1317c7664ada 100644
--- a/libcxx/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<class InputIterator, class OutputIterator, class T>
 //     OutputIterator exclusive_scan(InputIterator first, InputIterator last,
 //                                   OutputIterator result, T init);
@@ -16,6 +18,7 @@
 
 #include <numeric>
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <functional>
 #include <iterator>
@@ -23,27 +26,42 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+// FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER > 17
+#include <span>
+#endif
 
 template <class Iter1, class T, class Iter2>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first, Iter1 last, T init, Iter2 rFirst, Iter2 rLast)
 {
-    std::vector<typename std::iterator_traits<Iter1>::value_type> v;
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+    size_t size = std::distance(first, last);
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
+
+    std::vector<typename std::iterator_traits<Iter1>::value_type> v(size);
+#else
+    assert((size <= 5) && "Increment the size of the array");
+    typename std::iterator_traits<Iter1>::value_type b[5];
+    std::span<typename std::iterator_traits<Iter1>::value_type> v{b, size};
+#endif
 
 //  Not in place
-    std::exclusive_scan(first, last, std::back_inserter(v), init);
+    std::exclusive_scan(first, last, v.begin(), init);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 
 //  In place
-    v.clear();
-    v.assign(first, last);
+    std::copy(first, last, v.begin());
     std::exclusive_scan(v.begin(), v.end(), v.begin(), init);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 }
 
-
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
           int ia[]   = {1, 3, 5, 7,  9};
@@ -55,13 +73,14 @@ test()
         test(Iter(ia), Iter(ia + i), 0, pRes, pRes + i);
 }
 
-size_t triangle(size_t n) { return n*(n+1)/2; }
+constexpr size_t triangle(size_t n) { return n*(n+1)/2; }
 
 //  Basic sanity
-void basic_tests()
+TEST_CONSTEXPR_CXX20 void
+basic_tests()
 {
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::fill(v.begin(), v.end(), 3);
     std::exclusive_scan(v.begin(), v.end(), v.begin(), size_t{50});
     for (size_t i = 0; i < v.size(); ++i)
@@ -69,7 +88,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 0);
     std::exclusive_scan(v.begin(), v.end(), v.begin(), size_t{30});
     for (size_t i = 0; i < v.size(); ++i)
@@ -77,7 +96,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 1);
     std::exclusive_scan(v.begin(), v.end(), v.begin(), size_t{40});
     for (size_t i = 0; i < v.size(); ++i)
@@ -86,7 +105,8 @@ void basic_tests()
 
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     basic_tests();
 
@@ -98,5 +118,14 @@ int main(int, char**)
     test<const int*>();
     test<      int*>();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan_init_op.pass.cpp b/libcxx/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan_init_op.pass.cpp
index 471fa856be9c..fb2078dae7af 100644
--- a/libcxx/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan_init_op.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/exclusive.scan/exclusive_scan_init_op.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
 //     OutputIterator
 //     exclusive_scan(InputIterator first, InputIterator last,
@@ -17,6 +19,7 @@
 
 #include <numeric>
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <functional>
 #include <iterator>
@@ -24,27 +27,43 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+// FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER > 17
+#include <span>
+#endif
 
 template <class Iter1, class T, class Op, class Iter2>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first, Iter1 last, T init, Op op, Iter2 rFirst, Iter2 rLast)
 {
-    std::vector<typename std::iterator_traits<Iter1>::value_type> v;
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+    size_t size = std::distance(first, last);
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
+
+    std::vector<typename std::iterator_traits<Iter1>::value_type> v(size);
+#else
+    assert((size <= 5) && "Increment the size of the array");
+    typename std::iterator_traits<Iter1>::value_type b[5];
+    std::span<typename std::iterator_traits<Iter1>::value_type> v{b, size};
+#endif
 
 //  Not in place
-    std::exclusive_scan(first, last, std::back_inserter(v), init, op);
+    std::exclusive_scan(first, last, v.begin(), init, op);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 
 //  In place
-    v.clear();
-    v.assign(first, last);
+    std::copy(first, last, v.begin());
     std::exclusive_scan(v.begin(), v.end(), v.begin(), init, op);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 }
 
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
           int ia[]   = {1, 3, 5,  7,   9};
@@ -60,7 +79,8 @@ test()
         }
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
 //  All the iterator categories
     test<input_iterator        <const int*> >();
@@ -72,10 +92,20 @@ int main(int, char**)
 
 //  Make sure that the calculations are done using the init typedef
     {
-    std::vector<unsigned char> v(10);
+    std::array<unsigned char, 10> v;
     std::iota(v.begin(), v.end(), static_cast<unsigned char>(1));
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
     std::vector<size_t> res;
     std::exclusive_scan(v.begin(), v.end(), std::back_inserter(res), 1, std::multiplies<>());
+#else
+    std::array<size_t, 10> res;
+    std::exclusive_scan(v.begin(), v.end(), res.begin(), 1, std::multiplies<>());
+#endif
 
     assert(res.size() == 10);
     size_t j = 1;
@@ -87,5 +117,14 @@ int main(int, char**)
     }
     }
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan.pass.cpp b/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan.pass.cpp
index ca262254c16c..18178153b0b8 100644
--- a/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<class InputIterator, class OutputIterator, class T>
 //     OutputIterator inclusive_scan(InputIterator first, InputIterator last,
 //                                   OutputIterator result, T init);
@@ -16,6 +18,7 @@
 
 #include <numeric>
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <functional>
 #include <iterator>
@@ -23,27 +26,43 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+// FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER > 17
+#include <span>
+#endif
 
 template <class Iter1, class Iter2>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first, Iter1 last, Iter2 rFirst, Iter2 rLast)
 {
-    std::vector<typename std::iterator_traits<Iter1>::value_type> v;
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+    size_t size = std::distance(first, last);
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
+
+    std::vector<typename std::iterator_traits<Iter1>::value_type> v(size);
+#else
+    assert((size <= 5) && "Increment the size of the array");
+    typename std::iterator_traits<Iter1>::value_type b[5];
+    std::span<typename std::iterator_traits<Iter1>::value_type> v{b, size};
+#endif
 
 //  Not in place
-    std::inclusive_scan(first, last, std::back_inserter(v));
+    std::inclusive_scan(first, last, v.begin());
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 
 //  In place
-    v.clear();
-    v.assign(first, last);
+    std::copy(first, last, v.begin());
     std::inclusive_scan(v.begin(), v.end(), v.begin());
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 }
 
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
           int ia[]   = {1, 3, 5, 7,  9};
@@ -55,13 +74,14 @@ test()
         test(Iter(ia), Iter(ia + i), pRes, pRes + i);
 }
 
-size_t triangle(size_t n) { return n*(n+1)/2; }
+constexpr size_t triangle(size_t n) { return n*(n+1)/2; }
 
 //  Basic sanity
-void basic_tests()
+TEST_CONSTEXPR_CXX20 void
+basic_tests()
 {
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::fill(v.begin(), v.end(), 3);
     std::inclusive_scan(v.begin(), v.end(), v.begin());
     for (size_t i = 0; i < v.size(); ++i)
@@ -69,7 +89,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 0);
     std::inclusive_scan(v.begin(), v.end(), v.begin());
     for (size_t i = 0; i < v.size(); ++i)
@@ -77,7 +97,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 1);
     std::inclusive_scan(v.begin(), v.end(), v.begin());
     for (size_t i = 0; i < v.size(); ++i)
@@ -85,13 +105,24 @@ void basic_tests()
     }
 
     {
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
     std::vector<size_t> v, res;
     std::inclusive_scan(v.begin(), v.end(), std::back_inserter(res));
+#else
+    std::array<size_t, 0> v, res;
+    std::inclusive_scan(v.begin(), v.end(), res.begin());
+#endif
     assert(res.empty());
     }
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     basic_tests();
 
@@ -103,5 +134,14 @@ int main(int, char**)
     test<const int*>();
     test<      int*>();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op.pass.cpp b/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op.pass.cpp
index 322b502369f3..00092a69317c 100644
--- a/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
 //     OutputIterator
 //     inclusive_scan(InputIterator first, InputIterator last,
@@ -17,6 +19,7 @@
 
 #include <numeric>
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <functional>
 #include <iterator>
@@ -24,27 +27,43 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+// FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER > 17
+#include <span>
+#endif
 
-template <class Iter1, class T, class Op, class Iter2>
-void
+template <class Iter1, class Op, class Iter2>
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first, Iter1 last, Op op, Iter2 rFirst, Iter2 rLast)
 {
-    std::vector<typename std::iterator_traits<Iter1>::value_type> v;
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+    size_t size = std::distance(first, last);
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
+
+    std::vector<typename std::iterator_traits<Iter1>::value_type> v(size);
+#else
+    assert((size <= 5) && "Increment the size of the array");
+    typename std::iterator_traits<Iter1>::value_type b[5];
+    std::span<typename std::iterator_traits<Iter1>::value_type> v{b, size};
+#endif
 
 //  Not in place
-    std::inclusive_scan(first, last, std::back_inserter(v), op);
+    std::inclusive_scan(first, last, v.begin(), op);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 
 //  In place
-    v.clear();
-    v.assign(first, last);
+    std::copy(first, last, v.begin());
     std::inclusive_scan(v.begin(), v.end(), v.begin(), op);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 }
 
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
           int ia[]   = {1, 3,  5,   7,   9};
@@ -60,13 +79,14 @@ test()
         }
 }
 
-size_t triangle(size_t n) { return n*(n+1)/2; }
+constexpr size_t triangle(size_t n) { return n*(n+1)/2; }
 
 //  Basic sanity
-void basic_tests()
+TEST_CONSTEXPR_CXX20 void
+basic_tests()
 {
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::fill(v.begin(), v.end(), 3);
     std::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>());
     for (size_t i = 0; i < v.size(); ++i)
@@ -74,7 +94,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 0);
     std::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>());
     for (size_t i = 0; i < v.size(); ++i)
@@ -82,7 +102,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 1);
     std::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>());
     for (size_t i = 0; i < v.size(); ++i)
@@ -90,26 +110,43 @@ void basic_tests()
     }
 
     {
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
     std::vector<size_t> v, res;
     std::inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus<>());
+#else
+    std::array<size_t, 0> v, res;
+    std::inclusive_scan(v.begin(), v.end(), res.begin(), std::plus<>());
+#endif
     assert(res.empty());
     }
 }
 
-
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
-
     basic_tests();
 
 //  All the iterator categories
-//     test<input_iterator        <const int*> >();
-//     test<forward_iterator      <const int*> >();
-//     test<bidirectional_iterator<const int*> >();
-//     test<random_access_iterator<const int*> >();
-//     test<const int*>();
-//     test<      int*>();
-
+    test<input_iterator        <const int*> >();
+    test<forward_iterator      <const int*> >();
+    test<bidirectional_iterator<const int*> >();
+    test<random_access_iterator<const int*> >();
+    test<const int*>();
+    test<      int*>();
+
+    return true;
+}
 
-  return 0;
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op_init.pass.cpp b/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op_init.pass.cpp
index d941a8439d25..6c965000ccc0 100644
--- a/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op_init.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op_init.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
 //     OutputIterator
 //     inclusive_scan(InputIterator first, InputIterator last,
@@ -17,6 +19,7 @@
 
 #include <numeric>
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <functional>
 #include <iterator>
@@ -24,27 +27,43 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+// FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER > 17
+#include <span>
+#endif
 
 template <class Iter1, class T, class Op, class Iter2>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first, Iter1 last, Op op, T init, Iter2 rFirst, Iter2 rLast)
 {
-    std::vector<typename std::iterator_traits<Iter1>::value_type> v;
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+    size_t size = std::distance(first, last);
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
+
+    std::vector<typename std::iterator_traits<Iter1>::value_type> v(size);
+#else
+    assert((size <= 5) && "Increment the size of the array");
+    typename std::iterator_traits<Iter1>::value_type b[5];
+    std::span<typename std::iterator_traits<Iter1>::value_type> v{b, size};
+#endif
 
 //  Not in place
-    std::inclusive_scan(first, last, std::back_inserter(v), op, init);
+    std::inclusive_scan(first, last, v.begin(), op, init);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 
 //  In place
-    v.clear();
-    v.assign(first, last);
+    std::copy(first, last, v.begin());
     std::inclusive_scan(v.begin(), v.end(), v.begin(), op, init);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 }
 
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
           int ia[]   = {1, 3,  5,   7,   9};
@@ -60,13 +79,14 @@ test()
         }
 }
 
-size_t triangle(size_t n) { return n*(n+1)/2; }
+constexpr size_t triangle(size_t n) { return n*(n+1)/2; }
 
 //  Basic sanity
-void basic_tests()
+TEST_CONSTEXPR_CXX20 void
+basic_tests()
 {
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::fill(v.begin(), v.end(), 3);
     std::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>(), size_t{50});
     for (size_t i = 0; i < v.size(); ++i)
@@ -74,7 +94,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 0);
     std::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>(), size_t{40});
     for (size_t i = 0; i < v.size(); ++i)
@@ -82,7 +102,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 1);
     std::inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>(), size_t{30});
     for (size_t i = 0; i < v.size(); ++i)
@@ -90,17 +110,37 @@ void basic_tests()
     }
 
     {
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
     std::vector<size_t> v, res;
     std::inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus<>(), size_t{40});
+#else
+    std::array<size_t, 0> v, res;
+    std::inclusive_scan(v.begin(), v.end(), res.begin(), std::plus<>(), size_t{40});
+#endif
     assert(res.empty());
     }
 
 //  Make sure that the calculations are done using the init typedef
     {
-    std::vector<unsigned char> v(10);
+    std::array<unsigned char, 10> v;
     std::iota(v.begin(), v.end(), static_cast<unsigned char>(1));
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
     std::vector<size_t> res;
     std::inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::multiplies<>(), size_t{1});
+#else
+    std::array<size_t, 10> res;
+    std::inclusive_scan(v.begin(), v.end(), res.begin(), std::multiplies<>(), size_t{1});
+#endif
 
     assert(res.size() == 10);
     size_t j = 1;
@@ -113,10 +153,9 @@ void basic_tests()
     }
 }
 
-
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
-
     basic_tests();
 
 //  All the iterator categories
@@ -127,6 +166,14 @@ int main(int, char**)
     test<const int*>();
     test<      int*>();
 
+    return true;
+}
 
-  return 0;
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/inner.product/inner_product.pass.cpp b/libcxx/test/std/numerics/numeric.ops/inner.product/inner_product.pass.cpp
index 5e87325937a0..aa74bb483f7b 100644
--- a/libcxx/test/std/numerics/numeric.ops/inner.product/inner_product.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/inner.product/inner_product.pass.cpp
@@ -7,7 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 // <numeric>
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template <InputIterator Iter1, InputIterator Iter2, MoveConstructible T>
 //   requires HasMultiply<Iter1::reference, Iter2::reference>
 //         && HasPlus<T, HasMultiply<Iter1::reference, Iter2::reference>::result_type>
@@ -25,14 +27,14 @@
 #include "test_iterators.h"
 
 template <class Iter1, class Iter2, class T>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first1, Iter1 last1, Iter2 first2, T init, T x)
 {
     assert(std::inner_product(first1, last1, first2, init) == x);
 }
 
 template <class Iter1, class Iter2>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int a[] = {1, 2, 3, 4, 5, 6};
@@ -48,7 +50,8 @@ test()
     test(Iter1(a), Iter1(a+sa), Iter2(b), 10, 66);
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test<input_iterator<const int*>, input_iterator<const int*> >();
     test<input_iterator<const int*>, forward_iterator<const int*> >();
@@ -80,5 +83,14 @@ int main(int, char**)
     test<const int*, random_access_iterator<const int*> >();
     test<const int*, const int*>();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/inner.product/inner_product_comp.pass.cpp b/libcxx/test/std/numerics/numeric.ops/inner.product/inner_product_comp.pass.cpp
index be325b65ec29..9e3edc1573ab 100644
--- a/libcxx/test/std/numerics/numeric.ops/inner.product/inner_product_comp.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/inner.product/inner_product_comp.pass.cpp
@@ -7,7 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 // <numeric>
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template <InputIterator Iter1, InputIterator Iter2, MoveConstructible T,
 //           class BinaryOperation1,
 //           Callable<auto, Iter1::reference, Iter2::reference> BinaryOperation2>
@@ -31,7 +33,7 @@
 struct do_nothing_op
 {
     template<class T>
-    T operator()(T a, T)
+    constexpr T operator()(T a, T)
     { return a; }
 };
 
@@ -39,28 +41,28 @@ struct rvalue_addable
 {
     bool correctOperatorUsed = false;
 
-    rvalue_addable operator*(rvalue_addable const&) { return *this; }
+    constexpr rvalue_addable operator*(rvalue_addable const&) { return *this; }
 
     // make sure the predicate is passed an rvalue and an lvalue (so check that the first argument was moved)
-    rvalue_addable operator()(rvalue_addable&& r, rvalue_addable const&) {
+    constexpr rvalue_addable operator()(rvalue_addable&& r, rvalue_addable const&) {
         r.correctOperatorUsed = true;
         return std::move(r);
     }
 };
 
-rvalue_addable operator+(rvalue_addable& lhs, rvalue_addable const&)
+constexpr rvalue_addable operator+(rvalue_addable& lhs, rvalue_addable const&)
 {
     lhs.correctOperatorUsed = false;
     return lhs;
 }
 
-rvalue_addable operator+(rvalue_addable&& lhs, rvalue_addable const&)
+constexpr rvalue_addable operator+(rvalue_addable&& lhs, rvalue_addable const&)
 {
     lhs.correctOperatorUsed = true;
     return std::move(lhs);
 }
 
-void
+constexpr void
 test_use_move()
 {
     rvalue_addable arr[100];
@@ -72,7 +74,15 @@ test_use_move()
 }
 #endif // TEST_STD_VER > 17
 
+// C++20 can use string in constexpr evaluation, but both libc++ and MSVC
+// don't have the support yet. In these cases omit the constexpr test.
+// FIXME Remove constexpr string workaround introduced in D90569
+#if TEST_STD_VER > 17 && \
+	(!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
 void
+#else
+TEST_CONSTEXPR_CXX20 void
+#endif
 test_string()
 {
     std::string sa[] = {"a", "b", "c"};
@@ -81,7 +91,7 @@ test_string()
 }
 
 template <class Iter1, class Iter2, class T>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first1, Iter1 last1, Iter2 first2, T init, T x)
 {
     assert(std::inner_product(first1, last1, first2, init,
@@ -89,7 +99,7 @@ test(Iter1 first1, Iter1 last1, Iter2 first2, T init, T x)
 }
 
 template <class Iter1, class Iter2>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int a[] = {1, 2, 3, 4, 5, 6};
@@ -105,7 +115,8 @@ test()
     test(Iter1(a), Iter1(a+sa), Iter2(b), 10, 1176490);
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test<input_iterator<const int*>, input_iterator<const int*> >();
     test<input_iterator<const int*>, forward_iterator<const int*> >();
@@ -140,7 +151,23 @@ int main(int, char**)
 #if TEST_STD_VER > 17
     test_use_move();
 #endif // TEST_STD_VER > 17
+    // C++20 can use string in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases omit the constexpr test.
+    // FIXME Remove constexpr string workaround introduced in D90569
+#if TEST_STD_VER > 17 && \
+	(!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
+	if (!std::is_constant_evaluated())
+#endif
     test_string();
 
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
     return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/numeric.iota/iota.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.iota/iota.pass.cpp
index 2cf99f8d44e3..50d0a0632f6a 100644
--- a/libcxx/test/std/numerics/numeric.ops/numeric.iota/iota.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/numeric.iota/iota.pass.cpp
@@ -7,7 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 // <numeric>
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template <class ForwardIterator, class T>
 //     void iota(ForwardIterator first, ForwardIterator last, T value);
 
@@ -18,7 +20,7 @@
 #include "test_iterators.h"
 
 template <class InIter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[] = {1, 2, 3, 4, 5};
@@ -29,12 +31,22 @@ test()
         assert(ia[i] == ir[i]);
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test<forward_iterator<int*> >();
     test<bidirectional_iterator<int*> >();
     test<random_access_iterator<int*> >();
     test<int*>();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/partial.sum/partial_sum.pass.cpp b/libcxx/test/std/numerics/numeric.ops/partial.sum/partial_sum.pass.cpp
index 51ef81340d10..236b3fd00a8b 100644
--- a/libcxx/test/std/numerics/numeric.ops/partial.sum/partial_sum.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/partial.sum/partial_sum.pass.cpp
@@ -7,7 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 // <numeric>
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template <InputIterator InIter, OutputIterator<auto, const InIter::value_type&> OutIter>
 //   requires HasPlus<InIter::value_type, InIter::reference>
 //         && HasAssign<InIter::value_type,
@@ -23,7 +25,7 @@
 #include "test_iterators.h"
 
 template <class InIter, class OutIter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[] = {1, 2, 3, 4, 5};
@@ -36,7 +38,8 @@ test()
         assert(ib[i] == ir[i]);
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test<input_iterator<const int*>, output_iterator<int*> >();
     test<input_iterator<const int*>, forward_iterator<int*> >();
@@ -68,5 +71,14 @@ int main(int, char**)
     test<const int*, random_access_iterator<int*> >();
     test<const int*, int*>();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/partial.sum/partial_sum_op.pass.cpp b/libcxx/test/std/numerics/numeric.ops/partial.sum/partial_sum_op.pass.cpp
index 133edd73b2b7..4095cee01dba 100644
--- a/libcxx/test/std/numerics/numeric.ops/partial.sum/partial_sum_op.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/partial.sum/partial_sum_op.pass.cpp
@@ -7,7 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 // <numeric>
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<InputIterator InIter,
 //          OutputIterator<auto, const InIter::value_type&> OutIter,
 //          Callable<auto, const InIter::value_type&, InIter::reference> BinaryOperation>
@@ -31,25 +33,25 @@ struct rvalue_addable
     bool correctOperatorUsed = false;
 
     // make sure the predicate is passed an rvalue and an lvalue (so check that the first argument was moved)
-    rvalue_addable operator()(rvalue_addable&& r, rvalue_addable const&) {
+    constexpr rvalue_addable operator()(rvalue_addable&& r, rvalue_addable const&) {
         r.correctOperatorUsed = true;
         return std::move(r);
     }
 };
 
-rvalue_addable operator+(rvalue_addable& lhs, rvalue_addable const&)
+constexpr rvalue_addable operator+(rvalue_addable& lhs, rvalue_addable const&)
 {
     lhs.correctOperatorUsed = false;
     return lhs;
 }
 
-rvalue_addable operator+(rvalue_addable&& lhs, rvalue_addable const&)
+constexpr rvalue_addable operator+(rvalue_addable&& lhs, rvalue_addable const&)
 {
     lhs.correctOperatorUsed = true;
     return std::move(lhs);
 }
 
-void
+constexpr void
 test_use_move()
 {
     const std::size_t size = 100;
@@ -64,7 +66,15 @@ test_use_move()
 }
 #endif // TEST_STD_VER > 17
 
+// C++20 can use string in constexpr evaluation, but both libc++ and MSVC
+// don't have the support yet. In these cases omit the constexpr test.
+// FIXME Remove constexpr string workaround introduced in D90569
+#if TEST_STD_VER > 17 && \
+	(!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
 void
+#else
+TEST_CONSTEXPR_CXX20 void
+#endif
 test_string()
 {
     std::string sa[] = {"a", "b", "c"};
@@ -75,7 +85,7 @@ test_string()
 }
 
 template <class InIter, class OutIter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[] = {1, 2, 3, 4, 5};
@@ -88,7 +98,8 @@ test()
         assert(ib[i] == ir[i]);
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test<input_iterator<const int*>, output_iterator<int*> >();
     test<input_iterator<const int*>, forward_iterator<int*> >();
@@ -123,7 +134,24 @@ int main(int, char**)
 #if TEST_STD_VER > 17
     test_use_move();
 #endif // TEST_STD_VER > 17
+    // C++20 can use string in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases omit the constexpr test.
+    // FIXME Remove constexpr string workaround introduced in D90569
+#if TEST_STD_VER > 17 && \
+	(!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L)
+	if (!std::is_constant_evaluated())
+#endif
     test_string();
 
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+
     return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/reduce/reduce.pass.cpp b/libcxx/test/std/numerics/numeric.ops/reduce/reduce.pass.cpp
index adcdcaac26ca..88e2e24b605a 100644
--- a/libcxx/test/std/numerics/numeric.ops/reduce/reduce.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/reduce/reduce.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<class InputIterator>
 //     typename iterator_traits<InputIterator>::value_type
 //     reduce(InputIterator first, InputIterator last);
@@ -20,7 +22,7 @@
 #include "test_iterators.h"
 
 template <class Iter, class T>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter first, Iter last, T x)
 {
     static_assert( std::is_same_v<typename std::iterator_traits<decltype(first)>::value_type,
@@ -29,7 +31,7 @@ test(Iter first, Iter last, T x)
 }
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[] = {1, 2, 3, 4, 5, 6};
@@ -41,13 +43,15 @@ test()
 }
 
 template <typename T>
-void test_return_type()
+TEST_CONSTEXPR_CXX20 void
+test_return_type()
 {
     T *p = nullptr;
     static_assert( std::is_same_v<T, decltype(std::reduce(p, p))> );
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test_return_type<char>();
     test_return_type<int>();
@@ -61,5 +65,14 @@ int main(int, char**)
     test<random_access_iterator<const int*> >();
     test<const int*>();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/reduce/reduce_init.pass.cpp b/libcxx/test/std/numerics/numeric.ops/reduce/reduce_init.pass.cpp
index 6c9492330d3f..073d3f8bc2c3 100644
--- a/libcxx/test/std/numerics/numeric.ops/reduce/reduce_init.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/reduce/reduce_init.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<class InputIterator, class T>
 //   T reduce(InputIterator first, InputIterator last, T init);
 
@@ -19,7 +21,7 @@
 #include "test_iterators.h"
 
 template <class Iter, class T>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter first, Iter last, T init, T x)
 {
     static_assert( std::is_same_v<T, decltype(std::reduce(first, last, init))> );
@@ -27,7 +29,7 @@ test(Iter first, Iter last, T init, T x)
 }
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[] = {1, 2, 3, 4, 5, 6};
@@ -43,13 +45,15 @@ test()
 }
 
 template <typename T, typename Init>
-void test_return_type()
+TEST_CONSTEXPR_CXX20 void
+test_return_type()
 {
     T *p = nullptr;
     static_assert( std::is_same_v<Init, decltype(std::reduce(p, p, Init{}))> );
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test_return_type<char, int>();
     test_return_type<int, int>();
@@ -65,5 +69,14 @@ int main(int, char**)
     test<random_access_iterator<const int*> >();
     test<const int*>();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/reduce/reduce_init_op.pass.cpp b/libcxx/test/std/numerics/numeric.ops/reduce/reduce_init_op.pass.cpp
index 044b70d4f9a1..0f3be386e05d 100644
--- a/libcxx/test/std/numerics/numeric.ops/reduce/reduce_init_op.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/reduce/reduce_init_op.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<class InputIterator, class T, class BinaryOperation>
 //   T reduce(InputIterator first, InputIterator last, T init, BinaryOperation op);
 
@@ -19,7 +21,7 @@
 #include "test_iterators.h"
 
 template <class Iter, class T, class Op>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter first, Iter last, T init, Op op, T x)
 {
     static_assert( std::is_same_v<T, decltype(std::reduce(first, last, init, op))>, "" );
@@ -27,7 +29,7 @@ test(Iter first, Iter last, T init, Op op, T x)
 }
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[] = {1, 2, 3, 4, 5, 6};
@@ -43,13 +45,15 @@ test()
 }
 
 template <typename T, typename Init>
-void test_return_type()
+TEST_CONSTEXPR_CXX20 void
+test_return_type()
 {
     T *p = nullptr;
     static_assert( std::is_same_v<Init, decltype(std::reduce(p, p, Init{}, std::plus<>()))>, "" );
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test_return_type<char, int>();
     test_return_type<int, int>();
@@ -72,5 +76,14 @@ int main(int, char**)
     assert(res == 40320);       // 8! will not fit into a char
     }
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/transform.exclusive.scan/transform_exclusive_scan_init_bop_uop.pass.cpp b/libcxx/test/std/numerics/numeric.ops/transform.exclusive.scan/transform_exclusive_scan_init_bop_uop.pass.cpp
index 301fb2f24242..d7fef8e90d19 100644
--- a/libcxx/test/std/numerics/numeric.ops/transform.exclusive.scan/transform_exclusive_scan_init_bop_uop.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/transform.exclusive.scan/transform_exclusive_scan_init_bop_uop.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<class InputIterator, class OutputIterator, class T,
 //          class BinaryOperation, class UnaryOperation>
 //   OutputIterator transform_exclusive_scan(InputIterator first, InputIterator last,
@@ -19,6 +21,7 @@
 
 #include <numeric>
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <functional>
 #include <iterator>
@@ -26,6 +29,10 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+// FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER > 17
+#include <span>
+#endif
 
 struct add_one {
     template <typename T>
@@ -35,24 +42,37 @@ struct add_one {
 };
 
 template <class Iter1, class BOp, class UOp, class T, class Iter2>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first, Iter1 last, BOp bop, UOp uop, T init, Iter2 rFirst, Iter2 rLast)
 {
-    std::vector<typename std::iterator_traits<Iter1>::value_type> v;
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+    size_t size = std::distance(first, last);
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
+
+    std::vector<typename std::iterator_traits<Iter1>::value_type> v(size);
+#else
+    assert((size <= 5) && "Increment the size of the array");
+    typename std::iterator_traits<Iter1>::value_type b[5];
+    std::span<typename std::iterator_traits<Iter1>::value_type> v{b, size};
+#endif
+
 //  Test not in-place
-    std::transform_exclusive_scan(first, last, std::back_inserter(v), init, bop, uop);
+    std::transform_exclusive_scan(first, last, v.begin(), init, bop, uop);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 
 //  Test in-place
-    v.clear();
-    v.assign(first, last);
+    std::copy(first, last, v.begin());
     std::transform_exclusive_scan(v.begin(), v.end(), v.begin(), init, bop, uop);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 }
 
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
           int ia[]     = { 1,  3,  5,    7,   9 };
@@ -86,13 +106,14 @@ test()
         }
 }
 
-size_t triangle(size_t n) { return n*(n+1)/2; }
+constexpr size_t triangle(size_t n) { return n*(n+1)/2; }
 
 //  Basic sanity
-void basic_tests()
+TEST_CONSTEXPR_CXX20 void
+basic_tests()
 {
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::fill(v.begin(), v.end(), 3);
     std::transform_exclusive_scan(v.begin(), v.end(), v.begin(), size_t{50}, std::plus<>(), add_one{});
     for (size_t i = 0; i < v.size(); ++i)
@@ -100,7 +121,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 0);
     std::transform_exclusive_scan(v.begin(), v.end(), v.begin(), size_t{30}, std::plus<>(), add_one{});
     for (size_t i = 0; i < v.size(); ++i)
@@ -108,7 +129,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 1);
     std::transform_exclusive_scan(v.begin(), v.end(), v.begin(), size_t{40}, std::plus<>(), add_one{});
     for (size_t i = 0; i < v.size(); ++i)
@@ -116,17 +137,37 @@ void basic_tests()
     }
 
     {
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
     std::vector<size_t> v, res;
     std::transform_exclusive_scan(v.begin(), v.end(), std::back_inserter(res), size_t{40}, std::plus<>(), add_one{});
+#else
+    std::array<size_t, 0> v, res;
+    std::transform_exclusive_scan(v.begin(), v.end(), res.begin(), size_t{40}, std::plus<>(), add_one{});
+#endif
     assert(res.empty());
     }
 
 //  Make sure that the calculations are done using the init typedef
     {
-    std::vector<unsigned char> v(10);
+    std::array<unsigned char, 10> v;
     std::iota(v.begin(), v.end(), static_cast<unsigned char>(1));
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
     std::vector<size_t> res;
     std::transform_exclusive_scan(v.begin(), v.end(), std::back_inserter(res), size_t{1}, std::multiplies<>(), add_one{});
+#else
+    std::array<size_t, 10> res;
+    std::transform_exclusive_scan(v.begin(), v.end(), res.begin(), size_t{1}, std::multiplies<>(), add_one{});
+#endif
 
     assert(res.size() == 10);
     size_t j = 1;
@@ -139,7 +180,8 @@ void basic_tests()
     }
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     basic_tests();
 
@@ -151,5 +193,14 @@ int main(int, char**)
     test<const int*>();
     test<      int*>();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop.pass.cpp b/libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop.pass.cpp
index 9caec15ab853..41b3b6258d27 100644
--- a/libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop.pass.cpp
@@ -9,7 +9,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<class InputIterator, class OutputIterator, class T,
 //          class BinaryOperation, class UnaryOperation>
 //   OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last,
@@ -20,6 +22,7 @@
 
 #include <numeric>
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <functional>
 #include <iterator>
@@ -27,6 +30,10 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+// FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER > 17
+#include <span>
+#endif
 
 struct add_one {
     template <typename T>
@@ -36,24 +43,37 @@ struct add_one {
 };
 
 template <class Iter1, class BOp, class UOp, class Iter2>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first, Iter1 last, BOp bop, UOp uop, Iter2 rFirst, Iter2 rLast)
 {
-    std::vector<typename std::iterator_traits<Iter1>::value_type> v;
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+    size_t size = std::distance(first, last);
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
+
+    std::vector<typename std::iterator_traits<Iter1>::value_type> v(size);
+#else
+    assert((size <= 5) && "Increment the size of the array");
+    typename std::iterator_traits<Iter1>::value_type b[5];
+    std::span<typename std::iterator_traits<Iter1>::value_type> v{b, size};
+#endif
+
 //  Test not in-place
-    std::transform_inclusive_scan(first, last, std::back_inserter(v), bop, uop);
+    std::transform_inclusive_scan(first, last, v.begin(), bop, uop);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 
 //  Test in-place
-    v.clear();
-    v.assign(first, last);
+    std::copy(first, last, v.begin());
     std::transform_inclusive_scan(v.begin(), v.end(), v.begin(), bop, uop);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 }
 
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
           int ia[]     = {  1,  3,   5,   7,    9 };
@@ -75,13 +95,14 @@ test()
         }
 }
 
-size_t triangle(size_t n) { return n*(n+1)/2; }
+constexpr size_t triangle(size_t n) { return n*(n+1)/2; }
 
 //  Basic sanity
-void basic_tests()
+TEST_CONSTEXPR_CXX20 void
+basic_tests()
 {
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::fill(v.begin(), v.end(), 3);
     std::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>(), add_one{});
     for (size_t i = 0; i < v.size(); ++i)
@@ -89,7 +110,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 0);
     std::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>(), add_one{});
     for (size_t i = 0; i < v.size(); ++i)
@@ -97,7 +118,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 1);
     std::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>(), add_one{});
     for (size_t i = 0; i < v.size(); ++i)
@@ -105,13 +126,24 @@ void basic_tests()
     }
 
     {
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
     std::vector<size_t> v, res;
     std::transform_inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus<>(), add_one{});
+#else
+    std::array<size_t, 0> v, res;
+    std::transform_inclusive_scan(v.begin(), v.end(), res.begin(), std::plus<>(), add_one{});
+#endif
     assert(res.empty());
     }
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     basic_tests();
 
@@ -123,5 +155,14 @@ int main(int, char**)
     test<const int*>();
     test<      int*>();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop_init.pass.cpp b/libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop_init.pass.cpp
index 3b58d297ca99..3ffb954d02d3 100644
--- a/libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop_init.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop_init.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template<class InputIterator, class OutputIterator, class T,
 //          class BinaryOperation, class UnaryOperation>
 //   OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last,
@@ -20,6 +22,7 @@
 
 #include <numeric>
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <functional>
 #include <iterator>
@@ -27,6 +30,10 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+// FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER > 17
+#include <span>
+#endif
 
 struct add_one {
     template <typename T>
@@ -36,24 +43,37 @@ struct add_one {
 };
 
 template <class Iter1, class BOp, class UOp, class T, class Iter2>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first, Iter1 last, BOp bop, UOp uop, T init, Iter2 rFirst, Iter2 rLast)
 {
-    std::vector<typename std::iterator_traits<Iter1>::value_type> v;
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+    size_t size = std::distance(first, last);
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
+
+    std::vector<typename std::iterator_traits<Iter1>::value_type> v(size);
+#else
+    assert((size <= 5) && "Increment the size of the array");
+    typename std::iterator_traits<Iter1>::value_type b[5];
+    std::span<typename std::iterator_traits<Iter1>::value_type> v{b, size};
+#endif
+
 //  Test not in-place
-    std::transform_inclusive_scan(first, last, std::back_inserter(v), bop, uop, init);
+    std::transform_inclusive_scan(first, last, v.begin(), bop, uop, init);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 
 //  Test in-place
-    v.clear();
-    v.assign(first, last);
+    std::copy(first, last, v.begin());
     std::transform_inclusive_scan(v.begin(), v.end(), v.begin(), bop, uop, init);
     assert(std::equal(v.begin(), v.end(), rFirst, rLast));
 }
 
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
           int ia[]     = {  1,  3,   5,    7,     9 };
@@ -87,13 +107,14 @@ test()
         }
 }
 
-size_t triangle(size_t n) { return n*(n+1)/2; }
+constexpr size_t triangle(size_t n) { return n*(n+1)/2; }
 
 //  Basic sanity
-void basic_tests()
+TEST_CONSTEXPR_CXX20 void
+basic_tests()
 {
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::fill(v.begin(), v.end(), 3);
     std::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>(), add_one{}, size_t{50});
     for (size_t i = 0; i < v.size(); ++i)
@@ -101,7 +122,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 0);
     std::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>(), add_one{}, size_t{30});
     for (size_t i = 0; i < v.size(); ++i)
@@ -109,7 +130,7 @@ void basic_tests()
     }
 
     {
-    std::vector<size_t> v(10);
+    std::array<size_t, 10> v;
     std::iota(v.begin(), v.end(), 1);
     std::transform_inclusive_scan(v.begin(), v.end(), v.begin(), std::plus<>(), add_one{}, size_t{40});
     for (size_t i = 0; i < v.size(); ++i)
@@ -117,17 +138,37 @@ void basic_tests()
     }
 
     {
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
     std::vector<size_t> v, res;
     std::transform_inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::plus<>(), add_one{}, size_t{1});
+#else
+    std::array<size_t, 0> v, res;
+    std::transform_inclusive_scan(v.begin(), v.end(), res.begin(), std::plus<>(), add_one{}, size_t{1});
+#endif
     assert(res.empty());
     }
 
 //  Make sure that the calculations are done using the init typedef
     {
-    std::vector<unsigned char> v(10);
+    std::array<unsigned char, 10> v;
     std::iota(v.begin(), v.end(), static_cast<unsigned char>(1));
+    // C++17 doesn't test constexpr so can use a vector.
+    // C++20 can use vector in constexpr evaluation, but both libc++ and MSVC
+    // don't have the support yet. In these cases use a std::span for the test.
+    // FIXME Remove constexpr vector workaround introduced in D90569
+#if TEST_STD_VER < 20 || \
+    (defined(__cpp_lib_constexpr_vector) && __cpp_lib_constexpr_vector >= 201907L)
     std::vector<size_t> res;
     std::transform_inclusive_scan(v.begin(), v.end(), std::back_inserter(res), std::multiplies<>(), add_one{}, size_t{1});
+#else
+    std::array<size_t, 10> res;
+    std::transform_inclusive_scan(v.begin(), v.end(), res.begin(), std::multiplies<>(), add_one{}, size_t{1});
+#endif
 
     assert(res.size() == 10);
     size_t j = 2;
@@ -140,7 +181,8 @@ void basic_tests()
     }
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     basic_tests();
 
@@ -152,5 +194,14 @@ int main(int, char**)
     test<const int*>();
     test<      int*>();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_init_bop_uop.pass.cpp b/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_init_bop_uop.pass.cpp
index 78c38fcf76ca..44abb822ea27 100644
--- a/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_init_bop_uop.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_init_bop_uop.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template <class InputIterator1, class T,
 //           class BinaryOperation, class UnaryOperation>
 //    T transform_reduce(InputIterator1 first1, InputIterator1 last1,
@@ -41,7 +43,7 @@ struct twice
 };
 
 template <class Iter1, class T, class BOp, class UOp>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first1, Iter1 last1, T init, BOp bOp, UOp uOp, T x)
 {
     static_assert( std::is_same_v<T,
@@ -50,7 +52,7 @@ test(Iter1 first1, Iter1 last1, T init, BOp bOp, UOp uOp, T x)
 }
 
 template <class Iter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[]          = {1, 2, 3, 4, 5, 6};
@@ -76,14 +78,16 @@ test()
 }
 
 template <typename T, typename Init>
-void test_return_type()
+TEST_CONSTEXPR_CXX20 void
+test_return_type()
 {
     T *p = nullptr;
     static_assert( std::is_same_v<Init,
          decltype(std::transform_reduce(p, p, Init{}, std::plus<>(), identity()))> );
 }
 
-void test_move_only_types()
+TEST_CONSTEXPR_CXX20 void
+test_move_only_types()
 {
     MoveOnly ia[] = {{1}, {2}, {3}};
     assert(60 ==
@@ -92,7 +96,8 @@ void test_move_only_types()
         [](const MoveOnly& target) { return MoveOnly{target.get() * 10}; }).get());
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test_return_type<char, int>();
     test_return_type<int, int>();
@@ -119,5 +124,14 @@ int main(int, char**)
 
     test_move_only_types();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init.pass.cpp b/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init.pass.cpp
index 133b594e196f..4b9d210597f2 100644
--- a/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template <class InputIterator1, class InputIterator2, class T>
 //   T transform_reduce(InputIterator1 first1, InputIterator1 last1,
 //                      InputIterator2 first2, T init);
@@ -23,7 +25,7 @@
 #include "test_iterators.h"
 
 template <class Iter1, class Iter2, class T>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first1, Iter1 last1, Iter2 first2, T init, T x)
 {
     static_assert( std::is_same_v<T,
@@ -32,7 +34,7 @@ test(Iter1 first1, Iter1 last1, Iter2 first2, T init, T x)
 }
 
 template <class SIter, class UIter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[]          = {1, 2, 3, 4, 5, 6};
@@ -51,14 +53,16 @@ test()
 }
 
 template <typename T, typename Init>
-void test_return_type()
+TEST_CONSTEXPR_CXX20 void
+test_return_type()
 {
     T *p = nullptr;
     static_assert( std::is_same_v<Init,
                        decltype(std::transform_reduce(p, p, p, Init{}))> );
 }
 
-void test_move_only_types()
+TEST_CONSTEXPR_CXX20 void
+test_move_only_types()
 {
     MoveOnly ia[] = {{1}, {2}, {3}};
     MoveOnly ib[] = {{1}, {2}, {3}};
@@ -66,7 +70,8 @@ void test_move_only_types()
         std::transform_reduce(std::begin(ia), std::end(ia), std::begin(ib), MoveOnly{0}).get());
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test_return_type<char, int>();
     test_return_type<int, int>();
@@ -105,5 +110,14 @@ int main(int, char**)
 
     test_move_only_types();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init_op_op.pass.cpp b/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init_op_op.pass.cpp
index 6d99d465be64..73b110e2c7df 100644
--- a/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init_op_op.pass.cpp
+++ b/libcxx/test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init_op_op.pass.cpp
@@ -8,7 +8,9 @@
 
 // <numeric>
 // UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: clang-8
 
+// Became constexpr in C++20
 // template <class InputIterator1, class InputIterator2, class T,
 //           class BinaryOperation1, class BinaryOperation2>
 //    T transform_reduce(InputIterator1 first1, InputIterator1 last1,
@@ -25,7 +27,7 @@
 #include "test_iterators.h"
 
 template <class Iter1, class Iter2, class T, class Op1, class Op2>
-void
+TEST_CONSTEXPR_CXX20 void
 test(Iter1 first1, Iter1 last1, Iter2 first2, T init, Op1 op1, Op2 op2, T x)
 {
     static_assert( std::is_same_v<T,
@@ -34,7 +36,7 @@ test(Iter1 first1, Iter1 last1, Iter2 first2, T init, Op1 op1, Op2 op2, T x)
 }
 
 template <class SIter, class UIter>
-void
+TEST_CONSTEXPR_CXX20 void
 test()
 {
     int ia[]          = {1, 2, 3, 4, 5, 6};
@@ -53,14 +55,16 @@ test()
 }
 
 template <typename T, typename Init>
-void test_return_type()
+TEST_CONSTEXPR_CXX20 void
+test_return_type()
 {
     T *p = nullptr;
     static_assert( std::is_same_v<Init,
        decltype(std::transform_reduce(p, p, p, Init{}, std::plus<>(), std::multiplies<>()))> );
 }
 
-void test_move_only_types()
+TEST_CONSTEXPR_CXX20 void
+test_move_only_types()
 {
     MoveOnly ia[] = {{1}, {2}, {3}};
     MoveOnly ib[] = {{1}, {2}, {3}};
@@ -70,7 +74,8 @@ void test_move_only_types()
         [](const MoveOnly& lhs, const MoveOnly& rhs) { return MoveOnly{lhs.get() * rhs.get()}; }).get());
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20 bool
+test()
 {
     test_return_type<char, int>();
     test_return_type<int, int>();
@@ -109,5 +114,14 @@ int main(int, char**)
 
     test_move_only_types();
 
-  return 0;
+    return true;
+}
+
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
+    return 0;
 }

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 22389f85f4ad..79a9929ebb7c 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -374,6 +374,10 @@ def add_version_header(tc):
     "values": { "c++2a": int(201811) },
     "headers": ["array", "functional", "iterator", "string_view", "tuple", "utility"],
     "unimplemented": True,
+   }, {
+    "name": "__cpp_lib_constexpr_numeric",
+    "values": { "c++2a": int(201911) },
+    "headers": ["numeric"],
    }, {
     "name": "__cpp_lib_bind_front",
     "values": { "c++2a": int(201811) },


        


More information about the libcxx-commits mailing list