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
