[clang-tools-extra] 2755393 - [clang-tidy] Add support for diagnostics with no location

Nathan James via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 8 12:30:26 PST 2020


Author: Nathan James
Date: 2020-12-08T20:29:31Z
New Revision: 27553933a8693d508eb7f7c24a14f66b3d006d2c

URL: https://github.com/llvm/llvm-project/commit/27553933a8693d508eb7f7c24a14f66b3d006d2c
DIFF: https://github.com/llvm/llvm-project/commit/27553933a8693d508eb7f7c24a14f66b3d006d2c.diff

LOG: [clang-tidy] Add support for diagnostics with no location

Add methods for emitting diagnostics with no location as well as a special diagnostic for configuration errors.
These show up in the errors as [clang-tidy-config].
The reason to use a custom name rather than the check name is to distinguish the error isn't the same category as the check that reported it.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D91885

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
    clang-tools-extra/clang-tidy/ClangTidyCheck.h
    clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
    clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
    clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp
    clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp
    clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp
    clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
    clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
    clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
    clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
    clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
    clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-case-violation.cpp
    clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
    clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
index be68dfbedb29..af19da2419ab 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp
@@ -42,7 +42,7 @@ std::string UnparseableIntegerOptionError::message() const {
 
 ClangTidyCheck::ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context)
     : CheckName(CheckName), Context(Context),
-      Options(CheckName, Context->getOptions().CheckOptions) {
+      Options(CheckName, Context->getOptions().CheckOptions, Context) {
   assert(Context != nullptr);
   assert(!CheckName.empty());
 }
@@ -52,6 +52,17 @@ DiagnosticBuilder ClangTidyCheck::diag(SourceLocation Loc, StringRef Message,
   return Context->diag(CheckName, Loc, Message, Level);
 }
 
+DiagnosticBuilder ClangTidyCheck::diag(StringRef Message,
+                                       DiagnosticIDs::Level Level) {
+  return Context->diag(CheckName, Message, Level);
+}
+
+DiagnosticBuilder
+ClangTidyCheck::configurationDiag(StringRef Description,
+                                  DiagnosticIDs::Level Level) {
+  return Context->configurationDiag(Description, Level);
+}
+
 void ClangTidyCheck::run(const ast_matchers::MatchFinder::MatchResult &Result) {
   // For historical reasons, checks don't implement the MatchFinder run()
   // callback directly. We keep the run()/check() distinction to avoid interface
@@ -59,9 +70,11 @@ void ClangTidyCheck::run(const ast_matchers::MatchFinder::MatchResult &Result) {
   check(Result);
 }
 
-ClangTidyCheck::OptionsView::OptionsView(StringRef CheckName,
-                         const ClangTidyOptions::OptionMap &CheckOptions)
-    : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {}
+ClangTidyCheck::OptionsView::OptionsView(
+    StringRef CheckName, const ClangTidyOptions::OptionMap &CheckOptions,
+    ClangTidyContext *Context)
+    : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions),
+      Context(Context) {}
 
 llvm::Expected<std::string>
 ClangTidyCheck::OptionsView::get(StringRef LocalName) const {
@@ -121,7 +134,7 @@ bool ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName,
   llvm::Expected<bool> ValueOr = get<bool>(LocalName);
   if (ValueOr)
     return *ValueOr;
-  logIfOptionParsingError(ValueOr.takeError());
+  reportOptionParsingError(ValueOr.takeError());
   return Default;
 }
 
@@ -140,7 +153,7 @@ bool ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName,
   llvm::Expected<bool> ValueOr = getLocalOrGlobal<bool>(LocalName);
   if (ValueOr)
     return *ValueOr;
-  logIfOptionParsingError(ValueOr.takeError());
+  reportOptionParsingError(ValueOr.takeError());
   return Default;
 }
 
@@ -199,11 +212,11 @@ llvm::Expected<int64_t> ClangTidyCheck::OptionsView::getEnumInt(
                                                       Iter->getValue().Value);
 }
 
