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

Added support for `ParamRegions` as original region for captured variables by 
blocks and lambdas. Only 2 failing tests left.


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

https://reviews.llvm.org/D77229

Files:
  clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.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/NSErrorChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
  
clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
  clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
  clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
  clang/lib/StaticAnalyzer/Core/CallEvent.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
  clang/lib/StaticAnalyzer/Core/MemRegion.cpp
  clang/lib/StaticAnalyzer/Core/RegionStore.cpp
  clang/lib/StaticAnalyzer/Core/Store.cpp
  clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
  clang/test/Analysis/container-modeling.cpp
  clang/test/Analysis/explain-svals.cpp
  clang/test/Analysis/iterator-modeling.cpp
  clang/test/Analysis/temporaries.cpp

Index: clang/test/Analysis/temporaries.cpp
===================================================================
--- clang/test/Analysis/temporaries.cpp
+++ clang/test/Analysis/temporaries.cpp
@@ -56,7 +56,7 @@
 }
 
 namespace rdar13265460 {
-  struct TrivialSubclass : public Trivial {
+struct TrivialSubclass : public Trivial {
     TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}
     int anotherValue;
   };
@@ -890,12 +890,9 @@
 public:
   ~C() {
     glob = 1;
-    // FIXME: Why is destructor not inlined in C++17
     clang_analyzer_checkInlined(true);
 #ifdef TEMPORARY_DTORS
-#if __cplusplus < 201703L
-    // expected-warning@-3{{TRUE}}
-#endif
+    // expected-warning@-2{{TRUE}}
 #endif
   }
 };
@@ -914,16 +911,11 @@
   // temporaries returned from functions, so we took the wrong branch.
   coin && is(get()); // no-crash
   if (coin) {
-    // FIXME: Why is destructor not inlined in C++17
     clang_analyzer_eval(glob);
 #ifdef TEMPORARY_DTORS
-#if __cplusplus < 201703L
-    // expected-warning@-3{{TRUE}}
+    // expected-warning@-2{{TRUE}}
 #else
-    // expected-warning@-5{{UNKNOWN}}
-#endif
-#else
-    // expected-warning@-8{{UNKNOWN}}
+    // expected-warning@-4{{UNKNOWN}}
 #endif
   } else {
     // The destructor is not called on this branch.
@@ -1237,7 +1229,7 @@
 struct S {
   S() {}
   S(const S &) {}
-};
+  };
 
 void test() {
   int x = 0;
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/explain-svals.cpp
===================================================================
--- clang/test/Analysis/explain-svals.cpp
+++ clang/test/Analysis/explain-svals.cpp
@@ -93,6 +93,6 @@
 } // end of anonymous namespace
 
 void test_6() {
-  clang_analyzer_explain(conjure_S()); // expected-warning-re{{{{^lazily frozen compound value of temporary object constructed at statement 'conjure_S\(\)'$}}}}
+  clang_analyzer_explain(conjure_S()); // expected-warning-re{{{{^lazily frozen compound value of parameter 0 of function 'clang_analyzer_explain\(\)'$}}}}
   clang_analyzer_explain(conjure_S().z); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure_S\(\)'\) for field 'z' of temporary object constructed at statement 'conjure_S\(\)'$}}}}
 }
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/SymbolManager.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -440,6 +440,9 @@
   if (const auto *VR = dyn_cast<VarRegion>(MR))
     return isLive(VR, true);
 
+  if (const auto *PR = dyn_cast<ParamRegion>(MR))
+    return isLive(PR, true);
+
   // FIXME: This is a gross over-approximation. What we really need is a way to
   // tell if anything still refers to this region. Unlike SymbolicRegions,
   // AllocaRegions don't have associated symbols, though, so we don't actually
@@ -573,3 +576,53 @@
 
   return VarContext->isParentOf(CurrentContext);
 }
+
+bool SymbolReaper::isLive(const ParamRegion *PR,
+                          bool includeStoreBindings) const{
+  const StackFrameContext *ParamContext = PR->getStackFrame();
+
+  if (!ParamContext)
+    return true;
+
+  if (!LCtx)
+    return false;
+  const StackFrameContext *CurrentContext = LCtx->getStackFrame();
+
+  if (ParamContext == CurrentContext) {
+    // If no statement is provided, everything is live.
+    if (!Loc)
+      return true;
+
+    // Anonymous parameters of an inheriting constructor are live for the entire
+    // duration of the constructor.
+    if (isa<CXXInheritedCtorInitExpr>(Loc))
+      return true;
+
+    if (const ParmVarDecl *PVD = PR->getDecl()) {
+      if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, PVD))
+        return true;
+    }
+
+    if (!includeStoreBindings)
+      return false;
+
+    unsigned &cachedQuery =
+      const_cast<SymbolReaper *>(this)->includedRegionCache[PR];
+
+    if (cachedQuery) {
+      return cachedQuery == 1;
+    }
+
+    // Query the store to see if the region occurs in any live bindings.
+    if (Store store = reapedStore.getStore()) {
+      bool hasRegion =
+        reapedStore.getStoreManager().includedInBindings(store, PR);
+      cachedQuery = hasRegion ? 1 : 2;
+      return hasRegion;
+    }
+
+    return false;
+  }
+
+  return ParamContext->isParentOf(CurrentContext);
+}
Index: clang/lib/StaticAnalyzer/Core/Store.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/Store.cpp
+++ clang/lib/StaticAnalyzer/Core/Store.cpp
@@ -51,8 +51,9 @@
   SmallVector<CallEvent::FrameBindingTy, 16> InitialBindings;
   Call.getInitialStackFrameContents(LCtx, InitialBindings);
 
-  for (const auto &I : InitialBindings)
+  for (const auto &I : InitialBindings) {
     Store = Bind(Store.getStore(), I.first.castAs<Loc>(), I.second);
+  }
 
   return Store;
 }
@@ -138,6 +139,7 @@
     case MemRegion::CXXTempObjectRegionKind:
     case MemRegion::CXXBaseObjectRegionKind:
     case MemRegion::CXXDerivedObjectRegionKind:
+    case MemRegion::ParamRegionKind:
       return MakeElementRegion(cast<SubRegion>(R), PointeeTy);
 
     case MemRegion::ElementRegionKind: {
@@ -435,6 +437,19 @@
   return svalBuilder.dispatchCast(V, castTy);
 }
 
+Loc StoreManager::getLValueVar(const VarDecl *VD, const LocationContext *LC) {
+  if (const auto *PVD = dyn_cast<ParmVarDecl>(VD)) {
+    const Expr* Call;
+    unsigned Index;
+    std::tie(Call, Index) = ParamRegion::getExprAndIndexForParam(PVD, LC);
+
+    if (Call)
+      return svalBuilder.makeLoc(MRMgr.getParamRegion(Call, Index, LC));
+  }
+
+  return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC));
+}
+
 SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {
   if (Base.isUnknownOrUndef())
     return Base;
Index: clang/lib/StaticAnalyzer/Core/RegionStore.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -569,6 +569,8 @@
 
   SVal getBindingForVar(RegionBindingsConstRef B, const VarRegion *R);
 
+  SVal getBindingForParam(RegionBindingsConstRef B, const ParamRegion *R);
+
   SVal getBindingForLazySymbol(const TypedValueRegion *R);
 
   SVal getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
@@ -1510,6 +1512,16 @@
     return CastRetrievedVal(getBindingForVar(B, VR), VR, T);
   }
 
+  if (const ParamRegion *PR = dyn_cast<ParamRegion>(R)) {
+    // FIXME: Here we actually perform an implicit conversion from the loaded
+    // value to the variable type.  What we should model is stores to variables
+    // that blow past the extent of the variable.  If the address of the
+    // variable is reinterpretted, it is possible we stored a different value
+    // that could fit within the variable.  Either we need to cast these when
+    // storing them or reinterpret them lazily (as we do here).
+    return CastRetrievedVal(getBindingForParam(B, PR), PR, T);
+  }
+
   const SVal *V = B.lookup(R, BindingKey::Direct);
 
   // Check if the region has a binding.
@@ -2004,6 +2016,24 @@
   return UndefinedVal();
 }
 
+SVal RegionStoreManager::getBindingForParam(RegionBindingsConstRef B,
+                                            const ParamRegion *R) {
+  // Check if the region has a binding.
+  if (Optional<SVal> V = B.getDirectBinding(R))
+    return *V;
+
+  if (Optional<SVal> V = B.getDefaultBinding(R))
+    return *V;
+
+  // Lazily derive a value for the ParamRegion.
+  const MemSpaceRegion *MS = R->getMemorySpace();
+
+  assert (isa<StackArgumentsSpaceRegion>(MS));
+
+  SVal V = svalBuilder.getRegionValueSymbolVal(R);
+  return V;
+}
+
 SVal RegionStoreManager::getBindingForLazySymbol(const TypedValueRegion *R) {
   // All other values are symbolic.
   return svalBuilder.getRegionValueSymbolVal(R);
@@ -2505,6 +2535,13 @@
     return;
   }
 
+  if (const ParamRegion *PR = dyn_cast<ParamRegion>(baseR)) {
+    if (SymReaper.isLive(PR))
+      AddToWorkList(baseR, &C);
+
+    return;
+  }
+
   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
     if (SymReaper.isLive(SR->getSymbol()))
       AddToWorkList(SR, &C);
Index: clang/lib/StaticAnalyzer/Core/MemRegion.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -159,6 +159,11 @@
   return SSR ? SSR->getStackFrame() : nullptr;
 }
 
+const StackFrameContext *ParamRegion::getStackFrame() const {
+  const auto *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
+  return SSR ? SSR->getStackFrame() : nullptr;
+}
+
 ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg)
     : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
 
@@ -178,6 +183,123 @@
   return QualType(getDecl()->getTypeForDecl(), 0);
 }
 
