baloghadamsoftware updated this revision to Diff 145008.
baloghadamsoftware added a comment.

Rebased, and minor modifications done according to the comments.


https://reviews.llvm.org/D32906

Files:
  lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
  test/Analysis/iterator-range.cpp
  test/Analysis/mismatched-iterator.cpp

Index: test/Analysis/mismatched-iterator.cpp
===================================================================
--- test/Analysis/mismatched-iterator.cpp
+++ test/Analysis/mismatched-iterator.cpp
@@ -144,6 +144,19 @@
   v1.insert(i, n); // expected-warning{{Iterator access mismatched}}
 }
 
+template<typename Container, typename Iterator>
+bool is_cend(Container cont, Iterator it) {
+  return it == cont.cend();
+}
+
+void good_empty(std::vector<int> &v) {
+  is_cend(v, v.cbegin()); // no-warning
+}
+
+void bad_empty(std::vector<int> &v1, std::vector<int> &v2) {
+  is_cend(v1, v2.cbegin()); // expected-warning@149{{Iterator access mismatched}}
+}
+
 void good_move(std::vector<int> &v1, std::vector<int> &v2) {
   const auto i0 = ++v2.cbegin();
   v1 = std::move(v2);
Index: test/Analysis/iterator-range.cpp
===================================================================
--- test/Analysis/iterator-range.cpp
+++ test/Analysis/iterator-range.cpp
@@ -216,6 +216,11 @@
     *first; // no-warning
 }
 
+void bad_non_std_find(std::vector<int> &V, int e) {
+  auto first = nonStdFind(V.begin(), V.end(), e);
+  *first; // expected-warning{{Iterator accessed outside of its range}}
+}
+
 void tricky(std::vector<int> &V, int e) {
   const auto first = V.begin();
   const auto comp1 = (first != V.end()), comp2 = (first == V.end());
Index: lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
+++ lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
@@ -200,8 +200,8 @@
                      check::PreStmt<CXXConstructExpr>,
                      check::PreStmt<CXXOperatorCallExpr>,
                      check::PostStmt<MaterializeTemporaryExpr>, check::Bind,
-                     check::LiveSymbols, check::DeadSymbols,
-                     eval::Assume, eval::Call> {
+                     check::BeginFunction, check::LiveSymbols,
+                     check::DeadSymbols, eval::Assume, eval::Call> {
   mutable IdentifierInfo *II_find = nullptr, *II_find_end = nullptr,
                          *II_find_first_of = nullptr, *II_find_if = nullptr,
                          *II_find_if_not = nullptr, *II_lower_bound = nullptr,
@@ -292,6 +292,7 @@
   void checkPreStmt(const CXXConstructExpr *CCE, CheckerContext &C) const;
   void checkPreStmt(const CXXOperatorCallExpr *COCE, CheckerContext &C) const;
   void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const;
+  void checkBeginFunction(CheckerContext &C) const;
   void checkPostStmt(const CXXConstructExpr *CCE, CheckerContext &C) const;
   void checkPostStmt(const DeclStmt *DS, CheckerContext &C) const;
   void checkPostStmt(const MaterializeTemporaryExpr *MTE,
@@ -783,6 +784,39 @@
   }
 }
 
+void IteratorChecker::checkBeginFunction(CheckerContext &C) const {
+  // Copy state of iterator arguments to iterator parameters
+  auto State = C.getState();
+  const auto *LCtx = C.getLocationContext();
+
+  const auto *Site = cast<StackFrameContext>(LCtx)->getCallSite();
+  if (!Site)
+    return;
+
+  const auto *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
+  if (!FD)
+    return;
+
+  const auto *CE = dyn_cast<CallExpr>(Site);
+  if (!CE)
+    return;
+
+  bool Change = false;
+  int idx = 0;
+  for (const auto *P : FD->parameters()) {
+    auto Arg = State->getSVal(CE->getArg(idx++), LCtx->getParent());
+    const auto *Pos = getIteratorPosition(State, Arg);
+    if (!Pos)
+      continue;
+    auto Param = State->getLValue(P, LCtx);
+    State = setIteratorPosition(State, Param, *Pos);
+    Change = true;
+  }
+  if (Change) {
+    C.addTransition(State);
+  }
+}
+
 void IteratorChecker::checkPostStmt(const MaterializeTemporaryExpr *MTE,
                                     CheckerContext &C) const {
   /* Transfer iterator state to temporary objects */
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to