On Wed, Jul 31, 2024 at 10:19:06AM +0200, Jakub Jelinek wrote:
> On Wed, Jul 31, 2024 at 09:50:56AM +0200, Richard Biener wrote:
> > I wonder if
> > 
> > int foo (uintrptr_t x) { *(int *)x = 1; return 1; }
> > 
> > is considered "noptr" by the standard but then by making a pointer out of
> > 'x' invokes UB?
> 
> I don't know.  The paper claims same behavior as const for functions without
> pointer/array arguments (but arrays decay to pointers); that claim is
> most likely false because of the infinite loops, but still, I'm not sure
> about the
> struct S { int *p; };
> int bar (struct S x) [[unsequenced]] { x.p[0] = 1; return 1; }
> or
> int baz (...) [[unsequenced]] { va_list ap; va_start (ap); int *p = va_arg 
> (ap, int *); va_end (ap); *p = 1; return 1; }
> or
> typedef union { int *p; long long *q; } U __attribute__((transparent_union));
> int qux (int x, U y) [[unsequenced]] { if (x) y.p[0] = 1; else y.q[1] = 2; 
> return 3; }
> etc. cases too.

And neither I'm sure about pointers to pointers and the like, so
int corge (int **x) [[unsequenced]] { *x[0] = 42; return 5; }

BTW, my reading of the idempotent property is that
int garply (int *restrict x) { *x += 2; return 1; }
would be invalid, because you can't then schedule another call immediately
after an existing one without changing the observable state of execution.
But
int freddy (int *restrict x) [[unsequenced]] { x[0] = 42; return x[1]; }
would be ok.  So, for the memory reachable from the passed in pointers, each
byte can be either stored or read but not both (at least when such store or
read has then observable side-effects).  Not really sure if we could use
that info in some alias oracle decisions.

        Jakub

Reply via email to