Charusso created this revision.
Charusso added a reviewer: NoQ.
Charusso added a project: clang.
Herald added subscribers: cfe-commits, dkrupp, donat.nagy, Szelethus, 
mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun.

This patch introduces a new option:
`-analyzer-disable-warning`
which could be used to disable warnings of given checkers.

It could be used to "disable" core checkers, so they model the analysis as
before, just if some of them are too noisy it prevents to emit reports.

This patch also adds support for that new option to the scan-build.
Passing the option `-disable-checker core.DivideZero` to the scan-build
will be transferred to `-analyzer-disable-warning=core.DivideZero`.


Repository:
  rC Clang

https://reviews.llvm.org/D66042

Files:
  clang-tools-extra/clang-tidy/ClangTidy.cpp
  clang/include/clang/Driver/CC1Options.td
  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/turn-off-warnings-core-all.cpp
  clang/test/Analysis/turn-off-warnings-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,7 +46,7 @@
     std::unique_ptr<AnalysisASTConsumer> AnalysisConsumer =
         CreateAnalysisConsumer(Compiler);
     AnalysisConsumer->AddDiagnosticConsumer(new DiagConsumer(DiagsOutput));
-    Compiler.getAnalyzerOpts()->CheckersControlList = {
+    Compiler.getAnalyzerOpts()->CheckerAnalysisVector = {
         {"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 => {},
+  DisableWarnings => {},
   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/warnings are disabled.
+      # See whether it is a core checker to disable. That means we do not want
+      # to emit a report from the checker so we have to disable the warning.
+      if (index($Checker, "core") != -1) {
+        $Options{DisableWarnings}{$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{DisableWarnings}{$a} <=> $Options{DisableWarnings}{$b} }
+         keys %{$Options{DisableWarnings}}) {
+  # Push checkers' warnings in order they were disabled.
+  push @AnalysesToRun, "-analyzer-disable-warning", $_;
+}
 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/turn-off-warnings-core-div-by-zero.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/turn-off-warnings-core-div-by-zero.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_analyze_cc1 \
+// RUN:  -analyzer-checker=core \
+// RUN:  -analyzer-disable-warning 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: 'The result of the '/' expression is undefined'
+  // no-warning: 'Division by zero'
+}
Index: clang/test/Analysis/turn-off-warnings-core-all.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/turn-off-warnings-core-all.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_analyze_cc1 \
+// RUN:  -analyzer-checker=core \
+// RUN:  -analyzer-disable-warning=core \
+// RUN:  -verify %s
+
+// expected-no-diagnostics
+
+void test_disable_core_all(int *p) {
+  if (p)
+    return;
+
+  int x = p[0];
+  // no-warning: Array access (from variable 'p') results in a null pointer dereference
+}
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.CheckerAnalysisVector) {
     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();
+
+  // The 'CheckerName' could be 'core' so that 'contains()' is appropriate.
+  for (const std::string &CheckerName : Opts.CheckerWarningVector) {
+    if (ErrorTag.contains(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,7 +324,7 @@
       getLastArgIntValue(Args, OPT_analyzer_inline_max_stack_depth,
                          Opts.InlineMaxStackDepth, Diags);
 
-  Opts.CheckersControlList.clear();
+  Opts.CheckerAnalysisVector.clear();
   for (const Arg *A :
        Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) {
     A->claim();
@@ -332,10 +332,22 @@
     // We can have a list of comma separated checker names, e.g:
     // '-analyzer-checker=cocoa,unix'
     StringRef checkerList = A->getValue();
-    SmallVector<StringRef, 4> checkers;
+    SmallVector<StringRef, 16> checkers;
     checkerList.split(checkers, ",");
     for (auto checker : checkers)
-      Opts.CheckersControlList.emplace_back(checker, enable);
+      Opts.CheckerAnalysisVector.emplace_back(checker, enable);
+  }
+
+  Opts.CheckerWarningVector.clear();
+  for (const Arg *A : Args.filtered(OPT_analyzer_disable_warning)) {
+    A->claim();
+    // We can have a list of comma separated checker names, e.g:
+    // '-analyzer-checker=cocoa,unix'
+    StringRef checkerList = A->getValue();
+    SmallVector<StringRef, 16> checkers;
+    checkerList.split(checkers, ",");
+    for (auto checker : checkers)
+      Opts.CheckerWarningVector.emplace_back(checker);
   }
 
   // Go through the analyzer configuration options.
Index: clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -189,8 +189,11 @@
       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;
+  /// Pair of checker name and enable/disable to do analysis.
+  std::vector<std::pair<std::string, bool>> CheckerAnalysisVector;
+
+  /// Vector of checker names to do not emit warnings.
+  std::vector<std::string> CheckerWarningVector;
 
   /// A key-value table of use-specified configuration values.
   // TODO: This shouldn't be public.
Index: clang/include/clang/Driver/CC1Options.td
===================================================================
--- clang/include/clang/Driver/CC1Options.td
+++ clang/include/clang/Driver/CC1Options.td
@@ -124,6 +124,11 @@
 def analyzer_disable_checker_EQ : Joined<["-"], "analyzer-disable-checker=">,
   Alias<analyzer_disable_checker>;
 
+def analyzer_disable_warning : Separate<["-"], "analyzer-disable-warning">,
+  HelpText<"Choose analyzer checkers of the warnings to disable">;
+def analyzer_disable_warning_EQ : Joined<["-"], "analyzer-disable-warning=">,
+  Alias<analyzer_disable_warning>;
+
 def analyzer_disable_all_checks : Flag<["-"], "analyzer-disable-all-checks">,
   HelpText<"Disable all static analyzer checks">;
 
Index: clang-tools-extra/clang-tidy/ClangTidy.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -419,9 +419,9 @@
 
 #if CLANG_ENABLE_STATIC_ANALYZER
   AnalyzerOptionsRef AnalyzerOptions = Compiler.getAnalyzerOpts();
-  AnalyzerOptions->CheckersControlList =
+  AnalyzerOptions->CheckerAnalysisVector =
       getCheckersControlList(Context, Context.canEnableAnalyzerAlphaCheckers());
-  if (!AnalyzerOptions->CheckersControlList.empty()) {
+  if (!AnalyzerOptions->CheckerAnalysisVector.empty()) {
     setStaticAnalyzerCheckerOpts(Context.getOptions(), AnalyzerOptions);
     AnalyzerOptions->AnalysisStoreOpt = RegionStoreModel;
     AnalyzerOptions->AnalysisDiagOpt = PD_NONE;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to