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

More progress...


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

https://reviews.llvm.org/D77229

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
  clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
  clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
  clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
  clang/lib/StaticAnalyzer/Core/CallEvent.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  clang/test/Analysis/iterator-modeling.cpp

Index: clang/test/Analysis/iterator-modeling.cpp
===================================================================
--- clang/test/Analysis/iterator-modeling.cpp
+++ clang/test/Analysis/iterator-modeling.cpp
@@ -28,7 +28,7 @@
 void clang_analyzer_eval(bool);
 void clang_analyzer_warnIfReached();
 
-void begin(const std::vector<int> &v) {
+/*void begin(const std::vector<int> &v) {
   auto i = v.begin();
 
   clang_analyzer_eval(clang_analyzer_iterator_container(i) == &v); // expected-warning{{TRUE}}
@@ -1773,7 +1773,7 @@
   clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1 + 2}} FIXME: Should be $i1 + 1
   // clang_analyzer_express(clang_analyzer_iterator_position(i5)); FIXME: expect warning $i1 + 1
   clang_analyzer_express(clang_analyzer_iterator_position(i4)); // expected-warning{{$FL.end()}}
-}
+}*/
 
 struct simple_iterator_base {
   simple_iterator_base();
@@ -1812,7 +1812,7 @@
   }
 }
 
-void iter_diff(std::vector<int> &V) {
+/*void iter_diff(std::vector<int> &V) {
   auto i0 = V.begin(), i1 = V.end();
   ptrdiff_t len = i1 - i0; // no-crash
 }
@@ -1880,3 +1880,4 @@
 // CHECK-NEXT:     "i1 : Valid ; Container == SymRegion{reg_$[[#]]<std::vector<int> & V>} ; Offset == conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]}"
 // CHECK-NEXT:   ]}
 }
+*/
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -109,6 +109,96 @@
   return LValue;
 }
 
+Optional<SVal> ExprEngine::retrieveFromConstructionContext(
+    ProgramStateRef State, const LocationContext *LCtx,
+    const ConstructionContext *CC) const {
+  if (CC) {
+    switch (CC->getKind()) {
+    case ConstructionContext::CXX17ElidedCopyVariableKind:
+    case ConstructionContext::SimpleVariableKind: {
+      const auto *DSCC = cast<VariableConstructionContext>(CC);
+      const auto *DS = DSCC->getDeclStmt();
+      return getObjectUnderConstruction(State, DS, LCtx);
+    }
+    case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:
+    case ConstructionContext::SimpleConstructorInitializerKind: {
+      const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);
+      const auto *Init = ICC->getCXXCtorInitializer();
+      return getObjectUnderConstruction(State, Init, LCtx);
+    }
+    case ConstructionContext::SimpleReturnedValueKind:
+    case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {
+      const StackFrameContext *SFC = LCtx->getStackFrame();
+      if (const LocationContext *CallerLCtx = SFC->getParent()) {
+        auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]
+                       .getAs<CFGCXXRecordTypedCall>();
+        if (!RTC) {
+          // We were unable to find the correct construction context for the
+          // call in the parent stack frame. This is equivalent to not being
+          // able to find construction context at all.
+          break;
+        }
+        if (isa<BlockInvocationContext>(CallerLCtx)) {
+          // Unwrap block invocation contexts. They're mostly part of
+          // the current stack frame.
+          CallerLCtx = CallerLCtx->getParent();
+          assert(!isa<BlockInvocationContext>(CallerLCtx));
+        }
+        return retrieveFromConstructionContext(
+          State, CallerLCtx, RTC->getConstructionContext());
+      }
+      break;
+    }
+    case ConstructionContext::ElidedTemporaryObjectKind: {
+      assert(AMgr.getAnalyzerOptions().ShouldElideConstructors);
+      const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
+      Optional<SVal> RetVal = retrieveFromConstructionContext(
+          State, LCtx, TCC->getConstructionContextAfterElision());
+      if (RetVal.hasValue())
+        return RetVal;
+      
+      LLVM_FALLTHROUGH;
+    }
+    case ConstructionContext::SimpleTemporaryObjectKind: {
+      const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);
+      const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr();
+      Optional<SVal> RetVal;
+      if (BTE) {
+        RetVal = getObjectUnderConstruction(State, BTE, LCtx);
+        if (RetVal.hasValue())
+          return RetVal;
+      }
+      
+      const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
+      if (MTE)
+        RetVal = getObjectUnderConstruction(State, MTE, LCtx);
+
+      return RetVal;
+    }
+    case ConstructionContext::ArgumentKind: {
+      const auto *ACC = cast<ArgumentConstructionContext>(CC);
+      const Expr *E = ACC->getCallLikeExpr();
+      unsigned Idx = ACC->getIndex();
+      if (const auto *CE = dyn_cast<CallExpr>(E)) {
+        return getObjectUnderConstruction(State, {CE, Idx}, LCtx);
+      } else if (const auto *CCE = dyn_cast<CXXConstructExpr>(E)) {
+        return getObjectUnderConstruction(State, {CCE, Idx}, LCtx);
+      } else if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
+        return getObjectUnderConstruction(State, {ME, Idx}, LCtx);
+      } else if (const auto *BTE = ACC->getCXXBindTemporaryExpr()) {
+        return getObjectUnderConstruction(State, BTE, LCtx);
+      }
+
+      LLVM_FALLTHROUGH;
+    }
+    default:
+      return None;
+    }
+  }
+
+  return None;
+}
+
 std::pair<ProgramStateRef, SVal> ExprEngine::handleConstructionContext(
     const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
     const ConstructionContext *CC, EvalCallOptions &CallOpts) {
Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -466,7 +466,7 @@
   // incorrect handling of temporaries bound to default parameters.
   assert(!State->get<ObjectsUnderConstruction>(Key) ||
          Key.getItem().getKind() ==
-             ConstructionContextItem::TemporaryDestructorKind);
+         ConstructionContextItem::TemporaryDestructorKind);
   return State->set<ObjectsUnderConstruction>(Key, V);
 }
 