-void ClangTidyCheck::OptionsView::logIfOptionParsingError(llvm::Error &&Err) {
+void ClangTidyCheck::OptionsView::reportOptionParsingError(
+    llvm::Error &&Err) const {
   if (auto RemainingErrors =
           llvm::handleErrors(std::move(Err), [](const MissingOptionError &) {}))
-    llvm::logAllUnhandledErrors(std::move(RemainingErrors),
-                                llvm::WithColor::warning());
+    Context->configurationDiag(llvm::toString(std::move(RemainingErrors)));
 }
 
 template <>

diff  --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.h b/clang-tools-extra/clang-tidy/ClangTidyCheck.h
index 6237e216656b..9fa0d6328640 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyCheck.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.h
@@ -176,6 +176,15 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
   DiagnosticBuilder diag(SourceLocation Loc, StringRef Description,
                          DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
 
+  /// Add a diagnostic with the check's name.
+  DiagnosticBuilder diag(StringRef Description,
+                         DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
+
+  /// Adds a diagnostic to report errors in the check's configuration.
+  DiagnosticBuilder
+  configurationDiag(StringRef Description,
+                    DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
+
   /// Should store all options supported by this check with their
   /// current values or default values for options that haven't been overridden.
   ///
@@ -192,7 +201,8 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
   public:
     /// Initializes the instance using \p CheckName + "." as a prefix.
     OptionsView(StringRef CheckName,
-                const ClangTidyOptions::OptionMap &CheckOptions);
+                const ClangTidyOptions::OptionMap &CheckOptions,
+                ClangTidyContext *Context);
 
     /// Read a named option from the ``Context``.
     ///
@@ -268,7 +278,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
       if (llvm::Expected<T> ValueOr = get<T>(LocalName))
         return *ValueOr;
       else
-        logIfOptionParsingError(ValueOr.takeError());
+        reportOptionParsingError(ValueOr.takeError());
       return Default;
     }
 
@@ -314,7 +324,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
       if (llvm::Expected<T> ValueOr = getLocalOrGlobal<T>(LocalName))
         return *ValueOr;
       else
-        logIfOptionParsingError(ValueOr.takeError());
+        reportOptionParsingError(ValueOr.takeError());
       return Default;
     }
 
@@ -353,7 +363,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
       if (auto ValueOr = get<T>(LocalName, IgnoreCase))
         return *ValueOr;
       else
-        logIfOptionParsingError(ValueOr.takeError());
+        reportOptionParsingError(ValueOr.takeError());
       return Default;
     }
 
@@ -395,7 +405,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
       if (auto ValueOr = getLocalOrGlobal<T>(LocalName, IgnoreCase))
         return *ValueOr;
       else
-        logIfOptionParsingError(ValueOr.takeError());
+        reportOptionParsingError(ValueOr.takeError());
       return Default;
     }
 
@@ -407,7 +417,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
       if (auto ValueOr = get<T>(LocalName))
         return *ValueOr;
       else
-        logIfOptionParsingError(ValueOr.takeError());
+        reportOptionParsingError(ValueOr.takeError());
       return llvm::None;
     }
 
@@ -420,7 +430,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
       if (auto ValueOr = getLocalOrGlobal<T>(LocalName))
         return *ValueOr;
       else
-        logIfOptionParsingError(ValueOr.takeError());
+        reportOptionParsingError(ValueOr.takeError());
       return llvm::None;
     }
 
@@ -481,11 +491,12 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
     void storeInt(ClangTidyOptions::OptionMap &Options, StringRef LocalName,
                   int64_t Value) const;
 
-    /// Logs an Error to stderr if a \p Err is not a MissingOptionError.
-    static void logIfOptionParsingError(llvm::Error &&Err);
+    /// Emits a diagnostic if \p Err is not a MissingOptionError.
+    void reportOptionParsingError(llvm::Error &&Err) const;
 
     std::string NamePrefix;
     const ClangTidyOptions::OptionMap &CheckOptions;
+    ClangTidyContext *Context;
   };
 
 private:

diff  --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index e7b5b1db08eb..2c3f51a4034e 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -177,6 +177,21 @@ DiagnosticBuilder ClangTidyContext::diag(
   return DiagEngine->Report(Loc, ID);
 }
 
