Charusso updated this revision to Diff 215103.
Charusso marked 4 inline comments as done.
Charusso retitled this revision from "[analyzer] Analysis: "Disable" core
checkers" to "[analyzer] Analysis: Silence checkers".
Charusso edited the summary of this revision.
Charusso set the repository for this revision to rC Clang.
Charusso added a comment.
- Pink Fluffy Unicorns Dancing On Rainbows
<https://www.youtube.com/watch?v=a-xWhG4UU_Y>
Repository:
rC Clang
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D66042/new/
https://reviews.llvm.org/D66042
Files:
clang-tools-extra/clang-tidy/ClangTidy.cpp
clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
clang/lib/Frontend/CompilerInvocation.cpp
clang/lib/StaticAnalyzer/Core/BugReporter.cpp
clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
clang/test/Analysis/analyzer-config.c
clang/test/Analysis/silence-checker-core-all.cpp
clang/test/Analysis/silence-checker-core-div-by-zero.cpp
clang/tools/scan-build/bin/scan-build
clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
Index: clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
===================================================================
--- clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
+++ clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
@@ -46,8 +46,7 @@
std::unique_ptr<AnalysisASTConsumer> AnalysisConsumer =
CreateAnalysisConsumer(Compiler);
AnalysisConsumer->AddDiagnosticConsumer(new DiagConsumer(DiagsOutput));
- Compiler.getAnalyzerOpts()->CheckersControlList = {
- {"custom.CustomChecker", true}};
+ Compiler.getAnalyzerOpts()->Checkers = {{"custom.CustomChecker", true}};
AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry.addChecker<CheckerT>("custom.CustomChecker", "Description", "");
});
Index: clang/tools/scan-build/bin/scan-build
===================================================================
--- clang/tools/scan-build/bin/scan-build
+++ clang/tools/scan-build/bin/scan-build
@@ -57,6 +57,7 @@
KeepEmpty => 0, # Don't remove output directory even with 0 results.
EnableCheckers => {},
DisableCheckers => {},
+ SilenceCheckers => {},
Excludes => [],
UseCC => undef, # C compiler to use for compilation.
UseCXX => undef, # C++ compiler to use for compilation.
@@ -1742,9 +1743,15 @@
if ($arg eq "-disable-checker") {
shift @$Args;
my $Checker = shift @$Args;
- # Store $NumArgs to preserve the order the checkers were disabled.
- $Options{DisableCheckers}{$Checker} = $NumArgs;
- delete $Options{EnableCheckers}{$Checker};
+ # Store $NumArgs to preserve the order the checkers are disabled/silenced.
+ # See whether it is a core checker to disable. That means we do not want
+ # to emit a report from that checker so we have to silence it.
+ if (index($Checker, "core") == 0) {
+ $Options{SilenceCheckers}{$Checker} = $NumArgs;
+ } else {
+ $Options{DisableCheckers}{$Checker} = $NumArgs;
+ delete $Options{EnableCheckers}{$Checker};
+ }
next;
}
@@ -1882,6 +1889,11 @@
# Push checkers in order they were disabled.
push @AnalysesToRun, "-analyzer-disable-checker", $_;
}
+foreach (sort { $Options{SilenceCheckers}{$a} <=> $Options{SilenceCheckers}{$b} }
+ keys %{$Options{SilenceCheckers}}) {
+ # Push checkers in order they were silenced.
+ push @AnalysesToRun, "-analyzer-config silence-checker", $_;
+}
if ($Options{AnalyzeHeaders}) { push @AnalysesToRun, "-analyzer-opt-analyze-headers"; }
if ($Options{AnalyzerStats}) { push @AnalysesToRun, '-analyzer-checker=debug.Stats'; }
if ($Options{MaxLoop} > 0) { push @AnalysesToRun, "-analyzer-max-loop $Options{MaxLoop}"; }
Index: clang/test/Analysis/silence-checker-core-div-by-zero.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/silence-checker-core-div-by-zero.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_analyze_cc1 \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config silence-checkers=core.DivideZero \
+// RUN: -verify %s
+
+void test_disable_core_div_by_zero() {
+ (void)(1 / 0);
+ // expected-warning@-1 {{division by zero is undefined}}
+ // no-warning: 'Division by zero'
+}
+
+void test_disable_null_deref(int *p) {
+ if (p)
+ return;
+
+ int x = p[0];
+ // expected-warning@-1 {{Array access (from variable 'p') results in a null pointer dereference}}
+}
Index: clang/test/Analysis/silence-checker-core-all.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/silence-checker-core-all.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_analyze_cc1 \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config silence-checkers=core \
+// RUN: -verify %s
+// RUN: %clang_analyze_cc1 \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-config silence-checkers="core.DivideZero;core.NullDeref" \
+// RUN: -verify %s
+
+void test_disable_core_div_by_zero() {
+ (void)(1 / 0);
+ // expected-warning@-1 {{division by zero is undefined}}
+ // no-warning: 'Division by zero'
+}
+
+void test_disable_null_deref(int *p) {
+ if (p)
+ return;
+
+ int x = p[0];
+ // no-warning: Array access (from variable 'p') results in a null pointer dereference
+}
Index: clang/test/Analysis/analyzer-config.c
===================================================================
--- clang/test/Analysis/analyzer-config.c
+++ clang/test/Analysis/analyzer-config.c
@@ -82,6 +82,7 @@
// CHECK-NEXT: region-store-small-struct-limit = 2
// CHECK-NEXT: report-in-main-source-file = false
// CHECK-NEXT: serialize-stats = false
+// CHECK-NEXT: silence-checkers = ""
// CHECK-NEXT: stable-report-filename = false
// CHECK-NEXT: suppress-c++-stdlib = true
// CHECK-NEXT: suppress-inlined-defensive-checks = true
@@ -92,4 +93,4 @@
// CHECK-NEXT: unroll-loops = false
// CHECK-NEXT: widen-loops = false
// CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 89
+// CHECK-NEXT: num-entries = 90
Index: clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
+++ clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
@@ -200,7 +200,7 @@
// Parse '-analyzer-checker' and '-analyzer-disable-checker' options from the
// command line.
- for (const std::pair<std::string, bool> &Opt : AnOpts.CheckersControlList) {
+ for (const std::pair<std::string, bool> &Opt : AnOpts.Checkers) {
CheckerInfoListRange CheckerForCmdLineArg =
getMutableCheckersForCmdLineArg(Opt.first);
Index: clang/lib/StaticAnalyzer/Core/BugReporter.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1917,12 +1917,19 @@
PathDiagnosticBuilder &PDB,
const ExplodedNode *ErrorNode,
const VisitorsDiagnosticsTy &VisitorsDiagnostics) {
+ BugReport *R = PDB.getBugReport();
+ AnalyzerOptions &Opts = PDB.getBugReporter().getAnalyzerOptions();
+ StringRef ErrorTag = ErrorNode->getLocation().getTag()->getTagDescription();
+
+ // See whether we need to silence the checker.
+ for (const std::string &CheckerName : Opts.SilencedCheckers) {
+ if (ErrorTag.startswith(CheckerName))
+ return nullptr;
+ }
bool GenerateDiagnostics = (ActiveScheme != PathDiagnosticConsumer::None);
bool AddPathEdges = (ActiveScheme == PathDiagnosticConsumer::Extensive);
SourceManager &SM = PDB.getSourceManager();
- BugReport *R = PDB.getBugReport();
- AnalyzerOptions &Opts = PDB.getBugReporter().getAnalyzerOptions();
StackDiagVector CallStack;
InterestingExprs IE;
LocationContextMap LCM;
@@ -2686,9 +2693,12 @@
const ExplodedNode *ErrorNode = ErrorGraph.ErrorNode;
for (PathDiagnosticConsumer *PC : consumers) {
PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, PC);
- std::unique_ptr<PathDiagnostic> PD = generatePathDiagnosticForConsumer(
- PC->getGenerationScheme(), PDB, ErrorNode, *ReportInfo.second);
- (*Out)[PC] = std::move(PD);
+ if (std::unique_ptr<PathDiagnostic> PD =
+ generatePathDiagnosticForConsumer(PC->getGenerationScheme(), PDB,
+ ErrorNode,
+ *ReportInfo.second)) {
+ (*Out)[PC] = std::move(PD);
+ }
}
}
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -324,18 +324,18 @@
getLastArgIntValue(Args, OPT_analyzer_inline_max_stack_depth,
Opts.InlineMaxStackDepth, Diags);
- Opts.CheckersControlList.clear();
+ Opts.Checkers.clear();
for (const Arg *A :
Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) {
A->claim();
- bool enable = (A->getOption().getID() == OPT_analyzer_checker);
+ bool IsEnabled = A->getOption().getID() == OPT_analyzer_checker;
// We can have a list of comma separated checker names, e.g:
// '-analyzer-checker=cocoa,unix'
- StringRef checkerList = A->getValue();
- SmallVector<StringRef, 4> checkers;
- checkerList.split(checkers, ",");
- for (auto checker : checkers)
- Opts.CheckersControlList.emplace_back(checker, enable);
+ StringRef CheckerList = A->getValue();
+ SmallVector<StringRef, 16> Checkers;
+ CheckerList.split(Checkers, ",");
+ for (const StringRef Checker : Checkers)
+ Opts.Checkers.emplace_back(Checker, IsEnabled);
}
// Go through the analyzer configuration options.
@@ -479,6 +479,13 @@
!llvm::sys::fs::is_directory(AnOpts.ModelPath))
Diags->Report(diag::err_analyzer_config_invalid_input) << "model-path"
<< "a filename";
+
+ if (!AnOpts.RawSilencedCheckers.empty()) {
+ SmallVector<StringRef, 16> Checkers;
+ AnOpts.RawSilencedCheckers.split(Checkers, ";");
+ for (const StringRef Checker : Checkers)
+ AnOpts.SilencedCheckers.emplace_back(Checker);
+ }
}
static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) {
Index: clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -188,9 +188,11 @@
std::pair<StringRef, StringRef> EntryDescPair,
size_t EntryWidth, size_t InitialPad, size_t MinLineWidth = 0);
-
/// Pair of checker name and enable/disable.
- std::vector<std::pair<std::string, bool>> CheckersControlList;
+ std::vector<std::pair<std::string, bool>> Checkers;
+
+ /// Vector of checker names which will not emit warnings.
+ std::vector<std::string> SilencedCheckers;
/// A key-value table of use-specified configuration values.
// TODO: This shouldn't be public.
Index: clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
+++ clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -380,12 +380,6 @@
"Value: \"constructors\", \"destructors\", \"methods\".",
"destructors")
-ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
- StringRef, IPAMode, "ipa",
- "Controls the mode of inter-procedural analysis. Value: \"none\", "
- "\"basic-inlining\", \"inlining\", \"dynamic\", \"dynamic-bifurcate\".",
- /* SHALLOW_VAL */ "inlining", /* DEEP_VAL */ "dynamic-bifurcate")
-
ANALYZER_OPTION(
StringRef, ExplorationStrategy, "exploration_strategy",
"Value: \"dfs\", \"bfs\", \"unexplored_first\", "
@@ -393,5 +387,15 @@
"\"bfs_block_dfs_contents\".",
"unexplored_first_queue")
+ANALYZER_OPTION(
+ StringRef, RawSilencedCheckers, "silence-checkers",
+ "A semicolon separated list of checker and package names to silence.", "")
+
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
+ StringRef, IPAMode, "ipa",
+ "Controls the mode of inter-procedural analysis. Value: \"none\", "
+ "\"basic-inlining\", \"inlining\", \"dynamic\", \"dynamic-bifurcate\".",
+ /* SHALLOW_VAL */ "inlining", /* DEEP_VAL */ "dynamic-bifurcate")
+
#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
#undef ANALYZER_OPTION
Index: clang-tools-extra/clang-tidy/ClangTidy.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -334,8 +334,8 @@
typedef std::vector<std::pair<std::string, bool>> CheckersList;
-static CheckersList getCheckersControlList(ClangTidyContext &Context,
- bool IncludeExperimental) {
+static CheckersList getAnalyzerCheckers(ClangTidyContext &Context,
+ bool IncludeExperimental) {
CheckersList List;
const auto &RegisteredCheckers =
@@ -419,9 +419,9 @@
#if CLANG_ENABLE_STATIC_ANALYZER
AnalyzerOptionsRef AnalyzerOptions = Compiler.getAnalyzerOpts();
- AnalyzerOptions->CheckersControlList =
- getCheckersControlList(Context, Context.canEnableAnalyzerAlphaCheckers());
- if (!AnalyzerOptions->CheckersControlList.empty()) {
+ AnalyzerOptions->Checkers =
+ getAnalyzerCheckers(Context, Context.canEnableAnalyzerAlphaCheckers());
+ if (!AnalyzerOptions->Checkers.empty()) {
setStaticAnalyzerCheckerOpts(Context.getOptions(), AnalyzerOptions);
AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel;
AnalyzerOptions->AnalysisDiagOpt = PD_NONE;
@@ -447,8 +447,8 @@
}
#if CLANG_ENABLE_STATIC_ANALYZER
- for (const auto &AnalyzerCheck : getCheckersControlList(
- Context, Context.canEnableAnalyzerAlphaCheckers()))
+ for (const auto &AnalyzerCheck :
+ getAnalyzerCheckers(Context, Context.canEnableAnalyzerAlphaCheckers()))
CheckNames.push_back(AnalyzerCheckNamePrefix + AnalyzerCheck.first);
#endif // CLANG_ENABLE_STATIC_ANALYZER
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits