https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124100

            Bug ID: 124100
           Summary: "contract condition is not constant"
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: webrown.cpp at gmail dot com
  Target Milestone: ---

As demonstrated at https://godbolt.org/z/KjxET5rrP, the following code produces
the unexpected diagnostic
  16:5: error: contract condition is not constant
when compiled on trunk with flags -std=c++26 -fcontracts -Wall.

The diagnostic does not manifest:
- without -Wall, or
- when *either* of the 2 lines guarded by #ifdef is absent.


```
#define BUG

using ptrdiff_t   = decltype( (char *)nullptr - (char *)nullptr );
auto is_neg = [] ( ptrdiff_t k ) { return k < 0; };
auto is_pos = [] ( ptrdiff_t k ) { return k > 0; };
auto abs2    = [] ( ptrdiff_t k ) { return is_neg(k) ? -k : k; };

template< class > concept bi = true;

struct
  adv final
{
  template< class I >
  static constexpr void
    operator () ( I & i, ptrdiff_t n ) noexcept
    pre( bi<I> )  // error: "contract condition is not constant"
  { for( ; is_pos(n); --n )  ++i; }

  template< class I, class S >
  static constexpr ptrdiff_t
    operator () ( I & i, ptrdiff_t n, S bound ) noexcept
  {
    ptrdiff_t const delta = bound - i;
    ptrdiff_t const M     = abs2(n) > abs2(delta) ? delta : n;
    adv{}(i, M);
    return n - M;
  }

}
constexpr adv{};

struct
  nxt final
{
  template< class I, class S >
  static constexpr I
    operator () ( I x, ptrdiff_t n, S bound ) noexcept
  { return (void)adv(x, n, bound), x; }

}
constexpr nxt{};

//////////////////////////////////////////////////////////////////////////////

constexpr int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

#ifdef BUG
static_assert( nxt(a+0, 3, a+9) == a+3 );
static_assert( nxt(a+0, 6, a+5) == a+5 );
#endif  // BUG

constexpr bool
  test( int const * lower, int n, int const * upper, int const * expected )
{ return nxt(lower, n, upper) == expected; }

static_assert( test(a+0, 3, a+9, a+3) );
static_assert( test(a+0, 6, a+5, a+5) );

```

Reply via email to