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

OK. I solved almost every problem except that `checkDeadSymbols()` removes the 
iterator position keyed by the temporary region representing the argument from 
the map before it is needed. Either I must somehow recognize that although the 
region is not "live" but the call whose argument it stores is not postchecked 
yet. I have no idea how to do this. Or, which I would prefer is to modify 
`SymbolReaper` so that `isLive()` returns true for temporary regions storing 
arguments of calls not postchecked yet. I have no idea either how to do this. 
Maybe should we take the `Expr` of `CXXTempObjectRegion`, use `ParentMap` to 
recognize whether it is a parameter for a `FunctionDecl`, but how to check 
whether the call for the function of the `FunctionDecl` is not postchecked yet? 
@NoQ, could you please, help me in this? Thx!


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/CheckerContext.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
  clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
  clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
  clang/lib/StaticAnalyzer/Checkers/IteratorModeling.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/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
@@ -28,7 +28,7 @@
 void clang_analyzer_eval(bool);
 void clang_analyzer_warnIfReached();
 
-void begin(const std::vector<int> &v) {
+/*void begin(const std::vector<int> &v) {
   auto i = v.begin();
 
   clang_analyzer_eval(clang_analyzer_iterator_container(i) == &v); // expected-warning{{TRUE}}
@@ -945,7 +945,7 @@
   clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end() - 1}} FIXME: should be $L.end() - 2
   clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}}
   // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.end() - 1
-}
+}*/
 
 /// std::vector-like containers: Only the iterators before the insertion point
 ///                              remain valid. The past-the-end iterator is also
@@ -965,7 +965,7 @@
   // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $V.begin() - 1
 }
 
-void vector_insert_behind_begin(std::vector<int> &V, int n) {
+/*void vector_insert_behind_begin(std::vector<int> &V, int n) {
   auto i0 = V.cbegin(), i1 = ++V.cbegin(), i2 = V.cend();
 
   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
@@ -1880,3 +1880,4 @@
 // CHECK-NEXT:     "i1 : Valid ; Container == SymRegion{reg_$[[#]]<std::vector<int> & V>} ; Offset == conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]}"
 // CHECK-NEXT:   ]}
 }
+*/
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/ExprEngineCXX.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -109,6 +109,96 @@
   return LValue;
 }
 
+Optional<SVal> ExprEngine::retrieveFromConstructionContext(
+    ProgramStateRef State, const LocationContext *LCtx,
+    const ConstructionContext *CC) const {
+  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(AMgr.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) {
@@ -137,7 +227,16 @@
     case ConstructionContext::SimpleConstructorInitializerKind: {
       const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);
       const auto *Init = ICC->getCXXCtorInitializer();
-      assert(Init->isAnyMemberInitializer());
+      if (!Init->isAnyMemberInitializer()) {
+        const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
+        Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
+                                                  LCtx->getStackFrame());
+        SVal ThisVal = State->getSVal(ThisPtr);
+        SVal BaseVal =
+          getStoreManager().evalDerivedToBase(ThisVal, E->getType(),
+                                              Init->isBaseVirtual());
+        return std::make_pair(State, BaseVal);
+      }
       const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
       Loc ThisPtr =
       SVB.getCXXThis(CurCtor, LCtx->getStackFrame());
Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -466,7 +466,7 @@
   // incorrect handling of temporaries bound to default parameters.
   assert(!State->get<ObjectsUnderConstruction>(Key) ||
          Key.getItem().getKind() ==
-             ConstructionContextItem::TemporaryDestructorKind);
+         ConstructionContextItem::TemporaryDestructorKind);
   return State->set<ObjectsUnderConstruction>(Key, V);
 }
 
@@ -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
@@ -257,6 +257,143 @@
   return VR;
 }
 
+const ConstructionContext
+*CallEvent::getConstructionContext(unsigned BlockCount) const {
+  const CFGBlock *Block;
+  unsigned Index;
+
+  if (const StackFrameContext *StackFrame = getCalleeStackFrame(BlockCount)) {
+    Block = StackFrame->getCallSiteBlock();
+    if (!Block) {
+      llvm::errs()<<"No Call Site Block.\n";
+      return nullptr;
+    }
+
+    Index = StackFrame->getIndex();
+  } else {
+    CFGStmtMap *Map =
+      getLocationContext()->getAnalysisDeclContext()->getCFGStmtMap();
+    Block = Map->getBlock(getOriginExpr());
+    if (!Block) {
+      llvm::errs()<<"No Call Site Block.\n";
+      return nullptr;
+    }
+
+    for (Index = 0; Index < Block->size(); ++Index) {
+      if (const auto CS = (*Block)[Index].getAs<CFGStmt>()) {
+        if (CS->getStmt() == getOriginExpr())
+          break;
+      }
+    }
+  }
+
+  if (Index == Block->size()) {
+    llvm::errs()<<"    Stmt not found!\n";
+    return nullptr;
+  }
+
+  if(const auto Ctor = (*Block)[Index].getAs<CFGConstructor>()) {
+    return Ctor->getConstructionContext();
+  }
+
+  if (const auto RecCall = (*Block)[Index].getAs<CFGCXXRecordTypedCall>()) {
+    return RecCall->getConstructionContext();
+  }
+
+  llvm::errs()<<"    Neither a Constructor nor a CFG C++ Record-Typed Call!\n";
+  return nullptr;
+}
+
+Optional<SVal>
+CallEvent::getReturnValueUnderConstruction(ExprEngine &Engine,
+                                           unsigned BlockCount) const {
+  const auto *CC = getConstructionContext(BlockCount);
+  if (!CC) {
+    llvm::errs()<<"  No construction context!!!\n";
+    return None;
+  }
+
+  llvm::errs()<<"  Retrieving Original\n";
+  Optional<SVal> RetVal =
+    Engine.retrieveFromConstructionContext(getState(), getLocationContext(),
+                                           CC);
+  if (RetVal.hasValue())
+    return RetVal;
+
+  ExprEngine::EvalCallOptions CallOpts;
+  ProgramStateRef State;
+  SVal NewVal;
+  llvm::errs()<<"  Handling New\n";
+  std::tie(State, NewVal) =
+    Engine.handleConstructionContext(getOriginExpr(), getState(),
+                                     getLocationContext(), CC, CallOpts);
+  return NewVal;
+}
+
+const ConstructionContext
+*CallEvent::getArgConstructionContext(unsigned Index,
+                                      unsigned BlockCount) const {
+  const CFGBlock *Block;
+  unsigned CFGIndex;
+
+  CFGStmtMap *Map =
+    getLocationContext()->getAnalysisDeclContext()->getCFGStmtMap();
+  Block = Map->getBlock(getArgExpr(Index));
+  if (!Block) {
+    llvm::errs()<<"No Call Site Block.\n";
+    return nullptr;
+  }
+
+  for (CFGIndex = 0; CFGIndex < Block->size(); ++CFGIndex) {
+    if (const auto CS = (*Block)[CFGIndex].getAs<CFGStmt>()) {
+      if (CS->getStmt() == getArgExpr(Index))
+        break;
+    }
+  }
+
+  if (CFGIndex == Block->size()) {
+    llvm::errs()<<"    Stmt not found!\n";
+    return nullptr;
+  }
+
+  if(const auto Ctor = (*Block)[CFGIndex].getAs<CFGConstructor>()) {
+    return Ctor->getConstructionContext();
+  }
+
+  if (const auto RecCall = (*Block)[CFGIndex].getAs<CFGCXXRecordTypedCall>()) {
+    return RecCall->getConstructionContext();
+  }
+
+  llvm::errs()<<"    Neither a Constructor nor a CFG C++ Record-Typed Call!\n";
+  return nullptr;
+}
+
+Optional<SVal>
+CallEvent::getArgUnderConstruction(unsigned Index, ExprEngine &Engine,
+                                   unsigned BlockCount) const {
+  const auto *CC = getArgConstructionContext(Index, BlockCount);
+  if (!CC) {
+    llvm::errs()<<"  No construction context!!!\n";
+    return None;
+  }
+
+  llvm::errs()<<"  Retrieving Original\n";
+  Optional<SVal> RetVal =
+    Engine.retrieveFromConstructionContext(getState(), getLocationContext(),
+                                           CC);
+  if (RetVal.hasValue())
+    return RetVal;
+
+  ExprEngine::EvalCallOptions CallOpts;
+  ProgramStateRef State;
+  SVal NewVal;
+  llvm::errs()<<"  Handling New\n";
+  std::tie(State, NewVal) =
+    Engine.handleConstructionContext(getArgExpr(Index), getState(),
+                                     getLocationContext(), CC, CallOpts);
+  return NewVal;
+}
+
 /// 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,87 @@
 
 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 = 1;
   }
 
   // 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 (Call.getNumArgs() > 2 && isIteratorType(Call.getArgExpr(2)->getType())) {
+    ArgNum = 1;
+  }
+
+  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(0, C.blockCount());
+    if (ArgLoc) {
+      ArgB = loc::MemRegionVal(ArgLoc);
+    } else {
+      ArgB = Call.getArgUnderConstruction(0, C.getExprEngine(),
+                                          C.blockCount());
+      if (!ArgB.hasValue())
+        return false;
+    }
   }
+  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(0, C.blockCount());
+    if (ArgLoc) {
+      ArgE = loc::MemRegionVal(ArgLoc);
+    } else {
+      ArgE = Call.getArgUnderConstruction(0, C.getExprEngine(),
+                                          C.blockCount());
+      if (!ArgE.hasValue())
+        return false;
+    }
+  }
+  llvm::errs()<<"Updated ArgE: "<<*ArgE<<"\n";
+
+  const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
+  if (!CE)
+    return false;
 
-  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 +163,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 +186,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/IteratorModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -83,8 +83,8 @@
 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;
@@ -146,8 +146,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 +154,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
@@ -190,14 +186,25 @@
 
   auto State = C.getState();
 
+  llvm::errs()<<"Generic PostCall\n";
+  Optional<SVal> RetVal = Call.getReturnValue();
+  llvm::errs()<<"Original RetVal: "<<*RetVal<<"\n";
+  if (RetVal->getAs<nonloc::LazyCompoundVal>()) {
+    RetVal =
+      Call.getReturnValueUnderConstruction(C.getExprEngine(), C.blockCount());
+    if (!RetVal.hasValue())
+      RetVal = Call.getReturnValue();
+  }
+  llvm::errs()<<"Updated RetVal: "<<*RetVal<<"\n";
+
   // Already bound to container?
-  if (getIteratorPosition(State, Call.getReturnValue()))
+  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);
+      State = setIteratorPosition(State, *RetVal, *Pos);
       if (cast<CXXConstructorDecl>(Func)->isMoveConstructor()) {
         State = removeIteratorPosition(State, Call.getArgSVal(0));
       }
@@ -214,7 +221,7 @@
   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(),
+        assignToContainer(C, OrigExpr, *RetVal,
                           Pos->getContainer());
         return;
       }
@@ -225,6 +232,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,26 +250,18 @@
   }
 }
 
-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 {
+  llvm::errs()<<"CheckLive\n";
   // Keep symbolic expressions of iterator positions alive
   auto RegionMap = State->get<IteratorRegionMap>();
   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)) {
+        llvm::errs()<<"  Keeping position "<<*i<<".\n";
         SR.markLive(*i);
+      }
   }
 
   auto SymbolMap = State->get<IteratorSymbolMap>();
@@ -272,18 +276,17 @@
 
 void IteratorModeling::checkDeadSymbols(SymbolReaper &SR,
                                         CheckerContext &C) const {
+  llvm::errs()<<"CheckDead\n";
   // Cleanup
   auto State = C.getState();
 
   auto RegionMap = State->get<IteratorRegionMap>();
   for (const auto &Reg : RegionMap) {
+    llvm::errs()<<"Is live "<<Reg.first<<"?\n";
     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);
-      }
+      llvm::errs()<<"  Removing position for "<<Reg.first<<" (Pos: "<<Reg.second.getOffset()<<").\n";
+      llvm::errs()<<"    Base Region: "<<Reg.first->getBaseRegion()<<"\n";
+      State = State->remove<IteratorRegionMap>(Reg.first);
     }
   }
 
@@ -301,61 +304,74 @@
 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;
-      }
+  llvm::errs()<<"Overloaded Operator\n";
+  Optional<SVal> RetVal = Call.getReturnValue();
+  llvm::errs()<<"Original RetVal: "<<*RetVal<<"\n";
+  if (RetVal->getAs<nonloc::LazyCompoundVal>()) {
+    RetVal =
+      Call.getReturnValueUnderConstruction(C.getExprEngine(), C.blockCount());
+    if (!RetVal.hasValue())
+      RetVal = Call.getReturnValue();
+  }
+  llvm::errs()<<"Updated RetVal: "<<*RetVal<<"\n";
+  if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call))
+    llvm::errs()<<"ThisVal: "<<InstCall->getCXXThisVal()<<"\n";
+  
+  if (isSimpleComparisonOperator(Op)) {
+    const auto *OrigExpr = Call.getOriginExpr();
+    if (!OrigExpr)
+      return;
 
-      handleComparison(C, OrigExpr, Call.getReturnValue(), Call.getArgSVal(0),
-                         Call.getArgSVal(1), Op);
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      handleComparison(C, OrigExpr, *RetVal,
+                       InstCall->getCXXThisVal(), Call.getArgSVal(0), Op);
       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;
-        }
+    handleComparison(C, OrigExpr, *RetVal, Call.getArgSVal(0),
+                     Call.getArgSVal(1), 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, *RetVal,
+                               InstCall->getCXXThisVal(), Call.getArgSVal(0));
+        return;
       }
-    } else if (isIncrementOperator(Op)) {
-      if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        handleIncrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
-                        Call.getNumArgs());
+    } else {
+      if (Call.getNumArgs() >= 2 &&
+          Call.getArgExpr(1)->getType()->isIntegralOrEnumerationType()) {
+        handleRandomIncrOrDecr(C, OrigExpr, Op, *RetVal,
+                               Call.getArgSVal(0), Call.getArgSVal(1));
         return;
       }
-
-      handleIncrement(C, Call.getReturnValue(), Call.getArgSVal(0),
+    }
+  } else if (isIncrementOperator(Op)) {
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      handleIncrement(C, *RetVal, InstCall->getCXXThisVal(),
                       Call.getNumArgs());
       return;
-    } else if (isDecrementOperator(Op)) {
-      if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        handleDecrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
-                        Call.getNumArgs());
-        return;
-      }
+    }
 
-      handleDecrement(C, Call.getReturnValue(), Call.getArgSVal(0),
-                        Call.getNumArgs());
+    handleIncrement(C, *RetVal, Call.getArgSVal(0),
+                    Call.getNumArgs());
+    return;
+  } else if (isDecrementOperator(Op)) {
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      handleDecrement(C, *RetVal, InstCall->getCXXThisVal(),
+                      Call.getNumArgs());
       return;
     }
+
+    handleDecrement(C, *RetVal, Call.getArgSVal(0),
+                    Call.getNumArgs());
+    return;
+  }
 }
 
 void
@@ -363,8 +379,19 @@
                                             const CallEvent &Call,
                                             const Expr *OrigExpr,
                                             const AdvanceFn *Handler) const {
+  llvm::errs()<<"Advance-like Function\n";
+  Optional<SVal> RetVal = Call.getReturnValue();
+  llvm::errs()<<"Original RetVal: "<<*RetVal<<"\n";
+  if (RetVal->getAs<nonloc::LazyCompoundVal>()) {
+    RetVal =
+      Call.getReturnValueUnderConstruction(C.getExprEngine(), C.blockCount());
+    if (!RetVal.hasValue())
+      RetVal = Call.getReturnValue();
+  }
+  llvm::errs()<<"Updated RetVal: "<<*RetVal<<"\n";
+
   if (!C.wasInlined) {
-    (this->**Handler)(C, OrigExpr, Call.getReturnValue(),
+    (this->**Handler)(C, OrigExpr, *RetVal,
                       Call.getArgSVal(0), Call.getArgSVal(1));
     return;
   }
@@ -375,7 +402,7 @@
   if (IdInfo) {
     if (IdInfo->getName() == "advance") {
       if (noChangeInAdvance(C, Call.getArgSVal(0), OrigExpr)) {
-        (this->**Handler)(C, OrigExpr, Call.getReturnValue(),
+        (this->**Handler)(C, OrigExpr, *RetVal,
                           Call.getArgSVal(0), Call.getArgSVal(1));
       }
     }
@@ -647,10 +674,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 +710,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
@@ -153,28 +153,26 @@
 
 const IteratorPosition *getIteratorPosition(ProgramStateRef State,
                                             const SVal &Val) {
+  llvm::errs()<<"  Getting position for "<<Val<<".\n";
   if (auto Reg = Val.getAsRegion()) {
     Reg = Reg->getMostDerivedObjectRegion();
     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;
 }
 
 ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val,
                                     const IteratorPosition &Pos) {
+  llvm::errs()<<"  Setting position for "<<Val<<" (Pos: "<<Pos.getOffset()<<").\n";
   if (auto Reg = Val.getAsRegion()) {
     Reg = Reg->getMostDerivedObjectRegion();
     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/ContainerModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
@@ -163,6 +163,17 @@
   if (!Func)
     return;
 
+  llvm::errs()<<"Container PostCall: "<<Func->getNameAsString()<<"\n";
+  Optional<SVal> RetVal = Call.getReturnValue();
+  llvm::errs()<<"Original RetVal: "<<*RetVal<<"\n";
+  if (RetVal->getAs<nonloc::LazyCompoundVal>()) {
+    RetVal =
+      Call.getReturnValueUnderConstruction(C.getExprEngine(), C.blockCount());
+    if (!RetVal.hasValue())
+      RetVal = Call.getReturnValue();
+  }
+  llvm::errs()<<"Updated RetVal: "<<*RetVal<<"\n";
+
   if (Func->isOverloadedOperator()) {
     const auto Op = Func->getOverloadedOperator();
     if (Op == OO_Equal) {
@@ -188,7 +199,23 @@
 
       const OneItParamFn *Handler1 = OneIterParamFunctions.lookup(Call);
       if (Handler1) {
-        (this->**Handler1)(C, InstCall->getCXXThisVal(), Call.getArgSVal(0));
+        Optional<SVal> Arg = Call.getArgSVal(0);
+        llvm::errs()<<"Original Arg(0): "<<*Arg<<"\n";
+        if (Arg->getAs<nonloc::LazyCompoundVal>()) {
+          const MemRegion *ArgLoc = Call.getParameterLocation(0,
+                                                              C.blockCount());
+          if (ArgLoc) {
+            Arg = loc::MemRegionVal(ArgLoc);
+          } else {
+            Arg = Call.getArgUnderConstruction(0, C.getExprEngine(),
+                                               C.blockCount());
+            if (!Arg.hasValue())
+              return;
+          }
+        }
+        llvm::errs()<<"Updated Arg(0): "<<*Arg<<"\n";
+
+        (this->**Handler1)(C, InstCall->getCXXThisVal(), *Arg);
         return;
       }
 
@@ -204,13 +231,13 @@
         return;
 
       if (isBeginCall(Func)) {
-        handleBegin(C, OrigExpr, Call.getReturnValue(),
+        handleBegin(C, OrigExpr, *RetVal,
                     InstCall->getCXXThisVal());
         return;
       }
 
       if (isEndCall(Func)) {
-        handleEnd(C, OrigExpr, Call.getReturnValue(),
+        handleEnd(C, OrigExpr, *RetVal,
                   InstCall->getCXXThisVal());
         return;
       }
@@ -580,9 +607,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,21 @@
                        const CallEvent &Call,
                        const EvalCallOptions &CallOpts = {});
 
+  /// Update the program state with all the path-sensitive information
+  /// that's necessary to perform construction of an object with a given
+  /// syntactic construction context. If the construction context is unavailable
+  /// or unusable for any reason, a dummy temporary region is returned, and the
+  /// IsConstructorWithImproperlyModeledTargetRegion flag is set in \p CallOpts.
+  /// Returns the updated program state and the new object's this-region.
+  std::pair<ProgramStateRef, SVal> handleConstructionContext(
+      const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
+      const ConstructionContext *CC, EvalCallOptions &CallOpts);
+
+  ///
+  Optional<SVal> retrieveFromConstructionContext(
+      ProgramStateRef State, const LocationContext *LCtx,
+      const ConstructionContext *CC) const;
+
 private:
   ProgramStateRef finishArgumentConstruction(ProgramStateRef State,
                                              const CallEvent &Call);
@@ -804,16 +819,6 @@
   /// constructing into an existing region.
   const CXXConstructExpr *findDirectConstructorForCurrentCFGElement();
 
-  /// Update the program state with all the path-sensitive information
-  /// that's necessary to perform construction of an object with a given
-  /// syntactic construction context. If the construction context is unavailable
-  /// or unusable for any reason, a dummy temporary region is returned, and the
-  /// IsConstructorWithImproperlyModeledTargetRegion flag is set in \p CallOpts.
-  /// Returns the updated program state and the new object's this-region.
-  std::pair<ProgramStateRef, SVal> handleConstructionContext(
-      const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
-      const ConstructionContext *CC, EvalCallOptions &CallOpts);
-
   /// Common code that handles either a CXXConstructExpr or a
   /// CXXInheritedCtorInitExpr.
   void handleConstructor(const Expr *E, ExplodedNode *Pred,
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -52,6 +52,10 @@
            "We should not call the checkers on an empty state.");
   }
 
+  ExprEngine &getExprEngine() {
+    return Eng;
+  }
+
   AnalysisManager &getAnalysisManager() {
     return Eng.getAnalysisManager();
   }
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,19 @@
     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;
+
+  const ConstructionContext
+  *getArgConstructionContext(unsigned Index, unsigned BlockCount) const;
+
+  Optional<SVal> getArgUnderConstruction(unsigned Index, ExprEngine &Engine,
+                                         unsigned BlockCount) const;
+
+  Optional<SVal> getReturnValueUnderConstruction(ExprEngine &Engine,
+                                                 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