From: Anna Zaks Date: Wed, 30 Jan 2013 19:12:34 +0000 (+0000) Subject: [analyzer] Move report false positive suppression to report visitors. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=86ff12c8a8a356ca284ca7687749216fbfd74519;p=clang [analyzer] Move report false positive suppression to report visitors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173956 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 74579b7b4c..7a87e47f74 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -457,11 +457,6 @@ public: void Register(BugType *BT); - /// \brief Suppress reports that might lead to known false positives. - /// - /// Currently this suppresses reports based on locations of bugs. - bool suppressReport(BugReport *R); - /// \brief Add the given report to the set of reports tracked by BugReporter. /// /// The reports are usually generated by the checkers. Further, they are diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h index 86f9af352c..10fd445b8c 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -230,6 +230,33 @@ public: llvm::Optional &prunable); }; +/// \brief Suppress reports that might lead to known false positives. +/// +/// Currently this suppresses reports based on locations of bugs. +class LikelyFalsePositiveSuppressionBRVisitor + : public BugReporterVisitorImpl { +public: + static void *getTag() { + static int Tag = 0; + return static_cast(&Tag); + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddPointer(getTag()); + } + + virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *Prev, + BugReporterContext &BRC, + BugReport &BR) { + return 0; + } + + virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, + const ExplodedNode *N, + BugReport &BR); +}; + /// \brief When a region containing undefined value or '0' value is passed /// as an argument in a call, marks the call as interesting. /// diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 473472872b..fccebf4c79 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -2047,6 +2047,7 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, // Register additional node visitors. R->addVisitor(new NilReceiverBRVisitor()); R->addVisitor(new ConditionBRVisitor()); + R->addVisitor(new LikelyFalsePositiveSuppressionBRVisitor()); BugReport::VisitorList visitors; unsigned originalReportConfigToken, finalReportConfigToken; @@ -2067,16 +2068,17 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, // Generate the very last diagnostic piece - the piece is visible before // the trace is expanded. - if (PDB.getGenerationScheme() != PathDiagnosticConsumer::None) { - PathDiagnosticPiece *LastPiece = 0; - for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); - I != E; ++I) { - if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { - assert (!LastPiece && - "There can only be one final piece in a diagnostic."); - LastPiece = Piece; - } + PathDiagnosticPiece *LastPiece = 0; + for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); + I != E; ++I) { + if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { + assert (!LastPiece && + "There can only be one final piece in a diagnostic."); + LastPiece = Piece; } + } + + if (PDB.getGenerationScheme() != PathDiagnosticConsumer::None) { if (!LastPiece) LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); if (LastPiece) @@ -2141,32 +2143,7 @@ void BugReporter::Register(BugType *BT) { BugTypes = F.add(BugTypes, BT); } -bool BugReporter::suppressReport(BugReport *R) { - const Stmt *S = R->getStmt(); - if (!S) - return false; - - // Here we suppress false positives coming from system macros. This list is - // based on known issues. - - // Skip reports within the sys/queue.h macros as we do not have the ability to - // reason about data structure shapes. - SourceManager &SM = getSourceManager(); - SourceLocation Loc = S->getLocStart(); - while (Loc.isMacroID()) { - if (SM.isInSystemMacro(Loc) && - (SM.getFilename(SM.getSpellingLoc(Loc)).endswith("sys/queue.h"))) - return true; - Loc = SM.getSpellingLoc(Loc); - } - - return false; -} - void BugReporter::emitReport(BugReport* R) { - if (suppressReport(R)) - return; - // Compute the bug report's hash to determine its equivalence class. llvm::FoldingSetNodeID ID; R->Profile(ID); diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 7cd1319af2..3aa351527f 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1156,6 +1156,33 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond, return event; } +PathDiagnosticPiece * +LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, + const ExplodedNode *N, + BugReport &BR) { + const Stmt *S = BR.getStmt(); + if (!S) + return 0; + + // Here we suppress false positives coming from system macros. This list is + // based on known issues. + + // Skip reports within the sys/queue.h macros as we do not have the ability to + // reason about data structure shapes. + SourceManager &SM = BRC.getSourceManager(); + SourceLocation Loc = S->getLocStart(); + while (Loc.isMacroID()) { + if (SM.isInSystemMacro(Loc) && + (SM.getFilename(SM.getSpellingLoc(Loc)).endswith("sys/queue.h"))) { + BR.markInvalid(getTag(), 0); + return 0; + } + Loc = SM.getSpellingLoc(Loc); + } + + return 0; +} + PathDiagnosticPiece * UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN,