[PATCH] D27202: [analyzer] Do not conjure a symbol for return value of a conservatively evaluated function

Artem Dergachev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 29 04:47:03 PST 2016


NoQ created this revision.
NoQ added reviewers: zaks.anna, dcoughlin, xazax.hun, a.sidorin.
NoQ added subscribers: cfe-commits, baloghadamsoftware.

Instead, return a `nonloc::LazyCompoundVal` of a temporary region for the call expression, with a trivial store in which the temporary region is invalidated.

Returning a conjured record-type symbol is painful because the return value of the function may suddenly change during materialization of a temporary - it will be hotfixed into the same lazy compound value anyway in some cases, eg. in `createTemporaryRegionIfNeeded` when handling a `MaterializeTemporaryExpr`. After this patch, we should be receiving the same temporary region during materialization, instead of constructing a new region, and materialization of a conjured structure starts doing a lot less things.

I'm including a change in the yet-to-land iterator checker (https://reviews.llvm.org/D25660), which should or should not be committed depending on the order of patches landing. This change demonstrates how the problem explained above causes checkers to hack around.


https://reviews.llvm.org/D27202

Files:
  lib/StaticAnalyzer/Checkers/IteratorPastEndChecker.cpp
  lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
  test/Analysis/explain-svals.cpp


Index: test/Analysis/explain-svals.cpp
===================================================================
--- test/Analysis/explain-svals.cpp
+++ test/Analysis/explain-svals.cpp
@@ -94,5 +94,5 @@
 
 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().z); // expected-warning-re{{{{^value derived from \(symbol of type 'struct S' conjured at statement 'conjure_S\(\)'\) for field 'z' of temporary object constructed at statement 'conjure_S\(\)'$}}}}
+  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: lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -553,7 +553,28 @@
   QualType ResultTy = Call.getResultType();
   SValBuilder &SVB = getSValBuilder();
   unsigned Count = currBldrCtx->blockCount();
-  SVal R = SVB.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
+  SVal R;
+
+  if (NonLoc::isCompoundType(ResultTy)) {
+    // Return a (lazy) compound value for compound types.
+    MemRegionManager &MemMgr = SVB.getRegionManager();
+    StoreManager &StoreMgr = SVB.getStateManager().getStoreManager();
+
+    const CXXTempObjectRegion *TR = MemMgr.getCXXTempObjectRegion(E, LCtx);
+
+    StoreRef EmptyStore = StoreMgr.getInitialStore(LCtx);
+
+    InvalidatedSymbols IS;
+    RegionAndSymbolInvalidationTraits ITraits;
+    ITraits.setTrait(TR, RegionAndSymbolInvalidationTraits::TK_SuppressEscape);
+    StoreRef ConjuredStore = StoreMgr.invalidateRegions(
+        EmptyStore.getStore(), loc::MemRegionVal(TR), E, Count, LCtx, nullptr,
+        IS, ITraits, nullptr, nullptr);
+
+    R = SVB.makeLazyCompoundVal(ConjuredStore, TR);
+  } else {
+    R = SVB.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
+  }
   return State->BindExpr(E, LCtx, R);
 }
 
Index: lib/StaticAnalyzer/Checkers/IteratorPastEndChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/IteratorPastEndChecker.cpp
+++ lib/StaticAnalyzer/Checkers/IteratorPastEndChecker.cpp
@@ -68,10 +68,9 @@
 
 class IteratorPastEndChecker
     : public Checker<
-          check::PreCall, check::PostCall, check::PreStmt<CXXOperatorCallExpr>,
-          check::PostStmt<CXXConstructExpr>, check::PostStmt<DeclStmt>,
-          check::PostStmt<MaterializeTemporaryExpr>, check::BeginFunction,
-          check::DeadSymbols, eval::Assume, eval::Call> {
+          check::PreCall, check::PostCall, check::PostStmt<CXXConstructExpr>,
+          check::PostStmt<DeclStmt>, check::PostStmt<MaterializeTemporaryExpr>,
+          check::BeginFunction, check::DeadSymbols, eval::Assume, eval::Call> {
   mutable IdentifierInfo *II_std = nullptr, *II_find = nullptr,
                          *II_find_end = nullptr, *II_find_first_of = nullptr,
                          *II_find_if = nullptr, *II_find_if_not = nullptr,
@@ -105,7 +104,6 @@
 
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
-  void checkPreStmt(const CXXOperatorCallExpr *COCE, CheckerContext &C) const;
   void checkBeginFunction(CheckerContext &C) const;
   void checkPostStmt(const CXXConstructExpr *CCE, CheckerContext &C) const;
   void checkPostStmt(const DeclStmt *DS, CheckerContext &C) const;
@@ -216,27 +214,6 @@
   }
 }
 
-void IteratorPastEndChecker::checkPreStmt(const CXXOperatorCallExpr *COCE,
-                                          CheckerContext &C) const {
-  const auto *ThisExpr = COCE->getArg(0);
-
-  auto State = C.getState();
-  const auto *LCtx = C.getPredecessor()->getLocationContext();
-
-  const auto CurrentThis = State->getSVal(ThisExpr, LCtx);
-  if (const auto *Reg = CurrentThis.getAsRegion()) {
-    if (!Reg->getAs<CXXTempObjectRegion>())
-      return;
-    const auto OldState = C.getPredecessor()->getFirstPred()->getState();
-    const auto OldThis = OldState->getSVal(ThisExpr, LCtx);
-    const auto *Pos = getIteratorPosition(OldState, OldThis);
-    if (!Pos)
-      return;
-    State = setIteratorPosition(State, CurrentThis, *Pos);
-    C.addTransition(State);
-  }
-}
-
 void IteratorPastEndChecker::checkBeginFunction(CheckerContext &C) const {
   auto State = C.getState();
   const auto *LCtx = C.getLocationContext();


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D27202.79541.patch
Type: text/x-patch
Size: 4696 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20161129/f35a1ce9/attachment-0001.bin>


More information about the cfe-commits mailing list