[PATCH] D113480: [analyzer] Fix region cast between the same types with different qualifiers.
Denys Petrov via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 9 04:42:46 PST 2021
ASDenysPetrov created this revision.
ASDenysPetrov added reviewers: steakhal, NoQ, martong.
ASDenysPetrov added a project: clang.
Herald added subscribers: manas, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun.
ASDenysPetrov requested review of this revision.
Herald added a subscriber: cfe-commits.
Specifically, this fixes the case when we get an access to array element through the pointer to element. This covers several //FIXME's//. in D111654 <https://reviews.llvm.org/D111654>.
Example:
const int arr[4][2];
const int *ptr = arr[1]; // Fixes this.
The issue is that `arr[1]` is `int*` (`&Element{Element{glob_arr5,1 S64b,int[2]},0 S64b,int}`), and `ptr` is `const int*`. We don't take qualifiers into account. Consequently, we doesn't match the types as the same ones.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D113480
Files:
clang/lib/StaticAnalyzer/Core/Store.cpp
clang/test/Analysis/initialization.cpp
Index: clang/test/Analysis/initialization.cpp
===================================================================
--- clang/test/Analysis/initialization.cpp
+++ clang/test/Analysis/initialization.cpp
@@ -68,8 +68,7 @@
void glob_invalid_index4() {
const int *ptr = glob_arr4[1];
int idx = -42;
- // FIXME: Should warn {{garbage or undefined}}.
- auto x = ptr[idx]; // no-warning
+ auto x = ptr[idx]; // expected-warning{{garbage or undefined}}
}
int const glob_arr5[4][2] = {{1}, 3, 4, 5};
@@ -86,16 +85,11 @@
void glob_ptr_index2() {
int const *ptr = glob_arr5[1];
- // FIXME: Should be TRUE.
- clang_analyzer_eval(ptr[0] == 3); // expected-warning{{UNKNOWN}}
- // FIXME: Should be TRUE.
- clang_analyzer_eval(ptr[1] == 4); // expected-warning{{UNKNOWN}}
- // FIXME: Should be UNDEFINED.
- clang_analyzer_eval(ptr[2] == 5); // expected-warning{{UNKNOWN}}
- // FIXME: Should be UNDEFINED.
- clang_analyzer_eval(ptr[3] == 0); // expected-warning{{UNKNOWN}}
- // FIXME: Should be UNDEFINED.
- clang_analyzer_eval(ptr[4] == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(ptr[0] == 3); // expected-warning{{TRUE}}
+ clang_analyzer_eval(ptr[1] == 4); // expected-warning{{TRUE}}
+ clang_analyzer_eval(ptr[2] == 5); // expected-warning{{UNDEFINED}}
+ clang_analyzer_eval(ptr[3] == 0); // expected-warning{{UNDEFINED}}
+ clang_analyzer_eval(ptr[4] == 0); // expected-warning{{UNDEFINED}}
}
void glob_invalid_index5() {
@@ -106,8 +100,7 @@
void glob_invalid_index6() {
int const *ptr = &glob_arr5[1][0];
int idx = 42;
- // FIXME: Should warn {{garbage or undefined}}.
- auto x = ptr[idx]; // no-warning
+ auto x = ptr[idx]; // expected-warning{{garbage or undefined}}
}
extern const int glob_arr_no_init[10];
Index: clang/lib/StaticAnalyzer/Core/Store.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/Store.cpp
+++ clang/lib/StaticAnalyzer/Core/Store.cpp
@@ -101,13 +101,19 @@
if (CanonPointeeTy.getLocalUnqualifiedType() == Ctx.VoidTy)
return R;
- // Handle casts from compatible types.
- if (R->isBoundable())
+ const auto IsSameRegionType = [&Ctx, CanonPointeeTy](const MemRegion *R) {
if (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
- if (CanonPointeeTy == ObjTy)
- return R;
+ if (CanonPointeeTy.getLocalUnqualifiedType() ==
+ ObjTy.getLocalUnqualifiedType())
+ return true;
}
+ return false;
+ };
+
+ // Handle casts from compatible types.
+ if (R->isBoundable() && IsSameRegionType(R))
+ return R;
// Process region cast according to the kind of the region being cast.
switch (R->getKind()) {
@@ -174,16 +180,11 @@
CharUnits off = rawOff.getOffset();
if (off.isZero()) {
- // Edge case: we are at 0 bytes off the beginning of baseR. We
+ // Edge case: we are at 0 bytes off the beginning of baseR. We
// check to see if type we are casting to is the same as the base
- // region. If so, just return the base region.
- if (const auto *TR = dyn_cast<TypedValueRegion>(baseR)) {
- QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
- QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy);
- if (CanonPointeeTy == ObjTy)
- return baseR;
- }
-
+ // region. If so, just return the base region.
+ if (IsSameRegionType(baseR))
+ return baseR;
// Otherwise, create a new ElementRegion at offset 0.
return MakeElementRegion(cast<SubRegion>(baseR), PointeeTy);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D113480.385773.patch
Type: text/x-patch
Size: 3675 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20211109/2957af9a/attachment.bin>
More information about the cfe-commits
mailing list