[clang-tools-extra] r257642 - Teach clang-tidy how to upgrade warnings into errors.

Jonathan Roelofs via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 13 09:36:41 PST 2016


Author: jroelofs
Date: Wed Jan 13 11:36:41 2016
New Revision: 257642

URL: http://llvm.org/viewvc/llvm-project?rev=257642&view=rev
Log:
Teach clang-tidy how to upgrade warnings into errors.

Similar in format to the `-checks=` argument, this new `-warnings-as-errors=`
argument upgrades any warnings emitted by the former to errors.

http://reviews.llvm.org/D15528

Added:
    clang-tools-extra/trunk/test/clang-tidy/werrors-plural.cpp
    clang-tools-extra/trunk/test/clang-tidy/werrors.cpp
Modified:
    clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp
    clang-tools-extra/trunk/clang-tidy/ClangTidy.h
    clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp
    clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h
    clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.cpp
    clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.h
    clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp
    clang-tools-extra/trunk/docs/clang-tidy/index.rst

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp?rev=257642&r1=257641&r2=257642&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp Wed Jan 13 11:36:41 2016
@@ -101,7 +101,8 @@ public:
         Diags(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts,
               DiagPrinter),
         SourceMgr(Diags, Files), Rewrite(SourceMgr, LangOpts),
