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