forked from OSchip/llvm-project
[analysis] Discard type qualifiers when casting values retrieved from the Store.
This canonicalizes the representation of unknown pointer symbols, which reduces the overall confusion in pointer cast representation. Patch by Vince Bridgers! Differential Revision: https://reviews.llvm.org/D70836
This commit is contained in:
parent
84d8fa30f9
commit
6d3f43ec61
|
@ -393,6 +393,11 @@ SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType,
|
|||
return UnknownVal();
|
||||
}
|
||||
|
||||
static bool hasSameUnqualifiedPointeeType(QualType ty1, QualType ty2) {
|
||||
return ty1->getPointeeType().getTypePtr() ==
|
||||
ty2->getPointeeType().getTypePtr();
|
||||
}
|
||||
|
||||
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
|
||||
/// implicit casts that arise from loads from regions that are reinterpreted
|
||||
/// as another region.
|
||||
|
@ -421,10 +426,11 @@ SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
|
|||
// FIXME: We really need a single good function to perform casts for us
|
||||
// correctly every time we need it.
|
||||
if (castTy->isPointerType() && !castTy->isVoidPointerType())
|
||||
if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion()))
|
||||
if (SR->getSymbol()->getType().getCanonicalType() !=
|
||||
castTy.getCanonicalType())
|
||||
return loc::MemRegionVal(castRegion(SR, castTy));
|
||||
if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion())) {
|
||||
QualType sr = SR->getSymbol()->getType();
|
||||
if (!hasSameUnqualifiedPointeeType(sr, castTy))
|
||||
return loc::MemRegionVal(castRegion(SR, castTy));
|
||||
}
|
||||
|
||||
return svalBuilder.dispatchCast(V, castTy);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
// RUN: %clang_analyze_cc1 -analyzer-checker=core %s -verify
|
||||
// expected-no-diagnostics
|
||||
|
||||
#define SIZE 2
|
||||
|
||||
typedef struct {
|
||||
int noOfSymbols;
|
||||
} Params;
|
||||
|
||||
static void create(const Params * const params, int fooList[]) {
|
||||
int tmpList[SIZE] = {0};
|
||||
for (int i = 0; i < params->noOfSymbols; i++)
|
||||
fooList[i] = tmpList[i];
|
||||
}
|
||||
|
||||
int work(Params * const params) {
|
||||
int fooList[SIZE];
|
||||
create(params, fooList);
|
||||
int sum = 0;
|
||||
for (int i = 0; i < params->noOfSymbols; i++)
|
||||
sum += fooList[i]; // no-warning
|
||||
return sum;
|
||||
}
|
||||
|
||||
static void create2(const Params * const * pparams, int fooList[]) {
|
||||
const Params * params = *pparams;
|
||||
int tmpList[SIZE] = {0};
|
||||
for (int i = 0; i < params->noOfSymbols; i++)
|
||||
fooList[i] = tmpList[i];
|
||||
}
|
||||
|
||||
int work2(const Params * const params) {
|
||||
int fooList[SIZE];
|
||||
create2(¶ms, fooList);
|
||||
int sum = 0;
|
||||
for (int i = 0; i < params->noOfSymbols; i++)
|
||||
sum += fooList[i]; // no-warning
|
||||
return sum;
|
||||
}
|
||||
|
||||
static void create3(Params * const * pparams, int fooList[]) {
|
||||
const Params * params = *pparams;
|
||||
int tmpList[SIZE] = {0};
|
||||
for (int i = 0; i < params->noOfSymbols; i++)
|
||||
fooList[i] = tmpList[i];
|
||||
}
|
||||
|
||||
int work3(const Params * const params) {
|
||||
int fooList[SIZE];
|
||||
Params *const *ptr = (Params *const*)¶ms;
|
||||
create3(ptr, fooList);
|
||||
int sum = 0;
|
||||
for (int i = 0; i < params->noOfSymbols; i++)
|
||||
sum += fooList[i]; // no-warning
|
||||
return sum;
|
||||
}
|
Loading…
Reference in New Issue