-        ApplyFixes(ApplyFixes), TotalFixes(0), AppliedFixes(0) {
+        ApplyFixes(ApplyFixes), TotalFixes(0), AppliedFixes(0),
+        WarningsAsErrors(0) {
     DiagOpts->ShowColors = llvm::sys::Process::StandardOutHasColors();
     DiagPrinter->BeginSourceFile(LangOpts);
   }
@@ -114,8 +115,14 @@ public:
     SmallVector<std::pair<SourceLocation, bool>, 4> FixLocations;
     {
       auto Level = static_cast<DiagnosticsEngine::Level>(Error.DiagLevel);
+      std::string Name = Error.CheckName;
+      if (Error.IsWarningAsError) {
+        Name += ",-warnings-as-errors";
+        Level = DiagnosticsEngine::Error;
+        WarningsAsErrors++;
+      }
       auto Diag = Diags.Report(Loc, Diags.getCustomDiagID(Level, "%0 [%1]"))
-                  << Message.Message << Error.CheckName;
+                  << Message.Message << Name;
       for (const tooling::Replacement &Fix : Error.Fix) {
         SourceLocation FixLoc = getLocation(Fix.getFilePath(), Fix.getOffset());
         SourceLocation FixEndLoc = FixLoc.getLocWithOffset(Fix.getLength());
@@ -147,6 +154,8 @@ public:
     }
   }
 
+  unsigned getWarningsAsErrorsCount() const { return WarningsAsErrors; }
+
 private:
   SourceLocation getLocation(StringRef FilePath, unsigned Offset) {
     if (FilePath.empty())
@@ -174,6 +183,7 @@ private:
   bool ApplyFixes;
   unsigned TotalFixes;
   unsigned AppliedFixes;
+  unsigned WarningsAsErrors;
 };
 
 class ClangTidyASTConsumer : public MultiplexConsumer {
@@ -421,11 +431,13 @@ runClangTidy(std::unique_ptr<ClangTidyOp
   return Context.getStats();
 }
 
-void handleErrors(const std::vector<ClangTidyError> &Errors, bool Fix) {
+void handleErrors(const std::vector<ClangTidyError> &Errors, bool Fix,
+                  unsigned &WarningsAsErrorsCount) {
   ErrorReporter Reporter(Fix);
   for (const ClangTidyError &Error : Errors)
     Reporter.reportDiagnostic(Error);
   Reporter.Finish();
+  WarningsAsErrorsCount += Reporter.getWarningsAsErrorsCount();
 }
 
 void exportReplacements(const std::vector<ClangTidyError> &Errors,

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidy.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidy.h?rev=257642&r1=257641&r2=257642&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidy.h (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidy.h Wed Jan 13 11:36:41 2016
@@ -214,7 +214,8 @@ runClangTidy(std::unique_ptr<ClangTidyOp
 //
 /// \brief Displays the found \p Errors to the users. If \p Fix is true, \p
 /// Errors containing fixes are automatically applied.
-void handleErrors(const std::vector<ClangTidyError> &Errors, bool Fix);
+void handleErrors(const std::vector<ClangTidyError> &Errors, bool Fix,
+                  unsigned &WarningsAsErrorsCount);
 
 /// \brief Serializes replacements into YAML and writes them to the specified
 /// output stream.

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp?rev=257642&r1=257641&r2=257642&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp Wed Jan 13 11:36:41 2016
@@ -115,8 +115,10 @@ ClangTidyMessage::ClangTidyMessage(Strin
 }
 
 ClangTidyError::ClangTidyError(StringRef CheckName,
-                               ClangTidyError::Level DiagLevel)
-    : CheckName(CheckName), DiagLevel(DiagLevel) {}
+                               ClangTidyError::Level DiagLevel,
+                               bool IsWarningAsError)
+    : CheckName(CheckName), DiagLevel(DiagLevel),
+      IsWarningAsError(IsWarningAsError) {}
 
 // Returns true if GlobList starts with the negative indicator ('-'), removes it
 // from the GlobList.
@@ -204,6 +206,7 @@ void ClangTidyContext::setCurrentFile(St
   CurrentFile = File;
   CurrentOptions = getOptionsForFile(CurrentFile);
   CheckFilter.reset(new GlobList(*getOptions().Checks));
+  WarningAsErrorFilter.reset(new GlobList(*getOptions().WarningsAsErrors));
 }
 
 void ClangTidyContext::setASTContext(ASTContext *Context) {
@@ -237,6 +240,11 @@ bool ClangTidyContext::isCheckEnabled(St
   return CheckFilter->contains(CheckName);
 }
 
+GlobList &ClangTidyContext::getWarningAsErrorFilter() {
+  assert(WarningAsErrorFilter != nullptr);
+  return *WarningAsErrorFilter;
+}
+
 /// \brief Store a \c ClangTidyError.
 void ClangTidyContext::storeError(const ClangTidyError &Error) {
   Errors.push_back(Error);
@@ -324,7 +332,10 @@ void ClangTidyDiagnosticConsumer::Handle
       LastErrorRelatesToUserCode = true;
       LastErrorPassesLineFilter = true;
     }
-    Errors.push_back(ClangTidyError(CheckName, Level));
+    bool IsWarningAsError =
+        DiagLevel == DiagnosticsEngine::Warning &&
+        Context.getWarningAsErrorFilter().contains(CheckName);
+    Errors.push_back(ClangTidyError(CheckName, Level, IsWarningAsError));
   }
 
   // FIXME: Provide correct LangOptions for each file.

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h?rev=257642&r1=257641&r2=257642&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h Wed Jan 13 11:36:41 2016
@@ -57,7 +57,7 @@ struct ClangTidyError {
     Error = DiagnosticsEngine::Error
   };
 
-  ClangTidyError(StringRef CheckName, Level DiagLevel);
+  ClangTidyError(StringRef CheckName, Level DiagLevel, bool IsWarningAsError);
 
   std::string CheckName;
   ClangTidyMessage Message;
@@ -65,6 +65,7 @@ struct ClangTidyError {
   SmallVector<ClangTidyMessage, 1> Notes;
 
   Level DiagLevel;
+  bool IsWarningAsError;
 };
 
 /// \brief Read-only set of strings represented as a list of positive and
@@ -164,6 +165,10 @@ public:
   /// \brief Returns true if the check name is enabled for the \c CurrentFile.
   bool isCheckEnabled(StringRef CheckName) const;
 
+  /// \brief Returns check filter for the \c CurrentFile which
+  /// selects checks for upgrade to error.
+  GlobList &getWarningAsErrorFilter();
+
   /// \brief Returns global options.
   const ClangTidyGlobalOptions &getGlobalOptions() const;
 
@@ -211,6 +216,7 @@ private:
   std::string CurrentFile;
   ClangTidyOptions CurrentOptions;
   std::unique_ptr<GlobList> CheckFilter;
+  std::unique_ptr<GlobList> WarningAsErrorFilter;
 
   LangOptions LangOpts;
 

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.cpp?rev=257642&r1=257641&r2=257642&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.cpp Wed Jan 13 11:36:41 2016
@@ -85,6 +85,7 @@ template <> struct MappingTraits<ClangTi
     MappingNormalization<NOptionMap, ClangTidyOptions::OptionMap> NOpts(
         IO, Options.CheckOptions);
     IO.mapOptional("Checks", Options.Checks);
+    IO.mapOptional("WarningsAsErrors", Options.WarningsAsErrors);
     IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
     IO.mapOptional("AnalyzeTemporaryDtors", Options.AnalyzeTemporaryDtors);
     IO.mapOptional("User", Options.User);
@@ -103,6 +104,7 @@ namespace tidy {
 ClangTidyOptions ClangTidyOptions::getDefaults() {
   ClangTidyOptions Options;
   Options.Checks = "";
+  Options.WarningsAsErrors = "";
   Options.HeaderFilterRegex = "";
   Options.SystemHeaders = false;
   Options.AnalyzeTemporaryDtors = false;
@@ -123,6 +125,12 @@ ClangTidyOptions::mergeWith(const ClangT
     Result.Checks =
         (Result.Checks && !Result.Checks->empty() ? *Result.Checks + "," : "") +
         *Other.Checks;
+  if (Other.WarningsAsErrors)
+    Result.WarningsAsErrors =
+        (Result.WarningsAsErrors && !Result.WarningsAsErrors->empty()
+             ? *Result.WarningsAsErrors + ","
+             : "") +
+        *Other.WarningsAsErrors;
 
   if (Other.HeaderFilterRegex)
     Result.HeaderFilterRegex = Other.HeaderFilterRegex;

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.h?rev=257642&r1=257641&r2=257642&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.h (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyOptions.h Wed Jan 13 11:36:41 2016
@@ -62,6 +62,9 @@ struct ClangTidyOptions {
   /// \brief Checks filter.
   llvm::Optional<std::string> Checks;
 
+  /// \brief WarningsAsErrors filter.
+  llvm::Optional<std::string> WarningsAsErrors;
+
   /// \brief Output warnings from headers matching this filter. Warnings from
   /// main files will always be displayed.
   llvm::Optional<std::string> HeaderFilterRegex;

Modified: clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp?rev=257642&r1=257641&r2=257642&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp Wed Jan 13 11:36:41 2016
@@ -64,15 +64,21 @@ Checks("checks", cl::desc("Comma-separat
        cl::init(""), cl::cat(ClangTidyCategory));
 
 static cl::opt<std::string>
-HeaderFilter("header-filter",
-             cl::desc("Regular expression matching the names of the\n"
-                      "headers to output diagnostics from. Diagnostics\n"
-                      "from the main file of each translation unit are\n"
-                      "always displayed.\n"
-                      "Can be used together with -line-filter.\n"
-                      "This option overrides the value read from a\n"
-                      ".clang-tidy file."),
-             cl::init(""), cl::cat(ClangTidyCategory));
+    WarningsAsErrors("warnings-as-errors",
+                     cl::desc("Upgrades warnings to errors. "
+                              "Same format as '-checks'."),
+                     cl::init(""), cl::cat(ClangTidyCategory));
+
+static cl::opt<std::string>
+    HeaderFilter("header-filter",
+                 cl::desc("Regular expression matching the names of the\n"
+                          "headers to output diagnostics from. Diagnostics\n"
+                          "from the main file of each translation unit are\n"
+                          "always displayed.\n"
+                          "Can be used together with -line-filter.\n"
+                          "This option overrides the value read from a\n"
+                          ".clang-tidy file."),
+                 cl::init(""), cl::cat(ClangTidyCategory));
 
 static cl::opt<bool>
     SystemHeaders("system-headers",
@@ -227,6 +233,7 @@ static std::unique_ptr<ClangTidyOptionsP
 
   ClangTidyOptions DefaultOptions;
   DefaultOptions.Checks = DefaultChecks;
+  DefaultOptions.WarningsAsErrors = "";
   DefaultOptions.HeaderFilterRegex = HeaderFilter;
   DefaultOptions.SystemHeaders = SystemHeaders;
   DefaultOptions.AnalyzeTemporaryDtors = AnalyzeTemporaryDtors;
@@ -238,6 +245,8 @@ static std::unique_ptr<ClangTidyOptionsP
   ClangTidyOptions OverrideOptions;
   if (Checks.getNumOccurrences() > 0)
     OverrideOptions.Checks = Checks;
+  if (WarningsAsErrors.getNumOccurrences() > 0)
+    OverrideOptions.WarningsAsErrors = WarningsAsErrors;
   if (HeaderFilter.getNumOccurrences() > 0)
     OverrideOptions.HeaderFilterRegex = HeaderFilter;
   if (SystemHeaders.getNumOccurrences() > 0)
@@ -322,8 +331,10 @@ static int clangTidyMain(int argc, const
 
   const bool DisableFixes = Fix && FoundErrors && !FixErrors;
 
+  unsigned WErrorCount = 0;
+
   // -fix-errors implies -fix.
-  handleErrors(Errors, (FixErrors || Fix) && !DisableFixes);
+  handleErrors(Errors, (FixErrors || Fix) && !DisableFixes, WErrorCount);
 
   if (!ExportFixes.empty() && !Errors.empty()) {
     std::error_code EC;
@@ -344,6 +355,13 @@ static int clangTidyMain(int argc, const
   if (EnableCheckProfile)
     printProfileData(Profile, llvm::errs());
 
+  if (WErrorCount) {
+    StringRef Plural = WErrorCount == 1 ? "" : "s";
+    llvm::errs() << WErrorCount << " warning" << Plural << " treated as error"
+                 << Plural << "\n";
+    return WErrorCount;
+  }
+
   return 0;
 }
 

Modified: clang-tools-extra/trunk/docs/clang-tidy/index.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/index.rst?rev=257642&r1=257641&r2=257642&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/index.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/index.rst Wed Jan 13 11:36:41 2016
@@ -68,7 +68,9 @@ Clang diagnostics are treated in a simil
 diagnostics are displayed by clang-tidy and can be filtered out using
 ``-checks=`` option. However, the ``-checks=`` option does not affect
 compilation arguments, so it can not turn on Clang warnings which are not
-already turned on in build configuration.
+already turned on in build configuration. The ``-warnings-as-errors=`` option
+upgrades any warnings emitted under the ``-checks=`` flag to errors (but it
+does not enable any checks itself).
 
 Clang diagnostics have check names starting with ``clang-diagnostic-``.
 Diagnostics which have a corresponding warning option, are named
@@ -150,6 +152,7 @@ An overview of all the command-line opti
                                  -checks=* to list all available checks.
     -p=<string>                - Build path
     -system-headers            - Display the errors from system headers.
+    -warnings-as-errors=<string> - Upgrades warnings to errors. Same format as '-checks'.
 
   -p <build-path> is used to read a compile command database.
 

Added: clang-tools-extra/trunk/test/clang-tidy/werrors-plural.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/werrors-plural.cpp?rev=257642&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/werrors-plural.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/werrors-plural.cpp Wed Jan 13 11:36:41 2016
@@ -0,0 +1,15 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-comment' -- 2>&1 | FileCheck %s --check-prefix=CHECK-WARN
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment' -warnings-as-errors='llvm-namespace-comment' -- 2>&1 | FileCheck %s --check-prefix=CHECK-WERR
+
+namespace j {
+}
+// CHECK-WARN: warning: namespace 'j' not terminated with a closing comment [llvm-namespace-comment]
+// CHECK-WERR: error: namespace 'j' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+
+namespace k {
+}
+// CHECK-WARN: warning: namespace 'k' not terminated with a closing comment [llvm-namespace-comment]
+// CHECK-WERR: error: namespace 'k' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+
+// CHECK-WARN-NOT: treated as
+// CHECK-WERR: 2 warnings treated as errors

Added: clang-tools-extra/trunk/test/clang-tidy/werrors.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/werrors.cpp?rev=257642&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/werrors.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/werrors.cpp Wed Jan 13 11:36:41 2016
@@ -0,0 +1,10 @@
+// RUN: clang-tidy %s -checks='-*,llvm-namespace-comment' -- 2>&1 | FileCheck %s --check-prefix=CHECK-WARN
+// RUN: not clang-tidy %s -checks='-*,llvm-namespace-comment' -warnings-as-errors='llvm-namespace-comment' -- 2>&1 | FileCheck %s --check-prefix=CHECK-WERR
+
+namespace i {
+}
+// CHECK-WARN: warning: namespace 'i' not terminated with a closing comment [llvm-namespace-comment]
+// CHECK-WERR: error: namespace 'i' not terminated with a closing comment [llvm-namespace-comment,-warnings-as-errors]
+
+// CHECK-WARN-NOT: treated as
+// CHECK-WERR: 1 warning treated as error




More information about the cfe-commits mailing list