summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-12-14 20:47:58 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-12-14 20:47:58 +0000
commit12f7c2baccdfb7da56d018f34f29a954968ead6d (patch)
treec84fbe5873ea8630a5679902f710d2f0f03e0c9f /clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
parent3e5d847fa02f63d0026a6771be613e464530bb6f (diff)
downloadbcm5719-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.cpp46
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;
OpenPOWER on IntegriCloud