Enhance _GLIBCXX_DEBUG constexpr support

Message ID cdddb54a-33a2-8e54-0b37-1212d034987a@gmail.com
State New
Headers show
Series
  • Enhance _GLIBCXX_DEBUG constexpr support
Related show

Commit Message

François Dumont Dec. 2, 2019, 7:31 p.m.
Hi

     Here is a patch to enhance constexpr support in _GLIBCXX_DEBUG. I 
work on std::lower_bound/upper_bound to find out if Debug mode is well 
prepared. I'll continue on other algos later.

     I initially hope that I could count on the compiler for the 
valid_range check. But for lower_bound/upper_bound there is no constexpr 
dedicated implementation like for copy/copy_backward so it implies 
changing the existing implementation. So I tried to change the 
while(__len > 0) into a while(__len != 0) and it gave:

constexpr_valid_range_neg.cc:35:20: error: non-constant condition for 
static assertion
    35 | static_assert(test1()); // { dg-error "" }
       |               ~~~~~^~
In file included from 
/home/fdt/dev/gcc/install/include/c++/10.0.0/algorithm:61,
                  from constexpr_valid_range_neg.cc:22:
constexpr_valid_range_neg.cc:35:20:   in ‘constexpr’ expansion of ‘test1()’
constexpr_valid_range_neg.cc:30:38:   in ‘constexpr’ expansion of 
‘std::lower_bound<const int*, int>(ca0.std::array<int, 12>::end(), 
ca0.std::array<int, 12>::begin(), 6)’
/home/fdt/dev/gcc/install/include/c++/10.0.0/bits/stl_algobase.h:1484:32: 
in ‘constexpr’ expansion of ‘std::__lower_bound<const int*, int, 
__gnu_cxx::__ops::_Iter_less_val>(__first, __last, (* & __val), 
__gnu_cxx::__ops::__iter_less_val())’
/home/fdt/dev/gcc/install/include/c++/10.0.0/bits/stl_algobase.h:1444:7: 
error: ‘constexpr’ loop iteration count exceeds limit of 262144 (use 
‘-fconstexpr-loop-limit=’ to increase the limit)
  1444 |       while (__len != 0)
       |       ^~~~~

     It seems ok but it isn't. The compiler had to loop 262144 times to 
eventually give this status which is not even clear about the fact that 
begin/end has been inverted. It is a quite heavy operation for a limited 
result.

     So this patch rather enable _GLIBCXX_DEBUG valid_range check which 
gives:

constexpr_valid_range_neg.cc:35:20: error: non-constant condition for 
static assertion
    35 | static_assert(test1()); // { dg-error "" }
       |               ~~~~~^~
In file included from 
/home/fdt/dev/gcc/install/include/c++/10.0.0/debug/debug.h:90,
                  from 
/home/fdt/dev/gcc/install/include/c++/10.0.0/bits/stl_algobase.h:69,
                  from 
/home/fdt/dev/gcc/install/include/c++/10.0.0/algorithm:61,
                  from constexpr_valid_range_neg.cc:22:
constexpr_valid_range_neg.cc:35:20:   in ‘constexpr’ expansion of ‘test1()’
constexpr_valid_range_neg.cc:30:38:   in ‘constexpr’ expansion of 
‘std::lower_bound<const int*, int>(ca0.std::__debug::array<int, 
12>::end(), ca0.std::__debug::array<int, 12>::begin(), 6)’
/home/fdt/dev/gcc/install/include/c++/10.0.0/bits/stl_algobase.h:1482:7: 
error: inline assembly is not a constant expression
  1482 |       __glibcxx_requires_partitioned_lower(__first, __last, __val);
       |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/fdt/dev/gcc/install/include/c++/10.0.0/bits/stl_algobase.h:1482:7: 
note: only unevaluated inline assembly is allowed in a ‘constexpr’ 
function in C++2a

This time it is done in no time. Of course you can see that the asm 
trick to generate a non-constant condition is not so nice.

