diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 7 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporter.cpp | 5 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 51 |
3 files changed, 63 insertions, 0 deletions
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 6622e6e06d..0bc1532659 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -3454,6 +3454,13 @@ void RetainCountChecker::checkEndPath(CheckerContext &Ctx) const { return; } + // If the current LocationContext has a parent, don't check for leaks. + // We will do that later. + // FIXME: we should instead check for imblances of the retain/releases, + // and suggest annotations. + if (Ctx.getLocationContext()->getParent()) + return; + B = state->get<RefBindings>(); SmallVector<SymbolRef, 10> Leaked; diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 94368b5f4e..5101827d71 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1646,6 +1646,11 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, // Register additional node visitors. R->addVisitor(new NilReceiverBRVisitor()); R->addVisitor(new ConditionBRVisitor()); + + // If inlining is turning out, emit diagnostics for CallEnter and + // CallExit at the top level. + bool showTopLevel = Eng.getAnalysisManager().shouldInlineCall(); + R->addVisitor(new CallEnterExitBRVisitor(showTopLevel)); // Generate the very last diagnostic piece - the piece is visible before // the trace is expanded. diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 230e7c97eb..68ec6b0a93 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -726,3 +726,54 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond, PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LC); return new PathDiagnosticEventPiece(Loc, Out.str()); } + +static PathDiagnosticLocation getLastStmtLoc(const ExplodedNode *N, + const SourceManager &SM) { + while (N) { + ProgramPoint PP = N->getLocation(); + if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP)) + return PathDiagnosticLocation(SP->getStmt(), SM, PP.getLocationContext()); + if (N->pred_empty()) + break; + N = *N->pred_begin(); + } + return PathDiagnosticLocation(); +} + +PathDiagnosticPiece * +CallEnterExitBRVisitor::VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) { + ProgramPoint PP = N->getLocation(); + SmallString<256> buf; + llvm::raw_svector_ostream Out(buf); + PathDiagnosticLocation pos; + + if (const CallEnter *CEnter = dyn_cast<CallEnter>(&PP)) { + const Decl *callee = CEnter->getCalleeContext()->getDecl(); + pos = PathDiagnosticLocation(CEnter->getCallExpr(), BRC.getSourceManager(), + PP.getLocationContext()); + if (isa<BlockDecl>(callee)) + Out << "Entering call to block"; + else if (const NamedDecl *ND = dyn_cast<NamedDecl>(callee)) + Out << "Entering call to '" << ND->getNameAsString() << "'"; + } + else if (const CallExit *CExit = dyn_cast<CallExit>(&PP)) { + const Decl *caller = CExit->getLocationContext()->getParent()->getDecl(); + pos = getLastStmtLoc(PrevN, BRC.getSourceManager()); + if (const NamedDecl *ND = dyn_cast<NamedDecl>(caller)) + Out << "Returning to " << ND->getNameAsString(); + else + Out << "Returning to caller"; + } + + if (!pos.isValid()) + return 0; + + StringRef msg = Out.str(); + if (msg.empty()) + return 0; + + return new PathDiagnosticEventPiece(pos, msg); +} |