diff options
6 files changed, 26 insertions, 6 deletions
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 2b699a85f8..5ee52cc615 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -101,20 +101,27 @@ protected: /// Used for clients to tell if the report's configuration has changed /// since the last time they checked. unsigned ConfigurationChangeToken; + + /// When set, this flag disables all callstack pruning from a diagnostic + /// path. This is useful for some reports that want maximum fidelty + /// when reporting an issue. + bool DoNotPrunePath; public: BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) : BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(errornode), - ConfigurationChangeToken(0) {} + ConfigurationChangeToken(0), DoNotPrunePath(false) {} BugReport(BugType& bt, StringRef shortDesc, StringRef desc, const ExplodedNode *errornode) : BT(bt), DeclWithIssue(0), ShortDescription(shortDesc), Description(desc), - ErrorNode(errornode), ConfigurationChangeToken(0) {} + ErrorNode(errornode), ConfigurationChangeToken(0), + DoNotPrunePath(false) {} BugReport(BugType& bt, StringRef desc, PathDiagnosticLocation l) : BT(bt), DeclWithIssue(0), Description(desc), Location(l), ErrorNode(0), - ConfigurationChangeToken(0) {} + ConfigurationChangeToken(0), + DoNotPrunePath(false) {} /// \brief Create a BugReport with a custom uniqueing location. /// @@ -142,6 +149,13 @@ public: return ShortDescription.empty() ? Description : ShortDescription; } + /// Indicates whether or not any path pruning should take place + /// when generating a PathDiagnostic from this BugReport. + bool shouldPrunePath() const { return !DoNotPrunePath; } + + /// Disable all path pruning when generating a PathDiagnostic. + void disablePathPruning() { DoNotPrunePath = true; } + void markInteresting(SymbolRef sym); void markInteresting(const MemRegion *R); void markInteresting(SVal V); diff --git a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp index 81a27451cb..9b56c9fe13 100644 --- a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -88,6 +88,7 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S, new BugReport(*BT_undef, BT_undef->getDescription(), N); report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, bugreporter::GetDerefExpr(N), report)); + report->disablePathPruning(); C.EmitReport(report); } return; diff --git a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp index a30f6d5328..48b194107e 100644 --- a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp @@ -101,6 +101,7 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition, BugReport *R = new BugReport(*BT, BT->getDescription(), N); R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex, R)); R->addRange(Ex->getSourceRange()); + R->disablePathPruning(); Ctx.EmitReport(R); } diff --git a/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp index d57767eec9..675b38a5df 100644 --- a/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp @@ -94,6 +94,7 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE, if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD)) R->addRange(Ex->getSourceRange()); R->addVisitor(new FindLastStoreBRVisitor(VRVal, VR)); + R->disablePathPruning(); // need location of block C.EmitReport(R); } diff --git a/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp index 78f7fa61b2..7b1081f6bb 100644 --- a/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp @@ -80,6 +80,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val, R->addRange(ex->getSourceRange()); R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, ex, R)); } + R->disablePathPruning(); C.EmitReport(R); } diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index c774818edf..14fcb179cc 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1861,9 +1861,11 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, } while(finalReportConfigToken != originalReportConfigToken); // Finally, prune the diagnostic path of uninteresting stuff. - bool hasSomethingInteresting = RemoveUneededCalls(PD.getMutablePieces()); - assert(hasSomethingInteresting); - (void) hasSomethingInteresting; + if (R->shouldPrunePath()) { + bool hasSomethingInteresting = RemoveUneededCalls(PD.getMutablePieces()); + assert(hasSomethingInteresting); + (void) hasSomethingInteresting; + } } void BugReporter::Register(BugType *BT) { |