[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