diff options
4 files changed, 58 insertions, 0 deletions
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 7a87e47f74..74579b7b4c 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -457,6 +457,11 @@ 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/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 8e6bc69cc4..d64aa39feb 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -2137,7 +2137,32 @@ 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/test/Analysis/diagnostics/false-positive-suppression.c b/test/Analysis/diagnostics/false-positive-suppression.c new file mode 100644 index 0000000000..420a573380 --- /dev/null +++ b/test/Analysis/diagnostics/false-positive-suppression.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix -verify %s +// expected-no-diagnostics + +#include "include/sys/queue.h" + +typedef __typeof(sizeof(int)) size_t; +void *malloc(size_t); + +int radar12491259() { + int *p = malloc(12); + FREE_POINTER(p); + FREE_POINTER(p); // no-warning: we are suppressing errors coming from sys/queue macros. + return 0; +} + +#define MYMACRO(p) FREE_POINTER(p) + +int radar12491259_inside_macro() { + int *p = malloc(12); + MYMACRO(p); + MYMACRO(p); // no-warning: we are suppressing errors coming from sys/queue macros. + return 0; +} diff --git a/test/Analysis/diagnostics/include/sys/queue.h b/test/Analysis/diagnostics/include/sys/queue.h new file mode 100644 index 0000000000..e5698ed443 --- /dev/null +++ b/test/Analysis/diagnostics/include/sys/queue.h @@ -0,0 +1,5 @@ +#pragma clang system_header + +void free(void *); +#define FREE_POINTER(x) free(x) + |