Re: Is it time to take the middle-end stringop/array warnings out of -Wall?

Martin Uecker via Gcc <[email protected]>
Newsgroups gmane.comp.gcc.devel
Message-ID <[email protected]>
Am Freitag, dem 22.05.2026 um 15:24 +0200 schrieb Matthias Kretz via Gcc:
> Richard Biener via Gcc [Friday, 22 May 2026, 14:52:05 CEST]:
> > 
> > 
> > > Am 22.05.2026 um 13:49 schrieb Matthias Kretz <[email protected]>:
> > 
> > > Jason Merrill via Gcc [Thursday, 21 May 2026, 20:12:01 CEST]:
> > 
> > 
> > 
> > > > This seems too broad a category;
> > 
> > 
> > 
> > > I think it's a very interesting category. But, with that name, it's not
> > > very discoverable for users.
> > > 
> > > My experience with these kinds of warnings (and I implemented library
> > > precondition checking in a similar manner) is that they can be resolved by
> > > precondition checking that is visible to the optimizer. I like to think of
> > > this as "forcing precondition checks to bubble up".
> > > 
> > > Consider:
> > >  char str[] = "Hello";
> > >  
> > >  // precondition: cond == false
> > >  char
> > >  f(bool cond)
> > >  { return cond ? str[100] : str[0]; }
> > > 
> > > This warns about str[100] being out of bounds. But the real problem was
> > > that f was called out-of-contract. If we add "pre (cond == false)" and
> > > compile with -fno-contracts-conservative-ipa (and a terminating contracts
> > > evaluation semantic) the warning goes away.
> > > 
> > > So you can think about these warnings as "your function is missing a
> > > precondition check". Conceptually. Because C++ contracts currently default
> > > to hiding from the optimizer.
> > > 
> > > Thus:
> > > 1. middle-end warnings should hint at missing precondition checks
> > > 2. middle-end warnings maybe should only be on by default if contracts
> > > checking is visibly (to the optimizer) terminating. (I've been using
> > > __builtin_trap for this.)
> > > 
> > > On the name: "-Wmiddle-end" is an explanation to compiler devs and nobody
> > > else. How about something in the direction of "-Wstatic-precondition-
> > > checking"?
> > 
> > I think this is a good observation.  Much like that diagnostics that do this
> > should probably enable diagnostic-paths, at least for their emitted
> > diagnostics.  Because the path is what shows the currently visible
> > preconditions.  Remember that esp. with C++ the set of visible
> > preconditions is heavily dependent on inlining decisions.
> 
> Right. The other "solution" to remove the warning for f(bool) above is to 
> declare it inline. Then it's up to the caller to get precondition checks 
> right. Like this (https://compiler-explorer.com/z/E5GKfaWYz):
> 
> char str[10] = {};
> 
> // precondition: !cond
> inline char
> f(bool cond)
> { return cond ? str[100] : str[0]; }
> 
> // precondition: x < 0
> char
> g(int x)
> {
>   if (x >= 0) __builtin_trap(); // remove => the warning is emitted
>   return f(x > 0);
> }
> 
>  --- * ---
> 
> For reference, this is the precondition check macro I use while developing 
> std::simd:
> 
> #define _GLIBCXX_SIMD_LOC __FILE__ ":" _GLIBCXX_SIMD_TOSTRING(__LINE__) ": "
> 
> #define __glibcxx_simd_precondition(expr, msg, ...)                          \
>   do {                                                                       \
>     const bool __precondition_result = !bool(expr);                          \
>     if (__builtin_constant_p(__precondition_result) && __precondition_result)\
>       {                                                                      \
>         struct _Precondition                                                 \
>         {                                                                    \
>           [[__gnu__::__noipa__, __gnu__::__warning__("precondition failure. "\
>             "\n" _GLIBCXX_SIMD_LOC "note: " msg " (precondition '" #expr     \
>             "' does not hold)")]]                                            \
>           static inline void _S_fail() noexcept {}                           \
>         };                                                                   \
>         _Precondition::_S_fail();                                            \
>       }                                                                      \
>     if (__builtin_expect(__precondition_result, false))                      \
>       std::simd::__invoke_ub(                                                \
>         _GLIBCXX_SIMD_LOC "precondition failure in '%s':\n" msg " ('" #expr  \
>         "' does not hold)", __PRETTY_FUNCTION__ __VA_OPT__(,) __VA_ARGS__);  \
>   } while(false)
> 
> 
> I recently wrote (B is an mdspan):
> 
>   simd::unchecked_load<V>(&B[k, 0], &B[k, M-1], simd::flag_aligned);
> 
> where I wanted to load a matrix row of M values. The end iterator is off-by-
> one. And this is what I got:
> 
> /home/mkretz/src/simd/include/bits/simd_details.h|87 col 31 warning| call to 
> 'std::simd::unchecked_load<basic_vec<float, _Abi<8, 1, 0> >, std::span<const 
> float, 18446744073709551615>, __aligned_flag>(std::span<const float, 
> 18446744073709551615>&&, flags<__aligned_flag>)::_Precondition::_S_fail' 
> declared with attribute warning: precondition failure. 
> /home/mkretz/src/simd/include/bits/simd_loadstore.h|65| note: Input range is 
> too small. Did you mean to use 'partial_load'? (precondition 
> 'std::ranges::size(__r) >= _RV::size()' does not hold) [-Wattribute-warning]
> 
> Running the program traps by default. With -D_GLIBCXX_ASSERTIONS, running the 
> program aborts after printing:
> 
> /home/mkretz/src/simd/include/bits/simd_loadstore.h|65| precondition failure 
> in 'constexpr std::simd::__vec_load_return_t<_Vp, 
> std::ranges::range_value_t<_View> > std::simd::unchecked_load(_Rg&&, 
> flags<_Flags ...>) [with _Vp = basic_vec<float, _Abi<8, 1, 0> >; _Rg = 
> std::span<const float, 18446744073709551615>; _Flags = {__aligned_flag}; 
> __vec_load_return_t<_Vp, std::ranges::range_value_t<_View> > = 
> basic_vec<float, _Abi<8, 1, 0> >; std::ranges::range_value_t<_View> = float]':
> Input range is too small. Did you mean to use 'partial_load'? 
> ('std::ranges::size(__r) >= _RV::size()' does not hold)
> 
> 
> Somewhat similar to -fhardened, I think this is a useful build-mode to have.
> 
> - Matthias

Indeed, and for similar reasons, I wanted to have a warning option for
__builtin_trap() when not ellided, because this allows me to get
compile-time warning for UBsan inserted checks that are not eliminated
by the compiler.  I find this extremeley useful, and I do not even
have to insert the checks myself. 

Example: https://godbolt.org/z/qdWMrx6do


Martin




Martin
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.