+DiagnosticBuilder ClangTidyContext::diag(
+    StringRef CheckName, StringRef Description,
+    DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) {
+  unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(
+      Level, (Description + " [" + CheckName + "]").str());
+  CheckNamesByDiagnosticID.try_emplace(ID, CheckName);
+  return DiagEngine->Report(ID);
+}
+
+DiagnosticBuilder ClangTidyContext::configurationDiag(
+    StringRef Message,
+    DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) {
+  return diag("clang-tidy-config", Message, Level);
+}
+
 void ClangTidyContext::setSourceManager(SourceManager *SourceMgr) {
   DiagEngine->setSourceManager(SourceMgr);
 }
@@ -256,8 +271,10 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
 void ClangTidyDiagnosticConsumer::finalizeLastError() {
   if (!Errors.empty()) {
     ClangTidyError &Error = Errors.back();
-    if (!Context.isCheckEnabled(Error.DiagnosticName) &&
-        Error.DiagLevel != ClangTidyError::Error) {
+    if (Error.DiagnosticName == "clang-tidy-config") {
+      // Never ignore these.
+    } else if (!Context.isCheckEnabled(Error.DiagnosticName) &&
+               Error.DiagLevel != ClangTidyError::Error) {
       ++Context.Stats.ErrorsIgnoredCheckFilter;
       Errors.pop_back();
     } else if (!LastErrorRelatesToUserCode) {

diff  --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index eaa7f1851ce3..079293149e90 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -96,6 +96,14 @@ class ClangTidyContext {
                          StringRef Message,
                          DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
 
+  DiagnosticBuilder diag(StringRef CheckName, StringRef Message,
+                         DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
+
+  /// Report any errors to do with reading the configuration using this method.
+  DiagnosticBuilder
+  configurationDiag(StringRef Message,
+                    DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
+
   /// Sets the \c SourceManager of the used \c DiagnosticsEngine.
   ///
   /// This is called from the \c ClangTidyCheck base class.

diff  --git a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp
index 2d3f1755d988..308424869757 100644
--- a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp
@@ -34,8 +34,8 @@ DynamicStaticInitializersCheck::DynamicStaticInitializersCheck(StringRef Name,
   if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
                                   HeaderFileExtensions,
                                   utils::defaultFileExtensionDelimiters())) {
-    llvm::errs() << "Invalid header file extension: "
-                 << RawStringHeaderFileExtensions << "\n";
+    this->configurationDiag("Invalid header file extension: '%0'")
+        << RawStringHeaderFileExtensions;
   }
 }
 

diff  --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp
index 80004f91c069..a3e5c0e26d17 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp
@@ -46,15 +46,15 @@ SuspiciousIncludeCheck::SuspiciousIncludeCheck(StringRef Name,
   if (!utils::parseFileExtensions(RawStringImplementationFileExtensions,
                                   ImplementationFileExtensions,
                                   utils::defaultFileExtensionDelimiters())) {
-    llvm::errs() << "Invalid implementation file extension: "
-                 << RawStringImplementationFileExtensions << "\n";
+    this->configurationDiag("Invalid implementation file extension: '%0'")
+        << RawStringImplementationFileExtensions;
   }
 
   if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
                                   HeaderFileExtensions,
                                   utils::defaultFileExtensionDelimiters())) {
-    llvm::errs() << "Invalid header file extension: "
-                 << RawStringHeaderFileExtensions << "\n";
+    this->configurationDiag("Invalid header file extension: '%0'")
+        << RawStringHeaderFileExtensions;
   }
 }
 

diff  --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp
index bc0a3b98ac7a..2d7500943860 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp
@@ -97,7 +97,7 @@ PreferMemberInitializerCheck::PreferMemberInitializerCheck(
       IsUseDefaultMemberInitEnabled(
           Context->isCheckEnabled("modernize-use-default-member-init")),
       UseAssignment(OptionsView("modernize-use-default-member-init",
-                                Context->getOptions().CheckOptions)
+                                Context->getOptions().CheckOptions, Context)
                         .get("UseAssignment", false)) {}
 
 void PreferMemberInitializerCheck::storeOptions(

diff  --git a/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp b/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
index 968adb882391..ae3738aa691e 100644
--- a/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp
@@ -27,8 +27,8 @@ GlobalNamesInHeadersCheck::GlobalNamesInHeadersCheck(StringRef Name,
   if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
                                   HeaderFileExtensions,
                                   utils::defaultFileExtensionDelimiters())) {
-    llvm::errs() << "Invalid header file extension: "
-                 << RawStringHeaderFileExtensions << "\n";
+    this->configurationDiag("Invalid header file extension: '%0'")
+        << RawStringHeaderFileExtensions;
   }
 }
 

diff  --git a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
index fa1df281326c..5037799a90b4 100644
--- a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
+++ b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp
@@ -26,8 +26,8 @@ UnnamedNamespaceInHeaderCheck::UnnamedNamespaceInHeaderCheck(
   if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
                                   HeaderFileExtensions,
                                   utils::defaultFileExtensionDelimiters())) {
-    llvm::errs() << "Invalid header file extension: "
-                 << RawStringHeaderFileExtensions << "\n";
+    this->configurationDiag("Invalid header file extension: '%0'")
+        << RawStringHeaderFileExtensions;
   }
 }
 

