llvm::Optional<bool> &prunable);
};
+/// \brief Suppress reports that might lead to known false positives.
+///
+/// Currently this suppresses reports based on locations of bugs.
+class LikelyFalsePositiveSuppressionBRVisitor
+ : public BugReporterVisitorImpl<LikelyFalsePositiveSuppressionBRVisitor> {
+public:
+ static void *getTag() {
+ static int Tag = 0;
+ return static_cast<void *>(&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.
///
// Register additional node visitors.
R->addVisitor(new NilReceiverBRVisitor());
R->addVisitor(new ConditionBRVisitor());
+ R->addVisitor(new LikelyFalsePositiveSuppressionBRVisitor());
BugReport::VisitorList visitors;
unsigned originalReportConfigToken, finalReportConfigToken;
// 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)
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);
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,