[PATCH] D110927: [analyzer] Access stored value of a constant array through a pointer to another type

Bal√°zs Benics via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 10 09:08:42 PST 2021

steakhal added a comment.

In D110927#3118936 <https://reviews.llvm.org/D110927#3118936>, @ASDenysPetrov wrote:

>> You could have a parameter, and take its address to accomplish your reinterpret casts and type puns.
> Do you mean: ...
> If so, IMO it doesn't matter.

I see. Sorry about the confusion I caused.

In D110927#3115795 <https://reviews.llvm.org/D110927#3115795>, @ASDenysPetrov wrote:

> Does anyone know how to check the status of`-fno-strict-aliasing` flag from CSA side?

I think I know.
Within the `AnalysisConsumer::AnalysisConsumer()` you have access to the `CompilerInstance` object. Using that you can acquire the `CI.getCodeGenOpts().RelaxedAliasing` bool member, which represents exactly what we need, according to the `clang/include/clang/Basic/CodeGenOptions.def:211`:

  CODEGENOPT(RelaxedAliasing   , 1, 0) ///< Set when -fno-strict-aliasing is enabled.

I think you should simply save a `const` reference to the `CodeGenOptions` object from the `AnalysisConsumer`.

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:
> > 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
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.



More information about the cfe-commits mailing list