[PATCH] Enhance _GLIBCXX_DEBUG constexpr support

François Dumont frs.dumont@gmail.com
Mon Dec 2 19:31:00 GMT 2019


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

-------------- next part --------------
A non-text attachment was scrubbed...
Name: debug_constexpr.patch
Type: text/x-patch
Size: 21235 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/libstdc++/attachments/20191202/67c6fe42/attachment.bin>


More information about the Libstdc++ mailing list