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

Fixed git history


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,11 +35,19 @@
 using namespace ento;
 
 namespace {
+
+enum class MakeUniqueKind {
+  Regular,      // ie, std::make_unique
+  ForOverwrite, // ie, std::make_unique_for_overwrite
+  None          // ie, is neither of the above two
+};
+
 class SmartPtrModeling
     : public Checker<eval::Call, check::DeadSymbols, check::RegionChanges,
-                     check::LiveSymbols> {
+                     check::LiveSymbols, check::Bind> {
 
   bool isBoolConversionMethod(const CallEvent &Call) const;
+  MakeUniqueKind isStdMakeUniqueCall(const CallEvent &Call) const;
 
 public:
   // Whether the checker should model for null dereferences of smart pointers.
@@ -56,6 +64,7 @@
   void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
                   const char *Sep) const override;
   void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const;
+  void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
 
 private:
   void handleReset(const CallEvent &Call, CheckerContext &C) const;
@@ -68,6 +77,8 @@
   bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
                                 const MemRegion *OtherSmartPtrRegion) const;
   void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+  void handleStdMakeUnique(const CallEvent &Call, CheckerContext &C,
+                           MakeUniqueKind Kind) const;
 
   using SmartPtrMethodHandlerFn =
       void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
@@ -79,7 +90,21 @@
 };
 } // end of anonymous namespace
 
+class MakeUniqueKindWrapper {
+  const MakeUniqueKind Kind;
+
+public:
+  MakeUniqueKindWrapper(MakeUniqueKind Kind) : Kind(Kind) {}
+  MakeUniqueKind get() const { return Kind; }
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    ID.AddInteger(static_cast<int>(Kind));
+  }
+  bool operator==(const MakeUniqueKind &RHS) const { return Kind == RHS; }
+  bool operator!=(const MakeUniqueKind &RHS) const { return Kind != RHS; }
+};
+
 REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal)
+REGISTER_LIST_WITH_PROGRAMSTATE(MakeUniqueKindList, MakeUniqueKindWrapper)
 
 // Define the inter-checker API.
 namespace clang {
@@ -175,8 +200,35 @@
   return CD && CD->getConversionType()->isBooleanType();
 }
 
+MakeUniqueKind
+SmartPtrModeling::isStdMakeUniqueCall(const CallEvent &Call) const {
+  if (Call.getKind() != CallEventKind::CE_Function)
+    return MakeUniqueKind::None;
+  const auto *D = Call.getDecl();
+  if (!D)
+    return MakeUniqueKind::None;
+  const auto *FTD = llvm::dyn_cast<FunctionDecl>(D);
+  if (!FTD)
+    return MakeUniqueKind::None;
+  if (FTD->getDeclName().isIdentifier()) {
+    StringRef Name = FTD->getName();
+    if (Name == "make_unique")
+      return MakeUniqueKind::Regular;
+    else if (Name == "make_unique_for_overwrite")
+      return MakeUniqueKind::ForOverwrite;
+  }
+  return MakeUniqueKind::None;
+}
+
 bool SmartPtrModeling::evalCall(const CallEvent &Call,
                                 CheckerContext &C) const {
+
+  MakeUniqueKind Kind = isStdMakeUniqueCall(Call);
+  if (Kind != MakeUniqueKind::None) {
+    handleStdMakeUnique(Call, C, Kind);
+    return true;
+  }
+
   ProgramStateRef State = C.getState();
   if (!smartptr::isStdSmartPtrCall(Call))
     return false;
@@ -272,6 +324,59 @@
   return C.isDifferent();
 }
 
+void SmartPtrModeling::handleStdMakeUnique(const CallEvent &Call,
+                                           CheckerContext &C,
+                                           MakeUniqueKind Kind) const {
+  assert(Kind != MakeUniqueKind::None &&
+         "Call is not to make_unique or make_unique_for_overwrite");
+  ProgramStateRef State = C.getState();
+  State = State->add<MakeUniqueKindList>(Kind);
+  C.addTransition(State);
+}
+
+bool isUniquePtrType(QualType QT) {
+  const auto *T = QT.getTypePtr();
+  if (!T)
+    return false;
+  const auto *Decl = T->getAsCXXRecordDecl();
+  if (!Decl || !Decl->getDeclContext()->isStdNamespace())
+    return false;
+  const IdentifierInfo *ID = Decl->getIdentifier();
+  if (!ID)
+    return false;
+  const StringRef Name = ID->getName();
+  return Name == "unique_ptr";
+}
+
+void SmartPtrModeling::checkBind(SVal L, SVal V, const Stmt *S,
+                                 CheckerContext &C) const {
+  const auto *TVR = dyn_cast_or_null<TypedValueRegion>(L.getAsRegion());
+  if (!TVR)
+    return;
+  if (!isUniquePtrType(TVR->getValueType()))
+    return;
+  const auto *ThisRegion = dyn_cast<MemRegion>(TVR);
+  if (!ThisRegion)
+    return;
+
+  ProgramStateRef State = C.getState();
+  auto KindList = State->get<MakeUniqueKindList>();
+  assert(!KindList.isEmpty() &&
+         "Expected list to contain the kind of the last make_unique");
+  auto Kind = KindList.getHead();
+  assert(Kind != MakeUniqueKind::None &&
+         "Bind is not to make_unique or make_unique_for_overwrite");
+  if (Kind == MakeUniqueKind::ForOverwrite) {
+    auto RHSVal = C.getSValBuilder().makeNull();
+    State = State->set<TrackedRegionMap>(ThisRegion, RHSVal);
+  } else {
+    // TODO: Encode information that the inner pointer for
+    // unique_ptr made by std::make_unique is *not* null
+  }
+  State = State->set<MakeUniqueKindList>(KindList.getTail());
+  C.addTransition(State);
+}
+
 void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper,
                                         CheckerContext &C) const {
   ProgramStateRef State = C.getState();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to