Hi jordan_rose,

http://reviews.llvm.org/D4740

Files:
  lib/Analysis/LiveVariables.cpp
  lib/StaticAnalyzer/Core/CallEvent.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  test/Analysis/temporaries.cpp
Index: lib/Analysis/LiveVariables.cpp
===================================================================
--- lib/Analysis/LiveVariables.cpp
+++ lib/Analysis/LiveVariables.cpp
@@ -409,6 +409,13 @@
       val.liveDecls = DSetFact.add(val.liveDecls, Dtor->getVarDecl());
       continue;
     }
+    if (Optional<CFGTemporaryDtor> Dtor =
+            elem.getAs<CFGTemporaryDtor>()) {
+      // Temporary objects need to survive until the destructor is called.
+      val.liveStmts = SSetFact.add(val.liveStmts,
+                                   Dtor->getBindTemporaryExpr()->getSubExpr());
+      continue;
+    }
 
     if (!elem.getAs<CFGStmt>())
       continue;
Index: lib/StaticAnalyzer/Core/CallEvent.cpp
===================================================================
--- lib/StaticAnalyzer/Core/CallEvent.cpp
+++ lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -959,7 +959,6 @@
   CFGElement E = (*B)[CalleeCtx->getIndex()];
   assert(E.getAs<CFGImplicitDtor>() &&
          "All other CFG elements should have exprs");
-  assert(!E.getAs<CFGTemporaryDtor>() && "We don't handle temporaries yet");
 
   SValBuilder &SVB = State->getStateManager().getSValBuilder();
   const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CalleeCtx->getDecl());
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -662,9 +662,18 @@
 
   QualType varType = D.getBindTemporaryExpr()->getSubExpr()->getType();
 
-  // FIXME: Inlining of temporary destructors is not supported yet anyway, so we
-  // just put a NULL region for now. This will need to be changed later.
-  VisitCXXDestructor(varType, nullptr, D.getBindTemporaryExpr(),
+  const LocationContext *LCtx = Pred->getLocationContext();
+  SVal Val = Pred->getState()->getSVal(
+      D.getBindTemporaryExpr()->getSubExpr(), LCtx->getCurrentStackFrame());
+  const MemRegion *Region = nullptr;
+  // If the class does not have any members, there will not be a region
+  // for it bound in the environment.
+  if (Optional<nonloc::LazyCompoundVal> LCV =
+          Val.getAs<nonloc::LazyCompoundVal>()) {
+    Region = LCV->getRegion();
+  }
+
+  VisitCXXDestructor(varType, Region, D.getBindTemporaryExpr(),
                      /*IsBase=*/ false, Pred, Dst);
 }
 
Index: lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -637,12 +637,6 @@
     if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors))
       return CIP_DisallowedAlways;
 
-    // FIXME: This is a hack. We don't handle temporary destructors
-    // right now, so we shouldn't inline their constructors.
-    if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete)
-      if (!Target || !isa<DeclRegion>(Target))
-        return CIP_DisallowedOnce;
-
     break;
   }
   case CE_CXXDestructor: {
@@ -807,14 +801,6 @@
   AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();
   AnalysisDeclContext *CalleeADC = ADCMgr.getContext(D);
 
-  // Temporary object destructor processing is currently broken, so we never
-  // inline them.
-  // FIXME: Remove this once temp destructors are working.
-  if (isa<CXXDestructorCall>(Call)) {
-    if ((*currBldrCtx->getBlock())[currStmtIdx].getAs<CFGTemporaryDtor>())
-      return false;
-  }
-
   // The auto-synthesized bodies are essential to inline as they are
   // usually small and commonly used. Note: we should do this check early on to
   // ensure we always inline these calls.
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -506,16 +506,7 @@
 }
 
 bool ScanReachableSymbols::scan(nonloc::LazyCompoundVal val) {
-  bool wasVisited = !visited.insert(val.getCVData()).second;
-  if (wasVisited)
-    return true;
-
-  StoreManager &StoreMgr = state->getStateManager().getStoreManager();
-  // FIXME: We don't really want to use getBaseRegion() here because pointer
-  // arithmetic doesn't apply, but scanReachableSymbols only accepts base
-  // regions right now.
-  const MemRegion *R = val.getRegion()->getBaseRegion();
-  return StoreMgr.scanReachableSymbols(val.getStore(), R, *this);
+  return scan(val.getRegion());
 }
 
 bool ScanReachableSymbols::scan(nonloc::CompoundVal val) {
Index: test/Analysis/temporaries.cpp
===================================================================
--- test/Analysis/temporaries.cpp
+++ test/Analysis/temporaries.cpp
@@ -105,7 +105,7 @@
 
     // FIXME: should be TRUE, but we don't inline the constructors of
     // temporaries because we can't model their destructors yet.
-    clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); // expected-warning{{UNKNOWN}}
+    clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); // expected-warning{{TRUE}}
 #endif
   }
 }
@@ -234,6 +234,17 @@
     }
   }
 
+  struct WriteInDestructor {
+    WriteInDestructor(int *p) : p(p) {}
+    ~WriteInDestructor() { *p = 23; } // no warning
+    int *p;
+  };
+  void testDtorInlining() {
+    int x;
+    (WriteInDestructor(&x));
+    clang_analyzer_eval(x == 23); // expected-warning{{TRUE}}
+  }
+
 #endif // TEMPORARY_DTORS
 }
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to