+QualType ParamRegion::getValueType() const {
+  if (const ParmVarDecl *PVD = getDecl())
+    return PVD->getType();
+
+  const Expr *Arg = getArgExpr();
+  assert(Arg && "Both ParamRegion::getDecl() and ParamRegion::getArgExpr()"
+         " must not return null for the same region.");
+
+  switch (Arg->getValueKind()) {
+  case VK_RValue:
+    return Arg->getType();
+  case VK_LValue:
+    return getContext().getLValueReferenceType(Arg->getType());
+  case VK_XValue:
+    return getContext().getRValueReferenceType(Arg->getType());
+  default:
+    llvm_unreachable("Invalid value kind.");
+  }
+}
+
+const ParmVarDecl *ParamRegion::getDecl() const {
+  const Decl *D = getStackFrame()->getDecl();
+  /*llvm::errs()<<"ParamRegion::getDecl()\n\nDecl:\n";
+  D->dump();
+  llvm::errs()<<"\n\nOriginExpr:\n";
+  OriginExpr->dump();
+  llvm::errs()<<"\n\nIndex: "<<Index<<"\n\n";*/
+
+  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+    if (isa<CXXOperatorCallExpr>(OriginExpr) && isa<CXXMethodDecl>(FD)) {
+      assert(Index <= FD->param_size());
+      /*llvm::errs()<<"Returning param "<<(Index - 1)<<":\n";
+      FD->parameters()[Index - 1]->dump();
+      llvm::errs()<<"\n";*/
+      return FD->parameters()[Index - 1];
+    }
+
+    if (Index >= FD->param_size())
+      return nullptr;
+
+    /*llvm::errs()<<"Returning param "<<Index<<":\n";
+    FD->parameters()[Index]->dump();
+    llvm::errs()<<"\n";*/
+    return FD->parameters()[Index];
+  } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
+    assert (Index < BD->param_size());
+    return BD->parameters()[Index];
+  } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    assert (Index < MD->param_size());
+    return MD->parameters()[Index];
+  } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
+    assert (Index < CD->param_size());
+    return CD->parameters()[Index];
+  } else {
+    llvm_unreachable("Unexpected Decl kind!");
+  }
+  /*  if (const auto *CE = dyn_cast<CallExpr>(OriginExpr)) {
+    const FunctionDecl *FD = CE->getDirectCallee();
+    if (!FD)
+      return nullptr;
+
+    if (isa<CXXOperatorCallExpr>(CE) && isa<CXXMethodDecl>(FD)) {
+      assert(Index <= FD->param_size());
+      return FD->parameters()[Index - 1];
+    }
+
+    if (Index >= FD->param_size())
+      return nullptr;
+
+    return FD->parameters()[Index];
+  } else if (const auto *CCE = dyn_cast<CXXConstructExpr>(OriginExpr)) {
+    const auto *CCD = CCE->getConstructor();
+    assert(CCD && "Constructor not found for CXXConstructExpr");
+    assert(Index < CCD->param_size());
+    return CCD->parameters()[Index];
+  } else if (const auto *OCME = dyn_cast<ObjCMessageExpr>(OriginExpr)) {
+    const auto *OCMD = OCME->getMethodDecl();
+    assert(OCMD && "Method not found for CXXObjCMessageExpr");
+    assert(Index < OCMD->param_size());
+    return OCMD->parameters()[Index];
+  } else if (const auto *CNE = dyn_cast<CXXNewExpr>(OriginExpr)) {
+    const auto *FD = CNE->getOperatorNew();
+    assert(FD && "New operator not found for CXXNewExpr");
+    assert(Index < FD->param_size());
+    return FD->parameters()[Index];
+  } else {
+    llvm::errs()<<"Unknown Expression:\n";
+    OriginExpr->dump();
+    llvm::errs()<<"\n";
+    // FIXME: Any other kind of `Expr`?
+    llvm_unreachable("Unknown Expression type for ParamRegion.");
+    }*/
+}
+
+const Expr *ParamRegion::getArgExpr() const {
+  /*llvm::errs()<<"ParamRegion::getArgExpr()\n\nOriginExpr:\n";
+  OriginExpr->dump();
+  llvm::errs()<<"\n\nIndex: "<<Index<<"\n\n";*/
+  if (const auto *CE = dyn_cast<CallExpr>(OriginExpr)) {
+    assert(Index < CE->getNumArgs());
+    return CE->getArg(Index);
+  } else if (const auto *CCE = dyn_cast<CXXConstructExpr>(OriginExpr)) {
+    assert(Index < CCE->getNumArgs());
+    return CCE->getArg(Index);
+  } else if (const auto *OCME = dyn_cast<ObjCMessageExpr>(OriginExpr)) {
+    assert(Index < OCME->getNumArgs());
+    return OCME->getArg(Index);
+  } else if (const auto *CNE = dyn_cast<CXXNewExpr>(OriginExpr)) {
+    if (Index > 0)
+      return CNE->getPlacementArg(Index - 1);
+    return nullptr;
+  } else {
+    // FIXME: Any other kind of `Expr`?
+    llvm_unreachable("Unknown Expression type for ParamRegion.");
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // FoldingSet profiling.
 //===----------------------------------------------------------------------===//
@@ -368,6 +490,18 @@
   ProfileRegion(ID, getDecl(), superRegion);
 }
 
+void ParamRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE,
+                                unsigned Idx, const MemRegion *SReg) {
+  ID.AddInteger(static_cast<unsigned>(ParamRegionKind));
+  ID.AddPointer(OE);
+  ID.AddInteger(Idx);
+  ID.AddPointer(SReg);
+}
+
+void ParamRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+  ProfileRegion(ID, getOriginExpr(), getIndex(), superRegion);
+}
+
 //===----------------------------------------------------------------------===//
 // Region anchors.
 //===----------------------------------------------------------------------===//
@@ -531,6 +665,19 @@
   os << "StackLocalsSpaceRegion";
 }
 
+void ParamRegion::dumpToStream(raw_ostream &os) const {
+  if (const ParmVarDecl *PVD = getDecl()) {
+    if (const IdentifierInfo *ID = PVD->getIdentifier()) {
+      os << ID->getName();
+    } else {
+      os << "ParamRegion{P" << PVD->getID() << '}';
+    }
+  } else {
+    os << "ParamRegion{P("<<getOriginExpr()->getID(getContext()) << ", "
+       << Index << ")}\n";
+  }
+}
+
 bool MemRegion::canPrintPretty() const {
   return canPrintPrettyAsExpr();
 }
@@ -606,6 +753,14 @@
   superRegion->printPrettyAsExpr(os);
 }
 
+bool ParamRegion::canPrintPrettyAsExpr() const {
+  return getDecl();
+}
+
+void ParamRegion::printPrettyAsExpr(raw_ostream &os) const {
+  os << getDecl()->getName();
+}
+
 std::string MemRegion::getDescriptiveName(bool UseQuotes) const {
   std::string VariableName;
   std::string ArrayIndices;
@@ -695,7 +850,8 @@
   case MemRegion::ObjCIvarRegionKind:
   case MemRegion::VarRegionKind:
   case MemRegion::ElementRegionKind:
-  case MemRegion::ObjCStringRegionKind: {
+  case MemRegion::ObjCStringRegionKind:
+  case MemRegion::ParamRegionKind: {
     QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx);
     if (isa<VariableArrayType>(Ty))
       return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR));
@@ -847,9 +1003,14 @@
       for (BlockDataRegion::referenced_vars_iterator
            I = BR->referenced_vars_begin(),
            E = BR->referenced_vars_end(); I != E; ++I) {
-        const VarRegion *VR = I.getOriginalRegion();
-        if (VR->getDecl() == VD)
-          return cast<VarRegion>(I.getCapturedRegion());
+        const TypedValueRegion *OrigR = I.getOriginalRegion();
+        if (const auto *VR = dyn_cast<VarRegion>(OrigR)) {
+          if (VR->getDecl() == VD)
+            return cast<VarRegion>(I.getCapturedRegion());
+        } else if (const auto *PR = dyn_cast<ParamRegion>(OrigR)) {
+          if (PR->getDecl() && PR->getDecl() == VD)
+            return cast<VarRegion>(I.getCapturedRegion());
+        }
       }
     }
 