We just don't see the asm call parameter but showing 
__glibcxx_requires_partitioned_lower is not so bad. For this reason the 
tests in this patch are not checking for any failure message. We'll see 
how to adapt when we have the necessary front end help to generate this 
compilation error.

Of course I could have a nicer compilation error by directly calling 
__glibcxx_requires_valid_range in the algo and stop doing it within 
__glibcxx_requires_partitioned_lower. Do you want to expose all macros 
this way ?


     * include/debug/formatter.h (__check_singular): Add C++11 constexpr
     qualification.
     * include/debug/helper_functions.h (__check_singular): Likewise. Skip
     check if constant evaluated.
     (__valid_range): Remove check skip if constant evaluated.
     * include/debug/macros.h [_GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED]
     (_GLIBCXX_DEBUG_VERIFY_COND_AT): Define.
     * testsuite/25_algorithms/lower_bound/constexpr.cc (test): Add 
checks on
     lower_bound results.
     * testsuite/25_algorithms/upper_bound/constexpr.cc (test): Likewise.
     * testsuite/25_algorithms/lower_bound/debug/
     constexpr_partitioned_neg.cc: New.
     * testsuite/25_algorithms/lower_bound/debug/
     constexpr_partitioned_pred_neg.cc: New.
     * testsuite/25_algorithms/lower_bound/debug/
     constexpr_valid_range_neg.cc: New.
     * testsuite/25_algorithms/lower_bound/debug/partitioned_neg.cc: New.
     * testsuite/25_algorithms/lower_bound/debug/partitioned_pred_neg.cc:
     New.
     * testsuite/25_algorithms/upper_bound/debug/
     constexpr_partitioned_neg.cc: New.
     * testsuite/25_algorithms/upper_bound/debug/
     constexpr_partitioned_pred_neg.cc: New.
     * testsuite/25_algorithms/upper_bound/debug/
     constexpr_valid_range_neg.cc: New.
     * testsuite/25_algorithms/upper_bound/debug/partitioned_neg.cc: New.
     * testsuite/25_algorithms/upper_bound/debug/partitioned_pred_neg.cc:
     New.

Tested under Linux x86_64 normal and debug modes.

Ok to commit ?

Is there any request done to get the necessary front end help ? Ideally 
a builtin to generate the error at a given source/file line for a given 
function would be perfect cause we have all those info.

François

Comments

François Dumont Dec. 9, 2019, 8:53 a.m. | #1
After completing execution of all tests I had to fix implementation of 
__check_singular to get only 1 return statement.



On 12/2/19 8:31 PM, François Dumont wrote:
> Hi

>

>     Here is a patch to enhance constexpr support in _GLIBCXX_DEBUG. I 

> work on std::lower_bound/upper_bound to find out if Debug mode is well 

> prepared. I'll continue on other algos later.

>

>     I initially hope that I could count on the compiler for the 

> valid_range check. But for lower_bound/upper_bound there is no 

> constexpr dedicated implementation like for copy/copy_backward so it 

> implies changing the existing implementation. So I tried to change the 

> while(__len > 0) into a while(__len != 0) and it gave:

>

> constexpr_valid_range_neg.cc:35:20: error: non-constant condition for 

> static assertion

>    35 | static_assert(test1()); // { dg-error "" }

>       |               ~~~~~^~

> In file included from 

> /home/fdt/dev/gcc/install/include/c++/10.0.0/algorithm:61,

>                  from constexpr_valid_range_neg.cc:22:

> constexpr_valid_range_neg.cc:35:20:   in ‘constexpr’ expansion of 

> ‘test1()’

> constexpr_valid_range_neg.cc:30:38:   in ‘constexpr’ expansion of 

> ‘std::lower_bound<const int*, int>(ca0.std::array<int, 12>::end(), 

> ca0.std::array<int, 12>::begin(), 6)’

> /home/fdt/dev/gcc/install/include/c++/10.0.0/bits/stl_algobase.h:1484:32: 

