diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 |
| commit | 56d91b49b13fe55c918afbda19f6165b5fbff87a (patch) | |
| tree | 9abb1a658a297776086f4e0dfa6ca533de02104e /lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | |
| parent | 41e20f564abdb05101d6b2b29c59459a966c22cc (diff) | |
Notes
Diffstat (limited to 'lib/StaticAnalyzer/Core/BugReporterVisitors.cpp')
| -rw-r--r-- | lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 86 |
1 files changed, 53 insertions, 33 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 65324868518e0..46aa9e2b9123b 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -34,15 +34,23 @@ const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) { // a[0], p->f, *p const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); - if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) { - if (U->getOpcode() == UO_Deref) - return U->getSubExpr()->IgnoreParenCasts(); - } - else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) { - return ME->getBase()->IgnoreParenCasts(); - } - else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) { - return AE->getBase(); + while (true) { + if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) { + assert(B->isAssignmentOp()); + S = B->getLHS()->IgnoreParenCasts(); + continue; + } + else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) { + if (U->getOpcode() == UO_Deref) + return U->getSubExpr()->IgnoreParenCasts(); + } + else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) { + return ME->getBase()->IgnoreParenCasts(); + } + else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) { + return AE->getBase(); + } + break; } return NULL; @@ -55,14 +63,6 @@ const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) { return NULL; } -const Stmt *bugreporter::GetCalleeExpr(const ExplodedNode *N) { - // Callee is checked as a PreVisit to the CallExpr. - const Stmt *S = N->getLocationAs<PreStmt>()->getStmt(); - if (const CallExpr *CE = dyn_cast<CallExpr>(S)) - return CE->getCallee(); - return NULL; -} - const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) { const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) @@ -119,10 +119,16 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N, return NULL; if (!StoreSite) { - const ExplodedNode *Node = N, *Last = NULL; + // Make sure the region is actually bound to value V here. + // This is necessary because the region may not actually be live at the + // report's error node. + if (N->getState()->getSVal(R) != V) + return NULL; - for ( ; Node ; Node = Node->getFirstPred()) { + const ExplodedNode *Node = N, *Last = N; + // Now look for the store of V. + for ( ; Node ; Node = Node->getFirstPred()) { if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { if (const PostStmt *P = Node->getLocationAs<PostStmt>()) if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) @@ -137,9 +143,11 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N, // looking for store sites. if (Node->getState()->getSVal(R) != V) break; + + Last = Node; } - if (!Node || !Last) { + if (!Node) { satisfied = true; return NULL; } @@ -189,6 +197,9 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N, os << "declared without an initial value"; } } + else { + os << "initialized here"; + } } } @@ -215,7 +226,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N, << " is assigned to "; } else - return NULL; + os << "Value assigned to "; if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { os << '\'' << *VR->getDecl() << '\''; @@ -285,12 +296,11 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, return NULL; } -BugReporterVisitor * -bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N, - const Stmt *S, - BugReport *report) { +void bugreporter::addTrackNullOrUndefValueVisitor(const ExplodedNode *N, + const Stmt *S, + BugReport *report) { if (!S || !N) - return 0; + return; ProgramStateManager &StateMgr = N->getState()->getStateManager(); @@ -306,7 +316,7 @@ bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N, } if (!N) - return 0; + return; ProgramStateRef state = N->getState(); @@ -320,10 +330,18 @@ bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N, StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); // What did we load? - SVal V = state->getSVal(loc::MemRegionVal(R)); + SVal V = state->getRawSVal(loc::MemRegionVal(R)); report->markInteresting(R); report->markInteresting(V); - return new FindLastStoreBRVisitor(V, R); + + if (V.getAsLocSymbol()) { + BugReporterVisitor *ConstraintTracker + = new TrackConstraintBRVisitor(cast<loc::MemRegionVal>(V), false); + report->addVisitor(ConstraintTracker); + } + + report->addVisitor(new FindLastStoreBRVisitor(V, R)); + return; } } } @@ -343,11 +361,10 @@ bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N, if (R) { report->markInteresting(R); - return new TrackConstraintBRVisitor(loc::MemRegionVal(R), false); + report->addVisitor(new TrackConstraintBRVisitor(loc::MemRegionVal(R), + false)); } } - - return 0; } BugReporterVisitor * @@ -389,7 +406,7 @@ PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, // The receiver was nil, and hence the method was skipped. // Register a BugReporterVisitor to issue a message telling us how // the receiver was null. - BR.addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Receiver, &BR)); + bugreporter::addTrackNullOrUndefValueVisitor(N, Receiver, &BR); // Issue a message saying that the method was skipped. PathDiagnosticLocation L(Receiver, BRC.getSourceManager(), N->getLocationContext()); @@ -699,6 +716,9 @@ ConditionBRVisitor::VisitConditionVariable(StringRef LhsString, BugReporterContext &BRC, BugReport &report, const ExplodedNode *N) { + // FIXME: If there's already a constraint tracker for this variable, + // we shouldn't emit anything here (c.f. the double note in + // test/Analysis/inlining/path-notes.c) SmallString<256> buf; llvm::raw_svector_ostream Out(buf); Out << "Assuming " << LhsString << " is "; |
