diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2018-12-14 20:47:58 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2018-12-14 20:47:58 +0000 |
commit | 12f7c2baccdfb7da56d018f34f29a954968ead6d (patch) | |
tree | c84fbe5873ea8630a5679902f710d2f0f03e0c9f /clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp | |
parent | 3e5d847fa02f63d0026a6771be613e464530bb6f (diff) | |
download | bcm5719-llvm-12f7c2baccdfb7da56d018f34f29a954968ead6d.tar.gz bcm5719-llvm-12f7c2baccdfb7da56d018f34f29a954968ead6d.zip |
[analyzer] MoveChecker: Improve invalidation policies.
If a moved-from object is passed into a conservatively evaluated function
by pointer or by reference, we assume that the function may reset its state.
Make sure it doesn't apply to const pointers and const references. Add a test
that demonstrates that it does apply to rvalue references.
Additionally, make sure that the object is invalidated when its contents change
for reasons other than invalidation caused by evaluating a call conservatively.
In particular, when the object's fields are manipulated directly, we should
assume that some sort of reset may be happening.
Differential Revision: https://reviews.llvm.org/D55289
llvm-svn: 349190
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp | 46 |
1 files changed, 31 insertions, 15 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp index c93ba9d3b4e..dca0cbebd28 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp @@ -53,8 +53,8 @@ public: ProgramStateRef checkRegionChanges(ProgramStateRef State, const InvalidatedSymbols *Invalidated, - ArrayRef<const MemRegion *> ExplicitRegions, - ArrayRef<const MemRegion *> Regions, + ArrayRef<const MemRegion *> RequestedRegions, + ArrayRef<const MemRegion *> InvalidatedRegions, const LocationContext *LCtx, const CallEvent *Call) const; void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const override; @@ -525,19 +525,35 @@ void MoveChecker::checkDeadSymbols(SymbolReaper &SymReaper, ProgramStateRef MoveChecker::checkRegionChanges( ProgramStateRef State, const InvalidatedSymbols *Invalidated, - ArrayRef<const MemRegion *> ExplicitRegions, - ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx, - const CallEvent *Call) const { - // In case of an InstanceCall don't remove the ThisRegion from the GDM since - // it is handled in checkPreCall and checkPostCall. - const MemRegion *ThisRegion = nullptr; - if (const auto *IC = dyn_cast_or_null<CXXInstanceCall>(Call)) { - ThisRegion = IC->getCXXThisVal().getAsRegion(); - } - - for (const auto *Region : ExplicitRegions) { - if (ThisRegion != Region) - State = removeFromState(State, Region); + ArrayRef<const MemRegion *> RequestedRegions, + ArrayRef<const MemRegion *> InvalidatedRegions, + const LocationContext *LCtx, const CallEvent *Call) const { + if (Call) { + // Relax invalidation upon function calls: only invalidate parameters + // that are passed directly via non-const pointers or non-const references + // or rvalue references. + // In case of an InstanceCall don't invalidate the this-region since + // it is fully handled in checkPreCall and checkPostCall. + const MemRegion *ThisRegion = nullptr; + if (const auto *IC = dyn_cast<CXXInstanceCall>(Call)) + ThisRegion = IC->getCXXThisVal().getAsRegion(); + + // Requested ("explicit") regions are the regions passed into the call + // directly, but not all of them end up being invalidated. + // But when they do, they appear in the InvalidatedRegions array as well. + for (const auto *Region : RequestedRegions) { + if (ThisRegion != Region) { + if (llvm::find(InvalidatedRegions, Region) != + std::end(InvalidatedRegions)) { + State = removeFromState(State, Region); + } + } + } + } else { + // For invalidations that aren't caused by calls, assume nothing. In + // particular, direct write into an object's field invalidates the status. + for (const auto *Region : InvalidatedRegions) + State = removeFromState(State, Region->getBaseRegion()); } return State; |