> in ‘constexpr’ expansion of ‘std::__lower_bound<const int*, int, 

> __gnu_cxx::__ops::_Iter_less_val>(__first, __last, (* & __val), 

> __gnu_cxx::__ops::__iter_less_val())’

> /home/fdt/dev/gcc/install/include/c++/10.0.0/bits/stl_algobase.h:1444:7: 

> error: ‘constexpr’ loop iteration count exceeds limit of 262144 (use 

> ‘-fconstexpr-loop-limit=’ to increase the limit)

>  1444 |       while (__len != 0)

>       |       ^~~~~

>

>     It seems ok but it isn't. The compiler had to loop 262144 times to 

> eventually give this status which is not even clear about the fact 

> that begin/end has been inverted. It is a quite heavy operation for a 

> limited result.

>

>     So this patch rather enable _GLIBCXX_DEBUG valid_range check which 

> gives:

>

> constexpr_valid_range_neg.cc:35:20: error: non-constant condition for 

> static assertion

>    35 | static_assert(test1()); // { dg-error "" }

>       |               ~~~~~^~

> In file included from 

> /home/fdt/dev/gcc/install/include/c++/10.0.0/debug/debug.h:90,

>                  from 

> /home/fdt/dev/gcc/install/include/c++/10.0.0/bits/stl_algobase.h:69,

>                  from 

> /home/fdt/dev/gcc/install/include/c++/10.0.0/algorithm:61,

>                  from constexpr_valid_range_neg.cc:22:

> constexpr_valid_range_neg.cc:35:20:   in ‘constexpr’ expansion of 

> ‘test1()’

> constexpr_valid_range_neg.cc:30:38:   in ‘constexpr’ expansion of 

> ‘std::lower_bound<const int*, int>(ca0.std::__debug::array<int, 

> 12>::end(), ca0.std::__debug::array<int, 12>::begin(), 6)’

> /home/fdt/dev/gcc/install/include/c++/10.0.0/bits/stl_algobase.h:1482:7: 

> error: inline assembly is not a constant expression

>  1482 |       __glibcxx_requires_partitioned_lower(__first, __last, 

> __val);

>       |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

> /home/fdt/dev/gcc/install/include/c++/10.0.0/bits/stl_algobase.h:1482:7: 

> note: only unevaluated inline assembly is allowed in a ‘constexpr’ 

> function in C++2a

>

> This time it is done in no time. Of course you can see that the asm 

> trick to generate a non-constant condition is not so nice.

>

> We just don't see the asm call parameter but showing 

> __glibcxx_requires_partitioned_lower is not so bad. For this reason 

> the tests in this patch are not checking for any failure message. 

> We'll see how to adapt when we have the necessary front end help to 

> generate this compilation error.

>

> Of course I could have a nicer compilation error by directly calling 

> __glibcxx_requires_valid_range in the algo and stop doing it within 

> __glibcxx_requires_partitioned_lower. Do you want to expose all macros 

> this way ?

>

>

>     * include/debug/formatter.h (__check_singular): Add C++11 constexpr

>     qualification.

>     * include/debug/helper_functions.h (__check_singular): Likewise. Skip

>     check if constant evaluated.

>     (__valid_range): Remove check skip if constant evaluated.

>     * include/debug/macros.h 

> [_GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED]

>     (_GLIBCXX_DEBUG_VERIFY_COND_AT): Define.

>     * testsuite/25_algorithms/lower_bound/constexpr.cc (test): Add 

> checks on

>     lower_bound results.

>     * testsuite/25_algorithms/upper_bound/constexpr.cc (test): Likewise.

>     * testsuite/25_algorithms/lower_bound/debug/

>     constexpr_partitioned_neg.cc: New.

>     * testsuite/25_algorithms/lower_bound/debug/

>     constexpr_partitioned_pred_neg.cc: New.

>     * testsuite/25_algorithms/lower_bound/debug/

>     constexpr_valid_range_neg.cc: New.

