[cfe-commits] r160023 - in /cfe/trunk/lib/StaticAnalyzer/Core: ExprEngine.cpp ExprEngineC.cpp ExprEngineCallAndReturn.cpp Store.cpp

Jordan Rose jordan_rose at apple.com
Tue Jul 10 15:08:01 PDT 2012


Author: jrose
Date: Tue Jul 10 17:08:01 2012
New Revision: 160023

URL: http://llvm.org/viewvc/llvm-project?rev=160023&view=rev
Log:
[analyzer] Construct stack variables directly in their VarDecl.

Also contains a number of tweaks to inlining that are necessary
for constructors and destructors. (I have this enabled on a private
branch, but it is very much unstable.)

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=160023&r1=160022&r2=160023&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Tue Jul 10 17:08:01 2012
@@ -375,6 +375,7 @@
 
     const FieldDecl *FD = BMI->getAnyMember();
 
+    // FIXME: This does not work for initializers that call constructors.
     SVal FieldLoc = state->getLValue(FD, thisVal);
     SVal InitVal = state->getSVal(BMI->getInit(), Pred->getLocationContext());
     state = state->bindLoc(FieldLoc, InitVal);
@@ -458,7 +459,27 @@
                                       ExplodedNode *Pred,
                                       ExplodedNodeSet &Dst) {}
 
-void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, 
+static const VarDecl *findDirectConstruction(const DeclStmt *DS,
+                                             const Expr *Init) {
+  for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
+       I != E; ++I) {
+    const VarDecl *Var = dyn_cast<VarDecl>(*I);
+    if (!Var)
+      continue;
+    if (Var->getInit() != Init)
+      continue;
+    // FIXME: We need to decide how copy-elision should work here.
+    if (!Var->isDirectInit())
+      break;
+    if (Var->getType()->isReferenceType())
+      break;
+    return Var;
+  }
+
+  return 0;
+}
+
+void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
                        ExplodedNodeSet &DstTop) {
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                 S->getLocStart(),
@@ -724,10 +745,18 @@
     case Stmt::CXXTemporaryObjectExprClass:
     case Stmt::CXXConstructExprClass: {
       const CXXConstructExpr *C = cast<CXXConstructExpr>(S);
-      // For block-level CXXConstructExpr, we don't have a destination region.
-      // Let VisitCXXConstructExpr() create one.
+      const MemRegion *Target = 0;
+
+      const LocationContext *LCtx = Pred->getLocationContext();
+      const ParentMap &PM = LCtx->getParentMap();
+      if (const DeclStmt *DS = dyn_cast_or_null<DeclStmt>(PM.getParent(C)))
+        if (const VarDecl *Var = findDirectConstruction(DS, C))
+          Target = Pred->getState()->getLValue(Var, LCtx).getAsRegion();
+      // If we don't have a destination region, VisitCXXConstructExpr() will
+      // create one.
+      
       Bldr.takeNodes(Pred);
-      VisitCXXConstructExpr(C, 0, Pred, Dst);
+      VisitCXXConstructExpr(C, Target, Pred, Dst);
       Bldr.addNodes(Dst);
       break;
     }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=160023&r1=160022&r2=160023&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Tue Jul 10 17:08:01 2012
@@ -454,30 +454,37 @@
     
     if (const Expr *InitEx = VD->getInit()) {
       SVal InitVal = state->getSVal(InitEx, Pred->getLocationContext());
-      
-      // We bound the temp obj region to the CXXConstructExpr. Now recover
-      // the lazy compound value when the variable is not a reference.
-      if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() && 
-          !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){
-        InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion());
-        assert(isa<nonloc::LazyCompoundVal>(InitVal));
-      }
-      
-      // Recover some path-sensitivity if a scalar value evaluated to
-      // UnknownVal.
-      if (InitVal.isUnknown()) {
-	QualType Ty = InitEx->getType();
-	if (InitEx->isGLValue()) {
-	  Ty = getContext().getPointerType(Ty);
-	}
 
-        InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx, LC, Ty,
-                                 currentBuilderContext->getCurrentBlockCount());
+      if (InitVal == state->getLValue(VD, LC)) {
+        // We constructed the object directly in the variable.
+        // No need to bind anything.
+        B.generateNode(DS, N, state);
+      } else {
+        // We bound the temp obj region to the CXXConstructExpr. Now recover
+        // the lazy compound value when the variable is not a reference.
+        // FIXME: This is probably not correct for most constructors!
+        if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() && 
+            !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){
+          InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion());
+          assert(isa<nonloc::LazyCompoundVal>(InitVal));
+        }
+        
+        // Recover some path-sensitivity if a scalar value evaluated to
+        // UnknownVal.
+        if (InitVal.isUnknown()) {
+          QualType Ty = InitEx->getType();
+          if (InitEx->isGLValue()) {
+            Ty = getContext().getPointerType(Ty);
+          }
+
+          InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx, LC, Ty,
+                                   currentBuilderContext->getCurrentBlockCount());
+        }
+        B.takeNodes(N);
+        ExplodedNodeSet Dst2;
+        evalBind(Dst2, DS, N, state->getLValue(VD, LC), InitVal, true);
+        B.addNodes(Dst2);
       }
-      B.takeNodes(N);
-      ExplodedNodeSet Dst2;
-      evalBind(Dst2, DS, N, state->getLValue(VD, LC), InitVal, true);
-      B.addNodes(Dst2);
     }
     else {
       B.generateNode(DS, N,state->bindDeclWithNoInit(state->getRegion(VD, LC)));

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=160023&r1=160022&r2=160023&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Tue Jul 10 17:08:01 2012
@@ -137,7 +137,7 @@
     if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
       const LocationContext *LCtx = CEBNode->getLocationContext();
       SVal V = state->getSVal(RS, LCtx);
-      state = state->BindExpr(CE, callerCtx, V);
+      state = state->BindExpr(CE, calleeCtx->getParent(), V);
     }
 
     // Bind the constructed object value to CXXConstructExpr.
@@ -147,18 +147,10 @@
       SVal ThisV = state->getSVal(This);
 
       // Always bind the region to the CXXConstructExpr.
-      state = state->BindExpr(CCE, CEBNode->getLocationContext(), ThisV);
+      state = state->BindExpr(CCE, calleeCtx->getParent(), ThisV);
     }
   }
 
-  static SimpleProgramPointTag retValBindTag("ExprEngine : Bind Return Value");
-  PostStmt Loc(LastSt, calleeCtx, &retValBindTag);
-  bool isNew;
-  ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);
-  BindedRetNode->addPredecessor(CEBNode, G);
-  if (!isNew)
-    return;
-
   // Step 3: BindedRetNode -> CleanedNodes
   // If we can find a statement and a block in the inlined function, run remove
   // dead bindings before returning from the call. This is important to ensure
@@ -166,6 +158,14 @@
   // they occurred.
   ExplodedNodeSet CleanedNodes;
   if (LastSt && Blk) {
+    static SimpleProgramPointTag retValBind("ExprEngine : Bind Return Value");
+    PostStmt Loc(LastSt, calleeCtx, &retValBind);
+    bool isNew;
+    ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);
+    BindedRetNode->addPredecessor(CEBNode, G);
+    if (!isNew)
+      return;
+
     NodeBuilderContext Ctx(getCoreEngine(), Blk, BindedRetNode);
     currentBuilderContext = &Ctx;
     // Here, we call the Symbol Reaper with 0 statement and caller location
@@ -186,7 +186,8 @@
     // CleanedNodes -> CEENode
     CallExitEnd Loc(calleeCtx, callerCtx);
     bool isNew;
-    ExplodedNode *CEENode = G.getNode(Loc, (*I)->getState(), false, &isNew);
+    ProgramStateRef CEEState = (*I == CEBNode) ? state : (*I)->getState();
+    ExplodedNode *CEENode = G.getNode(Loc, CEEState, false, &isNew);
     CEENode->addPredecessor(*I, G);
     if (!isNew)
       return;
@@ -201,8 +202,12 @@
     SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex());
 
     // FIXME: This needs to call PostCall.
+    // FIXME: If/when we inline Objective-C messages, this also needs to call
+    // PostObjCMessage.
     if (CE)
       getCheckerManager().runCheckersForPostStmt(Dst, CEENode, CE, *this, true);
+    else
+      Dst.Add(CEENode);
 
     // Enqueue the next element in the block.
     for (ExplodedNodeSet::iterator PSI = Dst.begin(), PSE = Dst.end();

Modified: cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp?rev=160023&r1=160022&r2=160023&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp Tue Jul 10 17:08:01 2012
@@ -47,7 +47,7 @@
   // FIXME: We will eventually want to generalize this to handle other non-
   // parameter arguments besides 'this' (such as 'self' for ObjC methods).
   SVal ThisVal = Call.getCXXThisVal();
-  if (!ThisVal.isUndef()) {
+  if (isa<DefinedSVal>(ThisVal)) {
     const CXXMethodDecl *MD = cast<CXXMethodDecl>(Call.getDecl());
     loc::MemRegionVal ThisRegion = svalBuilder.getCXXThis(MD, LCtx);
     Store = Bind(Store.getStore(), ThisRegion, ThisVal);





More information about the cfe-commits mailing list