ASDenysPetrov added a comment.

In D110927#3117728 <https://reviews.llvm.org/D110927#3117728>, @steakhal wrote:

> For testing this I would recommend using a separate test file.
> That being said, you should avoid globals even in tests when you can. The 
> distance between its declaration and use just makes it harder to comprehend 
> and reason about.

I'll add a new tests file.

> You could have a parameter, and take its address to accomplish your 
> reinterpret casts and type puns.

Do you mean:

  void foo(signed char * ptr) {
    ptr = (signed char *)glob_arr2;
  }

instead of

  void foo() {
    auto *ptr = (signed char *)glob_arr2;
  }

?
If so, IMO it doesn't matter.

> BTW your patch crashes on the test suite:
> `initialization.cpp:242`:

I caught it. Thanks! I wonder how it slipped through unnoticed.



================
Comment at: clang/lib/StaticAnalyzer/Core/RegionStore.cpp:1661
+/// E.g. for `const int[1][2][3];` returns `int`.
+QualType getConstantArrayRootElement(const ConstantArrayType *CAT) {
+  assert(CAT && "ConstantArrayType should not be null");
----------------
steakhal wrote:
> Maybe //unwrapConstantArrayTypes()//?
I think about //getConstantArrayRoot**Type**//. IMO such name distinctly tells 
its intention and purpose.


================
Comment at: clang/lib/StaticAnalyzer/Core/RegionStore.cpp:1790
+  // paper P1839R0 be considered by the committee.
+  if ((Index != 0))
+    return false;
----------------
steakhal wrote:
> Even though you are technically correct, how can you know that the pointer 
> you try to dereference actually points to the beginning of the object?
> Consider something like this:
> 
> ```lang=C++
> void callback(void *payload) {
>   // lets skip the first char object...
>   int *num = (int*)((char*)payload + 1);
>   clang_analyzer_dump(num); // Element{Element{SymRegion{payload}, 1, char}, 
> 0, int}
> }
> ```
>  how can you know that the pointer you try to dereference actually points to 
> the beginning of the object?
We look at the offset of the region. In your example it is //1//. And it is UB. 
Unfortinatelly the Standard forbids to do such accesses due to the different 
strict access rules. I recommend this talk https://youtu.be/_qzMpk-22cc . I 
took inspiration from there.


================
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}}
+}
----------------
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`.



================
Comment at: clang/test/Analysis/initialization.cpp:311-314
+void glob_cast_invalid3() {
+  auto *ptr = (char32_t *)glob_arr2;
+  auto x = ptr[0]; // expected-warning{{garbage or undefined}}
+}
----------------
steakhal wrote:
> Please also try `char8_t`.
Correct. We should check it. It should be a different type as well 
(http://eel.is/c++draft/basic.fundamental#9).


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

Reply via email to