@@ -1153,6 +1314,14 @@
   return dyn_cast<MemSpaceRegion>(R);
 }
 
+const ParamRegion*
+MemRegionManager::getParamRegion(const Expr *OE, unsigned Index,
+                                 const LocationContext *LC) {
+  const StackFrameContext *STC = LC->getStackFrame();
+  assert(STC);
+  return getSubRegion<ParamRegion>(OE, Index, getStackArgumentsRegion(STC));
+}
+
 bool MemRegion::hasStackStorage() const {
   return isa<StackSpaceRegion>(getMemorySpace());
 }
@@ -1343,6 +1512,7 @@
     case MemRegion::ObjCStringRegionKind:
     case MemRegion::VarRegionKind:
     case MemRegion::CXXTempObjectRegionKind:
+    case MemRegion::ParamRegionKind:
       // Usual base regions.
       goto Finish;
 
@@ -1490,15 +1660,25 @@
 // BlockDataRegion
 //===----------------------------------------------------------------------===//
 
-std::pair<const VarRegion *, const VarRegion *>
+std::pair<const VarRegion *, const TypedValueRegion *>
 BlockDataRegion::getCaptureRegions(const VarDecl *VD) {
   MemRegionManager &MemMgr = getMemRegionManager();
   const VarRegion *VR = nullptr;
-  const VarRegion *OriginalVR = nullptr;
+  const TypedValueRegion *OriginalVR = nullptr;
 
   if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) {
     VR = MemMgr.getVarRegion(VD, this);
-    OriginalVR = MemMgr.getVarRegion(VD, LC);
+    if (const auto *PVD = dyn_cast<ParmVarDecl>(VD)) {
+      const Expr* Call;
+      unsigned Index;
+      std::tie(Call, Index) = ParamRegion::getExprAndIndexForParam(PVD, LC);
+
+      if (Call)
+        OriginalVR = MemMgr.getParamRegion(Call, Index, LC);
+      else
+        OriginalVR = MemMgr.getVarRegion(VD, LC);
+    } else
+      OriginalVR = MemMgr.getVarRegion(VD, LC);
   }
   else {
     if (LC) {
@@ -1540,7 +1720,7 @@
 
   for (const auto *VD : ReferencedBlockVars) {
     const VarRegion *VR = nullptr;
-    const VarRegion *OriginalVR = nullptr;
+    const TypedValueRegion *OriginalVR = nullptr;
     std::tie(VR, OriginalVR) = getCaptureRegions(VD);
     assert(VR);
     assert(OriginalVR);
@@ -1584,7 +1764,8 @@
                                                    VecOriginal->end());
 }
 
-const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const {
+const TypedValueRegion
+*BlockDataRegion::getOriginalRegion(const VarRegion *R) const {
   for (referenced_vars_iterator I = referenced_vars_begin(),
                                 E = referenced_vars_end();
        I != E; ++I) {
@@ -1635,3 +1816,36 @@
 
   return false;
 }
+
+//===----------------------------------------------------------------------===//
+// Utility functions
+//===----------------------------------------------------------------------===//
+
+std::pair<const Expr*, unsigned>
+ParamRegion::getExprAndIndexForParam(const ParmVarDecl *PVD,
+                                     const LocationContext *LC) {
+  unsigned Index = PVD->getFunctionScopeIndex();
+  const StackFrameContext *SFC = LC->getStackFrame();
+  const Stmt *CallSite = SFC->getCallSite();
+  if (!CallSite)
+    return std::make_pair(nullptr, UINT_MAX);
+
+  const Decl *D = SFC->getDecl();
+  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+    if (Index >= FD->param_size() || FD->parameters()[Index] != PVD)
+      return std::make_pair(nullptr, UINT_MAX);
+  } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
+    if (Index >= BD->param_size() || BD->parameters()[Index] != PVD)
+      return std::make_pair(nullptr, UINT_MAX);
+  }
+
+  // For `CallExpr` of C++ member operators we must shift the index by 1
+  if (isa<CXXOperatorCallExpr>(CallSite)) {
+    if (const auto *CMD = dyn_cast<CXXMethodDecl>(D)) {
+      if (CMD->isOverloadedOperator())
+        ++Index;
+    }
+  }
+
+  return std::make_pair(cast<Expr>(CallSite), Index);
+}
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -537,9 +537,11 @@
             getObjectUnderConstruction(State, {E, I}, LC)) {
       SVal VV = *V;
       (void)VV;
-      assert(cast<VarRegion>(VV.castAs<loc::MemRegionVal>().getRegion())
-                 ->getStackFrame()->getParent()
-                 ->getStackFrame() == LC->getStackFrame());
+      if (const auto *VR =
+          dyn_cast<VarRegion>(VV.castAs<loc::MemRegionVal>().getRegion())) {
+        assert(VR->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) {
@@ -342,20 +433,19 @@
         // Operator arguments do not correspond to operator parameters
         // because this-argument is implemented as a normal argument in
         // operator call expressions but not in operator declarations.
-        const VarRegion *VR = Caller->getParameterLocation(
+        const TypedValueRegion *TVR = Caller->getParameterLocation(
             *Caller->getAdjustedParameterIndex(Idx), currBldrCtx->blockCount());
-        if (!VR)
+        if (!TVR)
           return None;
 
-        return loc::MemRegionVal(VR);
+        return loc::MemRegionVal(TVR);
       };
 
       if (const auto *CE = dyn_cast<CallExpr>(E)) {
         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/ExprEngineC.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -218,7 +218,7 @@
     auto CE = BD->capture_end();
     for (; I != E; ++I) {
       const VarRegion *capturedR = I.getCapturedRegion();
-      const VarRegion *originalR = I.getOriginalRegion();
+      const TypedValueRegion *originalR = I.getOriginalRegion();
 
       // If the capture had a copy expression, use the result of evaluating
       // that expression, otherwise use the original value.
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;
@@ -222,39 +222,113 @@
   return ADC->getManager()->getStackFrame(ADC, LCtx, E, B, BlockCount, Idx);
 }
 
-const VarRegion *CallEvent::getParameterLocation(unsigned Index,
-                                                 unsigned BlockCount) const {
+const TypedValueRegion*
+CallEvent::getParameterLocation(unsigned Index,
+                                unsigned BlockCount) const {
   const StackFrameContext *SFC = getCalleeStackFrame(BlockCount);
   // 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.
+
   const Decl *D = SFC->getDecl();
 
   // TODO: Refactor into a virtual method of CallEvent, like parameters().
   const ParmVarDecl *PVD = nullptr;
-  if (const auto *FD = dyn_cast<FunctionDecl>(D))
-    PVD = FD->parameters()[Index];
-  else if (const auto *BD = dyn_cast<BlockDecl>(D))
+  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+    //if (FD->isDefined())
+      PVD = FD->parameters()[Index];
+  } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
     PVD = BD->parameters()[Index];
-  else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
-    PVD = MD->parameters()[Index];
-  else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D))
-    PVD = CD->parameters()[Index];
-  assert(PVD && "Unexpected Decl kind!");
+  } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    //if (MD->isDefined())
+      PVD = MD->parameters()[Index];
+  } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
+    //if (CD->isDefined())
+      PVD = CD->parameters()[Index];
+  } else {
+    llvm_unreachable("Unexpected Decl kind!");
+  }
 
-  const VarRegion *VR =
+  /*if (PVD) {
+    const VarRegion *VR =
       State->getStateManager().getRegionManager().getVarRegion(PVD, SFC);
 
-  // This sanity check would fail if our parameter declaration doesn't
-  // correspond to the stack frame's function declaration.
-  assert(VR->getStackFrame() == SFC);
+    // This sanity check would fail if our parameter declaration doesn't
+    // correspond to the stack frame's function declaration.
+    assert(VR->getStackFrame() == SFC);
+
+    return VR;
+    }
+    return nullptr;*/
+    if (isa<CXXMemberOperatorCall>(this))
+    ++Index;
+      const ParamRegion *PR =
+    State->getStateManager().getRegionManager().getParamRegion(getOriginExpr(),
+    Index, SFC);
+    return PR;
+}
+
+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;
 
-  return VR;
+  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
@@ -325,8 +399,9 @@
     if (getKind() != CE_CXXAllocator)
       if (isArgumentConstructedDirectly(Idx))
         if (auto AdjIdx = getAdjustedParameterIndex(Idx))
-          if (const VarRegion *VR = getParameterLocation(*AdjIdx, BlockCount))
-            ValuesToInvalidate.push_back(loc::MemRegionVal(VR));
+          if (const TypedValueRegion *TVR =
+              getParameterLocation(*AdjIdx, BlockCount))
+            ValuesToInvalidate.push_back(loc::MemRegionVal(TVR));
   }
 
   // Invalidate designated regions using the batch invalidation API.
@@ -528,8 +603,28 @@
     // which makes getArgSVal() fail and return UnknownVal.
     SVal ArgVal = Call.getArgSVal(Idx);
     if (!ArgVal.isUnknown()) {
-      Loc ParamLoc = SVB.makeLoc(MRMgr.getVarRegion(ParamDecl, CalleeCtx));
-      Bindings.push_back(std::make_pair(ParamLoc, ArgVal));
+      unsigned Index = Idx;
+      if (isa<CXXMemberOperatorCall>(Call))
+        ++Index;
+
+      // For C++ inherited constructor calls we take the construct
+      // expression since it is the real owner of the argument.
+            if (const auto *ICC = dyn_cast<CXXInheritedConstructorCall>(&Call)) {
+        Loc ParamLoc =
+          SVB.makeLoc(MRMgr.getParamRegion(ICC->getInheritingConstructor(),
+                                           Index, CalleeCtx));
+        Bindings.push_back(std::make_pair(ParamLoc, ArgVal));
+      } else {
+        Loc ParamLoc =
+          SVB.makeLoc(MRMgr.getParamRegion(Call.getOriginExpr(), Index,
+                                           CalleeCtx));
+        Bindings.push_back(std::make_pair(ParamLoc, ArgVal));
+        }
+      /*Loc ParamLoc =
+          SVB.makeLoc(MRMgr.getVarRegion(ParamDecl,
+                                           CalleeCtx));
+            llvm::errs()<<"Binding "<<ArgVal<<" to "<<ParamLoc<<"\n";
+            Bindings.push_back(std::make_pair(ParamLoc, ArgVal));*/
     }
   }
 
Index: clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -743,12 +743,19 @@
     os << Sep;
 
     // Can only reasonably pretty-print DeclRegions.
-    if (!isa<DeclRegion>(R))
-      return false;
+    if (const auto *DR = dyn_cast<DeclRegion>(R)) {
+      Sep = DR->getValueType()->isAnyPointerType() ? "->" : ".";
+      DR->getDecl()->getDeclName().print(os, PP);
+    } else if (const auto *PR = dyn_cast<ParamRegion>(R)) {
+      const ParmVarDecl *D = PR->getDecl();
+      if (!D)
+        return false;
 
-    const auto *DR = cast<DeclRegion>(R);
-    Sep = DR->getValueType()->isAnyPointerType() ? "->" : ".";
-    DR->getDecl()->getDeclName().print(os, PP);
+      Sep = PR->getValueType()->isAnyPointerType() ? "->" : ".";
+      D->getDeclName().print(os, PP);
+    } else {
+      return false;
+    }
   }
 
   if (Sep.empty())
@@ -1240,6 +1247,32 @@
   return FrameSpace->getStackFrame() == LCtx->getStackFrame();
 }
 
