steakhal added inline comments.
================ Comment at: clang/test/Analysis/initialization.cpp:295-299 +void glob_cast_opposite_sign1() { + auto *ptr = (unsigned int *)glob_arr2; + auto x1 = ptr[0]; // no-warning + auto x2 = ptr[1]; // expected-warning{{garbage or undefined}} +} ---------------- ASDenysPetrov wrote: > steakhal wrote: > > ASDenysPetrov wrote: > > > steakhal wrote: > > > > ASDenysPetrov wrote: > > > > > steakhal wrote: > > > > > > I think it's not correct. > > > > > > > > > > > > `glob_arr2` refers to an object of dynamic type `int[2]`. > > > > > > And the pointer decayed from it is `int *`, which has //similar > > > > > > type// to `unsigned *` what you are using to access the memory. > > > > > > Since they are //similar//, this operation should work for all the > > > > > > valid indices, thus `ptr[0]`, `ptr[1]`, `ptr[2]`, `ptr[3]` should > > > > > > all be valid. > > > > > > > > > > > > > > > > > > glob_arr2 refers to an object of dynamic type int[2]. > > > > > `glob_arr2` has an extent of 4. > > > > > > And the pointer decayed from it is int *, which has similar type to > > > > > > unsigned * what you are using to access the memory. > > > > > Yes, they are the same and it perfectly suits to > > > > > http://eel.is/c++draft/basic.lval#11 . But still you can't access > > > > > other element then the first one according to > > > > > http://eel.is/c++draft/basic.compound#3 : //For purposes of pointer > > > > > arithmetic ([expr.add]) and comparison ([expr.rel], [expr.eq]), [...] > > > > > an object of type T that is not an array element is considered to > > > > > belong to an array with one element of type T. // > > > > > `unsigned int` and `int` are different types according to > > > > > http://eel.is/c++draft/basic.fundamental#2 . The object of type > > > > > `unsigned int` is NOT an array, beacuse there is no array of type > > > > > `unsigned int`. Hence you can only only access the first and a single > > > > > element of type `unsigned int`. > > > > > > > > > Yes, `glob_arr` has 4 elements, sorry for this typo. > > > > > > > > --- > > > > I disagree with the second part though. It seems like gcc disagrees as > > > > well: https://godbolt.org/z/5o7ozvPar > > > > ```lang=C++ > > > > auto foo(unsigned (&p)[4], int (&q)[4]) { > > > > p[0] = 2; > > > > q[0] = 1; > > > > return p[0]; // memory read! thus, p and q can alias according to > > > > g++. > > > > } > > > > ``` > > > > `gcc` still thinks that `p` and `q` can refer to the same memory region > > > > even if the `-fstrict-aliasing` flag is present. > > > > In other circumstances, it would produce a `mov eax, 2` instead of a > > > > memory load if `p` and `q` cannot alias. > > > >I disagree with the second part though. It seems like gcc disagrees as > > > >well: https://godbolt.org/z/5o7ozvPar > > > I see how all the compilers handle this. I've switched several vendors on > > > Godbolt. They all have the similar behavior. You are right from compiler > > > perspective, but it's not quite the same in terms of C++ abstract machine. > > > Your example is correct, it works OK and is consistent with the Standard: > > > ``` > > > p[0] = 2; > > > q[0] = 1; > > > ``` > > > This one also works as expected but goes against the Standard: > > > ``` > > > p[1] = 2; > > > q[1] = 1; > > > ``` > > > I want you watch this particular part about access via aliased pointers: > > > https://youtu.be/_qzMpk-22cc?t=2623 For me it seems correct, at least I > > > can't argue against of it now. > > But in this example we have an array, thus pointer arithmetic should be > > fine according to the video. > > Could you find the mentioned email discussion? I would be really curious. > > BTW from the analyzer user's perspective, it would be 'better' to find > > strict aliasing violations which actually matter - now, and risking > > miscompilations. > I'm not enough confident about that to debate now. As you can see we started > arguing as well. That means that the Standard really leaves the subject for > misinterpretation. > OK, let's bring it to the form in which compilers operate. I mean, let's > legitimate indirections with a different offsets through aliased types: `auto > x = ((unsigened)arr)[42]; // OK`. > I think it will be enough for this patch for now. So, we agree that `glob_cast_opposite_sign1()` should have no warnings. At least for now. I would be okay with this direction. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D110927/new/ https://reviews.llvm.org/D110927 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits