diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-07-10 22:07:52 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-07-10 22:07:52 +0000 |
commit | 852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5 (patch) | |
tree | 479d6107f7b9d49e36af6eecacef6f06004202b2 /lib/StaticAnalyzer/Core | |
parent | 8d276d38c258dfc572586daf6c0e8f8fce249c0e (diff) |
[analyzer] Make CallEnter, CallExitBegin, and CallExitEnd not be StmtPoints
These ProgramPoints are used in inlining calls,
and not all calls have associated statements anymore.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160021 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporter.cpp | 46 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CoreEngine.cpp | 6 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp | 36 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 10 |
5 files changed, 64 insertions, 36 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 14fcb179cc..08588f60ab 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -48,6 +48,10 @@ static inline const Stmt *GetStmt(const ProgramPoint &P) { return SP->getStmt(); else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) return BE->getSrc()->getTerminator(); + else if (const CallEnter *CE = dyn_cast<CallEnter>(&P)) + return CE->getCallExpr(); + else if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&P)) + return CEE->getCalleeContext()->getCallSite(); return 0; } @@ -1102,11 +1106,10 @@ static void reversePropagateInterestingSymbols(BugReport &R, const LocationContext *CalleeCtx, const LocationContext *CallerCtx) { - // FIXME: Handle CXXConstructExpr. - // FIXME: Handle calls to blocks. + // FIXME: Handle non-CallExpr-based CallEvents. const StackFrameContext *Callee = CalleeCtx->getCurrentStackFrame(); const Stmt *CallSite = Callee->getCallSite(); - if (const CallExpr *CE = dyn_cast<CallExpr>(CallSite)) { + if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) { FunctionDecl::param_const_iterator PI = FD->param_begin(), PE = FD->param_end(); @@ -1149,17 +1152,24 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, if (const CallExitEnd *CE = dyn_cast<CallExitEnd>(&P)) { const StackFrameContext *LCtx = - CE->getLocationContext()->getCurrentStackFrame(); - PathDiagnosticLocation Loc(CE->getStmt(), - PDB.getSourceManager(), - LCtx); - EB.addEdge(Loc, true); - EB.flushLocations(); - PathDiagnosticCallPiece *C = - PathDiagnosticCallPiece::construct(N, *CE, SM); - PD.getActivePath().push_front(C); - PD.pushActivePath(&C->path); - CallStack.push_back(StackDiagPair(C, N)); + CE->getLocationContext()->getCurrentStackFrame(); + // FIXME: This needs to handle implicit calls. + if (const Stmt *S = CE->getCalleeContext()->getCallSite()) { + if (const Expr *Ex = dyn_cast<Expr>(S)) + reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, + N->getState().getPtr(), Ex, + N->getLocationContext()); + PathDiagnosticLocation Loc(S, + PDB.getSourceManager(), + LCtx); + EB.addEdge(Loc, true); + EB.flushLocations(); + PathDiagnosticCallPiece *C = + PathDiagnosticCallPiece::construct(N, *CE, SM); + PD.getActivePath().push_front(C); + PD.pushActivePath(&C->path); + CallStack.push_back(StackDiagPair(C, N)); + } break; } @@ -1191,8 +1201,12 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, const Decl * Caller = CE->getLocationContext()->getDecl(); C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); } - C->setCallee(*CE, SM); - EB.addContext(CE->getCallExpr()); + + // FIXME: We still need a location for implicit calls. + if (CE->getCallExpr()) { + C->setCallee(*CE, SM); + EB.addContext(CE->getCallExpr()); + } if (!CallStack.empty()) { assert(CallStack.back().first == C); diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp index 689f05714f..d7a4baa0a8 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -265,7 +265,8 @@ void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc, } default: assert(isa<PostStmt>(Loc) || - isa<PostInitializer>(Loc)); + isa<PostInitializer>(Loc) || + isa<CallExitEnd>(Loc)); HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred); break; } @@ -539,10 +540,9 @@ ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N) { // Create a CallExitBegin node and enqueue it. const StackFrameContext *LocCtx = cast<StackFrameContext>(N->getLocationContext()); - const Stmt *CE = LocCtx->getCallSite(); // Use the the callee location context. - CallExitBegin Loc(CE, LocCtx); + CallExitBegin Loc(LocCtx); bool isNew; ExplodedNode *Node = G->getNode(Loc, N->getState(), false, &isNew); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index a9387694ee..5e0a338084 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1001,6 +1001,8 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N, continue; if (isa<PreImplicitCall>(&L)) continue; + if (isa<CallEnter>(&L)) + continue; if (const StmtPoint *SP = dyn_cast<StmtPoint>(&L)) if (SP->getStmt() == CE) continue; diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index cce55ea023..92497dbb1e 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -134,23 +134,25 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) { const CFGBlock *Blk = 0; llvm::tie(LastSt, Blk) = getLastStmt(CEBNode); - // Step 2: generate node with binded return value: CEBNode -> BindedRetNode. + // Step 2: generate node with bound return value: CEBNode -> BindedRetNode. // If the callee returns an expression, bind its value to CallExpr. - 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); - } + if (CE) { + 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); + } - // Bind the constructed object value to CXXConstructExpr. - if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { - loc::MemRegionVal This = - svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx); - SVal ThisV = state->getSVal(This); + // Bind the constructed object value to CXXConstructExpr. + if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { + loc::MemRegionVal This = + svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx); + SVal ThisV = state->getSVal(This); - // Always bind the region to the CXXConstructExpr. - state = state->BindExpr(CCE, CEBNode->getLocationContext(), ThisV); + // Always bind the region to the CXXConstructExpr. + state = state->BindExpr(CCE, CEBNode->getLocationContext(), ThisV); + } } static SimpleProgramPointTag retValBindTag("ExprEngine : Bind Return Value"); @@ -186,7 +188,7 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) { // Step 4: Generate the CallExit and leave the callee's context. // CleanedNodes -> CEENode - CallExitEnd Loc(CE, callerCtx); + CallExitEnd Loc(calleeCtx, callerCtx); bool isNew; ExplodedNode *CEENode = G.getNode(Loc, (*I)->getState(), false, &isNew); CEENode->addPredecessor(*I, G); @@ -202,7 +204,9 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) { &Ctx); SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex()); - getCheckerManager().runCheckersForPostStmt(Dst, CEENode, CE, *this, true); + // FIXME: This needs to call PostCall. + if (CE) + getCheckerManager().runCheckersForPostStmt(Dst, CEENode, CE, *this, true); // Enqueue the next element in the block. for (ExplodedNodeSet::iterator PSI = Dst.begin(), PSE = Dst.end(); @@ -322,8 +326,8 @@ bool ExprEngine::inlineCall(ExplodedNodeSet &Dst, if (!ParentOfCallee) ParentOfCallee = CallerSFC; + // This may be NULL, but that's fine. const Expr *CallE = Call.getOriginExpr(); - assert(CallE && "It is not yet possible to have calls without statements"); // Construct a new stack frame for the callee. AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D); diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index a1e662f129..bfb8bf6432 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -339,6 +339,9 @@ PathDiagnosticLocation else if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) { S = PS->getStmt(); } + else if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&P)) { + S = CEE->getCalleeContext()->getCallSite(); + } return PathDiagnosticLocation(S, SMng, P.getLocationContext()); } @@ -501,6 +504,10 @@ static PathDiagnosticLocation getLastStmtLoc(const ExplodedNode *N, ProgramPoint PP = N->getLocation(); if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP)) return PathDiagnosticLocation(SP->getStmt(), SM, PP.getLocationContext()); + // FIXME: Handle implicit calls. + if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&PP)) + if (const Stmt *CallSite = CEE->getCalleeContext()->getCallSite()) + return PathDiagnosticLocation(CallSite, SM, PP.getLocationContext()); if (N->pred_empty()) break; N = *N->pred_begin(); @@ -670,7 +677,8 @@ std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){ const CallExitEnd *CExit = dyn_cast<CallExitEnd>(&P); assert(CExit && "Stack Hints should be constructed at CallExitEnd points."); - const CallExpr *CE = dyn_cast_or_null<CallExpr>(CExit->getStmt()); + const Stmt *CallSite = CExit->getCalleeContext()->getCallSite(); + const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite); if (!CE) return ""; |