+/// Returns true if \p N represents the DeclStmt declaring and initializing
+/// \p PR.
+static bool isInitializationOfParam(const ExplodedNode *N,
+                                    const ParamRegion *PR) {
+  Optional<PostStmt> P = N->getLocationAs<PostStmt>();
+  if (!P)
+    return false;
+
+  const DeclStmt *DS = P->getStmtAs<DeclStmt>();
+  if (!DS)
+    return false;
+
+  const ParmVarDecl *PVD = PR->getDecl();
+  if (!PVD)
+    return false;
+
+  if (DS->getSingleDecl() != PVD)
+    return false;
+
+  const MemSpaceRegion *ParamSpace = PR->getMemorySpace();
+  const auto *FrameSpace = dyn_cast<StackSpaceRegion>(ParamSpace);
+
+  const LocationContext *LCtx = N->getLocationContext();
+  return FrameSpace->getStackFrame() == LCtx->getStackFrame();
+}
+
 /// Show diagnostics for initializing or declaring a region \p R with a bad value.
 static void showBRDiagnostics(const char *action, llvm::raw_svector_ostream &os,
                               const MemRegion *R, SVal V, const DeclStmt *DS) {
@@ -1284,14 +1317,11 @@
 
 /// Display diagnostics for passing bad region as a parameter.
 static void showBRParamDiagnostics(llvm::raw_svector_ostream& os,
-    const VarRegion *VR,
-    SVal V) {
-  const auto *Param = cast<ParmVarDecl>(VR->getDecl());
-
+                                   const ParamRegion *PR, SVal V) {
   os << "Passing ";
 
   if (V.getAs<loc::ConcreteInt>()) {
-    if (Param->getType()->isObjCObjectPointerType())
+    if (PR->getValueType()->isObjCObjectPointerType())
       os << "nil object reference";
     else
       os << "null pointer value";
@@ -1304,11 +1334,11 @@
   }
 
   // Printed parameter indexes are 1-based, not 0-based.
-  unsigned Idx = Param->getFunctionScopeIndex() + 1;
+  unsigned Idx = PR->getIndex() + 1;
   os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter";
-  if (VR->canPrintPretty()) {
+  if (PR->canPrintPretty()) {
     os << " ";
-    VR->printPretty(os);
+    PR->printPretty(os);
   }
 }
 
@@ -1377,6 +1407,14 @@
     }
   }
 
+  // First see if we reached the declaration of the region.
+  if (const auto *PR = dyn_cast<ParamRegion>(R)) {
+    if (isInitializationOfParam(Pred, PR)) {
+      StoreSite = Pred;
+      InitE = PR->getDecl()->getInit();
+    }
+  }
+
   // If this is a post initializer expression, initializing the region, we
   // should track the initializer expression.
   if (Optional<PostInitializer> PIP = Pred->getLocationAs<PostInitializer>()) {
@@ -1416,7 +1454,14 @@
     // 'this' should never be NULL, but this visitor isn't just for NULL and
     // UndefinedVal.)
     if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
-      if (const auto *VR = dyn_cast<VarRegion>(R)) {
+      if (const auto *PR = dyn_cast<ParamRegion>(R)) {
+        ProgramStateManager &StateMgr = BRC.getStateManager();
+        CallEventManager &CallMgr = StateMgr.getCallEventManager();
+
+        CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(),
+                                                Succ->getState());
+        InitE = Call->getArgExpr(PR->getIndex());
+      } else if (const auto *VR = dyn_cast<VarRegion>(R)) {
 
         if (const auto *Param = dyn_cast<ParmVarDecl>(VR->getDecl())) {
           ProgramStateManager &StateMgr = BRC.getStateManager();
@@ -1482,7 +1527,7 @@
         SVal V = StoreSite->getSVal(S);
         if (const auto *BDR =
               dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
-          if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
+          if (const TypedValueRegion *OriginalR = BDR->getOriginalRegion(VR)) {
             if (auto KV = State->getSVal(OriginalR).getAs<KnownSVal>())
               BR.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
                   *KV, OriginalR, EnableNullFPSuppression, TKind, OriginSFC));
@@ -1494,8 +1539,9 @@
       showBRDiagnostics(action, os, R, V, DS);
 
   } else if (StoreSite->getLocation().getAs<CallEnter>()) {
-    if (const auto *VR = dyn_cast<VarRegion>(R))
-      showBRParamDiagnostics(os, VR, V);
+    if (const auto *PR = dyn_cast<ParamRegion>(R)) {
+      showBRParamDiagnostics(os, PR, V);
+    }
   }
 
   if (os.str().empty())
@@ -1834,7 +1880,16 @@
         return nullptr;
       ProgramStateManager &StateMgr = N->getState()->getStateManager();
       MemRegionManager &MRMgr = StateMgr.getRegionManager();
-      return MRMgr.getVarRegion(VD, N->getLocationContext());
+      const LocationContext *LCtx = N->getLocationContext();
+      if (const auto *PVD = dyn_cast<ParmVarDecl>(VD)) {
+        const Expr* Call;
+        unsigned Index;
+        std::tie(Call, Index) = ParamRegion::getExprAndIndexForParam(PVD, LCtx);
+
+        if (Call)
+          return MRMgr.getParamRegion(Call, Index, LCtx);
+      }
+      return MRMgr.getVarRegion(VD, LCtx);
     }
   }
 
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,51 +67,73 @@
 
 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;
+  }
+
+  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";
 
-  return false;
+  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);
 
@@ -119,7 +141,7 @@
   // 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/RetainCountChecker/RetainCountDiagnostics.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
+++ clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
@@ -432,13 +432,22 @@
       getRefBinding(N->getFirstPred()->getState(), Sym))
     return nullptr;
 
