aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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) {