diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 3 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 3 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/Calls.cpp | 19 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CheckerManager.cpp | 10 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExplodedGraph.cpp | 5 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 49 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp | 22 |
7 files changed, 75 insertions, 36 deletions
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 41cd80e01e..8c2e5295ee 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -1535,6 +1535,9 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, if (!S) return 0; + // FIXME: We will eventually need to handle non-statement-based events + // (__attribute__((cleanup))). + // Find out if this is an interesting point and what is the kind. if (Mode == Normal) { if (isAllocated(RS, RSPrev, S)) { diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index d0618d0ddd..32f7706bd9 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -1928,7 +1928,8 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) { - + // FIXME: We will eventually need to handle non-statement-based events + // (__attribute__((cleanup))). if (!isa<StmtPoint>(N->getLocation())) return NULL; diff --git a/lib/StaticAnalyzer/Core/Calls.cpp b/lib/StaticAnalyzer/Core/Calls.cpp index 24c5ab12ab..7b86d44276 100644 --- a/lib/StaticAnalyzer/Core/Calls.cpp +++ b/lib/StaticAnalyzer/Core/Calls.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h" +#include "clang/Analysis/ProgramPoint.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" @@ -195,6 +196,24 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount, BlockCount, LCtx, /*Symbols=*/0, this); } +ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit, + const ProgramPointTag *Tag) const { + if (const Expr *E = getOriginExpr()) { + if (IsPreVisit) + return PreStmt(E, LCtx, Tag); + return PostStmt(E, LCtx, Tag); + } + + const Decl *D = getDecl(); + assert(D && "Cannot get a program point without a statement or decl"); + + SourceLocation Loc = getSourceRange().getBegin(); + if (IsPreVisit) + return PreImplicitCall(D, Loc, LCtx, Tag); + return PostImplicitCall(D, Loc, LCtx, Tag); +} + + bool CallEvent::mayBeInlined(const Stmt *S) { return isa<CallExpr>(S); } diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp index 39a3621826..d0d212130a 100644 --- a/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -237,15 +237,7 @@ namespace { void runChecker(CheckerManager::CheckCallFunc checkFn, NodeBuilder &Bldr, ExplodedNode *Pred) { - // FIXME: This will be wrong as soon as we handle any calls without - // associated statements. - ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind - : ProgramPoint::PostStmtKind; - assert(Call.getOriginExpr() && "Calls without stmts not yet handled"); - const ProgramPoint &L = - ProgramPoint::getProgramPoint(Call.getOriginExpr(), - K, Pred->getLocationContext(), - checkFn.Checker); + const ProgramPoint &L = Call.getProgramPoint(IsPreVisit, checkFn.Checker); CheckerContext C(Bldr, Eng, Pred, L); checkFn(Call, C); diff --git a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp index aeb47a1316..5109912628 100644 --- a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp +++ b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp @@ -71,6 +71,7 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) { // (8) The PostStmt is for a non-consumed Stmt or Expr. // (9) The successor is not a CallExpr StmtPoint (so that we would be able to // find it when retrying a call with no inlining). + // FIXME: It may be safe to reclaim PreCall and PostCall nodes as well. // Conditions 1 and 2. if (node->pred_size() != 1 || node->succ_size() != 1) @@ -86,9 +87,7 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) { // Condition 3. ProgramPoint progPoint = node->getLocation(); - if (!isa<PostStmt>(progPoint) || - (isa<CallEnter>(progPoint) || - isa<CallExitBegin>(progPoint) || isa<CallExitEnd>(progPoint))) + if (!isa<PostStmt>(progPoint)) return false; // Condition 4. diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 63aa28fa0a..a9387694ee 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -984,6 +984,7 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N, const StackFrameContext *CallerSF = CalleeSF->getParent()->getCurrentStackFrame(); assert(CalleeSF && CallerSF); ExplodedNode *BeforeProcessingCall = 0; + const Stmt *CE = CalleeSF->getCallSite(); // Find the first node before we started processing the call expression. while (N) { @@ -995,11 +996,13 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N, if (L.getLocationContext()->getCurrentStackFrame() != CallerSF) continue; // We reached the caller. Find the node right before we started - // processing the CallExpr. + // processing the call. if (L.isPurgeKind()) continue; + if (isa<PreImplicitCall>(&L)) + continue; if (const StmtPoint *SP = dyn_cast<StmtPoint>(&L)) - if (SP->getStmt() == CalleeSF->getCallSite()) + if (SP->getStmt() == CE) continue; break; } @@ -1010,7 +1013,7 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N, // TODO: Clean up the unneeded nodes. // Build an Epsilon node from which we will restart the analyzes. - const Stmt *CE = CalleeSF->getCallSite(); + // Note that CE is permitted to be NULL! ProgramPoint NewNodeLoc = EpsilonPoint(BeforeProcessingCall->getLocationContext(), CE); // Add the special flag to GDM to signal retrying with no inlining. @@ -1872,6 +1875,16 @@ struct DOTGraphTraits<ExplodedNode*> : return ""; } + static void printLocation(llvm::raw_ostream &Out, SourceLocation SLoc) { + if (SLoc.isFileID()) { + Out << "\\lline=" + << GraphPrintSourceManager->getExpansionLineNumber(SLoc) + << " col=" + << GraphPrintSourceManager->getExpansionColumnNumber(SLoc) + << "\\l"; + } + } + static std::string getNodeLabel(const ExplodedNode *N, void*){ std::string sbuf; @@ -1921,22 +1934,34 @@ struct DOTGraphTraits<ExplodedNode*> : Out << "Epsilon Point"; break; + case ProgramPoint::PreImplicitCallKind: { + ImplicitCallPoint *PC = cast<ImplicitCallPoint>(&Loc); + Out << "PreCall: "; + + // FIXME: Get proper printing options. + PC->getDecl()->print(Out, LangOptions()); + printLocation(Out, PC->getLocation()); + break; + } + + case ProgramPoint::PostImplicitCallKind: { + ImplicitCallPoint *PC = cast<ImplicitCallPoint>(&Loc); + Out << "PostCall: "; + + // FIXME: Get proper printing options. + PC->getDecl()->print(Out, LangOptions()); + printLocation(Out, PC->getLocation()); + break; + } + default: { if (StmtPoint *L = dyn_cast<StmtPoint>(&Loc)) { const Stmt *S = L->getStmt(); - SourceLocation SLoc = S->getLocStart(); Out << S->getStmtClassName() << ' ' << (void*) S << ' '; LangOptions LO; // FIXME. S->printPretty(Out, 0, PrintingPolicy(LO)); - - if (SLoc.isFileID()) { - Out << "\\lline=" - << GraphPrintSourceManager->getExpansionLineNumber(SLoc) - << " col=" - << GraphPrintSourceManager->getExpansionColumnNumber(SLoc) - << "\\l"; - } + printLocation(Out, S->getLocStart()); if (isa<PreStmt>(Loc)) Out << "\\lPreStmt\\l;"; diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 6fb41930d3..bf55ceb5fd 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -346,11 +346,11 @@ static ProgramStateRef getInlineFailedState(ExplodedNode *&N, void *ReplayState = N->getState()->get<ReplayWithoutInlining>(); if (!ReplayState) return 0; - const Stmt *ReplayCallE = reinterpret_cast<const Stmt *>(ReplayState); - if (CallE == ReplayCallE) { - return N->getState()->remove<ReplayWithoutInlining>(); - } - return 0; + + assert(ReplayState == (const void*)CallE && "Backtracked to the wrong call."); + (void)CallE; + + return N->getState()->remove<ReplayWithoutInlining>(); } void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, @@ -421,13 +421,13 @@ void ExprEngine::evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, void ExprEngine::defaultEvalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call) { // Try to inline the call. - ProgramStateRef state = 0; + // The origin expression here is just used as a kind of checksum; + // for CallEvents that do not have origin expressions, this should still be + // safe. const Expr *E = Call.getOriginExpr(); - if (E) { - state = getInlineFailedState(Pred, E); - if (state == 0 && inlineCall(Dst, Call, Pred)) - return; - } + ProgramStateRef state = getInlineFailedState(Pred, E); + if (state == 0 && inlineCall(Dst, Call, Pred)) + return; // If we can't inline it, handle the return value and invalidate the regions. StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); |