-  const auto *VR = cast<VarRegion>(cast<SymbolRegionValue>(Sym)->getRegion());
-  const auto *PVD = cast<ParmVarDecl>(VR->getDecl());
-  PathDiagnosticLocation L = PathDiagnosticLocation(PVD, SM);
+  const VarDecl *VD;
+  if (const auto *VR =
+      dyn_cast<VarRegion>(cast<SymbolRegionValue>(Sym)->getRegion())) {
+    VD = cast<VarDecl>(VR->getDecl());
+  } else if (const auto *PR =
+             dyn_cast<ParamRegion>(cast<SymbolRegionValue>(Sym)->getRegion())) {
+    VD = cast<ParmVarDecl>(PR->getDecl());
+  }
+
+  assert(VD);
+
+  PathDiagnosticLocation L = PathDiagnosticLocation(VD, SM);
 
   std::string s;
   llvm::raw_string_ostream os(s);
-  os << "Parameter '" << PVD->getNameAsString() << "' starts at +";
+  os << "Parameter '" << VD->getNameAsString() << "' starts at +";
   if (CurrT->getCount() == 1) {
     os << "1, as it is marked as consuming";
   } else {
@@ -606,6 +615,8 @@
 static Optional<std::string> describeRegion(const MemRegion *MR) {
   if (const auto *VR = dyn_cast_or_null<VarRegion>(MR))
     return std::string(VR->getDecl()->getName());
+  if (const auto *PR = dyn_cast_or_null<ParamRegion>(MR))
+    return std::string(PR->getDecl()->getName());
   // Once we support more storage locations for bindings,
   // this would need to be improved.
   return None;
Index: clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
@@ -507,13 +507,20 @@
     return false;
 
   const auto *VR = dyn_cast<VarRegion>(R);
+  const auto *PR = dyn_cast<ParamRegion>(R);
 
-  if (!R->hasStackStorage() || !VR)
+  if (!R->hasStackStorage() || (!VR && !PR))
     return true;
 
-  const VarDecl *VD = VR->getDecl();
-  if (!VD->hasAttr<CleanupAttr>())
-    return false; // CleanupAttr attaches destructors, which cause escaping.
+  if (VR) {
+    const VarDecl *VD = VR->getDecl();
+    if (!VD->hasAttr<CleanupAttr>())
+      return false; // CleanupAttr attaches destructors, which cause escaping.
+  } else {
+    const ParmVarDecl *PVD = PR->getDecl();
+    if (!PVD->hasAttr<CleanupAttr>())
+      return false; // CleanupAttr attaches destructors, which cause escaping.
+  }
   return true;
 }
 
Index: clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
@@ -193,6 +193,11 @@
           stackReg = dyn_cast<StackArgumentsSpaceRegion>(VR->getMemorySpace()))
         if (stackReg->getStackFrame() == SFC)
           return VR->getValueType();
+    if (const ParamRegion *PR = R->getAs<ParamRegion>())
+      if (const StackArgumentsSpaceRegion *
+          stackReg = dyn_cast<StackArgumentsSpaceRegion>(PR->getMemorySpace()))
+        if (stackReg->getStackFrame() == SFC)
+          return PR->getValueType();
   }
 
   return QualType();
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
-    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-      if (Call.getNumArgs() < 1)
-        return;
+    Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+    if (!Arg0.hasValue())
+      return;
 
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
       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,9 @@
 void IteratorModeling::checkBind(SVal Loc, SVal Val, const Stmt *S,
                                  CheckerContext &C) const {
   auto State = C.getState();
+  if (Val.getAs<nonloc::LazyCompoundVal>())
+    return;
+
   const auto *Pos = getIteratorPosition(State, Val);
   if (Pos) {
     State = setIteratorPosition(State, Loc, *Pos);
@@ -238,17 +251,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 +258,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 +281,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 +299,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(1, 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;
+    }
+
+    Optional<SVal> Arg0 = Call.getArgObject(0, C.blockCount());
+    if (!Arg0.hasValue())
+      return;
 
-      handleDecrement(C, Call.getReturnValue(), Call.getArgSVal(0),
-                        Call.getNumArgs());
+    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 +383,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 +398,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 +460,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 +488,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 +510,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 +537,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 +650,7 @@
       Pos.getContainer()->dumpToStream(Out);
       Out<<" ; Offset == ";
       Pos.getOffset()->dumpToStream(Out);
+      Out<<"\n";
     }
 
     for (const auto &Reg : RegionMap) {
@@ -631,6 +661,7 @@
       Pos.getContainer()->dumpToStream(Out);
       Out<<" ; Offset == ";
       Pos.getOffset()->dumpToStream(Out);
+      Out<<"\n";
     }
   }
 }
@@ -647,10 +678,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 +714,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;
@@ -179,6 +179,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 +202,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 +270,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 +286,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 +311,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);
 }
 
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -584,6 +584,7 @@
   bool isLiveRegion(const MemRegion *region);
   bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const;
   bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
+  bool isLive(const ParamRegion *VR, bool includeStoreBindings = false) const;
 
   /// Unconditionally marks a symbol as live.
   ///
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -131,9 +131,7 @@
 
   SValBuilder& getSValBuilder() { return svalBuilder; }
 
-  virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) {
-    return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC));
-  }
+  virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC);
 
   Loc getLValueCompoundLiteral(const CompoundLiteralExpr *CL,
                                const LocationContext *LC) {
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
@@ -79,10 +79,11 @@
       REGION(ElementRegion, TypedValueRegion)
       REGION(ObjCStringRegion, TypedValueRegion)
       REGION(StringRegion, TypedValueRegion)
+      REGION(ParamRegion, TypedValueRegion)
       REGION_RANGE(TYPED_VALUE_REGIONS, CompoundLiteralRegionKind,
-                                        StringRegionKind)
+                                        ParamRegionKind)
     REGION_RANGE(TYPED_REGIONS, BlockDataRegionKind,
-                                StringRegionKind)
+                                ParamRegionKind)
 
 #undef REGION_RANGE
 #undef ABSTRACT_REGION
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -305,6 +305,10 @@
   Loc getLValue(const CXXRecordDecl *BaseClass, const SubRegion *Super,
                 bool IsVirtual) const;
 
