This revision was automatically updated to reflect the committed changes.
Closed by commit rG1b743a9efa08: [analyzer] Add modeling for unique_ptr move 
constructor (authored by vrnithinkumar).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86373/new/

https://reviews.llvm.org/D86373

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
  clang/test/Analysis/smart-ptr-text-output.cpp
  clang/test/Analysis/smart-ptr.cpp

Index: clang/test/Analysis/smart-ptr.cpp
===================================================================
--- clang/test/Analysis/smart-ptr.cpp
+++ clang/test/Analysis/smart-ptr.cpp
@@ -17,7 +17,8 @@
   if (P)
     clang_analyzer_warnIfReached(); // no-warning
   // TODO: Report a null dereference (instead).
-  *P.get() = 1; // expected-warning {{Method called on moved-from object 'P'}}
+  *P.get() = 1; // expected-warning {{Method called on moved-from object 'P' [cplusplus.Move]}}
+  // expected-warning@-1 {{Dereference of null pointer [core.NullDereference]}}
 }
 
 // Don't crash when attempting to model a call with unknown callee.
@@ -333,3 +334,44 @@
   P = returnRValRefOfUniquePtr();
   P->foo(); // No warning. 
 }
+
+void derefMoveConstructedWithValidPtr() {
+  std::unique_ptr<A> PToMove(new A());
+  std::unique_ptr<A> P(std::move(PToMove));
+  P->foo(); // No warning.
+}
+
+void derefMoveConstructedWithNullPtr() {
+  std::unique_ptr<A> PToMove;
+  std::unique_ptr<A> P(std::move(PToMove));
+  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefMoveConstructedWithUnknownPtr(std::unique_ptr<A> PToMove) {
+  std::unique_ptr<A> P(std::move(PToMove));
+  P->foo(); // No warning.
+}
+
+void derefValidPtrMovedToConstruct() {
+  std::unique_ptr<A> PToMove(new A());
+  std::unique_ptr<A> P(std::move(PToMove));
+  PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefNullPtrMovedToConstruct() {
+  std::unique_ptr<A> PToMove;
+  std::unique_ptr<A> P(std::move(PToMove));
+  PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
+}
+
+void derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove) {
+  std::unique_ptr<A> P(std::move(PToMove));
+  PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
+}
+
+std::unique_ptr<A> &&functionReturnsRValueRef();
+
+void derefMoveConstructedWithRValueRefReturn() {
+  std::unique_ptr<A> P(functionReturnsRValueRef());
+  P->foo();  // No warning.
+}
Index: clang/test/Analysis/smart-ptr-text-output.cpp
===================================================================
--- clang/test/Analysis/smart-ptr-text-output.cpp
+++ clang/test/Analysis/smart-ptr-text-output.cpp
@@ -144,7 +144,7 @@
   std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}}
   // FIXME: above note should go away once we fix marking region not interested. 
   std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}}
-  P = std::move(PToMove); // expected-note {{Null pointer value move-assigned to 'P'}}
+  P = std::move(PToMove); // expected-note {{A null pointer value is moved to 'P'}}
   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1 {{Dereference of null smart pointer 'P'}}
 }
@@ -170,3 +170,32 @@
   P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
   // expected-note@-1 {{Dereference of null smart pointer 'P'}}
 }
+
+void derefMoveConstructedWithNullPtr() {
+  std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}}
+  std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{A null pointer value is moved to 'P'}}
+  P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}}
+  // expected-note@-1{{Dereference of null smart pointer 'P'}}
+}
+
+void derefValidPtrMovedToConstruct() {
+  std::unique_ptr<A> PToMove(new A()); // expected-note {{Smart pointer 'PToMove' is constructed}}
+  // FIXME: above note should go away once we fix marking region not interested. 
+  std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}}
+  PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
+  // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
+}
+
+void derefNullPtrMovedToConstruct() {
+  std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}}
+  // FIXME: above note should go away once we fix marking region not interested. 
+  std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}}
+  PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
+  // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
+}
+
+void derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove) {
+  std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after; previous value moved to 'P'}}
+  PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}}
+  // expected-note@-1{{Dereference of null smart pointer 'PToMove'}}
+}
Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -58,6 +58,10 @@
   void handleSwap(const CallEvent &Call, CheckerContext &C) const;
   void handleGet(const CallEvent &Call, CheckerContext &C) const;
   bool handleAssignOp(const CallEvent &Call, CheckerContext &C) const;
+  bool handleMoveCtr(const CallEvent &Call, CheckerContext &C,
+                     const MemRegion *ThisRegion) const;
+  bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
+                                const MemRegion *OtherSmartPtrRegion) const;
 
   using SmartPtrMethodHandlerFn =
       void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -160,13 +164,16 @@
     return false;
 
   if (const auto *CC = dyn_cast<CXXConstructorCall>(&Call)) {
-    if (CC->getDecl()->isCopyOrMoveConstructor())
+    if (CC->getDecl()->isCopyConstructor())
       return false;
 
     const MemRegion *ThisRegion = CC->getCXXThisVal().getAsRegion();
     if (!ThisRegion)
       return false;
 
+    if (CC->getDecl()->isMoveConstructor())
+      return handleMoveCtr(Call, C, ThisRegion);
+
     if (Call.getNumArgs() == 0) {
       auto NullVal = C.getSValBuilder().makeNull();
       State = State->set<TrackedRegionMap>(ThisRegion, NullVal);
@@ -410,6 +417,22 @@
     return true;
   }
 
+  return updateMovedSmartPointers(C, ThisRegion, OtherSmartPtrRegion);
+}
+
+bool SmartPtrModeling::handleMoveCtr(const CallEvent &Call, CheckerContext &C,
+                                     const MemRegion *ThisRegion) const {
+  const auto *OtherSmartPtrRegion = Call.getArgSVal(0).getAsRegion();
+  if (!OtherSmartPtrRegion)
+    return false;
+
+  return updateMovedSmartPointers(C, ThisRegion, OtherSmartPtrRegion);
+}
+
+bool SmartPtrModeling::updateMovedSmartPointers(
+    CheckerContext &C, const MemRegion *ThisRegion,
+    const MemRegion *OtherSmartPtrRegion) const {
+  ProgramStateRef State = C.getState();
   const auto *OtherInnerPtr = State->get<TrackedRegionMap>(OtherSmartPtrRegion);
   if (OtherInnerPtr) {
     State = State->set<TrackedRegionMap>(ThisRegion, *OtherInnerPtr);
@@ -430,7 +453,7 @@
             ThisRegion->printPretty(OS);
           }
           if (BR.isInteresting(ThisRegion) && IsArgValNull) {
-            OS << "Null pointer value move-assigned to ";
+            OS << "A null pointer value is moved to ";
             ThisRegion->printPretty(OS);
             BR.markInteresting(OtherSmartPtrRegion);
           }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to