Skip to content

Commit 6d3f43e

Browse files
committed
[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
1 parent 84d8fa3 commit 6d3f43e

File tree

2 files changed

+66
-4
lines changed

2 files changed

+66
-4
lines changed

clang/lib/StaticAnalyzer/Core/Store.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,11 @@ SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType,
393393
return UnknownVal();
394394
}
395395

396+
static bool hasSameUnqualifiedPointeeType(QualType ty1, QualType ty2) {
397+
return ty1->getPointeeType().getTypePtr() ==
398+
ty2->getPointeeType().getTypePtr();
399+
}
400+
396401
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
397402
/// implicit casts that arise from loads from regions that are reinterpreted
398403
/// as another region.
@@ -421,10 +426,11 @@ SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
421426
// FIXME: We really need a single good function to perform casts for us
422427
// correctly every time we need it.
423428
if (castTy->isPointerType() && !castTy->isVoidPointerType())
424-
if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion()))
425-
if (SR->getSymbol()->getType().getCanonicalType() !=
426-
castTy.getCanonicalType())
427-
return loc::MemRegionVal(castRegion(SR, castTy));
429+
if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion())) {
430+
QualType sr = SR->getSymbol()->getType();
431+
if (!hasSameUnqualifiedPointeeType(sr, castTy))
432+
return loc::MemRegionVal(castRegion(SR, castTy));
433+
}
428434

429435
return svalBuilder.dispatchCast(V, castTy);
430436
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=core %s -verify
2+
// expected-no-diagnostics
3+
4+
#define SIZE 2
5+
6+
typedef struct {
7+
int noOfSymbols;
8+
} Params;
9+
10+
static void create(const Params * const params, int fooList[]) {
11+
int tmpList[SIZE] = {0};
12+
for (int i = 0; i < params->noOfSymbols; i++)
13+
fooList[i] = tmpList[i];
14+
}
15+
16+
int work(Params * const params) {
17+
int fooList[SIZE];
18+
create(params, fooList);
19+
int sum = 0;
20+
for (int i = 0; i < params->noOfSymbols; i++)
21+
sum += fooList[i]; // no-warning
22+
return sum;
23+
}
24+
25+
static void create2(const Params * const * pparams, int fooList[]) {
26+
const Params * params = *pparams;
27+
int tmpList[SIZE] = {0};
28+
for (int i = 0; i < params->noOfSymbols; i++)
29+
fooList[i] = tmpList[i];
30+
}
31+
32+
int work2(const Params * const params) {
33+
int fooList[SIZE];
34+
create2(&params, fooList);
35+
int sum = 0;
36+
for (int i = 0; i < params->noOfSymbols; i++)
37+
sum += fooList[i]; // no-warning
38+
return sum;
39+
}
40+
41+
static void create3(Params * const * pparams, int fooList[]) {
42+
const Params * params = *pparams;
43+
int tmpList[SIZE] = {0};
44+
for (int i = 0; i < params->noOfSymbols; i++)
45+
fooList[i] = tmpList[i];
46+
}
47+
48+
int work3(const Params * const params) {
49+
int fooList[SIZE];
50+
Params *const *ptr = (Params *const*)&params;
51+
create3(ptr, fooList);
52+
int sum = 0;
53+
for (int i = 0; i < params->noOfSymbols; i++)
54+
sum += fooList[i]; // no-warning
55+
return sum;
56+
}

0 commit comments

Comments
 (0)