>     * testsuite/25_algorithms/lower_bound/debug/partitioned_neg.cc: New.

>     * testsuite/25_algorithms/lower_bound/debug/partitioned_pred_neg.cc:

>     New.

>     * testsuite/25_algorithms/upper_bound/debug/

>     constexpr_partitioned_neg.cc: New.

>     * testsuite/25_algorithms/upper_bound/debug/

>     constexpr_partitioned_pred_neg.cc: New.

>     * testsuite/25_algorithms/upper_bound/debug/

>     constexpr_valid_range_neg.cc: New.

>     * testsuite/25_algorithms/upper_bound/debug/partitioned_neg.cc: New.

>     * testsuite/25_algorithms/upper_bound/debug/partitioned_pred_neg.cc:

>     New.

>

> Tested under Linux x86_64 normal and debug modes.

>

> Ok to commit ?

>

> Is there any request done to get the necessary front end help ? 

> Ideally a builtin to generate the error at a given source/file line 

> for a given function would be perfect cause we have all those info.

>

> François

>
diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h
index 3bab508e10e..a7873665f0e 100644
--- a/libstdc++-v3/include/debug/formatter.h
+++ b/libstdc++-v3/include/debug/formatter.h
@@ -95,7 +95,8 @@ namespace __gnu_debug
   using std::type_info;
 
   template<typename _Iterator>
-    bool __check_singular(const _Iterator&);
+    _GLIBCXX_CONSTEXPR
+    bool __check_singular(_Iterator const&);
 
   class _Safe_sequence_base;
 
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index 0344f27143b..5b1a5598cf0 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -120,15 +120,29 @@ namespace __gnu_debug
   // We may have an iterator that derives from _Safe_iterator_base but isn't
   // a _Safe_iterator.
   template<typename _Iterator>
+    _GLIBCXX_CONSTEXPR
     inline bool
     __check_singular(_Iterator const& __x)
-    { return __check_singular_aux(std::__addressof(__x)); }
+    {
+      return
+#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
+	__builtin_is_constant_evaluated() ? false :
+#endif
+	__check_singular_aux(std::__addressof(__x));
+    }
 
   /** Non-NULL pointers are nonsingular. */
   template<typename _Tp>
+    _GLIBCXX_CONSTEXPR
     inline bool
     __check_singular(_Tp* const& __ptr)
-    { return __ptr == 0; }
+    {
+      return
+#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
+	__builtin_is_constant_evaluated() ? false :
+#endif
+	__ptr == 0;
+    }
 
   /** We say that integral types for a valid range, and defer to other
    *  routines to realize what to do with integral types instead of
@@ -225,11 +239,6 @@ namespace __gnu_debug
     __valid_range(_InputIterator __first, _InputIterator __last,
 		  typename _Distance_traits<_InputIterator>::__type& __dist)
     {
-#ifdef __cpp_lib_is_constant_evaluated
-      if (std::is_constant_evaluated())
-	// Detected by the compiler directly.
-	return true;
-#endif
       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
       return __valid_range_aux(__first, __last, __dist, _Integral());
     }
@@ -253,11 +262,6 @@ namespace __gnu_debug
     inline bool
     __valid_range(_InputIterator __first, _InputIterator __last)
     {
-#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
-      if (__builtin_is_constant_evaluated())
-	// Detected by the compiler directly.
-	return true;
-#endif
       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
       return __valid_range_aux(__first, __last, _Integral());
     }
diff --git a/libstdc++-v3/include/debug/macros.h b/libstdc++-v3/include/debug/macros.h
index 97e54fd8390..75879a0b221 100644
--- a/libstdc++-v3/include/debug/macros.h
+++ b/libstdc++-v3/include/debug/macros.h
@@ -38,12 +38,15 @@
  * the user error and where the error is reported.
  *
  */
-#if 0 /* defined _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED */
+#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
 # define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func)	\
   if (__builtin_is_constant_evaluated())				\
