Enabled relaxed LiveVariables analysis in the path-sensitive engine to increase the coverage of bugs. Primarily affects IdempotentOperationChecker.
- Migrated a temporarily separated test back to its original file (bug has been fixed, null-deref-ps-temp.c -> null-deref-ps.c) - Changed SymbolManager to use relaxed LiveVariables - Updated several test cases that the IdempotentOperationChecker class now flags - Added test case to test relaxed LiveVariables use by the IdempotentOperationChecker llvm-svn: 112312
This commit is contained in:
parent
fd8967a82f
commit
98e679508d
|
@ -324,7 +324,8 @@ bool SymbolReaper::isLive(SymbolRef sym) {
|
|||
}
|
||||
|
||||
bool SymbolReaper::isLive(const Stmt* ExprVal) const {
|
||||
return LCtx->getLiveVariables()->isLive(Loc, ExprVal);
|
||||
return LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
|
||||
isLive(Loc, ExprVal);
|
||||
}
|
||||
|
||||
bool SymbolReaper::isLive(const VarRegion *VR) const {
|
||||
|
@ -332,7 +333,8 @@ bool SymbolReaper::isLive(const VarRegion *VR) const {
|
|||
const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
|
||||
|
||||
if (VarContext == CurrentContext)
|
||||
return LCtx->getLiveVariables()->isLive(Loc, VR->getDecl());
|
||||
return LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
|
||||
isLive(Loc, VR->getDecl());
|
||||
|
||||
return VarContext->isParentOf(CurrentContext);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
void f(void) {
|
||||
void (*p)(void);
|
||||
p = f;
|
||||
p = &f;
|
||||
p = &f; // expected-warning{{Assigned value is always the same as the existing value}}
|
||||
p();
|
||||
(*p)();
|
||||
}
|
||||
|
|
|
@ -78,6 +78,20 @@ void bailout() {
|
|||
}
|
||||
}
|
||||
|
||||
// Relaxed liveness - check that we don't kill liveness at assignments
|
||||
typedef unsigned uintptr_t;
|
||||
void kill_at_assign() {
|
||||
short array[2];
|
||||
uintptr_t x = array; // expected-warning{{incompatible pointer to integer conversion}}
|
||||
short *p = x; // expected-warning{{incompatible integer to pointer conversion}}
|
||||
|
||||
// The following branch should be infeasible.
|
||||
if (!(p = &array[0])) { // expected-warning{{Assigned value is always the same as the existing value}}
|
||||
p = 0;
|
||||
*p = 1; // no-warning
|
||||
}
|
||||
}
|
||||
|
||||
// False positive tests
|
||||
|
||||
unsigned false1() {
|
||||
|
|
|
@ -253,7 +253,7 @@ void rdar_7249327(unsigned int A[2*32]) {
|
|||
a = A;
|
||||
b = B;
|
||||
|
||||
n = *a++;
|
||||
n = *a++; // expected-warning{{Assigned value is always the same as the existing value}}
|
||||
if (n)
|
||||
x += *b++; // no-warning
|
||||
}
|
||||
|
@ -708,7 +708,7 @@ int pr5857(char *src) {
|
|||
long long *z = (long long *) (intptr_t) src;
|
||||
long long w = 0;
|
||||
int n = 0;
|
||||
for (n = 0; n < y; ++n) {
|
||||
for (n = 0; n < y; ++n) { // expected-warning{{Assigned value is always the same as the existing value}}
|
||||
// Previously we crashed analyzing this statement.
|
||||
w = *z++;
|
||||
}
|
||||
|
|
|
@ -458,7 +458,7 @@ void rdar_7062158_2() {
|
|||
// ElementRegion is created.
|
||||
unsigned char test_array_index_bitwidth(const unsigned char *p) {
|
||||
unsigned short i = 0;
|
||||
for (i = 0; i < 2; i++) p = &p[i];
|
||||
for (i = 0; i < 2; i++) p = &p[i]; // expected-warning{{Assigned value is always the same as the existing value}}
|
||||
return p[i+1];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -std=gnu99 -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -analyzer-no-purge-dead -verify %s -Wreturn-type
|
||||
|
||||
// This is a temporary file to isolate a test case that would cause a failure
|
||||
// only some of the time in null-deref-ps.c. The idempotent operations checker
|
||||
// has revealed a bug on line 18 ('=' instead of '==') when the
|
||||
// -analyzer-no-purge-dead flag is passed to cc1. Some fundamental design
|
||||
// changes are needed to make this work without the -analyzer-no-purge-dead flag
|
||||
// and this test will be integrated back into the main file when this happens.
|
||||
|
||||
typedef unsigned uintptr_t;
|
||||
|
||||
int f4_b() {
|
||||
short array[2];
|
||||
uintptr_t x = array; // expected-warning{{incompatible pointer to integer conversion}}
|
||||
short *p = x; // expected-warning{{incompatible integer to pointer conversion}}
|
||||
|
||||
// The following branch should be infeasible.
|
||||
if (!(p = &array[0])) { // expected-warning{{Assigned value is always the same as the existing value}}
|
||||
p = 0;
|
||||
*p = 1; // no-warning
|
||||
}
|
||||
|
||||
if (p) {
|
||||
*p = 5; // no-warning
|
||||
p = 0;
|
||||
}
|
||||
else return; // expected-warning {{non-void function 'f4_b' should return a value}}
|
||||
|
||||
*p += 10; // expected-warning{{Dereference of null pointer}}
|
||||
return 0;
|
||||
}
|
|
@ -60,7 +60,26 @@ int f4(int *p) {
|
|||
return *q; // expected-warning{{Dereference of null pointer (loaded from variable 'q')}}
|
||||
}
|
||||
|
||||
// Placeholder for f4_b, temporarily moved to null-deref-ps-temp.c
|
||||
int f4_b() {
|
||||
short array[2];
|
||||
uintptr_t x = array; // expected-warning{{incompatible pointer to integer conversion}}
|
||||
short *p = x; // expected-warning{{incompatible integer to pointer conversion}}
|
||||
|
||||
// The following branch should be infeasible.
|
||||
if (!(p == &array[0])) {
|
||||
p = 0;
|
||||
*p = 1; // no-warning
|
||||
}
|
||||
|
||||
if (p) {
|
||||
*p = 5; // no-warning
|
||||
p = 0;
|
||||
}
|
||||
else return; // expected-warning {{non-void function 'f4_b' should return a value}}
|
||||
|
||||
*p += 10; // expected-warning{{Dereference of null pointer}}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int f5() {
|
||||
|
||||
|
|
Loading…
Reference in New Issue