From ed7948b55fa4b2505f240cc5287137f451172b4c Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 31 May 2012 06:03:17 +0000 Subject: [PATCH] Allow some BugReports to opt-out of PathDiagnostic callstack pruning until we have significantly improved the pruning heuristics. The current heuristics are pretty good, but they make diagnostics for uninitialized variables warnings particularly useless in some cases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157734 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/BugReporter/BugReporter.h | 20 ++++++++++++++++--- .../Checkers/DereferenceChecker.cpp | 1 + .../Checkers/UndefBranchChecker.cpp | 1 + .../Checkers/UndefCapturedBlockVarChecker.cpp | 1 + .../Checkers/UndefinedAssignmentChecker.cpp | 1 + lib/StaticAnalyzer/Core/BugReporter.cpp | 8 +++++--- 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) { -- 2.40.0