Let me start with your last point:

Tomasz Kaminski [Monday, 20 October 2025, 11:24:55 CEST]:
> I think I would prefer the direction of just using plain __glibcxx_assert
> for libstdc++, and not innovate a new error checking
> strategies.

Yes. I guess the simd PR should just use __glibcxx_assert and I should open a 
separate PR that would innovate new precondition checking consistently all 
over libstdc++. That said, I don't want to miss these error messages in my 
simd code. They have been helpful.

> Another topic is that SIMD uses following custom precondition macro:
> #if not IFNDR_SIMD_PRECONDITIONS
> #define __glibcxx_simd_precondition(expr, msg, ...)
> […]
> 
> I do not think that turning (possible) preconditions violations into an
> ill-formed program is conforming,

I agree.

> and the error should be emitted only if the part of code is evaluated. In
> particular it is fine to to have a
> template instantiation that will emit a call that will break precondition,
> if it is never reached.

I should have called this out. And I wanted to talk about this pattern of 
precondition checking in general.

My main reason for keeping it in (besides helping me find bugs) was to 
understand what works, what doesn't, and what it breaks. IOW, what I really 
want to propose we should do. (I have long used a patch against all of 
libstdc++, replacing __glibcxx_assert with an equivalent macro.)

What I submitted in the PR is actually not what I wanted. :-( Sorry for that.

I believe what we want (as default) is:

1. A precondition failure on constant propagation should turn into a warning. 
With -Werror users can turn that warning into an error if they want.

2. If the optimizer sees an unconditional precondition violation it should 
result in __builtin_trap().

3. A precondition violation in a constant expression is always ill-formed.

4. A precondition violation at runtime results in a __builtin_trap().

If you agree with the direction (not necessarily now, but after trying a patch 
against libstdc++), then we may want something nicer for users than 
[[gnu::warning("")]]. As long as we only have [[gnu::warning]] as a tool, that 
warning/Werror is not easy enough to control. It would be nice if we had a 
__builtin_emit_precond_warning("message") that acts equivalent to the 
[[gnu::warning]] lambda I put into the macro. The important difference is that 
it could be controlled via its own -W<I don't know what to call it> flag (also 
for -Werror). And maybe it could also avoid emitting the lambda function 
definition into the object file?

> The second, most important concern I have is that this lead to checks being
> completely removed,
> without any message, even if assertion would be enabled. For example for
> this very simple test program:
> void foo(int n)
> {
> const bool __precondition_result = !bool(n < 5);
> if (__builtin_constant_p(__precondition_result) && __precondition_result)
> []() __attribute__(( __error__("precondition failure."
> "\n" "foo" "note: " "err" " (precondition 'n < 5' does not hold)")))
> { __builtin_unreachable(); }();
> }
> 
> void bar(bool b, int x) {
> if (b)
> foo(x + 7);
> }
> The `bar` gets compiled to [ret]

Yes, what I have in the PR is the more dangerous variant of the macro. The 
`bar` function is "safe" as long as `bar` and `foo` get inlined from a caller:

void baz()
{
  bar(true, 1); // attribute error makes this call ill-formed
}

This is what I'd like to propose instead:
  https://compiler-explorer.com/z/Pnn3MeMss

If you add `-D_GLIBCXX_SIMD_TRAP_ON_UB=0` you get the dangerous 
__builtin_unreachable() behavior back.

- Matthias

> Would be interested to hear other people's opinions on this.

-- 
──────────────────────────────────────────────────────────────────────────
 Dr. Matthias Kretz                           https://mattkretz.github.io
 GSI Helmholtz Center for Heavy Ion Research               https://gsi.de
 std::simd
──────────────────────────────────────────────────────────────────────────



Reply via email to