> On 8 Sep 2025, at 15:05, Jakub Jelinek <ja...@redhat.com> wrote:
>
> On Mon, Sep 08, 2025 at 02:54:18PM +0100, Iain Sandoe wrote:
>> (for pre-conditions) they lower to a series of statements like
>> if (some check fails)
>> handle the contract violation
>> if (some other check fails)
>> handle the contract violation
>> …
>>
>>> The only "example" is for in(p) in (*p > 5) where the contract
>>> *p > 5 would "elide" the 'p' one. Whatever "eliding" means here.
>>
>> So, IIRC, the argument was
>>
>> *p > 5 would be UB for p == nullptr
>>
>> therefore an earlier check for p == nulptr can be removed, because
>> that case cannot happen in a well-formed program.
>>
>> However, that prevents the contract check from doing its job (diagnosing
>> the bad case).
>>
>> I cannot say that GCC would make that optimisation - it was, in general,
>> quite hard to find cases that time-traveled.
>
> If handle the contract violation is just __builtin_unreachable () or
> it isn't evaluated at all and handled more like [[assume ()]] for the ignore
> semantics, then I don't see a problem with that kind of time travel.
> If handle the contract violation is a function call which gcc knows nothing
> about (including calling ::handle_contract_violation), I don't see how gcc
> could optimize that (unless it is buggy), exactly because it needs to count
> with the function exiting or looping forever or doing thread synchronization
> and other threads observe the state etc.
The contract violation handling depends on the chosen contract semantic
it can:
* terminate (in an implementation-defined way - so could trap or abort
equally).
* do some diagnostic output or logging and then terminate (etc).
* do some diagnostic output or logging and then continue.
I completely agree with Richi that, in the given case, continuation means
that the program will segv. I guess the question is whether the violation
handler logging a cause before that is considered a useful functionality.
Iain
>
> Jakub
>