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

I commented out lines which prevent creation of `StackFrameContext` for 
non-inlined functions. Now everything works regarding the iterator checkers. I 
also simplified things and created new methods for `CallEvent`: 
`getArgObject()` and `getReturnObject()`.

Two tests fail now: `temporaries.cpp` emits `TRUE` in lines `894` and `918` (I 
wonder whether they are correct) and `explain-svals.cpp` emits `lazily frozen 
compound value of parameter ''` in line `96` which is surely incorrect.

The main problem remains to solve is what we already discussed: either to find 
always the same `Decl` or create a new kind of region for arguments.


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

https://reviews.llvm.org/D77229

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
  clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
  clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
  clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
  clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
  clang/lib/StaticAnalyzer/Core/CallEvent.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
  clang/test/Analysis/container-modeling.cpp
  clang/test/Analysis/iterator-modeling.cpp

Index: clang/test/Analysis/iterator-modeling.cpp
===================================================================
--- clang/test/Analysis/iterator-modeling.cpp
+++ clang/test/Analysis/iterator-modeling.cpp
@@ -1862,7 +1862,7 @@
 void clang_analyzer_printState();
 
 void print_state(std::vector<int> &V) {
-  const auto i0 = V.cbegin();
+  auto i0 = V.cbegin();
   clang_analyzer_printState();
 
 // CHECK:      "checker_messages": [
@@ -1871,7 +1871,8 @@
 // CHECK-NEXT:     "i0 : Valid ; Container == SymRegion{reg_$[[#]]<std::vector<int> & V>} ; Offset == conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]}"
 // CHECK-NEXT:   ]}
 
-  const auto i1 = V.cend();
+  ++i0;
+  auto i1 = V.cend();
   clang_analyzer_printState();
   
 // CHECK:      "checker_messages": [
@@ -1879,4 +1880,6 @@
 // CHECK-NEXT:     "Iterator Positions :",
 // CHECK-NEXT:     "i1 : Valid ; Container == SymRegion{reg_$[[#]]<std::vector<int> & V>} ; Offset == conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]}"
 // CHECK-NEXT:   ]}
+
+  --i1;
 }
Index: clang/test/Analysis/container-modeling.cpp
===================================================================
--- clang/test/Analysis/container-modeling.cpp
+++ clang/test/Analysis/container-modeling.cpp
@@ -17,7 +17,7 @@
 void clang_analyzer_warnIfReached();
 
 void begin(const std::vector<int> &V) {
-  V.begin();
+  const auto i0 = V.begin();
 
   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
   clang_analyzer_express(clang_analyzer_container_begin(V)); // expected-warning{{$V.begin()}}
@@ -25,7 +25,7 @@
 }
 
 void end(const std::vector<int> &V) {
-  V.end();
+  const auto i0 = V.end();
 
   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
   clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end()}}
@@ -41,10 +41,10 @@
 // Move
 
 void move_assignment(std::vector<int> &V1, std::vector<int> &V2) {
-  V1.cbegin();
-  V1.cend();
-  V2.cbegin();
-  V2.cend();
+  const auto i0 = V1.cbegin();
+  const auto i1 = V1.cend();
+  const auto i2 = V2.cbegin();
+  const auto i3 = V2.cend();
   long B1 = clang_analyzer_container_begin(V1);
   long E1 = clang_analyzer_container_end(V1);
   long B2 = clang_analyzer_container_begin(V2);
@@ -70,8 +70,8 @@
 void clang_analyzer_dump(void*);
 
 void push_back(std::vector<int> &V, int n) {
-  V.cbegin();
-  V.cend();
+  const auto i0 = V.cbegin();
+  const auto i1 = V.cend();
 
   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
@@ -90,8 +90,8 @@
 /// past-the-end position of the container is incremented).
 
 void emplace_back(std::vector<int> &V, int n) {
-  V.cbegin();
-  V.cend();
+  const auto i0 = V.cbegin();
+  const auto i1 = V.cend();
 
   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
@@ -110,8 +110,8 @@
 /// past-the-end position of the container is decremented).
 
 void pop_back(std::vector<int> &V, int n) {
-  V.cbegin();
-  V.cend();
+  const auto i0 = V.cbegin();
+  const auto i1 = V.cend();
 
   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
@@ -131,8 +131,8 @@
 /// position of the container is decremented).
 
 void push_front(std::list<int> &L, int n) {
-  L.cbegin();
-  L.cend();
+  const auto i0 = L.cbegin();
+  const auto i1 = L.cend();
 
   clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
   clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
@@ -151,8 +151,8 @@
 /// position of the container is decremented).
 
 void emplace_front(std::list<int> &L, int n) {
-  L.cbegin();
-  L.cend();
+  const auto i0 = L.cbegin();
+  const auto i1 = L.cend();
 
   clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
   clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
@@ -171,8 +171,8 @@
 /// position of the container is incremented).
 
 void pop_front(std::list<int> &L, int n) {
-  L.cbegin();
-  L.cend();
+  const auto i0 = L.cbegin();
+  const auto i1 = L.cend();
 
   clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
   clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
@@ -195,7 +195,7 @@
 
 void push_back() {
   std::vector<int> V;
-  V.end();
+  const auto i0 = V.end();
   
   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
 
@@ -208,10 +208,10 @@
 /// Track the right container only
 
 void push_back1(std::vector<int> &V1, std::vector<int> &V2, int n) {
-  V1.cbegin();
-  V1.cend();
-  V2.cbegin();
-  V2.cend();
+  const auto i0 = V1.cbegin();
+  const auto i1 = V1.cend();
+  const auto i2 = V2.cbegin();
+  const auto i3 = V2.cend();
 
   clang_analyzer_denote(clang_analyzer_container_begin(V1), "$V1.begin()");
 
@@ -222,10 +222,10 @@
 }
 
 void push_back2(std::vector<int> &V1, std::vector<int> &V2, int n) {
-  V1.cbegin();
-  V1.cend();
-  V2.cbegin();
-  V2.cend();
+  const auto i0 = V1.cbegin();
+  const auto i1 = V1.cend();
+  const auto i2 = V2.cbegin();
+  const auto i3 = V2.cend();
 
   clang_analyzer_denote(clang_analyzer_container_begin(V1), "$V1.begin()");
   clang_analyzer_denote(clang_analyzer_container_begin(V2), "$V2.begin()");
@@ -245,7 +245,7 @@
 void clang_analyzer_printState();
 
 void print_state(std::vector<int> &V) {
-  V.cbegin();
+  const auto i0 = V.cbegin();
   clang_analyzer_printState();
 
 // CHECK:      "checker_messages": [
@@ -263,3 +263,4 @@
 // CHECK-NEXT:     "SymRegion{reg_$[[#]]<std::vector<int> & V>} : [ conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]} .. conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]} ]"
 // CHECK-NEXT:   ]}
 }
+
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -538,8 +538,8 @@
       SVal VV = *V;
       (void)VV;
       assert(cast<VarRegion>(VV.castAs<loc::MemRegionVal>().getRegion())
-                 ->getStackFrame()->getParent()
-                 ->getStackFrame() == LC->getStackFrame());
+             ->getStackFrame()->getParent()
+             ->getStackFrame() == LC->getStackFrame());
       State = finishObjectConstruction(State, {E, I}, LC);
     }
   }
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -109,6 +109,97 @@
   return LValue;
 }
 
+Optional<SVal> ExprEngine::retrieveFromConstructionContext(
+    ProgramStateRef State, const LocationContext *LCtx,
+    const ConstructionContext *CC) {
+  if (CC) {
+    switch (CC->getKind()) {
+    case ConstructionContext::CXX17ElidedCopyVariableKind:
+    case ConstructionContext::SimpleVariableKind: {
+      const auto *DSCC = cast<VariableConstructionContext>(CC);
+      const auto *DS = DSCC->getDeclStmt();
+      return getObjectUnderConstruction(State, DS, LCtx);
+    }
+    case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:
+    case ConstructionContext::SimpleConstructorInitializerKind: {
+      const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);
+      const auto *Init = ICC->getCXXCtorInitializer();
+      return getObjectUnderConstruction(State, Init, LCtx);
+    }
+    case ConstructionContext::SimpleReturnedValueKind:
+    case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {
+      const StackFrameContext *SFC = LCtx->getStackFrame();
+      if (const LocationContext *CallerLCtx = SFC->getParent()) {
+        auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]
+                       .getAs<CFGCXXRecordTypedCall>();
+        if (!RTC) {
+          // We were unable to find the correct construction context for the
+          // call in the parent stack frame. This is equivalent to not being
+          // able to find construction context at all.
+          break;
+        }
+        if (isa<BlockInvocationContext>(CallerLCtx)) {
+          // Unwrap block invocation contexts. They're mostly part of
+          // the current stack frame.
+          CallerLCtx = CallerLCtx->getParent();
+          assert(!isa<BlockInvocationContext>(CallerLCtx));
+        }
+        return retrieveFromConstructionContext(
+          State, CallerLCtx, RTC->getConstructionContext());
+      }
+      break;
+    }
+    case ConstructionContext::ElidedTemporaryObjectKind: {
+      assert(State->getAnalysisManager().getAnalyzerOptions()
+             .ShouldElideConstructors);
+      const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
+      Optional<SVal> RetVal = retrieveFromConstructionContext(
+          State, LCtx, TCC->getConstructionContextAfterElision());
+      if (RetVal.hasValue())
+        return RetVal;
+
+      LLVM_FALLTHROUGH;
+    }
+    case ConstructionContext::SimpleTemporaryObjectKind: {
+      const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);
+      const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr();
+      Optional<SVal> RetVal;
+      if (BTE) {
+        RetVal = getObjectUnderConstruction(State, BTE, LCtx);
+        if (RetVal.hasValue())
+          return RetVal;
+      }
+
+      const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
+      if (MTE)
+        RetVal = getObjectUnderConstruction(State, MTE, LCtx);
+
+      return RetVal;
+    }
+    case ConstructionContext::ArgumentKind: {
+      const auto *ACC = cast<ArgumentConstructionContext>(CC);
+      const Expr *E = ACC->getCallLikeExpr();
+      unsigned Idx = ACC->getIndex();
+      if (const auto *CE = dyn_cast<CallExpr>(E)) {
+        return getObjectUnderConstruction(State, {CE, Idx}, LCtx);
+      } else if (const auto *CCE = dyn_cast<CXXConstructExpr>(E)) {
+        return getObjectUnderConstruction(State, {CCE, Idx}, LCtx);
+      } else if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
+        return getObjectUnderConstruction(State, {ME, Idx}, LCtx);
+      } else if (const auto *BTE = ACC->getCXXBindTemporaryExpr()) {
+        return getObjectUnderConstruction(State, BTE, LCtx);
+      }
+
+      LLVM_FALLTHROUGH;
+    }
+    default:
+      return None;
+    }
+  }
+
+  return None;
+}
+
 std::pair<ProgramStateRef, SVal> ExprEngine::handleConstructionContext(
     const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
     const ConstructionContext *CC, EvalCallOptions &CallOpts) {
@@ -354,8 +445,7 @@
         CallEventRef<> Caller = CEMgr.getSimpleCall(CE, State, LCtx);
         if (auto OptV = getArgLoc(Caller))
           V = *OptV;
-        else
-          break;
+        else break;
         State = addObjectUnderConstruction(State, {CE, Idx}, LCtx, V);
       } else if (const auto *CCE = dyn_cast<CXXConstructExpr>(E)) {
         // Don't bother figuring out the target region for the future
Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -602,7 +602,6 @@
                            const LocationContext *LCtx, const char *NL,
                            unsigned int Space, bool IsDot) const {
   Indent(Out, Space, IsDot) << "\"constructing_objects\": ";
-
   if (LCtx && !State->get<ObjectsUnderConstruction>().isEmpty()) {
     ++Space;
     Out << '[' << NL;
Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -178,15 +178,15 @@
   // situation because there's a loss of precision anyway because we cannot
   // inline the call.
   RuntimeDefinition RD = getRuntimeDefinition();
-  if (!RD.getDecl())
-    return nullptr;
+  //  if (!RD.getDecl())
+  //    return nullptr;
 
   AnalysisDeclContext *ADC =
       LCtx->getAnalysisDeclContext()->getManager()->getContext(D);
 
   // TODO: For now we skip virtual functions, because this also rises
   // the problem of which decl to use, but now it's across different classes.
-  if (RD.mayHaveOtherDefinitions() || RD.getDecl() != ADC->getDecl())
+  if (RD.getDecl() && (RD.mayHaveOtherDefinitions() || RD.getDecl() != ADC->getDecl()))
     return nullptr;
 
   return ADC;
@@ -228,11 +228,11 @@
   // We cannot construct a VarRegion without a stack frame.
   if (!SFC)
     return nullptr;
+    // Retrieve parameters of the definition, which are different from
+    // CallEvent's parameters() because getDecl() isn't necessarily
+    // the definition. SFC contains the definition that would be used
+    // during analysis.
 
-  // Retrieve parameters of the definition, which are different from
-  // CallEvent's parameters() because getDecl() isn't necessarily
-  // the definition. SFC contains the definition that would be used
-  // during analysis.
   const Decl *D = SFC->getDecl();
 
   // TODO: Refactor into a virtual method of CallEvent, like parameters().
@@ -257,6 +257,65 @@
   return VR;
 }
 
+const ConstructionContext
+*CallEvent::getConstructionContext(unsigned BlockCount) const {
+  const CFGBlock *Block;
+  unsigned Index;
+
+  const StackFrameContext *StackFrame = getCalleeStackFrame(BlockCount);
+  if (!StackFrame)
+    return nullptr;
+
+  Block = StackFrame->getCallSiteBlock();
+  if (!Block)
+    return nullptr;
+
+  Index = StackFrame->getIndex();
+
+  if(const auto Ctor = (*Block)[Index].getAs<CFGConstructor>()) {
+    return Ctor->getConstructionContext();
+  }
+
+  if (const auto RecCall = (*Block)[Index].getAs<CFGCXXRecordTypedCall>()) {
+    return RecCall->getConstructionContext();
+  }
+
+  return nullptr;
+}
+
+Optional<SVal>
+CallEvent::getReturnValueUnderConstruction(unsigned BlockCount) const {
+  const auto *CC = getConstructionContext(BlockCount);
+  if (!CC)
+    return None;
+
+  Optional<SVal> RetVal =
+    ExprEngine::retrieveFromConstructionContext(getState(),
+                                                getLocationContext(), CC);
+  return RetVal;
+}
+
+Optional<SVal> CallEvent::getArgObject(unsigned Index,
+                                       unsigned BlockCount) const {
+  SVal Arg = getArgSVal(Index);
+  if (Arg.getAsSymbol() || Arg.getAsRegion())
+    return Arg;
+
+  const MemRegion *ArgLoc = getParameterLocation(Index, BlockCount);
+  if (ArgLoc)
+    return loc::MemRegionVal(ArgLoc);
+
+  return None;
+}
+
+Optional<SVal> CallEvent::getReturnObject(unsigned BlockCount) const {
+  SVal RetVal = getReturnValue();
+  if (RetVal.getAsSymbol() || RetVal.getAsRegion())
+    return RetVal;
+
+  return getReturnValueUnderConstruction(BlockCount);
+}
+
 /// Returns true if a type is a pointer-to-const or reference-to-const
 /// with no further indirection.
 static bool isPointerToConst(QualType Ty) {
Index: clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
@@ -24,12 +24,12 @@
 namespace {
 
 class STLAlgorithmModeling : public Checker<eval::Call> {
-  bool evalFind(CheckerContext &C, const CallExpr *CE) const;
+  void evalFind(CheckerContext &C, const CallExpr *CE, SVal Begin,
+                SVal End) const;
 
-  void Find(CheckerContext &C, const CallExpr *CE, unsigned paramNum) const;
-
-  using FnCheck = bool (STLAlgorithmModeling::*)(CheckerContext &,
-                                                const CallExpr *) const;
+  using FnCheck = void (STLAlgorithmModeling::*)(CheckerContext &,
+                                                 const CallExpr *, SVal Begin,
+                                                 SVal End) const;
 
   const CallDescriptionMap<FnCheck> Callbacks = {
     {{{"std", "find"}, 3}, &STLAlgorithmModeling::evalFind},
@@ -67,59 +67,81 @@
 
 bool STLAlgorithmModeling::evalCall(const CallEvent &Call,
                                     CheckerContext &C) const {
-  const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
-  if (!CE)
-    return false;
-
-  const FnCheck *Handler = Callbacks.lookup(Call);
-  if (!Handler)
-    return false;
-
-  return (this->**Handler)(C, CE);
-}
-
-bool STLAlgorithmModeling::evalFind(CheckerContext &C,
-                                    const CallExpr *CE) const {
   // std::find()-like functions either take their primary range in the first
   // two parameters, or if the first parameter is "execution policy" then in
   // the second and third. This means that the second parameter must always be
   // an iterator.
-  if (!isIteratorType(CE->getArg(1)->getType()))
+  if (Call.getNumArgs() < 2 || !isIteratorType(Call.getArgExpr(1)->getType()))
     return false;
 
+  unsigned ArgNum = 999;
+
   // If no "execution policy" parameter is used then the first argument is the
   // beginning of the range.
-  if (isIteratorType(CE->getArg(0)->getType())) {
-    Find(C, CE, 0);
-    return true;
+  if (isIteratorType(Call.getArgExpr(0)->getType())) {
+    ArgNum = 0;
   }
 
   // If "execution policy" parameter is used then the second argument is the
   // beginning of the range.
-  if (isIteratorType(CE->getArg(2)->getType())) {
-    Find(C, CE, 1);
-    return true;
+  if (ArgNum > 0 &&
+      Call.getNumArgs() > 2 && isIteratorType(Call.getArgExpr(2)->getType())) {
+    ArgNum = 1;
   }
 
-  return false;
+  if (ArgNum == 999)
+    return false;
+
+  Optional<SVal> ArgB = Call.getArgSVal(ArgNum);
+  llvm::errs()<<"Original ArgB: "<<*ArgB<<"\n";
+  if (ArgB->getAs<nonloc::LazyCompoundVal>()) {
+    const MemRegion *ArgLoc = Call.getParameterLocation(ArgNum, C.blockCount());
+    if (!ArgLoc)
+      return false;
+
+    ArgB = loc::MemRegionVal(ArgLoc);
+  }
+  llvm::errs()<<"Updated ArgB: "<<*ArgB<<"\n";
+  
+  Optional<SVal> ArgE = Call.getArgSVal(ArgNum + 1);
+  llvm::errs()<<"Original ArgE: "<<*ArgE<<"\n";
+  if (ArgE->getAs<nonloc::LazyCompoundVal>()) {
+    const MemRegion *ArgLoc = Call.getParameterLocation(ArgNum + 1,
+                                                        C.blockCount());
+    if (!ArgLoc)
+      return false;
+
+    ArgE = loc::MemRegionVal(ArgLoc);
+  }
+  llvm::errs()<<"Updated ArgE: "<<*ArgE<<"\n";
+
+  const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
+  if (!CE)
+    return false;
+
+  const FnCheck *Handler = Callbacks.lookup(Call);
+  if (!Handler)
+    return false;
+
+  (this->**Handler)(C, CE, *ArgB, *ArgE);
+  return true;
 }
 
-void STLAlgorithmModeling::Find(CheckerContext &C, const CallExpr *CE,
-                                unsigned paramNum) const {
+void STLAlgorithmModeling::evalFind(CheckerContext &C, const CallExpr *CE,
+                                    SVal Begin, SVal End) const {
   auto State = C.getState();
   auto &SVB = C.getSValBuilder();
   const auto *LCtx = C.getLocationContext();
 
   SVal RetVal = SVB.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount());
-  SVal Param = State->getSVal(CE->getArg(paramNum), LCtx);
-
+  
   auto StateFound = State->BindExpr(CE, LCtx, RetVal);
 
   // If we have an iterator position for the range-begin argument then we can
   // assume that in case of successful search the position of the found element
   // is not ahead of it.
   // FIXME: Reverse iterators
-  const auto *Pos = getIteratorPosition(State, Param);
+  const auto *Pos = getIteratorPosition(State, Begin);
   if (Pos) {
     StateFound = createIteratorPosition(StateFound, RetVal, Pos->getContainer(),
                                         CE, LCtx, C.blockCount());
@@ -135,13 +157,11 @@
     StateFound = StateFound->assume(GreaterOrEqual.castAs<DefinedSVal>(), true);
   }
 
-  Param = State->getSVal(CE->getArg(paramNum + 1), LCtx);
-
   // If we have an iterator position for the range-end argument then we can
   // assume that in case of successful search the position of the found element
   // is ahead of it.
   // FIXME: Reverse iterators
-  Pos = getIteratorPosition(State, Param);
+  Pos = getIteratorPosition(State, End);
   if (Pos) {
     StateFound = createIteratorPosition(StateFound, RetVal, Pos->getContainer(),
                                         CE, LCtx, C.blockCount());
@@ -160,7 +180,7 @@
   C.addTransition(StateFound);
 
   if (AggressiveStdFindModeling) {
-    auto StateNotFound = State->BindExpr(CE, LCtx, Param);
+    auto StateNotFound = State->BindExpr(CE, LCtx, End);
     C.addTransition(StateNotFound);
   }
 }
Index: clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp
@@ -32,10 +32,8 @@
 
   std::unique_ptr<BugType> MismatchedBugType;
 
-  void verifyMatch(CheckerContext &C, const SVal &Iter,
-                   const MemRegion *Cont) const;
-  void verifyMatch(CheckerContext &C, const SVal &Iter1,
-                   const SVal &Iter2) const;
+  void verifyMatch(CheckerContext &C, SVal Iter, const MemRegion *Cont) const;
+  void verifyMatch(CheckerContext &C, SVal Iter1, SVal Iter2) const;
   void reportBug(const StringRef &Message, const SVal &Val1,
                  const SVal &Val2, CheckerContext &C,
                  ExplodedNode *ErrNode) const;
@@ -65,51 +63,70 @@
   if (!Func)
     return;
 
+  // If the call has no arguments, there is nothing to check here
+  if (Call.getNumArgs() < 1)
+    return;
+
   if (Func->isOverloadedOperator() &&
       isComparisonOperator(Func->getOverloadedOperator())) {
     // Check for comparisons of iterators of different containers
+    Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+    if (!Arg0.hasValue())
+      return;
+    
     if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-      if (Call.getNumArgs() < 1)
-        return;
-
       if (!isIteratorType(InstCall->getCXXThisExpr()->getType()) ||
           !isIteratorType(Call.getArgExpr(0)->getType()))
         return;
 
-      verifyMatch(C, InstCall->getCXXThisVal(), Call.getArgSVal(0));
+      verifyMatch(C, InstCall->getCXXThisVal(), *Arg0);
     } else {
       if (Call.getNumArgs() < 2)
         return;
 
+      Optional<SVal> Arg1 = Call.getArgObject(1, C.blockCount());
+      if (!Arg1.hasValue())
+        return;
+    
       if (!isIteratorType(Call.getArgExpr(0)->getType()) ||
           !isIteratorType(Call.getArgExpr(1)->getType()))
         return;
 
-      verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
+      verifyMatch(C, *Arg0, *Arg1);
     }
   } else if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
     const auto *ContReg = InstCall->getCXXThisVal().getAsRegion();
     if (!ContReg)
       return;
+
+    Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+    if (!Arg0.hasValue())
+      return;
+    
     // Check for erase, insert and emplace using iterator of another container
     if (isEraseCall(Func) || isEraseAfterCall(Func)) {
-      verifyMatch(C, Call.getArgSVal(0),
-                  InstCall->getCXXThisVal().getAsRegion());
+      verifyMatch(C, *Arg0, InstCall->getCXXThisVal().getAsRegion());
       if (Call.getNumArgs() == 2) {
-        verifyMatch(C, Call.getArgSVal(1),
-                    InstCall->getCXXThisVal().getAsRegion());
+        Optional<SVal> Arg1 = Call.getArgObject(1, C.blockCount());
+        if (!Arg1.hasValue())
+          return;
+
+        verifyMatch(C, *Arg1, InstCall->getCXXThisVal().getAsRegion());
       }
     } else if (isInsertCall(Func)) {
-      verifyMatch(C, Call.getArgSVal(0),
-                  InstCall->getCXXThisVal().getAsRegion());
+      verifyMatch(C, *Arg0, InstCall->getCXXThisVal().getAsRegion());
       if (Call.getNumArgs() == 3 &&
           isIteratorType(Call.getArgExpr(1)->getType()) &&
           isIteratorType(Call.getArgExpr(2)->getType())) {
-        verifyMatch(C, Call.getArgSVal(1), Call.getArgSVal(2));
+        Optional<SVal> Arg1 = Call.getArgObject(1, C.blockCount());
+        Optional<SVal> Arg2 = Call.getArgObject(2, C.blockCount());
+        if (!Arg1.hasValue() || !Arg2.hasValue())
+          return;
+
+        verifyMatch(C, *Arg1, *Arg2);
       }
     } else if (isEmplaceCall(Func)) {
-      verifyMatch(C, Call.getArgSVal(0),
-                  InstCall->getCXXThisVal().getAsRegion());
+      verifyMatch(C, *Arg0, InstCall->getCXXThisVal().getAsRegion());
     }
   } else if (isa<CXXConstructorCall>(&Call)) {
     // Check match of first-last iterator pair in a constructor of a container
@@ -128,7 +145,12 @@
         !isIteratorType(Call.getArgExpr(1)->getType()))
       return;
 
-    verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
+    Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+    Optional<SVal> Arg1 = Call.getArgObject(1, C.blockCount());
+    if (!Arg0.hasValue() || !Arg1.hasValue())
+      return;
+
+    verifyMatch(C, *Arg0, *Arg1);
   } else {
     // The main purpose of iterators is to abstract away from different
     // containers and provide a (maybe limited) uniform access to them.
@@ -166,7 +188,7 @@
       if (!isIteratorType(TAType))
         continue;
 
-      SVal LHS = UndefinedVal();
+      Optional<SVal> LHS = None;
 
       // For every template parameter which is an iterator type in the
       // instantiation look for all functions' parameters' type by it and
@@ -178,17 +200,22 @@
         if (!ParamType ||
             ParamType->getReplacedParameter()->getDecl() != TPDecl)
           continue;
-        if (LHS.isUndef()) {
-          LHS = Call.getArgSVal(J);
+
+        const Optional<SVal> ArgJ = Call.getArgObject(J, C.blockCount());
+        if (!ArgJ.hasValue())
+          continue;
+
+        if (!LHS.hasValue()) {
+          LHS = ArgJ;
         } else {
-          verifyMatch(C, LHS, Call.getArgSVal(J));
+          verifyMatch(C, *LHS, *ArgJ);
         }
       }
     }
   }
 }
 
-void MismatchedIteratorChecker::verifyMatch(CheckerContext &C, const SVal &Iter,
+void MismatchedIteratorChecker::verifyMatch(CheckerContext &C, SVal Iter,
                                             const MemRegion *Cont) const {
   // Verify match between a container and the container of an iterator
   Cont = Cont->getMostDerivedObjectRegion();
@@ -219,14 +246,13 @@
     if (!N) {
       return;
     }
-    reportBug("Container accessed using foreign iterator argument.",
-                        Iter, Cont, C, N);
+    reportBug("Container accessed using foreign iterator argument.", Iter, Cont,
+              C, N);
   }
 }
 
-void MismatchedIteratorChecker::verifyMatch(CheckerContext &C,
-                                            const SVal &Iter1,
-                                            const SVal &Iter2) const {
+void MismatchedIteratorChecker::verifyMatch(CheckerContext &C, SVal Iter1,
+                                            SVal Iter2) const {
   // Verify match between the containers of two iterators
   auto State = C.getState();
   const auto *Pos1 = getIteratorPosition(State, Iter1);
Index: clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
@@ -76,14 +76,18 @@
   if (!Func)
     return;
 
+  Optional<SVal> Arg0 = None;
+  if (Call.getNumArgs() >= 1)
+    Arg0 = Call.getArgObject(0, C.blockCount());
+
   if (Func->isOverloadedOperator()) {
     if (isIncrementOperator(Func->getOverloadedOperator())) {
       // Check for out-of-range incrementions
       if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
         verifyIncrement(C, InstCall->getCXXThisVal());
       } else {
-        if (Call.getNumArgs() >= 1) {
-          verifyIncrement(C, Call.getArgSVal(0));
+        if (Arg0.hasValue()) {
+          verifyIncrement(C, *Arg0);
         }
       }
     } else if (isDecrementOperator(Func->getOverloadedOperator())) {
@@ -91,8 +95,8 @@
       if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
         verifyDecrement(C, InstCall->getCXXThisVal());
       } else {
-        if (Call.getNumArgs() >= 1) {
-          verifyDecrement(C, Call.getArgSVal(0));
+        if (Arg0.hasValue()) {
+          verifyDecrement(C, *Arg0);
         }
       }
     } else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
@@ -105,29 +109,31 @@
                                  Call.getArgSVal(0));
         }
       } else {
-        if (Call.getNumArgs() >= 2 &&
+        if (Arg0.hasValue() && Call.getNumArgs() >= 2 &&
             Call.getArgExpr(1)->getType()->isIntegralOrEnumerationType()) {
           verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
-                                 Call.getArgSVal(0), Call.getArgSVal(1));
+                                 *Arg0, Call.getArgSVal(1));
         }
       }
     } else if (isDereferenceOperator(Func->getOverloadedOperator())) {
       // Check for dereference of out-of-range iterators
       if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
         verifyDereference(C, InstCall->getCXXThisVal());
-      } else {
-        verifyDereference(C, Call.getArgSVal(0));
+      } else if (Arg0.hasValue()) {
+        verifyDereference(C, *Arg0);
       }
     }
   } else {
     const AdvanceFn *Verifier = AdvanceFunctions.lookup(Call);
     if (Verifier) {
+      Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+
       if (Call.getNumArgs() > 1) {
-        (this->**Verifier)(C, Call.getArgSVal(0), Call.getArgSVal(1));
+        (this->**Verifier)(C, *Arg0, Call.getArgSVal(1));
       } else {
         auto &BVF = C.getSValBuilder().getBasicValueFactory();
         (this->**Verifier)(
-            C, Call.getArgSVal(0),
+            C, *Arg0,
             nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))));
       }
     }
Index: clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -83,11 +83,12 @@
 namespace {
 
 class IteratorModeling
-    : public Checker<check::PostCall, check::PostStmt<MaterializeTemporaryExpr>,
-                     check::Bind, check::LiveSymbols, check::DeadSymbols> {
+    : public Checker<check::PostCall, check::Bind, check::LiveSymbols,
+                     check::DeadSymbols> {
 
   using AdvanceFn = void (IteratorModeling::*)(CheckerContext &, const Expr *,
-                                               SVal, SVal, SVal) const;
+                                               Optional<SVal>, SVal,
+                                               SVal) const;
 
   void handleOverloadedOperator(CheckerContext &C, const CallEvent &Call,
                                 OverloadedOperatorKind Op) const;
@@ -96,25 +97,25 @@
                                  const AdvanceFn *Handler) const;
 
   void handleComparison(CheckerContext &C, const Expr *CE, SVal RetVal,
-                        const SVal &LVal, const SVal &RVal,
-                        OverloadedOperatorKind Op) const;
+                        SVal LVal, SVal RVal, OverloadedOperatorKind Op) const;
   void processComparison(CheckerContext &C, ProgramStateRef State,
-                         SymbolRef Sym1, SymbolRef Sym2, const SVal &RetVal,
+                         SymbolRef Sym1, SymbolRef Sym2, SVal RetVal,
                          OverloadedOperatorKind Op) const;
