return RegionMap;
}
+static ProgramStateRef updateSwappedRegion(ProgramStateRef State,
+ const MemRegion *Region,
+ const SVal *RegionInnerPointerVal) {
+ if (RegionInnerPointerVal) {
+ State = State->set<TrackedRegionMap>(Region, *RegionInnerPointerVal);
+ } else {
+ State = State->remove<TrackedRegionMap>(Region);
+ }
+ return State;
+}
+
bool SmartPtrModeling::isNullAfterMoveMethod(const CallEvent &Call) const {
// TODO: Update CallDescription to support anonymous calls?
// TODO: Handle other methods, such as .get() or .release().
cast<CXXInstanceCall>(&Call)->getCXXThisVal().getAsRegion();
if (!move::isMovedFrom(State, ThisR)) {
- // TODO: Model this case as well. At least, avoid invalidation of globals.
+ // TODO: Model this case as well. At least, avoid invalidation of
+ // globals.
return false;
}
return;
auto State = updateTrackedRegion(Call, C, ThisValRegion);
C.addTransition(State);
- // TODO: Make sure to ivalidate the the region in the Store if we don't have
+ // TODO: Make sure to ivalidate the region in the Store if we don't have
// time to model all methods.
}
void SmartPtrModeling::handleSwap(const CallEvent &Call,
CheckerContext &C) const {
- // TODO: Add support to handle swap method.
+ // To model unique_ptr::swap() method.
+ const auto *IC = dyn_cast<CXXInstanceCall>(&Call);
+ if (!IC)
+ return;
+
+ const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
+ if (!ThisRegion)
+ return;
+
+ const auto *ArgRegion = Call.getArgSVal(0).getAsRegion();
+ if (!ArgRegion)
+ return;
+
+ auto State = C.getState();
+ const auto *ThisRegionInnerPointerVal =
+ State->get<TrackedRegionMap>(ThisRegion);
+ const auto *ArgRegionInnerPointerVal =
+ State->get<TrackedRegionMap>(ArgRegion);
+
+ // Swap the tracked region values.
+ State = updateSwappedRegion(State, ThisRegion, ArgRegionInnerPointerVal);
+ State = updateSwappedRegion(State, ArgRegion, ThisRegionInnerPointerVal);
+
+ C.addTransition(State);
}
ProgramStateRef
Q->foo(); // no-warning
}
}
+
+void derefOnSwappedNullPtr() {
+ std::unique_ptr<A> P(new A());
+ std::unique_ptr<A> PNull;
+ P.swap(PNull);
+ PNull->foo(); // No warning.
+ (*P).foo(); // expected-warning {{Dereference of null smart pointer [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefOnStdSwappedNullPtr() {
+ std::unique_ptr<A> P;
+ std::unique_ptr<A> PNull;
+ std::swap(P, PNull);
+ PNull->foo(); // expected-warning {{Dereference of null smart pointer [alpha.cplusplus.SmartPtr]}}
+ P->foo(); // expected-warning {{Dereference of null smart pointer [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefOnSwappedValidPtr() {
+ std::unique_ptr<A> P(new A());
+ std::unique_ptr<A> PValid(new A());
+ P.swap(PValid);
+ (*P).foo(); // No warning.
+ PValid->foo(); // No warning.
+ std::swap(P, PValid);
+ P->foo(); // No warning.
+ PValid->foo(); // No warning.
+}