aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/CallEvent.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-03-20 20:35:53 +0000
committerJordan Rose <jordan_rose@apple.com>2013-03-20 20:35:53 +0000
commitf8ddc098981d4d85cad4e72fc6dfcfe83b842b66 (patch)
treef03f97abd1fd285147db499e1c4379d961cdc49a /lib/StaticAnalyzer/Core/CallEvent.cpp
parente1a2e90876cbe2187250939374d26036ccba2ad6 (diff)
[analyzer] Invalidate regions indirectly accessible through const pointers.
In this case, the value of 'x' may be changed after the call to indirectAccess: struct Wrapper { int *ptr; }; void indirectAccess(const Wrapper &w); void test() { int x = 42; Wrapper w = { x }; clang_analyzer_eval(x == 42); // TRUE indirectAccess(w); clang_analyzer_eval(x == 42); // UNKNOWN } This is important for modelling return-by-value objects in C++, to show that the contents of the struct are escaping in the return copy-constructor. <rdar://problem/13239826> git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177570 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/CallEvent.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/CallEvent.cpp31
1 files changed, 12 insertions, 19 deletions
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp
index d7e1b1253e..78400ba359 100644
--- a/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -125,7 +125,7 @@ static bool isPointerToConst(QualType Ty) {
// Try to retrieve the function declaration and find the function parameter
// types which are pointers/references to a non-pointer const.
// We will not invalidate the corresponding argument regions.
-static void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs,
+static void findPtrToConstParams(llvm::SmallSet<unsigned, 4> &PreserveArgs,
const CallEvent &Call) {
unsigned Idx = 0;
for (CallEvent::param_type_iterator I = Call.param_type_begin(),
@@ -137,36 +137,29 @@ static void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs,
}
ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
- ProgramStateRef Orig) const {
+ ProgramStateRef Orig) const {
ProgramStateRef Result = (Orig ? Orig : getState());
+ SmallVector<const MemRegion *, 8> ConstRegions;
SmallVector<const MemRegion *, 8> RegionsToInvalidate;
getExtraInvalidatedRegions(RegionsToInvalidate);
// Indexes of arguments whose values will be preserved by the call.
- llvm::SmallSet<unsigned, 1> PreserveArgs;
+ llvm::SmallSet<unsigned, 4> PreserveArgs;
if (!argumentsMayEscape())
findPtrToConstParams(PreserveArgs, *this);
for (unsigned Idx = 0, Count = getNumArgs(); Idx != Count; ++Idx) {
- if (PreserveArgs.count(Idx))
- continue;
-
- SVal V = getArgSVal(Idx);
-
- // If we are passing a location wrapped as an integer, unwrap it and
- // invalidate the values referred by the location.
- if (Optional<nonloc::LocAsInteger> Wrapped =
- V.getAs<nonloc::LocAsInteger>())
- V = Wrapped->getLoc();
- else if (!V.getAs<Loc>())
+ const MemRegion *R = getArgSVal(Idx).getAsRegion();
+ if (!R)
continue;
- if (const MemRegion *R = V.getAsRegion()) {
- // Mark this region for invalidation. We batch invalidate regions
- // below for efficiency.
+ // Mark this region for invalidation. We batch invalidate regions
+ // below for efficiency.
+ if (PreserveArgs.count(Idx))
+ ConstRegions.push_back(R);
+ else
RegionsToInvalidate.push_back(R);
- }
}
// Invalidate designated regions using the batch invalidation API.
@@ -175,7 +168,7 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
return Result->invalidateRegions(RegionsToInvalidate, getOriginExpr(),
BlockCount, getLocationContext(),
/*CausedByPointerEscape*/ true,
- /*Symbols=*/0, this);
+ /*Symbols=*/0, this, ConstRegions);
}
ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,