Consider the following example:
void foo(const char *i);
int bar()
{
const char i = 9;
foo(&i);
return i;
}
https://godbolt.org/z/ve6jx84W9
Currently, SDCC does not make use of the fact that modification of i would be undefined behaviour in order to optimise the return value of bar to a constant; it only does so if i is constexpr instead of const. Is that distinction accidental or intentional?
My understanding is that i is an immutable object regardless of whether it is also an integer constant expression. I suspect that the behaviour of SDCC will become more optimal if the new rules for integer constant expressions that were accepted into C2Y are implemented, because const char i will be treated as like constexpr char i. But from the point of view that foo could modify i (and thereby invoke undefined behaviour) in either case, that does not seem logical.
The unwanted diagnostic message produced by the following example is probably related:
void baz(_Optional int *const *ppoi);
void qux(_Optional int *poi)
{
// constrains poi to non-null on the fallthrough path
if (!poi) return;
_Optional int *const cpoi = poi; // must always point to poi
*cpoi = 1; // no warning is produced
baz(&cpoi); // non-null constraint on poi is unaffected
*cpoi = 2; // unwanted warning is produced
}
https://godbolt.org/z/4K6Kj87G3
Unlike the version in (rejected) [bugs:#3958], the alternative version shown above does not rely on trusting baz not to cast away const-ness; instead, it relies on the fact that modifying cpoi has undefined behaviour.
Diff:
What I find more surprising is that neither Clang nor GCC optimise the return value of a function even if illicit modification of the object with the escaped address would have undefined behaviour:
https://godbolt.org/z/EGqes58bh
But that seemingly-excessive abundance of caution does not extend to non-pointer types, which seems inconsistent:
https://godbolt.org/z/hMx3Wbeo4
(I can only assume that it's something to do with
ibeing treated as an integer constant expression, unlikepiand&i.)Diff:
Please consider the attached patch developed in discussion with Codex. The actual compiler change is small but there are many tests to ensure that the change is safe.
Replacing the candidate patch with one that uses
__reentrantto avoid the usual test issues when targeting PDK13 and similar machines.Further changes to the candidate patch to avoid assuming that redundant loads are not discarded by the optimiser in tests that warnings are not produced.
Looks good to me.