diff options
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 20 | ||||
-rw-r--r-- | test/Analysis/global_region_invalidation.mm | 30 | ||||
-rw-r--r-- | test/Analysis/string.c | 4 |
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) { |