r179554 - [analyzer] Re-enable using global regions as a symbolic base.
Jordan Rose
jordan_rose at apple.com
Mon Apr 15 13:39:45 PDT 2013
Author: jrose
Date: Mon Apr 15 15:39:45 2013
New Revision: 179554
URL: http://llvm.org/viewvc/llvm-project?rev=179554&view=rev
Log:
[analyzer] Re-enable using global regions as a symbolic base.
Now that we're invalidating global regions properly, we want to continue
taking advantage of a particular optimization: if all global regions are
invalidated together, we can represent the bindings of each region with
a "derived region value" symbol. Essentially, this lazily links each
global region with a single symbol created at invalidation time, rather
than binding each region with a new symbolic value.
We used to do this, but haven't been for a while; the previous commit
re-enabled this code path, and this handles the fallout.
<rdar://problem/13464044>
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
cfe/trunk/test/Analysis/Inputs/system-header-simulator.h
cfe/trunk/test/Analysis/global-region-invalidation.c
cfe/trunk/test/Analysis/global_region_invalidation.mm
Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=179554&r1=179553&r2=179554&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Mon Apr 15 15:39:45 2013
@@ -490,8 +490,7 @@ public: // Part of public interface to c
SVal getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
const TypedValueRegion *R,
- QualType Ty,
- const MemRegion *superR);
+ QualType Ty);
SVal getLazyBinding(const SubRegion *LazyBindingRegion,
RegionBindingsRef LazyBinding);
@@ -1546,7 +1545,7 @@ SVal RegionStoreManager::getBindingForEl
}
}
}
- return getBindingForFieldOrElementCommon(B, R, R->getElementType(),superR);
+ return getBindingForFieldOrElementCommon(B, R, R->getElementType());
}
SVal RegionStoreManager::getBindingForField(RegionBindingsConstRef B,
@@ -1557,7 +1556,7 @@ SVal RegionStoreManager::getBindingForFi
return *V;
QualType Ty = R->getValueType();
- return getBindingForFieldOrElementCommon(B, R, Ty, R->getSuperRegion());
+ return getBindingForFieldOrElementCommon(B, R, Ty);
}
Optional<SVal>
@@ -1620,8 +1619,7 @@ SVal RegionStoreManager::getLazyBinding(
SVal
RegionStoreManager::getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
const TypedValueRegion *R,
- QualType Ty,
- const MemRegion *superR) {
+ QualType Ty) {
// At this point we have already checked in either getBindingForElement or
// getBindingForField if 'R' has a direct binding.
@@ -1654,8 +1652,9 @@ RegionStoreManager::getBindingForFieldOr
// quickly result in a warning.
bool hasPartialLazyBinding = false;
- const SubRegion *Base = dyn_cast<SubRegion>(superR);
- while (Base) {
+ const SubRegion *SR = dyn_cast<SubRegion>(R);
+ while (SR) {
+ const MemRegion *Base = SR->getSuperRegion();
if (Optional<SVal> D = getBindingForDerivedDefaultValue(B, Base, R, Ty)) {
if (D->getAs<nonloc::LazyCompoundVal>()) {
hasPartialLazyBinding = true;
@@ -1673,7 +1672,7 @@ RegionStoreManager::getBindingForFieldOr
// If our super region is a field or element itself, walk up the region
// hierarchy to see if there is a default value installed in an ancestor.
- Base = dyn_cast<SubRegion>(Base->getSuperRegion());
+ SR = dyn_cast<SubRegion>(Base);
}
if (R->hasStackNonParametersStorage()) {
@@ -1681,7 +1680,7 @@ RegionStoreManager::getBindingForFieldOr
// Currently we don't reason specially about Clang-style vectors. Check
// if superR is a vector and if so return Unknown.
if (const TypedValueRegion *typedSuperR =
- dyn_cast<TypedValueRegion>(superR)) {
+ dyn_cast<TypedValueRegion>(R->getSuperRegion())) {
if (typedSuperR->getValueType()->isVectorType())
return UnknownVal();
}
Modified: cfe/trunk/test/Analysis/Inputs/system-header-simulator.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/system-header-simulator.h?rev=179554&r1=179553&r2=179554&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator.h (original)
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator.h Mon Apr 15 15:39:45 2013
@@ -5,6 +5,10 @@
// suppressed.
#pragma clang system_header
+#ifdef __cplusplus
+#define restrict /*restrict*/
+#endif
+
typedef struct _FILE FILE;
extern FILE *stdin;
extern FILE *stdout;
Modified: cfe/trunk/test/Analysis/global-region-invalidation.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/global-region-invalidation.c?rev=179554&r1=179553&r2=179554&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/global-region-invalidation.c (original)
+++ cfe/trunk/test/Analysis/global-region-invalidation.c Mon Apr 15 15:39:45 2013
@@ -44,7 +44,10 @@ int testErrnoSystem() {
fscanf(stdin, "%d", &i); // errno gets invalidated here.
return 5 / errno; // no-warning
}
- return 0;
+
+ errno = 0;
+ fscanf(stdin, "%d", &i); // errno gets invalidated here.
+ return 5 / errno; // no-warning
}
// Test that errno gets invalidated by internal calls.
Modified: cfe/trunk/test/Analysis/global_region_invalidation.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/global_region_invalidation.mm?rev=179554&r1=179553&r2=179554&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/global_region_invalidation.mm (original)
+++ cfe/trunk/test/Analysis/global_region_invalidation.mm Mon Apr 15 15:39:45 2013
@@ -2,6 +2,8 @@
void clang_analyzer_eval(int);
+#include "Inputs/system-header-simulator.h"
+
void use(int);
id foo(int x) {
if (x)
@@ -19,9 +21,10 @@ void testGlobalRef() {
}
extern int globalInt;
-extern struct {
+struct IntWrapper {
int value;
-} globalStruct;
+};
+extern struct IntWrapper globalStruct;
extern void invalidateGlobals();
void testGlobalInvalidation() {
@@ -38,6 +41,18 @@ void testGlobalInvalidation() {
invalidateGlobals();
clang_analyzer_eval(globalInt == 42); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(globalStruct.value == 43); // expected-warning{{UNKNOWN}}
+
+ // Repeat to make sure we don't get the /same/ new symbolic values.
+ if (globalInt != 42)
+ return;
+ if (globalStruct.value != 43)
+ return;
+ clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}}
+ clang_analyzer_eval(globalStruct.value == 43); // expected-warning{{TRUE}}
+
+ invalidateGlobals();
+ clang_analyzer_eval(globalInt == 42); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(globalStruct.value == 43); // expected-warning{{UNKNOWN}}
}
void testGlobalInvalidationWithDirectBinding() {
@@ -53,3 +68,121 @@ void testGlobalInvalidationWithDirectBin
clang_analyzer_eval(globalInt == 42); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(globalStruct.value == 43); // expected-warning{{UNKNOWN}}
}
+
+void testStaticLocals(void) {
+ static int i;
+ int tmp;
+
+ extern int someSymbolicValue();
+ i = someSymbolicValue();
+
+ if (i == 5) {
+ clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}
+ scanf("%d", &tmp);
+ clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}
+ invalidateGlobals();
+ clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}
+ }
+
+ i = 6;
+ clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
+ scanf("%d", &tmp);
+ clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
+ invalidateGlobals();
+ clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
+
+ i = someSymbolicValue();
+ if (i == 7) {
+ clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}
+ scanf("%d", &i);
+ clang_analyzer_eval(i == 7); // expected-warning{{UNKNOWN}}
+ }
+
+ i = 8;
+ clang_analyzer_eval(i == 8); // expected-warning{{TRUE}}
+ scanf("%d", &i);
+ clang_analyzer_eval(i == 8); // expected-warning{{UNKNOWN}}
+}
+
+void testNonSystemGlobals(void) {
+ extern int i;
+ int tmp;
+
+ if (i == 5) {
+ clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}
+ scanf("%d", &tmp);
+ clang_analyzer_eval(i == 5); // expected-warning{{TRUE}}
+ invalidateGlobals();
+ clang_analyzer_eval(i == 5); // expected-warning{{UNKNOWN}}
+ }
+
+ i = 6;
+ clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
+ scanf("%d", &tmp);
+ clang_analyzer_eval(i == 6); // expected-warning{{TRUE}}
+ invalidateGlobals();
+ clang_analyzer_eval(i == 6); // expected-warning{{UNKNOWN}}
+
+ if (i == 7) {
+ clang_analyzer_eval(i == 7); // expected-warning{{TRUE}}
+ scanf("%d", &i);
+ clang_analyzer_eval(i == 7); // expected-warning{{UNKNOWN}}
+ }
+
+ i = 8;
+ clang_analyzer_eval(i == 8); // expected-warning{{TRUE}}
+ scanf("%d", &i);
+ clang_analyzer_eval(i == 8); // expected-warning{{UNKNOWN}}
+}
+
+void testWrappedGlobals(void) {
+ extern char c;
+ SomeStruct s;
+
+ if (c == 'C') {
+ s.p = &c;
+ clang_analyzer_eval(c == 'C'); // expected-warning{{TRUE}}
+ fakeSystemHeaderCall(0);
+ clang_analyzer_eval(c == 'C'); // expected-warning{{TRUE}}
+ fakeSystemHeaderCall(&s);
+ clang_analyzer_eval(c == 'C'); // expected-warning{{UNKNOWN}}
+ }
+
+ c = 'c';
+ s.p = &c;
+ clang_analyzer_eval(c == 'c'); // expected-warning{{TRUE}}
+ fakeSystemHeaderCall(0);
+ clang_analyzer_eval(c == 'c'); // expected-warning{{TRUE}}
+ fakeSystemHeaderCall(&s);
+ clang_analyzer_eval(c == 'c'); // expected-warning{{UNKNOWN}}
+
+ if (c == 'C') {
+ s.p = &c;
+ clang_analyzer_eval(c == 'C'); // expected-warning{{TRUE}}
+ fakeSystemHeaderCall(0);
+ clang_analyzer_eval(c == 'C'); // expected-warning{{TRUE}}
+ fakeSystemHeaderCall(&s);
+ clang_analyzer_eval(c == 'C'); // expected-warning{{UNKNOWN}}
+ }
+}
+
+void testWrappedStaticsViaGlobal(void) {
+ static char c;
+ extern SomeStruct s;
+
+ extern char getSomeChar();
+ c = getSomeChar();
+
+ if (c == 'C') {
+ s.p = &c;
+ clang_analyzer_eval(c == 'C'); // expected-warning{{TRUE}}
+ invalidateGlobals();
+ clang_analyzer_eval(c == 'C'); // expected-warning{{UNKNOWN}}
+ }
+
+ c = 'c';
+ s.p = &c;
+ clang_analyzer_eval(c == 'c'); // expected-warning{{TRUE}}
+ invalidateGlobals();
+ clang_analyzer_eval(c == 'c'); // expected-warning{{UNKNOWN}}
+}
More information about the cfe-commits
mailing list