diff  --git a/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp b/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
index 6b4618ea042c..820bb3bebd91 100644
--- a/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
@@ -36,10 +36,8 @@ DefinitionsInHeadersCheck::DefinitionsInHeadersCheck(StringRef Name,
   if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
                                   HeaderFileExtensions,
                                   utils::defaultFileExtensionDelimiters())) {
-    // FIXME: Find a more suitable way to handle invalid configuration
-    // options.
-    llvm::errs() << "Invalid header file extension: "
-                 << RawStringHeaderFileExtensions << "\n";
+    this->configurationDiag("Invalid header file extension: '%0'")
+        << RawStringHeaderFileExtensions;
   }
 }
 

diff  --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
index 20791c60339a..0562467f5c61 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -19,7 +19,6 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/Casting.h"
-#include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <cstring>
@@ -501,10 +500,10 @@ LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context)
       ReverseHeader(Options.get("MakeReverseRangeHeader", "")) {
 
   if (ReverseFunction.empty() && !ReverseHeader.empty()) {
-    llvm::WithColor::warning()
-        << "modernize-loop-convert: 'MakeReverseRangeHeader' is set but "
-           "'MakeReverseRangeFunction' is not, disabling reverse loop "
-           "transformation\n";
+    configurationDiag(
+        "modernize-loop-convert: 'MakeReverseRangeHeader' is set but "
+        "'MakeReverseRangeFunction' is not, disabling reverse loop "
+        "transformation");
     UseReverseRanges = false;
   } else if (ReverseFunction.empty()) {
     UseReverseRanges = UseCxx20IfAvailable && getLangOpts().CPlusPlus20;

diff  --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
index ef8f54913ed9..d33040a00e15 100644
--- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
@@ -773,7 +773,8 @@ IdentifierNamingCheck::getStyleForFile(StringRef FileName) const {
   ClangTidyOptions Options = Context->getOptionsForFile(FileName);
   if (Options.Checks && GlobList(*Options.Checks).contains(CheckName)) {
     auto It = NamingStylesCache.try_emplace(
-        Parent, getFileStyleFromOptions({CheckName, Options.CheckOptions}));
+        Parent,
+        getFileStyleFromOptions({CheckName, Options.CheckOptions, Context}));
     assert(It.second);
     return It.first->getValue();
   }

diff  --git a/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-case-violation.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-case-violation.cpp
index 454999ed7c25..aa4a76821d66 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-case-violation.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-case-violation.cpp
@@ -5,11 +5,11 @@
 // RUN:   {key: readability-identifier-naming.ClassCase, value: UUPER_CASE}, \
 // RUN:   {key: readability-identifier-naming.StructCase, value: CAMEL}, \
 // RUN:   {key: readability-identifier-naming.EnumCase, value: AnY_cASe}, \
-// RUN:   ]}" 2>&1 | FileCheck %s --implicit-check-not warning
+// RUN:   ]}" 2>&1 | FileCheck %s --implicit-check-not="{{warning|error}}:"
 
-// CHECK-DAG: warning: invalid configuration value 'camelback' for option 'readability-identifier-naming.FunctionCase'; did you mean 'camelBack'?{{$}}
-// CHECK-DAG: warning: invalid configuration value 'UUPER_CASE' for option 'readability-identifier-naming.ClassCase'; did you mean 'UPPER_CASE'?{{$}}
+// CHECK-DAG: warning: invalid configuration value 'camelback' for option 'readability-identifier-naming.FunctionCase'; did you mean 'camelBack'? [clang-tidy-config]
+// CHECK-DAG: warning: invalid configuration value 'UUPER_CASE' for option 'readability-identifier-naming.ClassCase'; did you mean 'UPPER_CASE'? [clang-tidy-config]
 // Don't try to suggest an alternative for 'CAMEL'
-// CHECK-DAG: warning: invalid configuration value 'CAMEL' for option 'readability-identifier-naming.StructCase'{{$}}
+// CHECK-DAG: warning: invalid configuration value 'CAMEL' for option 'readability-identifier-naming.StructCase' [clang-tidy-config]
 // This fails on the EditDistance, but as it matches ignoring case suggest the correct value
-// CHECK-DAG: warning: invalid configuration value 'AnY_cASe' for option 'readability-identifier-naming.EnumCase'; did you mean 'aNy_CasE'?{{$}}
+// CHECK-DAG: warning: invalid configuration value 'AnY_cASe' for option 'readability-identifier-naming.EnumCase'; did you mean 'aNy_CasE'? [clang-tidy-config]

diff  --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
index 0894e5fd5eb9..fec9fddccd0a 100644
--- a/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
+++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp
@@ -10,7 +10,9 @@ namespace {
 class TestCheck : public ClangTidyCheck {
 public:
   TestCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+      : ClangTidyCheck(Name, Context) {
+    diag("DiagWithNoLoc");
+  }
   void registerMatchers(ast_matchers::MatchFinder *Finder) override {
     Finder->addMatcher(ast_matchers::varDecl().bind("var"), this);
   }
@@ -26,9 +28,10 @@ class TestCheck : public ClangTidyCheck {
 TEST(ClangTidyDiagnosticConsumer, SortsErrors) {
   std::vector<ClangTidyError> Errors;
   runCheckOnCode<TestCheck>("int a;", &Errors);
-  EXPECT_EQ(2ul, Errors.size());
-  EXPECT_EQ("type specifier", Errors[0].Message.Message);
-  EXPECT_EQ("variable", Errors[1].Message.Message);
+  EXPECT_EQ(3ul, Errors.size());
+  EXPECT_EQ("DiagWithNoLoc", Errors[0].Message.Message);
+  EXPECT_EQ("type specifier", Errors[1].Message.Message);
+  EXPECT_EQ("variable", Errors[2].Message.Message);
 }
 
 } // namespace test

diff  --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp
index 729dfa80502d..7e71f28d18bd 100644
--- a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp
+++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp
@@ -166,6 +166,10 @@ TEST(CheckOptionsValidation, MissingOptions) {
   ClangTidyOptions Options;
   ClangTidyContext Context(std::make_unique<DefaultOptionsProvider>(
       ClangTidyGlobalOptions(), Options));
+  ClangTidyDiagnosticConsumer DiagConsumer(Context);
+  DiagnosticsEngine DE(new DiagnosticIDs(), new DiagnosticOptions,
+                       &DiagConsumer, false);
+  Context.setDiagnosticsEngine(&DE);
   TestCheck TestCheck(&Context);
   CHECK_ERROR(TestCheck.getLocal("Opt"), MissingOptionError,
               "option not found 'test.Opt'");
@@ -191,6 +195,10 @@ TEST(CheckOptionsValidation, ValidIntOptions) {
 
   ClangTidyContext Context(std::make_unique<DefaultOptionsProvider>(
       ClangTidyGlobalOptions(), Options));
+  ClangTidyDiagnosticConsumer DiagConsumer(Context);
+  DiagnosticsEngine DE(new DiagnosticIDs(), new DiagnosticOptions,
+                       &DiagConsumer, false);
+  Context.setDiagnosticsEngine(&DE);
   TestCheck TestCheck(&Context);
 
 #define CHECK_ERROR_INT(Name, Expected)                                        \


        


More information about the cfe-commits mailing list