aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-03-20 20:36:01 +0000
committerJordan Rose <jordan_rose@apple.com>2013-03-20 20:36:01 +0000
commitf8e2c06cea1548c437761cb65cfbf97d50a057a7 (patch)
tree0c1705965385e119ef57f931d76739b565772b06
parent74f6982232c25ae723b1cc5abc59665a10867f21 (diff)
[analyzer] Don't invalidate globals when there's no call involved.
This fixes some mistaken condition logic in RegionStore that caused global variables to be invalidated when /any/ region was invalidated, rather than only as part of opaque function calls. This was only being used by CStringChecker, and so users will now see that strcpy() and friends do not invalidate global variables. Also, add a test case we don't handle properly: explicitly-assigned global variables aren't being invalidated by opaque calls. This is being tracked by <rdar://problem/13464044>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177572 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp20
-rw-r--r--test/Analysis/global_region_invalidation.mm30
-rw-r--r--test/Analysis/string.c4
3 files changed, 41 insertions, 13 deletions
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index cf7858fd5f..3ff0a53335 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1073,20 +1073,18 @@ RegionStoreManager::invalidateRegions(Store store,
// Return the new bindings.
B = W.getRegionBindings();
- // For all globals which are not static nor immutable: determine which global
- // regions should be invalidated and invalidate them.
+ // For calls, determine which global regions should be invalidated and
+ // invalidate them. (Note that function-static and immutable globals are never
+ // invalidated by this.)
// TODO: This could possibly be more precise with modules.
- //
- // System calls invalidate only system globals.
- if (Call && Call->isInSystemHeader()) {
- B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind,
- Ex, Count, LCtx, B, Invalidated);
- // Internal calls might invalidate both system and internal globals.
- } else {
+ if (Call) {
B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind,
Ex, Count, LCtx, B, Invalidated);
- B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind,
- Ex, Count, LCtx, B, Invalidated);
+
+ if (!Call->isInSystemHeader()) {
+ B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind,
+ Ex, Count, LCtx, B, Invalidated);
+ }
}
return StoreRef(B.asStore(), *this);
diff --git a/test/Analysis/global_region_invalidation.mm b/test/Analysis/global_region_invalidation.mm
index be337edab1..f853470a5f 100644
--- a/test/Analysis/global_region_invalidation.mm
+++ b/test/Analysis/global_region_invalidation.mm
@@ -11,9 +11,35 @@ id foo(int x) {
return p;
}
-const int &globalInt = 42;
+const int &globalIntRef = 42;
-void testGlobal() {
+void testGlobalRef() {
// FIXME: Should be TRUE, but should at least not crash.
+ clang_analyzer_eval(globalIntRef == 42); // expected-warning{{UNKNOWN}}
+}
+
+extern int globalInt;
+extern void invalidateGlobals();
+
+void testGlobalInvalidation() {
+ if (globalInt != 42)
+ return;
+ clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}}
+
+ invalidateGlobals();
clang_analyzer_eval(globalInt == 42); // expected-warning{{UNKNOWN}}
}
+
+
+//---------------------------------
+// False negatives
+//---------------------------------
+
+void testGlobalInvalidationWithDirectBinding() {
+ globalInt = 42;
+ clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}}
+
+ invalidateGlobals();
+ // FIXME: Should be UNKNOWN.
+ clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}}
+}
diff --git a/test/Analysis/string.c b/test/Analysis/string.c
index 17a93ec013..74cf33c4bc 100644
--- a/test/Analysis/string.c
+++ b/test/Analysis/string.c
@@ -279,12 +279,16 @@ void strcpy_fn_const(char *x) {
strcpy(x, (const char*)&strcpy_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
}
+extern int globalInt;
void strcpy_effects(char *x, char *y) {
char a = x[0];
+ if (globalInt != 42)
+ return;
clang_analyzer_eval(strcpy(x, y) == x); // expected-warning{{TRUE}}
clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}}
clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}}
}
void strcpy_overflow(char *y) {