]> granicus.if.org Git - clang/commitdiff
[analyzer] MisusedMovedObject: Fix state-resetting a base-class sub-object.
authorArtem Dergachev <artem.dergachev@gmail.com>
Tue, 10 Oct 2017 11:55:56 +0000 (11:55 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Tue, 10 Oct 2017 11:55:56 +0000 (11:55 +0000)
If a method is resetting the state of an object that was moved from, it should
be safe to use this object again. However if the method was defined in a parent
class, but used in a child class, the reset didn't happen from the checker's
perspective.

Differential Revision: https://reviews.llvm.org/D31538

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@315301 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
test/Analysis/MisusedMovedObject.cpp

index 70da66dba47f71194c46d25e71264c6e2e370594..4b69a1bd1edb243d015351c5f58f6e296c319535 100644 (file)
@@ -416,7 +416,14 @@ void MisusedMovedObjectChecker::checkPreCall(const CallEvent &Call,
     return;
 
   if (isStateResetMethod(MethodDecl)) {
-    State = State->remove<TrackedRegionMap>(ThisRegion);
+    // A state reset method resets the whole object, not only sub-object
+    // of a parent class in which it is defined.
+    const MemRegion *WholeObjectRegion = ThisRegion;
+    while (const CXXBaseObjectRegion *BR =
+               dyn_cast<CXXBaseObjectRegion>(WholeObjectRegion))
+      WholeObjectRegion = BR->getSuperRegion();
+
+    State = State->remove<TrackedRegionMap>(WholeObjectRegion);
     C.addTransition(State);
     return;
   }
index 44e055fd407b3bb213ed4854450311ff27ee6021..57c1ecc912b54e187fe071deb71bd1f4e804aa48 100644 (file)
@@ -617,3 +617,11 @@ void subRegionMoveTest() {
     a.b.foo();           // no-warning
   }
 }
+
+class C: public A {};
+void resetSuperClass() {
+  C c;
+  C c1 = std::move(c);
+  c.clear();
+  C c2 = c; // no-warning
+}