-  void handleIncrement(CheckerContext &C, const SVal &RetVal, const SVal &Iter,
-                       bool Postfix) const;
-  void handleDecrement(CheckerContext &C, const SVal &RetVal, const SVal &Iter,
-                       bool Postfix) const;
+  void handleIncrement(CheckerContext &C, Optional<SVal> RetVal,
+                       SVal Iter, bool Postfix) const;
+  void handleDecrement(CheckerContext &C, Optional<SVal> RetVal,
+                       SVal Iter, bool Postfix) const;
   void handleRandomIncrOrDecr(CheckerContext &C, const Expr *CE,
-                              OverloadedOperatorKind Op, const SVal &RetVal,
-                              const SVal &LHS, const SVal &RHS) const;
-  void handleAdvance(CheckerContext &C, const Expr *CE, SVal RetVal, SVal Iter,
-                     SVal Amount) const;
-  void handlePrev(CheckerContext &C, const Expr *CE, SVal RetVal, SVal Iter,
-                  SVal Amount) const;
-  void handleNext(CheckerContext &C, const Expr *CE, SVal RetVal, SVal Iter,
-                  SVal Amount) const;
-  void assignToContainer(CheckerContext &C, const Expr *CE, const SVal &RetVal,
+                              OverloadedOperatorKind Op,
+                              Optional<SVal> RetVal, SVal LHS,
+                              SVal RHS) const;
+  void handleAdvance(CheckerContext &C, const Expr *CE, Optional<SVal> RetVal,
+                     SVal Iter, SVal Amount) const;
+  void handlePrev(CheckerContext &C, const Expr *CE, Optional<SVal> RetVal,
+                  SVal Iter, SVal Amount) const;
+  void handleNext(CheckerContext &C, const Expr *CE, Optional<SVal> RetVal,
+                  SVal Iter, SVal Amount) const;
+  void assignToContainer(CheckerContext &C, const Expr *CE, SVal RetVal,
                          const MemRegion *Cont) const;
   bool noChangeInAdvance(CheckerContext &C, SVal Iter, const Expr *CE) const;
   void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