+  /// Get the lvalue for a parameter.
+  Loc getLValue(const Expr *Call, unsigned Index,
+                const LocationContext *LC) const;
+
   /// Get the lvalue for a variable reference.
   Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
 
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -704,8 +704,8 @@
       return cast<VarRegion>(*R);
     }
 
-    const VarRegion *getOriginalRegion() const {
-      return cast<VarRegion>(*OriginalR);
+    const TypedValueRegion *getOriginalRegion() const {
+      return cast<TypedValueRegion>(*OriginalR);
     }
 
     bool operator==(const referenced_vars_iterator &I) const {
@@ -727,7 +727,7 @@
 
   /// Return the original region for a captured region, if
   /// one exists.
-  const VarRegion *getOriginalRegion(const VarRegion *VR) const;
+  const TypedValueRegion *getOriginalRegion(const VarRegion *VR) const;
 
   referenced_vars_iterator referenced_vars_begin() const;
   referenced_vars_iterator referenced_vars_end() const;
@@ -742,7 +742,7 @@
 
 private:
   void LazyInitializeReferencedVars();
-  std::pair<const VarRegion *, const VarRegion *>
+  std::pair<const VarRegion *, const TypedValueRegion *>
   getCaptureRegions(const VarDecl *VD);
 };
 
@@ -923,6 +923,8 @@
     // which, unlike everything else on this list, are not memory spaces.
     assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) ||
            isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg));
+    //    assert(!isa<ParmVarDecl>(vd) && "For `ParmVarDecl` `ParamRegion` should "
+    //                                    "be used.");
   }
 
   static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl *VD,
@@ -1041,6 +1043,43 @@
   }
 };
 
+class ParamRegion : public TypedValueRegion {
+  friend class MemRegionManager;
+
+  const Expr *OriginExpr;
+  unsigned Index;
+
+  ParamRegion(const Expr *OE, unsigned Idx, const MemRegion *SReg)
+      : TypedValueRegion(SReg, ParamRegionKind), OriginExpr(OE), Index(Idx) {}
+
+  static void ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE,
+                            unsigned Idx, const MemRegion *SReg);
+
+public:
+  const Expr *getOriginExpr() const { return OriginExpr; }
+  unsigned getIndex() const { return Index; }
+
+  void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+  void dumpToStream(raw_ostream &os) const override;
+
+  const StackFrameContext *getStackFrame() const;
+
+  QualType getValueType() const override;
+  const ParmVarDecl* getDecl() const;
+  const Expr* getArgExpr() const;
+
+  bool canPrintPrettyAsExpr() const override;
+  void printPrettyAsExpr(raw_ostream &os) const override;
+
+  static bool classof(const MemRegion* R) {
+    return R->getKind() == ParamRegionKind;
+  }
+
+  static std::pair<const Expr*, unsigned>
+  getExprAndIndexForParam(const ParmVarDecl *PVD, const LocationContext *LC);
+};
+
 //===----------------------------------------------------------------------===//
 // Auxiliary data classes for use with MemRegions.
 //===----------------------------------------------------------------------===//
@@ -1395,6 +1434,11 @@
   /// super-region used.
   const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex);
 
+  /// getParamRegion - Retrieve or create the memory region
+  /// associated with a specified CallExpr, Index and LocationContext.
+  const ParamRegion *getParamRegion(const Expr *OE, unsigned Index,
+                                    const LocationContext *LC);
+
 private:
   template <typename RegionTy, typename SuperTy,
             typename Arg1Ty>
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
@@ -400,8 +400,8 @@
 
   /// Returns memory location for a parameter variable within the callee stack
   /// frame. May fail; returns null on failure.
-  const VarRegion *getParameterLocation(unsigned Index,
-                                        unsigned BlockCount) const;
+  const TypedValueRegion *getParameterLocation(unsigned Index,
+                                               unsigned BlockCount) const;
 
   /// Returns true if on the current path, the argument was constructed by
   /// calling a C++ constructor over it. This is an internal detail of the
@@ -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 {
Index: clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -216,6 +216,47 @@
            "' inside " + Visit(R->getSuperRegion());
   }
 
+  std::string VisitParamRegion(const ParamRegion *R) {
+    std::string Str;
+    llvm::raw_string_ostream OS(Str);
+
+    OS << "parameter " << R->getIndex() << " of";
+    ParmVarDecl *PVD = nullptr;
+    if (const auto *CE = dyn_cast<CallExpr>(R->getOriginExpr())) {
+      const FunctionDecl *FD = CE->getDirectCallee();
+      if (FD) {
+        assert(R->getIndex() < FD->param_size());
+        OS << " function '" << FD->getQualifiedNameAsString() << "()'";
+        PVD = FD->parameters()[R->getIndex()];
+      }
+    } else if (const auto *CCE =
+               dyn_cast<CXXConstructExpr>(R->getOriginExpr())) {
+      const CXXConstructorDecl *CCD = CCE->getConstructor();
+      assert(R->getIndex() < CCD->param_size());
+      OS << " C++ constructor '" << CCD->getQualifiedNameAsString() << "()'";
+      PVD = CCD->parameters()[R->getIndex()];
+    } else if (const auto *OCME =
+               dyn_cast<ObjCMessageExpr>(R->getOriginExpr())) {
+      const ObjCMethodDecl *OCMD = OCME->getMethodDecl();
+      assert(R->getIndex() < OCMD->param_size());
+      OS << " Objective-C method '" << OCMD->getQualifiedNameAsString() << "'";
+      PVD = OCMD->parameters()[R->getIndex()];
+    } else {
+      // FIXME: Any other kind of `Expr`?
+      llvm_unreachable("Maybe we forgot something...");
+    }
+
+    if (PVD) {
+      std::string ParamName = PVD->getQualifiedNameAsString();
+      if (!ParamName.empty())
+        OS << " named '" << ParamName <<"'";
+    } else {
+      OS << R->getOriginExpr()->getID(R->getContext());
+    }
+
+    return Str;
+  }
+
   std::string VisitSVal(SVal V) {
     std::string Str;
     llvm::raw_string_ostream OS(Str);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to