forked from OSchip/llvm-project
[analyzer] Move report false positive suppression to report visitors.
llvm-svn: 173956
This commit is contained in:
parent
70aa53180d
commit
be60830378
|
@ -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
|
||||
|
|
|
@ -230,6 +230,33 @@ public:
|
|||
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.
|
||||
///
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue