[cfe-commits] r147904 - in /cfe/trunk: lib/StaticAnalyzer/Core/Environment.cpp lib/StaticAnalyzer/Core/ExplodedGraph.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp test/Analysis/inline.c

Ted Kremenek kremenek at apple.com
Tue Jan 10 17:06:27 PST 2012


Author: kremenek
Date: Tue Jan 10 19:06:27 2012
New Revision: 147904

URL: http://llvm.org/viewvc/llvm-project?rev=147904&view=rev
Log:
Remove '#if 0' from ExprEngine::InlineCall(), and start fresh by wiring up inlining for straight C calls.
My hope is to reimplement this from first principles based on the simplifications of removing unneeded node builders
and re-evaluating how C++ calls are handled in the CFG.  The hope is to turn inlining "on-by-default" as soon as possible
with a core set of things working well, and then expand over time.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
    cfe/trunk/test/Analysis/inline.c

Modified: cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp?rev=147904&r1=147903&r2=147904&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp Tue Jan 10 19:06:27 2012
@@ -90,6 +90,14 @@
         continue;
       case Stmt::ObjCPropertyRefExprClass:
         return loc::ObjCPropRef(cast<ObjCPropertyRefExpr>(E));
+      case Stmt::ReturnStmtClass: {
+        const ReturnStmt *RS = cast<ReturnStmt>(E);
+        if (const Expr *RE = RS->getRetValue()) {
+          E = RE;
+          continue;
+        }
+        return UndefinedVal();        
+      }
         
       // Handle all other Stmt* using a lookup.
       default:

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp?rev=147904&r1=147903&r2=147904&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp Tue Jan 10 19:06:27 2012
@@ -91,7 +91,8 @@
 
     // Condition 3.
     ProgramPoint progPoint = node->getLocation();
-    if (!isa<PostStmt>(progPoint))
+    if (!isa<PostStmt>(progPoint) ||
+        (isa<CallEnter>(progPoint) || isa<CallExit>(progPoint)))
       continue;
     // Condition 4.
     PostStmt ps = cast<PostStmt>(progPoint);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=147904&r1=147903&r2=147904&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Tue Jan 10 19:06:27 2012
@@ -1569,83 +1569,6 @@
   BldrTop.addNodes(Tmp);
 }
 
-bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, 
-                              ExplodedNode *Pred) {
-  return false;
-  
-  // Inlining isn't correct right now because we:
-  // (a) don't generate CallExit nodes.
-  // (b) we need a way to postpone doing post-visits of CallExprs until
-  // the CallExit.  This means we need CallExits for the non-inline
-  // cases as well.
-  
-#if 0
-  const ProgramState *state = Pred->getState();
-  const Expr *Callee = CE->getCallee();
-  SVal L = state->getSVal(Callee);
-  
-  const FunctionDecl *FD = L.getAsFunctionDecl();
-  if (!FD)
-    return false;
-
-  // Specially handle CXXMethods.
-  const CXXMethodDecl *methodDecl = 0;
-  
-  switch (CE->getStmtClass()) {
-    default: break;
-    case Stmt::CXXOperatorCallExprClass: {
-      const CXXOperatorCallExpr *opCall = cast<CXXOperatorCallExpr>(CE);
-      methodDecl = 
-        dyn_cast_or_null<CXXMethodDecl>(opCall->getCalleeDecl());
-      break;
-    }
-    case Stmt::CXXMemberCallExprClass: {
-      const CXXMemberCallExpr *memberCall = cast<CXXMemberCallExpr>(CE);
-      const MemberExpr *memberExpr = 
-        cast<MemberExpr>(memberCall->getCallee()->IgnoreParens());
-      methodDecl = cast<CXXMethodDecl>(memberExpr->getMemberDecl());
-      break;
-    }
-  }
-      
-  
-  
-  
-  // Check if the function definition is in the same translation unit.
-  if (FD->hasBody(FD)) {
-    const StackFrameContext *stackFrame = 
-      AMgr.getStackFrame(AMgr.getAnalysisDeclContext(FD), 
-                         Pred->getLocationContext(),
-                         CE, currentBuilderContext->getBlock(),
-                         currentStmtIdx);
-    // Now we have the definition of the callee, create a CallEnter node.
-    CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
-
-    ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
-    Dst.Add(N);
-    return true;
-  }
-
-  // Check if we can find the function definition in other translation units.
-  if (AMgr.hasIndexer()) {
-    AnalysisDeclContext *C = AMgr.getAnalysisDeclContextInAnotherTU(FD);
-    if (C == 0)
-      return false;
-    const StackFrameContext *stackFrame = 
-      AMgr.getStackFrame(C, Pred->getLocationContext(),
-                         CE, currentBuilderContext->getBlock(), currentStmtIdx);
-    CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
-    ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
-    Dst.Add(N);
-    return true;
-  }
-  
-  // Generate the CallExit node.
-
-  return false;
-#endif
-}
-
 std::pair<const ProgramPointTag *, const ProgramPointTag*>
 ExprEngine::getEagerlyAssumeTags() {
   static SimpleProgramPointTag

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=147904&r1=147903&r2=147904&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Tue Jan 10 19:06:27 2012
@@ -14,20 +14,12 @@
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "clang/Analysis/Support/SaveAndRestore.h"
 #include "clang/AST/DeclCXX.h"
 
 using namespace clang;
 using namespace ento;
 
-namespace {
-  // Trait class for recording returned expression in the state.
-  struct ReturnExpr {
-    static int TagInt;
-    typedef const Stmt *data_type;
-  };
-  int ReturnExpr::TagInt; 
-}
-
 void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
   // Get the entry block in the CFG of the callee.
   const StackFrameContext *SFC = CE.getCalleeContext();
@@ -56,20 +48,36 @@
     Engine.getWorkList()->enqueue(Node);
 }
 
+static const ReturnStmt *getReturnStmt(const ExplodedNode *Node) {
+  while (Node) {
+    const ProgramPoint &PP = Node->getLocation();
+    // Skip any BlockEdges.
+    if (isa<BlockEdge>(PP) || isa<CallExit>(PP)) {
+      assert(Node->pred_size() == 1);
+      Node = *Node->pred_begin();
+      continue;
+    } 
+    if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP)) {
+      const Stmt *S = SP->getStmt();
+      return dyn_cast<ReturnStmt>(S);
+    }
+    break;
+  }
+  return 0;
+}
+
 void ExprEngine::processCallExit(ExplodedNode *Pred) {
   const ProgramState *state = Pred->getState();
   const StackFrameContext *calleeCtx = 
     Pred->getLocationContext()->getCurrentStackFrame();
+  const LocationContext *callerCtx = calleeCtx->getParent();
   const Stmt *CE = calleeCtx->getCallSite();
   
   // If the callee returns an expression, bind its value to CallExpr.
-  const Stmt *ReturnedExpr = state->get<ReturnExpr>();
-  if (ReturnedExpr) {
+  if (const ReturnStmt *RS = getReturnStmt(Pred)) {
     const LocationContext *LCtx = Pred->getLocationContext();
-    SVal RetVal = state->getSVal(ReturnedExpr, LCtx);
-    state = state->BindExpr(CE, LCtx, RetVal);
-    // Clear the return expr GDM.
-    state = state->remove<ReturnExpr>();
+    SVal V = state->getSVal(RS, LCtx);
+    state = state->BindExpr(CE, callerCtx, V);
   }
   
   // Bind the constructed object value to CXXConstructExpr.
@@ -82,7 +90,8 @@
     state = state->BindExpr(CCE, Pred->getLocationContext(), ThisV);
   }
   
-  PostStmt Loc(CE, calleeCtx->getParent());
+  static SimpleProgramPointTag returnTag("ExprEngine : Call Return");
+  PostStmt Loc(CE, callerCtx, &returnTag);
   bool isNew;
   ExplodedNode *N = G.getNode(Loc, state, false, &isNew);
   N->addPredecessor(Pred, G);
@@ -91,6 +100,11 @@
   
   // Perform the post-condition check of the CallExpr.
   ExplodedNodeSet Dst;
+  NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), N);
+  SaveAndRestore<const NodeBuilderContext*> NBCSave(currentBuilderContext,
+                                                    &Ctx);
+  SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex());
+  
   getCheckerManager().runCheckersForPostStmt(Dst, N, CE, *this);
   
   // Enqueue the next element in the block.
@@ -101,6 +115,42 @@
   }
 }
 
+bool ExprEngine::InlineCall(ExplodedNodeSet &Dst,
+                            const CallExpr *CE, 
+                            ExplodedNode *Pred) {
+  const ProgramState *state = Pred->getState();
+  const Expr *Callee = CE->getCallee();
+  const FunctionDecl *FD =
+  state->getSVal(Callee, Pred->getLocationContext()).getAsFunctionDecl();
+  if (!FD || !FD->hasBody(FD))
+    return false;
+  
+  switch (CE->getStmtClass()) {
+    default:
+      // FIXME: Handle C++.
+      break;
+    case Stmt::CallExprClass: {
+      // Construct a new stack frame for the callee.
+      AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(FD);
+      const StackFrameContext *CallerSFC =
+      Pred->getLocationContext()->getCurrentStackFrame();
+      const StackFrameContext *CalleeSFC =
+      CalleeADC->getStackFrame(CallerSFC, CE,
+                               currentBuilderContext->getBlock(),
+                               currentStmtIdx);
+      
+      CallEnter Loc(CE, CalleeSFC, Pred->getLocationContext());
+      bool isNew;
+      ExplodedNode *N = G.getNode(Loc, state, false, &isNew);
+      N->addPredecessor(Pred, G);
+      if (isNew)
+        Engine.getWorkList()->enqueue(N);
+      return true;
+    }
+  }
+  return false;
+}
+
 static bool isPointerToConst(const ParmVarDecl *ParamDecl) {
   QualType PointeeTy = ParamDecl->getOriginalType()->getPointeeType();
   if (PointeeTy != QualType() && PointeeTy.isConstQualified() &&
@@ -315,27 +365,19 @@
 
 void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) {
-  ExplodedNodeSet Src;
-  {
-    StmtNodeBuilder Bldr(Pred, Src, *currentBuilderContext);
-    if (const Expr *RetE = RS->getRetValue()) {
-      // Record the returned expression in the state. It will be used in
-      // processCallExit to bind the return value to the call expr.
-      {
-        static SimpleProgramPointTag tag("ExprEngine: ReturnStmt");
-        const ProgramState *state = Pred->getState();
-        state = state->set<ReturnExpr>(RetE);
-        Pred = Bldr.generateNode(RetE, Pred, state, false, &tag);
-      }
-      // We may get a NULL Pred because we generated a cached node.
-      if (Pred) {
-        Bldr.takeNodes(Pred);
-        ExplodedNodeSet Tmp;
-        Visit(RetE, Pred, Tmp);
-        Bldr.addNodes(Tmp);
-      }
+  
+  ExplodedNodeSet dstPreVisit;
+  getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *this);
+
+  StmtNodeBuilder B(dstPreVisit, Dst, *currentBuilderContext);
+  
+  if (RS->getRetValue()) {
+    for (ExplodedNodeSet::iterator it = dstPreVisit.begin(),
+                                  ei = dstPreVisit.end(); it != ei; ++it) {
+      B.generateNode(RS, *it, (*it)->getState());
     }
   }
-  
-  getCheckerManager().runCheckersForPreStmt(Dst, Src, RS, *this);
+  else {
+    B.takeNodes(dstPreVisit);
+  }
 }

Modified: cfe/trunk/test/Analysis/inline.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inline.c?rev=147904&r1=147903&r2=147904&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/inline.c (original)
+++ cfe/trunk/test/Analysis/inline.c Tue Jan 10 19:06:27 2012
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-inline-call -analyzer-store region -verify %s
-// XFAIL: *
 
 int test1_f1() {
   int y = 1;





More information about the cfe-commits mailing list