@@ -146,8 +147,6 @@
   void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const;
   void checkPostStmt(const CXXConstructExpr *CCE, CheckerContext &C) const;
   void checkPostStmt(const DeclStmt *DS, CheckerContext &C) const;
-  void checkPostStmt(const MaterializeTemporaryExpr *MTE,
-                     CheckerContext &C) const;
   void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const;
   void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
 };
@@ -156,8 +155,6 @@
 ProgramStateRef removeIteratorPosition(ProgramStateRef State, const SVal &Val);
 ProgramStateRef relateSymbols(ProgramStateRef State, SymbolRef Sym1,
                               SymbolRef Sym2, bool Equal);
-bool isBoundThroughLazyCompoundVal(const Environment &Env,
-                                   const MemRegion *Reg);
 const ExplodedNode *findCallEnter(const ExplodedNode *Node, const Expr *Call);
 
 } // namespace
@@ -191,15 +188,23 @@
   auto State = C.getState();
 
   // Already bound to container?
-  if (getIteratorPosition(State, Call.getReturnValue()))
+  Optional<SVal> RetVal = Call.getReturnObject(C.blockCount());
+  if (!RetVal.hasValue())
+    return;
+
+  if (getIteratorPosition(State, *RetVal))
     return;
 
   // Copy-like and move constructors
   if (isa<CXXConstructorCall>(&Call) && Call.getNumArgs() == 1) {
-    if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(0))) {
-      State = setIteratorPosition(State, Call.getReturnValue(), *Pos);
+    Optional<SVal> Arg = Call.getArgObject(0, C.blockCount());
+    if (!Arg.hasValue())
+      return;
+    
+    if (const auto *Pos = getIteratorPosition(State, *Arg)) {
+      State = setIteratorPosition(State, *RetVal, *Pos);
       if (cast<CXXConstructorDecl>(Func)->isMoveConstructor()) {
-        State = removeIteratorPosition(State, Call.getArgSVal(0));
+        State = removeIteratorPosition(State, *Arg);
       }
       C.addTransition(State);
       return;
@@ -213,11 +218,16 @@
   // FIXME: Add a more conservative mode
   for (unsigned i = 0; i < Call.getNumArgs(); ++i) {
     if (isIteratorType(Call.getArgExpr(i)->getType())) {
-      if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(i))) {
-        assignToContainer(C, OrigExpr, Call.getReturnValue(),
-                          Pos->getContainer());
+      Optional<SVal> Arg = Call.getArgObject(i, C.blockCount());
+      if (!Arg.hasValue())
         return;
-      }
+
+      const auto *Pos = getIteratorPosition(State, *Arg);
+      if (!Pos)
+        return;
+
+      assignToContainer(C, OrigExpr, *RetVal, Pos->getContainer());
+      return;
     }
   }
 }
@@ -225,6 +235,11 @@
 void IteratorModeling::checkBind(SVal Loc, SVal Val, const Stmt *S,
                                  CheckerContext &C) const {
   auto State = C.getState();
+  if (Val.getAs<nonloc::LazyCompoundVal>())
+    return;
+
+  llvm::errs()<<"Bind Old: "<<Val<<"\n";
+  llvm::errs()<<"Bind New: "<<Loc<<"\n";
   const auto *Pos = getIteratorPosition(State, Val);
   if (Pos) {
     State = setIteratorPosition(State, Loc, *Pos);
@@ -238,17 +253,6 @@
   }
 }
 
-void IteratorModeling::checkPostStmt(const MaterializeTemporaryExpr *MTE,
-                                     CheckerContext &C) const {
-  /* Transfer iterator state to temporary objects */
-  auto State = C.getState();
-  const auto *Pos = getIteratorPosition(State, C.getSVal(MTE->getSubExpr()));
-  if (!Pos)
-    return;
-  State = setIteratorPosition(State, C.getSVal(MTE), *Pos);
-  C.addTransition(State);
-}
-
 void IteratorModeling::checkLiveSymbols(ProgramStateRef State,
                                         SymbolReaper &SR) const {
   // Keep symbolic expressions of iterator positions alive
@@ -256,8 +260,9 @@
   for (const auto &Reg : RegionMap) {
     const auto Offset = Reg.second.getOffset();
     for (auto i = Offset->symbol_begin(); i != Offset->symbol_end(); ++i)
-      if (isa<SymbolData>(*i))
+      if (isa<SymbolData>(*i)) {
         SR.markLive(*i);
+      }
   }
 
   auto SymbolMap = State->get<IteratorSymbolMap>();
@@ -278,12 +283,7 @@
   auto RegionMap = State->get<IteratorRegionMap>();
   for (const auto &Reg : RegionMap) {
     if (!SR.isLiveRegion(Reg.first)) {
-      // The region behind the `LazyCompoundVal` is often cleaned up before
-      // the `LazyCompoundVal` itself. If there are iterator positions keyed
-      // by these regions their cleanup must be deferred.
-      if (!isBoundThroughLazyCompoundVal(State->getEnvironment(), Reg.first)) {
-        State = State->remove<IteratorRegionMap>(Reg.first);
-      }
+      State = State->remove<IteratorRegionMap>(Reg.first);
     }
   }
 
@@ -301,61 +301,83 @@
 IteratorModeling::handleOverloadedOperator(CheckerContext &C,
                                            const CallEvent &Call,
                                            OverloadedOperatorKind Op) const {
-    if (isSimpleComparisonOperator(Op)) {
-      const auto *OrigExpr = Call.getOriginExpr();
-      if (!OrigExpr)
-        return;
+  const auto *OrigExpr = Call.getOriginExpr();
+  if (!OrigExpr)
+    return;
 
-      if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        handleComparison(C, OrigExpr, Call.getReturnValue(),
-                         InstCall->getCXXThisVal(), Call.getArgSVal(0), Op);
-        return;
-      }
+  if (isSimpleComparisonOperator(Op)) {
+    const auto *OrigExpr = Call.getOriginExpr();
+    if (!OrigExpr)
+      return;
 
-      handleComparison(C, OrigExpr, Call.getReturnValue(), Call.getArgSVal(0),
-                         Call.getArgSVal(1), Op);
+    Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+    if (!Arg0.hasValue())
       return;
-    } else if (isRandomIncrOrDecrOperator(Op)) {
-      const auto *OrigExpr = Call.getOriginExpr();
-      if (!OrigExpr)
-        return;
 
-      if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        if (Call.getNumArgs() >= 1 &&
-              Call.getArgExpr(0)->getType()->isIntegralOrEnumerationType()) {
-          handleRandomIncrOrDecr(C, OrigExpr, Op, Call.getReturnValue(),
-                                 InstCall->getCXXThisVal(), Call.getArgSVal(0));
-          return;
-        }
-      } else {
-        if (Call.getNumArgs() >= 2 &&
-              Call.getArgExpr(1)->getType()->isIntegralOrEnumerationType()) {
-          handleRandomIncrOrDecr(C, OrigExpr, Op, Call.getReturnValue(),
-                                 Call.getArgSVal(0), Call.getArgSVal(1));
-          return;
-        }
-      }
-    } else if (isIncrementOperator(Op)) {
-      if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        handleIncrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
-                        Call.getNumArgs());
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      handleComparison(C, OrigExpr, Call.getReturnValue(),
+                       InstCall->getCXXThisVal(), *Arg0, Op);
+      return;
+    }
+
+    Optional<SVal> Arg1 = Call.getArgObject(0, C.blockCount());
+    if (!Arg1.hasValue())
+      return;
+
+    handleComparison(C, OrigExpr, Call.getReturnValue(), *Arg0, *Arg1, Op);
+    return;
+  } else if (isRandomIncrOrDecrOperator(Op)) {
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      if (Call.getNumArgs() >= 1 &&
+          Call.getArgExpr(0)->getType()->isIntegralOrEnumerationType()) {
+        handleRandomIncrOrDecr(C, OrigExpr, Op,
+                               Call.getReturnObject(C.blockCount()),
+                               InstCall->getCXXThisVal(),
+                               Call.getArgSVal(0));
         return;
       }
+    } else {
+      if (Call.getNumArgs() >= 2 &&
+          Call.getArgExpr(1)->getType()->isIntegralOrEnumerationType()) {
+        Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+        if (!Arg0.hasValue())
+          return;
 
-      handleIncrement(C, Call.getReturnValue(), Call.getArgSVal(0),
-                      Call.getNumArgs());
-      return;
-    } else if (isDecrementOperator(Op)) {
-      if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        handleDecrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
-                        Call.getNumArgs());
+        handleRandomIncrOrDecr(C, OrigExpr, Op,
+                               Call.getReturnObject(C.blockCount()), *Arg0,
+                               Call.getArgSVal(1));
         return;
       }
+    }
+  } else if (isIncrementOperator(Op)) {
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      handleIncrement(C, Call.getReturnObject(C.blockCount()),
+                      InstCall->getCXXThisVal(), Call.getNumArgs());
+      return;
+    }
 
-      handleDecrement(C, Call.getReturnValue(), Call.getArgSVal(0),
-                        Call.getNumArgs());
+    Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+    if (!Arg0.hasValue())
+      return;
+
+    handleIncrement(C, Call.getReturnObject(C.blockCount()), *Arg0,
+                    Call.getNumArgs());
+    return;
+  } else if (isDecrementOperator(Op)) {
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      handleDecrement(C, Call.getReturnObject(C.blockCount()),
+                      InstCall->getCXXThisVal(), Call.getNumArgs());
       return;
     }
+
+    Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+    if (!Arg0.hasValue())
+      return;
+
+    handleDecrement(C, Call.getReturnObject(C.blockCount()), *Arg0,
+                    Call.getNumArgs());
+    return;
+  }
 }
 
 void
