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:
Tom Care 2010-08-27 22:46:32 +00:00
parent fd8967a82f
commit 98e679508d
7 changed files with 42 additions and 38 deletions

View File

@ -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);
}

View File

@ -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)();
}

View File

@ -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() {

View File

@ -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++;
}

View File

@ -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];
}

View File

@ -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;
}

View File

@ -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() {