-    /* FIXME: Compilation error here when !_Cond. */			\
-    break;								\
-  if (! (_Cond))							\
+    {									\
+      if (!(_Cond))							\
+	/* FIXME Compilation error here. */				\
+	asm("debug mode assertion failure");				\
+    }									\
+  else if (! (_Cond))							\
     __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func)		\
       ._ErrMsg._M_error()
 #else
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/constexpr.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/constexpr.cc
index 45eeeba294a..c6506353258 100644
--- a/libstdc++-v3/testsuite/25_algorithms/lower_bound/constexpr.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/constexpr.cc
@@ -31,7 +31,7 @@ test()
   const auto outcc = std::lower_bound(ca0.begin(), ca0.end(), 6,
 				      std::less<int>());
 
-  return true;
+  return outbb == ca0.begin() + 6 && outcc == ca0.begin() + 6;
 }
 
 static_assert(test());
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc
new file mode 100644
index 00000000000..efd2b45dc4f
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc
@@ -0,0 +1,48 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+struct A
+{
+  int _i;
+
+  constexpr bool
+  operator<(const A& a) const
+  { return _i < a._i; }
+};
+
+constexpr bool
+test()
+{
+  constexpr std::array<A, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 5, 8, 9, 10, 11}};
+
+  constexpr A a6{ 6 };
+  const auto it = std::lower_bound(ca0.begin(), ca0.end(), a6);
+
+  return true;
+}
+
+static_assert(test()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc
new file mode 100644
index 00000000000..f30556b2897
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc
@@ -0,0 +1,38 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+constexpr bool
+test()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 5, 8, 9, 10, 11}};
+
+  const auto it = std::lower_bound(ca0.begin(), ca0.end(), 6, std::less<int>());
+
+  return true;
+}
+
+static_assert(test()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc
new file mode 100644
index 00000000000..81a4ad57a3f
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc
@@ -0,0 +1,52 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+constexpr bool
+test1()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}};
+
+  const auto outbb = std::lower_bound(ca0.end(), ca0.begin(), 6);
+
+  return true;
+}
+
+static_assert(test1()); // { dg-error "" }
+
+constexpr bool
+test2()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}};
+
+  const auto outcc = std::lower_bound(ca0.end(), ca0.begin(), 6,
+				      std::less<int>());
+
+  return true;
+}
+
+static_assert(test2()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
+
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_neg.cc
new file mode 100644
index 00000000000..15ae43b4784
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_neg.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <algorithm>
+
+struct A
+{
+  A(int i) : _i(i)
+  { }
+
+  int _i;
+
+  bool
+  operator<(const A& a) const
+  { return _i < a._i; }
+};
+
+void test01()
+{
+  A as[] = { 0, 1, 2, 0, 2, 3 };
+  std::lower_bound(as, as + 6, A(1));
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_pred_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_pred_neg.cc
new file mode 100644
index 00000000000..fafd6c9cea6
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_pred_neg.cc
@@ -0,0 +1,35 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <algorithm>
+
+void test01()
+{
+  int as[] = { 0, 1, 0, 2, 3 };
+  std::lower_bound(as, as + 5, 1, std::less<int>());
+}
+
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/constexpr.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/constexpr.cc
index f6312b8fb75..5a02187d7ca 100644
--- a/libstdc++-v3/testsuite/25_algorithms/upper_bound/constexpr.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/constexpr.cc
@@ -24,14 +24,14 @@
 constexpr bool
 test()
 {
-  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5,  6, 7, 8,  9, 10, 11}};
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}};
 
   const auto out77 = std::upper_bound(ca0.begin(), ca0.end(), 6);
 
   const auto out88 = std::upper_bound(ca0.begin(), ca0.end(), 6,
 				      std::less<int>());
 