@@ -363,9 +385,13 @@
                                             const CallEvent &Call,
                                             const Expr *OrigExpr,
                                             const AdvanceFn *Handler) const {
-  if (!C.wasInlined) {
-    (this->**Handler)(C, OrigExpr, Call.getReturnValue(),
-                      Call.getArgSVal(0), Call.getArgSVal(1));
+  Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+  if (!Arg0.hasValue())
+    return;
+
+   if (!C.wasInlined) {
+     (this->**Handler)(C, OrigExpr, Call.getReturnObject(C.blockCount()), *Arg0,
+                       Call.getArgSVal(1));
     return;
   }
 
@@ -374,23 +400,22 @@
   const auto *IdInfo = cast<FunctionDecl>(Call.getDecl())->getIdentifier();
   if (IdInfo) {
     if (IdInfo->getName() == "advance") {
-      if (noChangeInAdvance(C, Call.getArgSVal(0), OrigExpr)) {
-        (this->**Handler)(C, OrigExpr, Call.getReturnValue(),
-                          Call.getArgSVal(0), Call.getArgSVal(1));
+      if (noChangeInAdvance(C, *Arg0, OrigExpr)) {
+        (this->**Handler)(C, OrigExpr, Call.getReturnObject(C.blockCount()),
+                          *Arg0, Call.getArgSVal(1));
       }
     }
   }
 }
 
 void IteratorModeling::handleComparison(CheckerContext &C, const Expr *CE,
-                                       SVal RetVal, const SVal &LVal,
-                                       const SVal &RVal,
-                                       OverloadedOperatorKind Op) const {
+                                        SVal RetVal, SVal LVal, SVal RVal,
+                                        OverloadedOperatorKind Op) const {
   // Record the operands and the operator of the comparison for the next
   // evalAssume, if the result is a symbolic expression. If it is a concrete
   // value (only one branch is possible), then transfer the state between
   // the operands according to the operator and the result
-   auto State = C.getState();
+  auto State = C.getState();
   const auto *LPos = getIteratorPosition(State, LVal);
   const auto *RPos = getIteratorPosition(State, RVal);
   const MemRegion *Cont = nullptr;
@@ -437,7 +462,7 @@
 
 void IteratorModeling::processComparison(CheckerContext &C,
                                          ProgramStateRef State, SymbolRef Sym1,
-                                         SymbolRef Sym2, const SVal &RetVal,
+                                         SymbolRef Sym2, SVal RetVal,
                                          OverloadedOperatorKind Op) const {
   if (const auto TruthVal = RetVal.getAs<nonloc::ConcreteInt>()) {
     if ((State = relateSymbols(State, Sym1, Sym2,
@@ -465,8 +490,8 @@
   }
 }
 
-void IteratorModeling::handleIncrement(CheckerContext &C, const SVal &RetVal,
-                                       const SVal &Iter, bool Postfix) const {
+void IteratorModeling::handleIncrement(CheckerContext &C, Optional<SVal> RetVal,
+                                       SVal Iter, bool Postfix) const {
   // Increment the symbolic expressions which represents the position of the
   // iterator
   auto State = C.getState();
@@ -487,12 +512,13 @@
          "Iterator should have position after successful advancement");
 
   State = setIteratorPosition(State, Iter, *NewPos);
-  State = setIteratorPosition(State, RetVal, Postfix ? *Pos : *NewPos);
+  if (RetVal.hasValue())
+    State = setIteratorPosition(State, *RetVal, Postfix ? *Pos : *NewPos);
   C.addTransition(State);
 }
 
-void IteratorModeling::handleDecrement(CheckerContext &C, const SVal &RetVal,
-                                       const SVal &Iter, bool Postfix) const {
+void IteratorModeling::handleDecrement(CheckerContext &C, Optional<SVal> RetVal,
+                                       SVal Iter, bool Postfix) const {
   // Decrement the symbolic expressions which represents the position of the
   // iterator
   auto State = C.getState();
@@ -513,64 +539,69 @@
          "Iterator should have position after successful advancement");
 
   State = setIteratorPosition(State, Iter, *NewPos);
-  State = setIteratorPosition(State, RetVal, Postfix ? *Pos : *NewPos);
+  if (RetVal.hasValue())
+    State = setIteratorPosition(State, *RetVal, Postfix ? *Pos : *NewPos);
   C.addTransition(State);
 }
 
 void IteratorModeling::handleRandomIncrOrDecr(CheckerContext &C,
                                               const Expr *CE,
                                               OverloadedOperatorKind Op,
-                                              const SVal &RetVal,
-                                              const SVal &LHS,
-                                              const SVal &RHS) const {
+                                              Optional<SVal> RetVal, SVal Iter,
+                                              SVal Amount) const {
   // Increment or decrement the symbolic expressions which represents the
   // position of the iterator
   auto State = C.getState();
 
-  const auto *Pos = getIteratorPosition(State, LHS);
+  const auto *Pos = getIteratorPosition(State, Iter);
   if (!Pos)
     return;
 
-  const auto *value = &RHS;
-  if (auto loc = RHS.getAs<Loc>()) {
-    const auto val = State->getRawSVal(*loc);
-    value = &val;
+  const auto *AmountVal = &Amount;
+  if (auto L = Amount.getAs<Loc>()) {
+    const auto AmountV = State->getRawSVal(*L);
+    AmountVal = &AmountV;
   }
 
-  auto &TgtVal = (Op == OO_PlusEqual || Op == OO_MinusEqual) ? LHS : RetVal;
+  Optional<SVal> TgtVal =
+    (Op == OO_PlusEqual || Op == OO_MinusEqual) ? Iter : RetVal;
+  if (!TgtVal.hasValue())
+    return;
 
   auto NewState =
-    advancePosition(State, LHS, Op, *value);
+    advancePosition(State, Iter, Op, *AmountVal);
   if (NewState) {
-    const auto *NewPos = getIteratorPosition(NewState, LHS);
+    const auto *NewPos = getIteratorPosition(NewState, Iter);
     assert(NewPos &&
            "Iterator should have position after successful advancement");
 
-    State = setIteratorPosition(NewState, TgtVal, *NewPos);
+    State = setIteratorPosition(NewState, *TgtVal, *NewPos);
     C.addTransition(State);
   } else {
-    assignToContainer(C, CE, TgtVal, Pos->getContainer());
+    assignToContainer(C, CE, *TgtVal, Pos->getContainer());
   }
 }
 
 void IteratorModeling::handleAdvance(CheckerContext &C, const Expr *CE,
-                                     SVal RetVal, SVal Iter,
+                                     Optional<SVal> RetVal, SVal Iter,
                                      SVal Amount) const {
   handleRandomIncrOrDecr(C, CE, OO_PlusEqual, RetVal, Iter, Amount);
 }
 
 void IteratorModeling::handlePrev(CheckerContext &C, const Expr *CE,
-                                  SVal RetVal, SVal Iter, SVal Amount) const {
+                                  Optional<SVal> RetVal, SVal Iter,
+                                  SVal Amount) const {
   handleRandomIncrOrDecr(C, CE, OO_Minus, RetVal, Iter, Amount);
 }
 
 void IteratorModeling::handleNext(CheckerContext &C, const Expr *CE,
-                                  SVal RetVal, SVal Iter, SVal Amount) const {
+                                  Optional<SVal> RetVal, SVal Iter,
+                                  SVal Amount) const {
   handleRandomIncrOrDecr(C, CE, OO_Plus, RetVal, Iter, Amount);
 }
 
 void IteratorModeling::assignToContainer(CheckerContext &C, const Expr *CE,
-                                         const SVal &RetVal,
+                                         SVal RetVal,
                                          const MemRegion *Cont) const {
   Cont = Cont->getMostDerivedObjectRegion();
 
@@ -621,6 +652,7 @@
       Pos.getContainer()->dumpToStream(Out);
       Out<<" ; Offset == ";
       Pos.getOffset()->dumpToStream(Out);
+      Out<<"\n";
     }
 
     for (const auto &Reg : RegionMap) {
@@ -631,6 +663,7 @@
       Pos.getContainer()->dumpToStream(Out);
       Out<<" ; Offset == ";
       Pos.getOffset()->dumpToStream(Out);
+      Out<<"\n";
     }
   }
 }
@@ -647,10 +680,8 @@
     return State->remove<IteratorRegionMap>(Reg);
   } else if (const auto Sym = Val.getAsSymbol()) {
     return State->remove<IteratorSymbolMap>(Sym);
-  } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
-    return State->remove<IteratorRegionMap>(LCVal->getRegion());
   }
-  return nullptr;
+  return State;
 }
 
 ProgramStateRef relateSymbols(ProgramStateRef State, SymbolRef Sym1,
@@ -685,18 +716,6 @@
   return NewState;
 }
 
-bool isBoundThroughLazyCompoundVal(const Environment &Env,
-                                   const MemRegion *Reg) {
-  for (const auto &Binding : Env) {
-    if (const auto LCVal = Binding.second.getAs<nonloc::LazyCompoundVal>()) {
-      if (LCVal->getRegion() == Reg)
-        return true;
-    }
-  }
-
-  return false;
-}
-
 const ExplodedNode *findCallEnter(const ExplodedNode *Node, const Expr *Call) {
   while (Node) {
     ProgramPoint PP = Node->getLocation();
Index: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
+++ clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
@@ -158,8 +158,6 @@
     return State->get<IteratorRegionMap>(Reg);
   } else if (const auto Sym = Val.getAsSymbol()) {
     return State->get<IteratorSymbolMap>(Sym);
-  } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
-    return State->get<IteratorRegionMap>(LCVal->getRegion());
   }
   return nullptr;
 }
@@ -171,10 +169,8 @@
     return State->set<IteratorRegionMap>(Reg, Pos);
   } else if (const auto Sym = Val.getAsSymbol()) {
     return State->set<IteratorSymbolMap>(Sym, Pos);
-  } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
-    return State->set<IteratorRegionMap>(LCVal->getRegion(), Pos);
   }