@@ -602,7 +602,6 @@
                            const LocationContext *LCtx, const char *NL,
                            unsigned int Space, bool IsDot) const {
   Indent(Out, Space, IsDot) << "\"constructing_objects\": ";
-
   if (LCtx && !State->get<ObjectsUnderConstruction>().isEmpty()) {
     ++Space;
     Out << '[' << NL;
Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -257,6 +257,79 @@
   return VR;
 }
 
+const ConstructionContext
+*CallEvent::getConstructionContext(unsigned BlockCount) const {
+  const CFGBlock *Block;
+  unsigned Index;
+
+  if (const StackFrameContext *StackFrame = getCalleeStackFrame(BlockCount)) {
+    Block = StackFrame->getCallSiteBlock();
+    if (!Block) {
+      llvm::errs()<<"No Call Site Block.\n";
+      return nullptr;
+    }
+
+    Index = StackFrame->getIndex();
+  } else {
+    CFGStmtMap *Map =
+      getLocationContext()->getAnalysisDeclContext()->getCFGStmtMap();
+    Block = Map->getBlock(getOriginExpr());
+    if (!Block) {
+      llvm::errs()<<"No Call Site Block.\n";
+      return nullptr;
+    }
+
+    for (Index = 0; Index < Block->size(); ++Index) {
+      if (const auto CS = (*Block)[Index].getAs<CFGStmt>()) {
+        if (CS->getStmt() == getOriginExpr())
+          break;
+      }
+    }
+  }
+
+  if (Index == Block->size()) {
+    llvm::errs()<<"    Stmt not found!\n";
+    return nullptr;
+  }
+
+  if(const auto Ctor = (*Block)[Index].getAs<CFGConstructor>()) {
+    return Ctor->getConstructionContext();
+  }
+
+  if (const auto RecCall = (*Block)[Index].getAs<CFGCXXRecordTypedCall>()) {
+    return RecCall->getConstructionContext();
+  }
+
+  llvm::errs()<<"    Neither a Constructor nor a CFG C++ Record-Typed Call!\n";
+  return nullptr;
+}
+
+Optional<SVal>
+CallEvent::getReturnValueUnderConstruction(ExprEngine &Engine,
+                                           unsigned BlockCount) const {
+  const auto *CC = getConstructionContext(BlockCount);
+  if (!CC) {
+    llvm::errs()<<"  No construction context!!!\n";
+    return None;
+  }
+
+  llvm::errs()<<"  Retrieving Original\n";
+  Optional<SVal> RetVal =
+    Engine.retrieveFromConstructionContext(getState(), getLocationContext(),
+                                           CC);
+  if (RetVal.hasValue())
+    return RetVal;
+
+  ExprEngine::EvalCallOptions CallOpts;
+  ProgramStateRef State;
+  SVal NewVal;
+  llvm::errs()<<"  Handling New\n";
+  std::tie(State, NewVal) =
+    Engine.handleConstructionContext(getOriginExpr(), getState(),
+                                     getLocationContext(), CC, CallOpts);
+  return NewVal;
+}
+
 /// Returns true if a type is a pointer-to-const or reference-to-const
 /// with no further indirection.
 static bool isPointerToConst(QualType Ty) {
Index: clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -83,8 +83,8 @@
 namespace {
 
 class IteratorModeling
-    : public Checker<check::PostCall, check::PostStmt<MaterializeTemporaryExpr>,
-                     check::Bind, check::LiveSymbols, check::DeadSymbols> {
+    : public Checker<check::PostCall, check::Bind, check::LiveSymbols,
+                     check::DeadSymbols> {
 
   using AdvanceFn = void (IteratorModeling::*)(CheckerContext &, const Expr *,
                                                SVal, SVal, SVal) const;
@@ -146,8 +146,6 @@
   void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const;
   void checkPostStmt(const CXXConstructExpr *CCE, CheckerContext &C) const;
   void checkPostStmt(const DeclStmt *DS, CheckerContext &C) const;
-  void checkPostStmt(const MaterializeTemporaryExpr *MTE,
-                     CheckerContext &C) const;
   void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const;
   void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
 };
@@ -156,8 +154,6 @@
 ProgramStateRef removeIteratorPosition(ProgramStateRef State, const SVal &Val);
 ProgramStateRef relateSymbols(ProgramStateRef State, SymbolRef Sym1,
                               SymbolRef Sym2, bool Equal);
-bool isBoundThroughLazyCompoundVal(const Environment &Env,
-                                   const MemRegion *Reg);
 const ExplodedNode *findCallEnter(const ExplodedNode *Node, const Expr *Call);
 
 } // namespace
@@ -190,14 +186,25 @@
 
   auto State = C.getState();
 
+  llvm::errs()<<"Generic PostCall\n";
+  Optional<SVal> RetVal = Call.getReturnValue();
+  llvm::errs()<<"Original RetVal: "<<*RetVal<<"\n";
+  if (RetVal->getAs<nonloc::LazyCompoundVal>()) {
+    RetVal =
+      Call.getReturnValueUnderConstruction(C.getExprEngine(), C.blockCount());
+    if (!RetVal.hasValue())
+      return;
+  }
+  llvm::errs()<<"Updated RetVal: "<<*RetVal<<"\n";
+
   // Already bound to container?
-  if (getIteratorPosition(State, Call.getReturnValue()))
+  if (getIteratorPosition(State, *RetVal))
     return;
 
   // Copy-like and move constructors
   if (isa<CXXConstructorCall>(&Call) && Call.getNumArgs() == 1) {
     if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(0))) {
-      State = setIteratorPosition(State, Call.getReturnValue(), *Pos);
+      State = setIteratorPosition(State, *RetVal, *Pos);
       if (cast<CXXConstructorDecl>(Func)->isMoveConstructor()) {
         State = removeIteratorPosition(State, Call.getArgSVal(0));
       }
@@ -214,7 +221,7 @@
   for (unsigned i = 0; i < Call.getNumArgs(); ++i) {
     if (isIteratorType(Call.getArgExpr(i)->getType())) {
       if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(i))) {
-        assignToContainer(C, OrigExpr, Call.getReturnValue(),
+        assignToContainer(C, OrigExpr, *RetVal,
                           Pos->getContainer());
         return;
       }
@@ -225,7 +232,9 @@
 void IteratorModeling::checkBind(SVal Loc, SVal Val, const Stmt *S,
                                  CheckerContext &C) const {
   auto State = C.getState();
-  const auto *Pos = getIteratorPosition(State, Val);
+  llvm::errs()<<"Bind Old: "<<Val<<"\n";
+  llvm::errs()<<"Bind New: "<<Loc<<"\n";
+   const auto *Pos = getIteratorPosition(State, Val);
   if (Pos) {
     State = setIteratorPosition(State, Loc, *Pos);
     C.addTransition(State);
@@ -238,17 +247,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
@@ -278,12 +276,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 +294,72 @@
 IteratorModeling::handleOverloadedOperator(CheckerContext &C,
                                            const CallEvent &Call,
                                            OverloadedOperatorKind Op) const {
-    if (isSimpleComparisonOperator(Op)) {
-      const auto *OrigExpr = Call.getOriginExpr();
-      if (!OrigExpr)
-        return;
+  const auto *OrigExpr = Call.getOriginExpr();
+  if (!OrigExpr)
+    return;
 
-      if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        handleComparison(C, OrigExpr, Call.getReturnValue(),
-                         InstCall->getCXXThisVal(), Call.getArgSVal(0), Op);
-        return;
-      }
+  llvm::errs()<<"Overloaded Operator\n";
+  Optional<SVal> RetVal = Call.getReturnValue();
+  llvm::errs()<<"Original RetVal: "<<*RetVal<<"\n";
+  if (RetVal->getAs<nonloc::LazyCompoundVal>()) {
+    RetVal =
+      Call.getReturnValueUnderConstruction(C.getExprEngine(), C.blockCount());
+    if (!RetVal.hasValue())
+      return;
+  }
+  llvm::errs()<<"Updated RetVal: "<<*RetVal<<"\n";
 
-      handleComparison(C, OrigExpr, Call.getReturnValue(), Call.getArgSVal(0),
-                         Call.getArgSVal(1), Op);
+  if (isSimpleComparisonOperator(Op)) {
+    const auto *OrigExpr = Call.getOriginExpr();
+    if (!OrigExpr)
       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;
-        }
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      handleComparison(C, OrigExpr, *RetVal,
+                       InstCall->getCXXThisVal(), Call.getArgSVal(0), Op);
+      return;
+    }
+
+    handleComparison(C, OrigExpr, *RetVal, Call.getArgSVal(0),
+                     Call.getArgSVal(1), Op);
+    return;
+  } else if (isRandomIncrOrDecrOperator(Op)) {
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      if (Call.getNumArgs() >= 1 &&
+          Call.getArgExpr(0)->getType()->isIntegralOrEnumerationType()) {
+        handleRandomIncrOrDecr(C, OrigExpr, Op, *RetVal,
+                               InstCall->getCXXThisVal(), Call.getArgSVal(0));
+        return;
       }
-    } else if (isIncrementOperator(Op)) {
-      if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        handleIncrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
-                        Call.getNumArgs());
+    } else {
+      if (Call.getNumArgs() >= 2 &&
+          Call.getArgExpr(1)->getType()->isIntegralOrEnumerationType()) {
+        handleRandomIncrOrDecr(C, OrigExpr, Op, *RetVal,
+                               Call.getArgSVal(0), Call.getArgSVal(1));
         return;
       }
-
-      handleIncrement(C, Call.getReturnValue(), Call.getArgSVal(0),
+    }
+  } else if (isIncrementOperator(Op)) {
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      handleIncrement(C, *RetVal, InstCall->getCXXThisVal(),
                       Call.getNumArgs());
       return;
-    } else if (isDecrementOperator(Op)) {
-      if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
-        handleDecrement(C, Call.getReturnValue(), InstCall->getCXXThisVal(),
-                        Call.getNumArgs());
-        return;
-      }
+    }
 
-      handleDecrement(C, Call.getReturnValue(), Call.getArgSVal(0),
-                        Call.getNumArgs());
+    handleIncrement(C, *RetVal, Call.getArgSVal(0),
+                    Call.getNumArgs());
+    return;
+  } else if (isDecrementOperator(Op)) {
+    if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+      handleDecrement(C, *RetVal, InstCall->getCXXThisVal(),
+                      Call.getNumArgs());
       return;
     }
+
+    handleDecrement(C, *RetVal, Call.getArgSVal(0),
+                    Call.getNumArgs());
+    return;
+  }
 }
 
 void
@@ -363,8 +367,19 @@
                                             const CallEvent &Call,
                                             const Expr *OrigExpr,
                                             const AdvanceFn *Handler) const {
+  llvm::errs()<<"Advance-like Function\n";
+  Optional<SVal> RetVal = Call.getReturnValue();
+  llvm::errs()<<"Original RetVal: "<<*RetVal<<"\n";
+  if (RetVal->getAs<nonloc::LazyCompoundVal>()) {
+    RetVal =
+      Call.getReturnValueUnderConstruction(C.getExprEngine(), C.blockCount());
+    if (!RetVal.hasValue())
+      return;
+  }
+  llvm::errs()<<"Updated RetVal: "<<*RetVal<<"\n";
+
   if (!C.wasInlined) {
-    (this->**Handler)(C, OrigExpr, Call.getReturnValue(),
+    (this->**Handler)(C, OrigExpr, *RetVal,
                       Call.getArgSVal(0), Call.getArgSVal(1));
     return;
   }
@@ -375,7 +390,7 @@
   if (IdInfo) {
     if (IdInfo->getName() == "advance") {
       if (noChangeInAdvance(C, Call.getArgSVal(0), OrigExpr)) {
-        (this->**Handler)(C, OrigExpr, Call.getReturnValue(),
+        (this->**Handler)(C, OrigExpr, *RetVal,
                           Call.getArgSVal(0), Call.getArgSVal(1));
       }
     }
@@ -647,8 +662,6 @@
     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;
 }
@@ -685,18 +698,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,8 +169,6 @@
     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;
 }
Index: clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
+++ clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
@@ -163,6 +163,18 @@
   if (!Func)
     return;
 
+  llvm::errs()<<"CFG Block: "<<C.getBlockID()<<"\n";
+  llvm::errs()<<"Container PostCall\n";
+  Optional<SVal> RetVal = Call.getReturnValue();
+  llvm::errs()<<"Original RetVal: "<<*RetVal<<"\n";
+  if (RetVal->getAs<nonloc::LazyCompoundVal>()) {
+    RetVal =
+      Call.getReturnValueUnderConstruction(C.getExprEngine(), C.blockCount());
+    if (!RetVal.hasValue())
+      return;
+  }
+  llvm::errs()<<"Updated RetVal: "<<*RetVal<<"\n";
+
   if (Func->isOverloadedOperator()) {
     const auto Op = Func->getOverloadedOperator();
     if (Op == OO_Equal) {
@@ -204,13 +216,13 @@
         return;
 
       if (isBeginCall(Func)) {
-        handleBegin(C, OrigExpr, Call.getReturnValue(),
+        handleBegin(C, OrigExpr, *RetVal,
                     InstCall->getCXXThisVal());
         return;
       }
 
       if (isEndCall(Func)) {
-        handleEnd(C, OrigExpr, Call.getReturnValue(),
+        handleEnd(C, OrigExpr, *RetVal,
                   InstCall->getCXXThisVal());
         return;
       }
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -686,6 +686,21 @@
                        const CallEvent &Call,
                        const EvalCallOptions &CallOpts = {});
 
+  /// Update the program state with all the path-sensitive information
+  /// that's necessary to perform construction of an object with a given
+  /// syntactic construction context. If the construction context is unavailable
+  /// or unusable for any reason, a dummy temporary region is returned, and the
+  /// IsConstructorWithImproperlyModeledTargetRegion flag is set in \p CallOpts.
+  /// Returns the updated program state and the new object's this-region.
+  std::pair<ProgramStateRef, SVal> handleConstructionContext(
+      const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
+      const ConstructionContext *CC, EvalCallOptions &CallOpts);
+
+  ///
+  Optional<SVal> retrieveFromConstructionContext(
+      ProgramStateRef State, const LocationContext *LCtx,
+      const ConstructionContext *CC) const;
+
 private:
   ProgramStateRef finishArgumentConstruction(ProgramStateRef State,
                                              const CallEvent &Call);
@@ -804,16 +819,6 @@
   /// constructing into an existing region.
   const CXXConstructExpr *findDirectConstructorForCurrentCFGElement();
 
-  /// Update the program state with all the path-sensitive information
-  /// that's necessary to perform construction of an object with a given
-  /// syntactic construction context. If the construction context is unavailable
-  /// or unusable for any reason, a dummy temporary region is returned, and the
-  /// IsConstructorWithImproperlyModeledTargetRegion flag is set in \p CallOpts.
-  /// Returns the updated program state and the new object's this-region.
-  std::pair<ProgramStateRef, SVal> handleConstructionContext(
-      const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
-      const ConstructionContext *CC, EvalCallOptions &CallOpts);
-
   /// Common code that handles either a CXXConstructExpr or a
   /// CXXInheritedCtorInitExpr.
   void handleConstructor(const Expr *E, ExplodedNode *Pred,
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -52,6 +52,10 @@
            "We should not call the checkers on an empty state.");
   }
 
+  ExprEngine &getExprEngine() {
+    return Eng;
+  }
+
   AnalysisManager &getAnalysisManager() {
     return Eng.getAnalysisManager();
   }
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -431,6 +431,13 @@
     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(ExprEngine &Engine,
+                                                 unsigned BlockCount) const;
+
   // Iterator access to formal parameters and their types.
 private:
   struct GetTypeFn {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to