-  return true;
+  return out77 == ca0.begin() + 7 && out88 == ca0.begin() + 7;
 }
 
 static_assert(test());
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc
new file mode 100644
index 00000000000..e6365029630
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc
@@ -0,0 +1,48 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+struct A
+{
+  int _i;
+
+  constexpr bool
+  operator<(const A& a) const
+  { return _i == a._i; }
+};
+
+constexpr bool
+test()
+{
+  constexpr std::array<A, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 5, 8, 9, 10, 11}};
+
+  constexpr A a6{ 6 };
+  const auto it = std::upper_bound(ca0.begin(), ca0.end(), a6);
+
+  return true;
+}
+
+static_assert(test()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc
new file mode 100644
index 00000000000..0e8dc784434
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc
@@ -0,0 +1,38 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+constexpr bool
+test()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 7, 6, 8, 9, 10, 11}};
+
+  const auto it = std::upper_bound(ca0.begin(), ca0.end(), 6, std::less<int>());
+
+  return true;
+}
+
+static_assert(test()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc
new file mode 100644
index 00000000000..47a766b629e
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc
@@ -0,0 +1,51 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+constexpr bool
+test1()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}};
+
+  const auto outbb = std::upper_bound(ca0.end(), ca0.begin(), 6);
+
+  return true;
+}
+
+static_assert(test1()); // { dg-error "" }
+
+constexpr bool
+test2()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}};
+
+  const auto outcc = std::upper_bound(ca0.end(), ca0.begin(), 6,
+				      std::less<int>());
+
+  return true;
+}
+
+static_assert(test2()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_neg.cc
new file mode 100644
index 00000000000..a29b7a7caf6
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_neg.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <algorithm>
+
+struct A
+{
+  A(int i) : _i(i)
+  { }
+
+  int _i;
+
+  bool
+  operator<(const A& a) const
+  { return _i < a._i; }
+};
+
+void test01()
+{
+  A as[] = { 0, 2, 1, 3, 4, 5 };
+  std::upper_bound(as, as + 6, A(1));
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_pred_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_pred_neg.cc
new file mode 100644
index 00000000000..27df467d8f9
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_pred_neg.cc
@@ -0,0 +1,35 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <algorithm>
+
+void test01()
+{
+  int as[] = { 0, 2, 1, 3, 4 };
+  std::upper_bound(as, as + 5, 1, std::less<int>());
+}
+
+
+int
+main()
+{
+  test01();
+  return 0;
+}

Patch

diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h
index 3bab508e10e..a7873665f0e 100644
--- a/libstdc++-v3/include/debug/formatter.h
+++ b/libstdc++-v3/include/debug/formatter.h
@@ -95,7 +95,8 @@  namespace __gnu_debug
   using std::type_info;
 
   template<typename _Iterator>
-    bool __check_singular(const _Iterator&);
+    _GLIBCXX_CONSTEXPR
+    bool __check_singular(_Iterator const&);
 
   class _Safe_sequence_base;
 
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index 0344f27143b..7e38ef1f25d 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -120,15 +120,29 @@  namespace __gnu_debug
   // We may have an iterator that derives from _Safe_iterator_base but isn't
   // a _Safe_iterator.
   template<typename _Iterator>
+    _GLIBCXX_CONSTEXPR
     inline bool
     __check_singular(_Iterator const& __x)
-    { return __check_singular_aux(std::__addressof(__x)); }
+    {
+#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
+      if (__builtin_is_constant_evaluated())
+	return false;
+#endif
+      return __check_singular_aux(std::__addressof(__x));
+    }
 
   /** Non-NULL pointers are nonsingular. */
   template<typename _Tp>
+    _GLIBCXX_CONSTEXPR
     inline bool
     __check_singular(_Tp* const& __ptr)
-    { return __ptr == 0; }
+    {
+#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
+      if (__builtin_is_constant_evaluated())
+	return false;
+#endif
+      return __ptr == 0;
+    }
 
   /** We say that integral types for a valid range, and defer to other
    *  routines to realize what to do with integral types instead of
@@ -225,11 +239,6 @@  namespace __gnu_debug
     __valid_range(_InputIterator __first, _InputIterator __last,
 		  typename _Distance_traits<_InputIterator>::__type& __dist)
     {
-#ifdef __cpp_lib_is_constant_evaluated
-      if (std::is_constant_evaluated())
-	// Detected by the compiler directly.
-	return true;
-#endif
       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
       return __valid_range_aux(__first, __last, __dist, _Integral());
     }
@@ -253,11 +262,6 @@  namespace __gnu_debug
     inline bool
     __valid_range(_InputIterator __first, _InputIterator __last)
     {
-#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
-      if (__builtin_is_constant_evaluated())
-	// Detected by the compiler directly.
-	return true;
-#endif
       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
       return __valid_range_aux(__first, __last, _Integral());
     }
diff --git a/libstdc++-v3/include/debug/macros.h b/libstdc++-v3/include/debug/macros.h
index 97e54fd8390..75879a0b221 100644
--- a/libstdc++-v3/include/debug/macros.h
+++ b/libstdc++-v3/include/debug/macros.h
@@ -38,12 +38,15 @@ 
  * the user error and where the error is reported.
  *
  */
-#if 0 /* defined _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED */
+#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
 # define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func)	\
   if (__builtin_is_constant_evaluated())				\
-    /* FIXME: Compilation error here when !_Cond. */			\
-    break;								\
-  if (! (_Cond))							\
+    {									\
+      if (!(_Cond))							\
+	/* FIXME Compilation error here. */				\
+	asm("debug mode assertion failure");				\
+    }									\
+  else if (! (_Cond))							\
     __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func)		\
       ._ErrMsg._M_error()
 #else
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/constexpr.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/constexpr.cc
index 45eeeba294a..c6506353258 100644
--- a/libstdc++-v3/testsuite/25_algorithms/lower_bound/constexpr.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/constexpr.cc
@@ -31,7 +31,7 @@  test()
   const auto outcc = std::lower_bound(ca0.begin(), ca0.end(), 6,
 				      std::less<int>());
 
-  return true;
+  return outbb == ca0.begin() + 6 && outcc == ca0.begin() + 6;
 }
 
 static_assert(test());
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc
new file mode 100644
index 00000000000..efd2b45dc4f
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_neg.cc
@@ -0,0 +1,48 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+struct A
+{
+  int _i;
+
+  constexpr bool
+  operator<(const A& a) const
+  { return _i < a._i; }
+};
+
+constexpr bool
+test()
+{
+  constexpr std::array<A, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 5, 8, 9, 10, 11}};
+
+  constexpr A a6{ 6 };
+  const auto it = std::lower_bound(ca0.begin(), ca0.end(), a6);
+
+  return true;
+}
+
+static_assert(test()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc
new file mode 100644
index 00000000000..f30556b2897
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_partitioned_pred_neg.cc
@@ -0,0 +1,38 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+constexpr bool
+test()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 5, 8, 9, 10, 11}};
+
+  const auto it = std::lower_bound(ca0.begin(), ca0.end(), 6, std::less<int>());
+
+  return true;
+}
+
+static_assert(test()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc
new file mode 100644
index 00000000000..81a4ad57a3f
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/constexpr_valid_range_neg.cc
@@ -0,0 +1,52 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+constexpr bool
+test1()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}};
+
+  const auto outbb = std::lower_bound(ca0.end(), ca0.begin(), 6);
+
+  return true;
+}
+
+static_assert(test1()); // { dg-error "" }
+
+constexpr bool
+test2()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}};
+
+  const auto outcc = std::lower_bound(ca0.end(), ca0.begin(), 6,
+				      std::less<int>());
+
+  return true;
+}
+
+static_assert(test2()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
+
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_neg.cc
new file mode 100644
index 00000000000..15ae43b4784
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_neg.cc
@@ -0,0 +1,46 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <algorithm>
+
+struct A
+{
+  A(int i) : _i(i)
+  { }
+
+  int _i;
+
+  bool
+  operator<(const A& a) const
+  { return _i < a._i; }
+};
+
+void test01()
+{
+  A as[] = { 0, 1, 2, 0, 2, 3 };
+  std::lower_bound(as, as + 6, A(1));
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_pred_neg.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_pred_neg.cc
new file mode 100644
index 00000000000..fafd6c9cea6
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/debug/partitioned_pred_neg.cc
@@ -0,0 +1,35 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <algorithm>
+
+void test01()
+{
+  int as[] = { 0, 1, 0, 2, 3 };
+  std::lower_bound(as, as + 5, 1, std::less<int>());
+}
+
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/constexpr.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/constexpr.cc
index f6312b8fb75..5a02187d7ca 100644
--- a/libstdc++-v3/testsuite/25_algorithms/upper_bound/constexpr.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/constexpr.cc
@@ -24,14 +24,14 @@ 
 constexpr bool
 test()
 {
-  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5,  6, 7, 8,  9, 10, 11}};
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}};
 
   const auto out77 = std::upper_bound(ca0.begin(), ca0.end(), 6);
 
   const auto out88 = std::upper_bound(ca0.begin(), ca0.end(), 6,
 				      std::less<int>());
 