-  return nullptr;
+  return State;
 }
 
 ProgramStateRef createIteratorPosition(ProgramStateRef State, const SVal &Val,
Index: clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/InvalidatedIteratorChecker.cpp
@@ -60,7 +60,11 @@
     if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
       verifyAccess(C, InstCall->getCXXThisVal());
     } else {
-      verifyAccess(C, Call.getArgSVal(0));
+      Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+      if (!Arg0.hasValue())
+          return;
+
+      verifyAccess(C, *Arg0);
     }
   }
 }
Index: clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
@@ -32,9 +32,9 @@
 class ContainerModeling
   : public Checker<check::PostCall, check::LiveSymbols, check::DeadSymbols> {
 
-  void handleBegin(CheckerContext &C, const Expr *CE, SVal RetVal,
+  void handleBegin(CheckerContext &C, const Expr *CE, Optional<SVal> RetVal,
                    SVal Cont) const;
-  void handleEnd(CheckerContext &C, const Expr *CE, SVal RetVal,
+  void handleEnd(CheckerContext &C, const Expr *CE, Optional<SVal> RetVal,
                  SVal Cont) const;
   void handleAssignment(CheckerContext &C, SVal Cont, const Expr *CE = nullptr,
                         SVal OldCont = UndefinedVal()) const;
@@ -163,6 +163,7 @@
   if (!Func)
     return;
 
+  llvm::errs()<<"Container PostCall: "<<Func->getNameAsString()<<"\n";
   if (Func->isOverloadedOperator()) {
     const auto Op = Func->getOverloadedOperator();
     if (Op == OO_Equal) {
@@ -179,6 +180,22 @@
     }
   } else {
     if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      const auto *OrigExpr = Call.getOriginExpr();
+      if (!OrigExpr)
+        return;
+
+      if (isBeginCall(Func)) {
+        handleBegin(C, OrigExpr, Call.getReturnObject(C.blockCount()),
+                    InstCall->getCXXThisVal());
+        return;
+      }
+
+      if (isEndCall(Func)) {
+        handleEnd(C, OrigExpr, Call.getReturnObject(C.blockCount()),
+                  InstCall->getCXXThisVal());
+        return;
+      }
+
       const NoItParamFn *Handler0 = NoIterParamFunctions.lookup(Call);
       if (Handler0) {
         (this->**Handler0)(C, InstCall->getCXXThisVal(),
@@ -186,32 +203,29 @@
         return;
       }
 
-      const OneItParamFn *Handler1 = OneIterParamFunctions.lookup(Call);
-      if (Handler1) {
-        (this->**Handler1)(C, InstCall->getCXXThisVal(), Call.getArgSVal(0));
+      if (Call.getNumArgs() < 1)
         return;
-      }
 
-      const TwoItParamFn *Handler2 = TwoIterParamFunctions.lookup(Call);
-      if (Handler2) {
-        (this->**Handler2)(C, InstCall->getCXXThisVal(), Call.getArgSVal(0),
-                           Call.getArgSVal(1));
+      Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+      if (!Arg0.hasValue())
+        return;
+
+      const OneItParamFn *Handler1 = OneIterParamFunctions.lookup(Call);
+      if (Handler1) {
+        (this->**Handler1)(C, InstCall->getCXXThisVal(), *Arg0);
         return;
       }
 
-      const auto *OrigExpr = Call.getOriginExpr();
-      if (!OrigExpr)
+      if (Call.getNumArgs() < 2)
         return;
 
-      if (isBeginCall(Func)) {
-        handleBegin(C, OrigExpr, Call.getReturnValue(),
-                    InstCall->getCXXThisVal());
+      Optional<SVal> Arg1 = Call.getArgObject(1, C.blockCount());
+      if (!Arg1.hasValue())
         return;
-      }
 
-      if (isEndCall(Func)) {
-        handleEnd(C, OrigExpr, Call.getReturnValue(),
-                  InstCall->getCXXThisVal());
+      const TwoItParamFn *Handler2 = TwoIterParamFunctions.lookup(Call);
+      if (Handler2) {
+        (this->**Handler2)(C, InstCall->getCXXThisVal(), *Arg0, *Arg1);
         return;
       }
     }
@@ -257,7 +271,7 @@
 }
 
 void ContainerModeling::handleBegin(CheckerContext &C, const Expr *CE,
-                                   SVal RetVal, SVal Cont) const {
+                                    Optional<SVal> RetVal, SVal Cont) const {
   const auto *ContReg = Cont.getAsRegion();
   if (!ContReg)
     return;
@@ -273,13 +287,16 @@
                                  C.getLocationContext(), C.blockCount());
     BeginSym = getContainerBegin(State, ContReg);
   }
-  State = setIteratorPosition(State, RetVal,
-                              IteratorPosition::getPosition(ContReg, BeginSym));
+
+  if (RetVal.hasValue())
+    State =
+      setIteratorPosition(State, *RetVal,
+                          IteratorPosition::getPosition(ContReg, BeginSym));
   C.addTransition(State);
 }
 
 void ContainerModeling::handleEnd(CheckerContext &C, const Expr *CE,
-                                 SVal RetVal, SVal Cont) const {
+                                  Optional<SVal> RetVal, SVal Cont) const {
   const auto *ContReg = Cont.getAsRegion();
   if (!ContReg)
     return;
@@ -295,8 +312,10 @@
                                C.getLocationContext(), C.blockCount());
     EndSym = getContainerEnd(State, ContReg);
   }
-  State = setIteratorPosition(State, RetVal,
-                              IteratorPosition::getPosition(ContReg, EndSym));
+
+  if (RetVal.hasValue())
+    State = setIteratorPosition(State, *RetVal,
+                                IteratorPosition::getPosition(ContReg, EndSym));
   C.addTransition(State);
 }
 
@@ -580,9 +599,13 @@
 
   auto State = C.getState();
   const auto *Pos = getIteratorPosition(State, Iter);
-  if (!Pos)
+  llvm::errs()<<"Inserting to: "<<Iter;
+  if (!Pos) {
+    llvm::errs()<<" (No Pos)\n";
     return;
+  }
 
+  llvm::errs()<<" (Pos: "<<Pos->getOffset()<<")\n";
   // For deque-like containers invalidate all iterator positions. For
   // vector-like containers invalidate iterator positions after the insertion.
   if (hasSubscriptOperator(State, ContReg) && backModifiable(State, ContReg)) {
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -686,6 +686,11 @@
                        const CallEvent &Call,
                        const EvalCallOptions &CallOpts = {});
 
+  ///
+  static Optional<SVal> retrieveFromConstructionContext(
+      ProgramStateRef State, const LocationContext *LCtx,
+      const ConstructionContext *CC);
+
 private:
   ProgramStateRef finishArgumentConstruction(ProgramStateRef State,
                                              const CallEvent &Call);
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -431,6 +431,16 @@
     return CallArgumentIndex;
   }
 
+  /// If the call returns a C++ record type then the call has a construction
+  /// context from where the region of its return value can be retrieved.
+  const ConstructionContext *getConstructionContext(unsigned BlockCount) const;
+
+  Optional<SVal> getReturnValueUnderConstruction(unsigned BlockCount) const;
+
+  Optional<SVal> getArgObject(unsigned Index, unsigned BlockCount) const;
+
+  Optional<SVal> getReturnObject(unsigned BlockCount) const;
+
   // Iterator access to formal parameters and their types.
 private:
   struct GetTypeFn {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to