RedDocMD updated this revision to Diff 351349.
RedDocMD added a comment.

Put changes discussed in the meeting, tests to come in next revision


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D103750

Files:
  clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp

Index: clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -35,6 +35,7 @@
 using namespace ento;
 
 namespace {
+
 class SmartPtrModeling
     : public Checker<eval::Call, check::DeadSymbols, check::RegionChanges,
                      check::LiveSymbols> {
@@ -76,6 +77,9 @@
       {{"release"}, &SmartPtrModeling::handleRelease},
       {{"swap", 1}, &SmartPtrModeling::handleSwap},
       {{"get"}, &SmartPtrModeling::handleGet}};
+  const CallDescription StdMakeUniqueCall{{"std", "make_unique"}};
+  const CallDescription StdMakeUniqueForOverwriteCall{
+      {"std", "make_unique_for_overwrite"}};
 };
 } // end of anonymous namespace
 
@@ -137,12 +141,8 @@
 
 // Helper method to get the inner pointer type of specialized smart pointer
 // Returns empty type if not found valid inner pointer type.
-static QualType getInnerPointerType(const CallEvent &Call, CheckerContext &C) {
-  const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(Call.getDecl());
-  if (!MethodDecl || !MethodDecl->getParent())
-    return {};
-
-  const auto *RecordDecl = MethodDecl->getParent();
+static QualType getInnerPointerType(const CXXRecordDecl *RecordDecl,
+                                    CheckerContext &C) {
   if (!RecordDecl || !RecordDecl->isInStdNamespace())
     return {};
 
@@ -157,6 +157,17 @@
   return C.getASTContext().getPointerType(InnerValueType.getCanonicalType());
 }
 
+// Helper method to get the inner pointer type of specialized smart pointer
+// Returns empty type if not found valid inner pointer type.
+static QualType getInnerPointerType(const CallEvent &Call, CheckerContext &C) {
+  const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(Call.getDecl());
+  if (!MethodDecl || !MethodDecl->getParent())
+    return {};
+
+  const auto *RecordDecl = MethodDecl->getParent();
+  return getInnerPointerType(RecordDecl, C);
+}
+
 // Helper method to pretty print region and avoid extra spacing.
 static void checkAndPrettyPrintRegion(llvm::raw_ostream &OS,
                                       const MemRegion *Region) {
@@ -177,7 +188,55 @@
 
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
                                 CheckerContext &C) const {
+
   ProgramStateRef State = C.getState();
+
+  if (Call.isCalled(StdMakeUniqueCall)) {
+    const Optional<SVal> ThisRegionOpt = Call.getReturnValueUnderConstruction();
+    if (!ThisRegionOpt)
+      return false;
+
+    const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion();
+    const TypedValueRegion *TVR = llvm::dyn_cast<TypedValueRegion>(ThisRegion);
+    assert(TVR && "expected std::make_unique to return a std::unique_ptr "
+                  "object (which is typed)");
+    const QualType InnerPtrType =
+        getInnerPointerType(TVR->getValueType()->getAsCXXRecordDecl(), C);
+    assert(InnerPtrType.getTypePtr() &&
+           "expected to retrieve type of inner pointer of std::make_unique");
+    const auto PtrVal = C.getSValBuilder().conjureSymbolVal(
+        Call.getOriginExpr(), C.getLocationContext(), InnerPtrType,
+        C.blockCount());
+
+    State = State->set<TrackedRegionMap>(ThisRegion, PtrVal);
+    State = State->assume(PtrVal, true);
+
+    auto &Engine = State->getStateManager().getOwningEngine();
+    State = Engine.updateObjectsUnderConstruction(
+        *ThisRegionOpt, nullptr, State, C.getLocationContext(),
+        Call.getConstructionContext(), {});
+
+    C.addTransition(State);
+    return true;
+  }
+
+  if (Call.isCalled(StdMakeUniqueForOverwriteCall)) {
+    const Optional<SVal> ThisRegionOpt = Call.getReturnValueUnderConstruction();
+    if (!ThisRegionOpt)
+      return false;
+    const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion();
+    const auto NullVal = C.getSValBuilder().makeNull();
+    State = State->set<TrackedRegionMap>(ThisRegion, NullVal);
+
+    auto &Engine = State->getStateManager().getOwningEngine();
+    State = Engine.updateObjectsUnderConstruction(
+        *ThisRegionOpt, nullptr, State, C.getLocationContext(),
+        Call.getConstructionContext(), {});
+
+    C.addTransition(State);
+    return true;
+  }
+
   if (!smartptr::isStdSmartPtrCall(Call))
     return false;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to