diff options
author | Jordan Rose <jordan_rose@apple.com> | 2013-03-20 20:35:53 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2013-03-20 20:35:53 +0000 |
commit | f8ddc098981d4d85cad4e72fc6dfcfe83b842b66 (patch) | |
tree | f03f97abd1fd285147db499e1c4379d961cdc49a /lib/StaticAnalyzer/Core/CallEvent.cpp | |
parent | e1a2e90876cbe2187250939374d26036ccba2ad6 (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.cpp | 31 |
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, |