aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp3
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp3
-rw-r--r--lib/StaticAnalyzer/Core/Calls.cpp19
-rw-r--r--lib/StaticAnalyzer/Core/CheckerManager.cpp10
-rw-r--r--lib/StaticAnalyzer/Core/ExplodedGraph.cpp5
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp49
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp22
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);