-  return true;
+  return out77 == ca0.begin() + 7 && out88 == ca0.begin() + 7;
 }
 
 static_assert(test());
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc
new file mode 100644
index 00000000000..e6365029630
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_neg.cc
@@ -0,0 +1,48 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+struct A
+{
+  int _i;
+
+  constexpr bool
+  operator<(const A& a) const
+  { return _i == a._i; }
+};
+
+constexpr bool
+test()
+{
+  constexpr std::array<A, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 5, 8, 9, 10, 11}};
+
+  constexpr A a6{ 6 };
+  const auto it = std::upper_bound(ca0.begin(), ca0.end(), a6);
+
+  return true;
+}
+
+static_assert(test()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc
new file mode 100644
index 00000000000..0e8dc784434
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_partitioned_pred_neg.cc
@@ -0,0 +1,38 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+constexpr bool
+test()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 7, 6, 8, 9, 10, 11}};
+
+  const auto it = std::upper_bound(ca0.begin(), ca0.end(), 6, std::less<int>());
+
+  return true;
+}
+
+static_assert(test()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc
new file mode 100644
index 00000000000..47a766b629e
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/constexpr_valid_range_neg.cc
@@ -0,0 +1,51 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <array>
+
+constexpr bool
+test1()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}};
+
+  const auto outbb = std::upper_bound(ca0.end(), ca0.begin(), 6);
+
+  return true;
+}
+
+static_assert(test1()); // { dg-error "" }
+
+constexpr bool
+test2()
+{
+  constexpr std::array<int, 12> ca0{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}};
+
+  const auto outcc = std::upper_bound(ca0.end(), ca0.begin(), 6,
+				      std::less<int>());
+
+  return true;
+}
+
+static_assert(test2()); // { dg-error "" }
+
+// { dg-prune-output "not a constant expression" }
+// { dg-prune-output "in 'constexpr'" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_neg.cc
new file mode 100644
index 00000000000..a29b7a7caf6
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_neg.cc
@@ -0,0 +1,46 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <algorithm>
+
+struct A
+{
+  A(int i) : _i(i)
+  { }
+
+  int _i;
+
+  bool
+  operator<(const A& a) const
+  { return _i < a._i; }
+};
+
+void test01()
+{
+  A as[] = { 0, 2, 1, 3, 4, 5 };
+  std::upper_bound(as, as + 6, A(1));
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_pred_neg.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_pred_neg.cc
new file mode 100644
index 00000000000..27df467d8f9
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/debug/partitioned_pred_neg.cc
@@ -0,0 +1,35 @@ 
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <algorithm>
+
+void test01()
+{
+  int as[] = { 0, 2, 1, 3, 4 };
+  std::upper_bound(as, as + 5, 1, std::less<int>());
+}
+
+
+int
+main()
+{
+  test01();
+  return 0;
+}