[clang-tools-extra] bf6b0d1 - [clang-tidy] Support globbing in NOLINT* expressions

Carlos Galvez via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 19 09:31:20 PDT 2021


Author: Carlos Galvez
Date: 2021-10-19T16:30:51Z
New Revision: bf6b0d16747f6d1107de1a51d42ae3b0bf904537

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

LOG: [clang-tidy] Support globbing in NOLINT* expressions

To simplify suppressing warnings (for example, for
when multiple check aliases are enabled).

The globbing format reuses the same code as for
globbing when enabling checks, so the semantics
and behavior is identical.

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

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
    clang-tools-extra/clang-tidy/GlobList.cpp
    clang-tools-extra/clang-tidy/GlobList.h
    clang-tools-extra/docs/ReleaseNotes.rst
    clang-tools-extra/docs/clang-tidy/index.rst
    clang-tools-extra/test/clang-tidy/infrastructure/nolint.cpp
    clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-global-end-specific.cpp
    clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-specific-end-global.cpp
    clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-mismatched-check-names.cpp
    clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend.cpp
    clang-tools-extra/test/clang-tidy/infrastructure/nolintnextline.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index 1aa093a2e8db2..35abda42d92d7 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -35,6 +35,7 @@
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Regex.h"
 #include <tuple>
+#include <utility>
 #include <vector>
 using namespace clang;
 using namespace tidy;
@@ -321,11 +322,11 @@ void ClangTidyDiagnosticConsumer::finalizeLastError() {
 
 static bool isNOLINTFound(StringRef NolintDirectiveText, StringRef CheckName,
                           StringRef Line, size_t *FoundNolintIndex = nullptr,
-                          bool *SuppressionIsSpecific = nullptr) {
+                          StringRef *FoundNolintChecksStr = nullptr) {
   if (FoundNolintIndex)
     *FoundNolintIndex = StringRef::npos;
-  if (SuppressionIsSpecific)
-    *SuppressionIsSpecific = false;
+  if (FoundNolintChecksStr)
+    *FoundNolintChecksStr = StringRef();
 
   size_t NolintIndex = Line.find(NolintDirectiveText);
   if (NolintIndex == StringRef::npos)
@@ -345,18 +346,13 @@ static bool isNOLINTFound(StringRef NolintDirectiveText, StringRef CheckName,
     if (BracketEndIndex != StringRef::npos) {
       StringRef ChecksStr =
           Line.substr(BracketIndex, BracketEndIndex - BracketIndex);
-      // Allow disabling all the checks with "*".
-      if (ChecksStr != "*") {
-        // Allow specifying a few check names, delimited with comma.
-        SmallVector<StringRef, 1> Checks;
-        ChecksStr.split(Checks, ',', -1, false);
-        llvm::transform(Checks, Checks.begin(),
-                        [](StringRef S) { return S.trim(); });
-        if (llvm::find(Checks, CheckName) == Checks.end())
-          return false;
-        if (SuppressionIsSpecific)
-          *SuppressionIsSpecific = true;
-      }
+      if (FoundNolintChecksStr)
+        *FoundNolintChecksStr = ChecksStr;
+      // Allow specifying a few checks with a glob expression, ignoring
+      // negative globs (which would effectively disable the suppression).
+      GlobList Globs(ChecksStr, /*KeepNegativeGlobs=*/false);
+      if (!Globs.contains(CheckName))
+        return false;
     }
   }
 
@@ -388,28 +384,27 @@ static ClangTidyError createNolintError(const ClangTidyContext &Context,
   return Error;
 }
 
-static Optional<ClangTidyError>
-tallyNolintBegins(const ClangTidyContext &Context, const SourceManager &SM,
-                  StringRef CheckName, SmallVector<StringRef> Lines,
-                  SourceLocation LinesLoc,
-                  SmallVector<SourceLocation> &SpecificNolintBegins,
-                  SmallVector<SourceLocation> &GlobalNolintBegins) {
-  // Keep a running total of how many NOLINT(BEGIN...END) blocks are active.
+static Optional<ClangTidyError> tallyNolintBegins(
+    const ClangTidyContext &Context, const SourceManager &SM,
+    StringRef CheckName, SmallVector<StringRef> Lines, SourceLocation LinesLoc,
+    SmallVector<std::pair<SourceLocation, StringRef>> &NolintBegins) {
+  // Keep a running total of how many NOLINT(BEGIN...END) blocks are active, as
+  // well as the bracket expression (if any) that was used in the NOLINT
+  // expression.
   size_t NolintIndex;
-  bool SuppressionIsSpecific;
-  auto List = [&]() -> SmallVector<SourceLocation> * {
-    return SuppressionIsSpecific ? &SpecificNolintBegins : &GlobalNolintBegins;
-  };
+  StringRef NolintChecksStr;
   for (const auto &Line : Lines) {
     if (isNOLINTFound("NOLINTBEGIN", CheckName, Line, &NolintIndex,
-                      &SuppressionIsSpecific)) {
+                      &NolintChecksStr)) {
       // Check if a new block is being started.
-      List()->emplace_back(LinesLoc.getLocWithOffset(NolintIndex));
+      NolintBegins.emplace_back(std::make_pair(
+          LinesLoc.getLocWithOffset(NolintIndex), NolintChecksStr));
     } else if (isNOLINTFound("NOLINTEND", CheckName, Line, &NolintIndex,
-                             &SuppressionIsSpecific)) {
+                             &NolintChecksStr)) {
       // Check if the previous block is being closed.
-      if (!List()->empty()) {
-        List()->pop_back();
+      if (!NolintBegins.empty() &&
+          NolintBegins.back().second == NolintChecksStr) {
+        NolintBegins.pop_back();
       } else {
         // Trying to close a nonexistent block. Return a diagnostic about this
         // misuse that can be displayed along with the original clang-tidy check
@@ -432,42 +427,33 @@ lineIsWithinNolintBegin(const ClangTidyContext &Context,
                         StringRef TextAfterDiag) {
   Loc = SM.getExpansionRange(Loc).getBegin();
   SourceLocation FileStartLoc = SM.getLocForStartOfFile(SM.getFileID(Loc));
+  SmallVector<std::pair<SourceLocation, StringRef>> NolintBegins;
 
   // Check if there's an open NOLINT(BEGIN...END) block on the previous lines.
   SmallVector<StringRef> PrevLines;
   TextBeforeDiag.split(PrevLines, '\n');
-  SmallVector<SourceLocation> SpecificNolintBegins;
-  SmallVector<SourceLocation> GlobalNolintBegins;
-  auto Error =
-      tallyNolintBegins(Context, SM, CheckName, PrevLines, FileStartLoc,
-                        SpecificNolintBegins, GlobalNolintBegins);
+  auto Error = tallyNolintBegins(Context, SM, CheckName, PrevLines,
+                                 FileStartLoc, NolintBegins);
   if (Error) {
     SuppressionErrors.emplace_back(Error.getValue());
-    return false;
   }
-  bool WithinNolintBegin =
-      !SpecificNolintBegins.empty() || !GlobalNolintBegins.empty();
+  bool WithinNolintBegin = !NolintBegins.empty();
 
   // Check that every block is terminated correctly on the following lines.
   SmallVector<StringRef> FollowingLines;
   TextAfterDiag.split(FollowingLines, '\n');
   Error = tallyNolintBegins(Context, SM, CheckName, FollowingLines, Loc,
-                            SpecificNolintBegins, GlobalNolintBegins);
+                            NolintBegins);
   if (Error) {
     SuppressionErrors.emplace_back(Error.getValue());
-    return false;
   }
 
   // The following blocks were never closed. Return diagnostics for each
   // instance that can be displayed along with the original clang-tidy check
   // that the user was attempting to suppress.
-  for (const auto NolintBegin : SpecificNolintBegins) {
-    auto Error = createNolintError(Context, SM, NolintBegin, true);
-    SuppressionErrors.emplace_back(Error);
-  }
-  for (const auto NolintBegin : GlobalNolintBegins) {
-    auto Error = createNolintError(Context, SM, NolintBegin, true);
-    SuppressionErrors.emplace_back(Error);
+  for (const auto NolintBegin : NolintBegins) {
+    SuppressionErrors.emplace_back(
+        createNolintError(Context, SM, NolintBegin.first, true));
   }
 
   return WithinNolintBegin && SuppressionErrors.empty();

diff  --git a/clang-tools-extra/clang-tidy/GlobList.cpp b/clang-tools-extra/clang-tidy/GlobList.cpp
index 863bb4672852d..ccdf856083759 100644
--- a/clang-tools-extra/clang-tidy/GlobList.cpp
+++ b/clang-tools-extra/clang-tidy/GlobList.cpp
@@ -42,13 +42,14 @@ static llvm::Regex consumeGlob(StringRef &GlobList) {
   return llvm::Regex(RegexText);
 }
 
-GlobList::GlobList(StringRef Globs) {
+GlobList::GlobList(StringRef Globs, bool KeepNegativeGlobs /* =true */) {
   Items.reserve(Globs.count(',') + 1);
   do {
     GlobListItem Item;
     Item.IsPositive = !consumeNegativeIndicator(Globs);
     Item.Regex = consumeGlob(Globs);
-    Items.push_back(std::move(Item));
+    if (Item.IsPositive || KeepNegativeGlobs)
+      Items.push_back(std::move(Item));
   } while (!Globs.empty());
 }
 

diff  --git a/clang-tools-extra/clang-tidy/GlobList.h b/clang-tools-extra/clang-tidy/GlobList.h
index fe68a3497c92a..17730078b6f31 100644
--- a/clang-tools-extra/clang-tidy/GlobList.h
+++ b/clang-tools-extra/clang-tidy/GlobList.h
@@ -29,7 +29,10 @@ class GlobList {
   ///
   /// An empty \p Globs string is interpreted as one glob that matches an empty
   /// string.
-  GlobList(StringRef Globs);
+  ///
+  /// \p KeepNegativeGlobs a bool flag indicating whether to keep negative
+  /// globs from \p Globs or not. When false, negative globs are simply ignored.
+  GlobList(StringRef Globs, bool KeepNegativeGlobs = true);
 
   /// Returns \c true if the pattern matches \p S. The result is the last
   /// matching glob's Positive flag.

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 498c36e9beeb4..0ca2c5a5abc6d 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -67,6 +67,9 @@ The improvements are...
 Improvements to clang-tidy
 --------------------------
 
+- Added support for globbing in `NOLINT*` expressions, to simplify suppressing
+  multiple warnings in the same line.
+
 - Added support for `NOLINTBEGIN` ... `NOLINTEND` comments to suppress
   Clang-Tidy warnings over multiple lines.
 

diff  --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst
index e3c454554eab8..165dc4e30fe42 100644
--- a/clang-tools-extra/docs/clang-tidy/index.rst
+++ b/clang-tools-extra/docs/clang-tidy/index.rst
@@ -173,11 +173,11 @@ An overview of all the command-line options:
                                      errors were found. If compiler errors have
                                      attached fix-its, clang-tidy will apply them as
                                      well.
-    --fix-notes                    - 
-                                     If a warning has no fix, but a single fix can 
-                                     be found through an associated diagnostic note, 
-                                     apply the fix. 
-                                     Specifying this flag will implicitly enable the 
+    --fix-notes                    -
+                                     If a warning has no fix, but a single fix can
+                                     be found through an associated diagnostic note,
+                                     apply the fix.
+                                     Specifying this flag will implicitly enable the
                                      '--fix' flag.
     --format-style=<string>        -
                                      Style for formatting code around applied fixes:
@@ -308,7 +308,9 @@ clang-tidy warnings on *multiple lines* (affecting all lines between the two
 comments).
 
 All comments can be followed by an optional list of check names in parentheses
-(see below for the formal syntax).
+(see below for the formal syntax). The list of check names supports globbing,
+with the same format and semantics as for enabling checks. Note: negative globs
+are ignored here, as they would effectively re-activate the warning.
 
 For example:
 
@@ -324,15 +326,39 @@ For example:
     // Silence only the specified checks for the line
     Foo(double param); // NOLINT(google-explicit-constructor, google-runtime-int)
 
+    // Silence all checks from the `google` module
+    Foo(bool param); // NOLINT(google*)
+
+    // Silence all checks ending with `-avoid-c-arrays`
+    int array[10]; // NOLINT(*-avoid-c-arrays)
+
     // Silence only the specified diagnostics for the next line
     // NOLINTNEXTLINE(google-explicit-constructor, google-runtime-int)
     Foo(bool param);
 
+    // Silence all checks from the `google` module for the next line
+    // NOLINTNEXTLINE(google*)
+    Foo(bool param);
+
+    // Silence all checks ending with `-avoid-c-arrays` for the next line
+    // NOLINTNEXTLINE(*-avoid-c-arrays)
+    int array[10];
+
     // Silence only the specified checks for all lines between the BEGIN and END
     // NOLINTBEGIN(google-explicit-constructor, google-runtime-int)
     Foo(short param);
     Foo(long param);
     // NOLINTEND(google-explicit-constructor, google-runtime-int)
+
+    // Silence all checks from the `google` module for all lines between the BEGIN and END
+    // NOLINTBEGIN(google*)
+    Foo(bool param);
+    // NOLINTEND(google*)
+
+    // Silence all checks ending with `-avoid-c-arrays` for all lines between the BEGIN and END
+    // NOLINTBEGIN(*-avoid-c-arrays)
+    int array[10];
+    // NOLINTEND(*-avoid-c-arrays)
   };
 
 The formal syntax of ``NOLINT``, ``NOLINTNEXTLINE``, and ``NOLINTBEGIN`` ...

diff  --git a/clang-tools-extra/test/clang-tidy/infrastructure/nolint.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/nolint.cpp
index fc17f12855127..4b80bbe4eb3ca 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/nolint.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/nolint.cpp
@@ -1,5 +1,5 @@
 // REQUIRES: static-analyzer
-// RUN: %check_clang_tidy %s google-explicit-constructor,clang-diagnostic-unused-variable,clang-analyzer-core.UndefinedBinaryOperatorResult %t -- -extra-arg=-Wunused-variable -- -I%S/Inputs/nolint
+// RUN: %check_clang_tidy %s google-explicit-constructor,clang-diagnostic-unused-variable,clang-analyzer-core.UndefinedBinaryOperatorResult,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays %t -- -extra-arg=-Wunused-variable -- -I%S/Inputs/nolint
 
 #include "trigger_warning.h"
 void I(int& Out) {
@@ -17,17 +17,20 @@ class B { B(int i); }; // NOLINT
 class C { C(int i); }; // NOLINT(for-some-other-check)
 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
 
-class C1 { C1(int i); }; // NOLINT(*)
+class C1 { C1(int i); }; // NOLINT()
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: single-argument constructors must be marked explicit
+
+class C2 { C2(int i); }; // NOLINT(*)
 
-class C2 { C2(int i); }; // NOLINT(not-closed-bracket-is-treated-as-skip-all
+class C3 { C3(int i); }; // NOLINT(not-closed-bracket-is-treated-as-skip-all
 
-class C3 { C3(int i); }; // NOLINT(google-explicit-constructor)
+class C4 { C4(int i); }; // NOLINT(google-explicit-constructor)
 
-class C4 { C4(int i); }; // NOLINT(some-check, google-explicit-constructor)
+class C5 { C5(int i); }; // NOLINT(some-check, google-explicit-constructor)
 
-class C5 { C5(int i); }; // NOLINT without-brackets-skip-all, another-check
+class C6 { C6(int i); }; // NOLINT without-brackets-skip-all, another-check
 
-class C6 { C6(int i); }; // NOLINTNEXTLINE doesn't get misconstrued as a NOLINT
+class C7 { C7(int i); }; // NOLINTNEXTLINE doesn't get misconstrued as a NOLINT
 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: single-argument constructors must be marked explicit
 
 void f() {
@@ -51,4 +54,21 @@ MACRO_NOLINT
 #define DOUBLE_MACRO MACRO(H) // NOLINT
 DOUBLE_MACRO
 
-// CHECK-MESSAGES: Suppressed 13 warnings (13 NOLINT)
+class D1 { D1(int x); }; // NOLINT(google*)
+class D2 { D2(int x); }; // NOLINT(*explicit-constructor)
+class D3 { D3(int x); }; // NOLINT(*explicit*)
+class D4 { D4(int x); }; // NOLINT(-explicit-constructor)
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: single-argument constructors must be marked explicit
+class D5 { D5(int x); }; // NOLINT(google*,-google*)
+class D6 { D6(int x); }; // NOLINT(*,-google*)
+
+int array1[10];
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead [cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays]
+
+int array2[10];  // NOLINT(cppcoreguidelines-avoid-c-arrays)
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead [modernize-avoid-c-arrays]
+
+int array3[10];  // NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
+int array4[10];  // NOLINT(*-avoid-c-arrays)
+
+// CHECK-MESSAGES: Suppressed 23 warnings (23 NOLINT)

diff  --git a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-global-end-specific.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-global-end-specific.cpp
index b19d987994cad..01e69ddf6352a 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-global-end-specific.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-global-end-specific.cpp
@@ -11,3 +11,15 @@ class A { A(int i); };
 // CHECK: :[[@LINE-6]]:4: error: unmatched 'NOLIN
 // CHECK: TEND' comment without a previous 'NOLIN
 // CHECK: TBEGIN' comment [clang-tidy-nolint]
+
+// NOLINTBEGIN
+class B { B(int i); };
+// NOLINTEND(*)
+
+// Note: the expected output has been split over several lines so that clang-tidy
+//       does not see the "no lint" suppression comment and mistakenly assume it
+//       is meant for itself.
+// CHECK: :[[@LINE-6]]:11: warning: single-argument constructors must be marked explicit
+// CHECK: :[[@LINE-6]]:4: error: unmatched 'NOLIN
+// CHECK: TEND' comment without a previous 'NOLIN
+// CHECK: TBEGIN' comment [clang-tidy-nolint]

diff  --git a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-specific-end-global.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-specific-end-global.cpp
index 67ca4b7aaf0d7..c6fcfddd09ba8 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-specific-end-global.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-specific-end-global.cpp
@@ -11,3 +11,15 @@ class A { A(int i); };
 // CHECK: :[[@LINE-6]]:4: error: unmatched 'NOLIN
 // CHECK: TEND' comment without a previous 'NOLIN
 // CHECK: TBEGIN' comment [clang-tidy-nolint]
+
+// NOLINTBEGIN(*)
+class B { B(int i); };
+// NOLINTEND
+
+// Note: the expected output has been split over several lines so that clang-tidy
+//       does not see the "no lint" suppression comment and mistakenly assume it
+//       is meant for itself.
+// CHECK: :[[@LINE-6]]:11: warning: single-argument constructors must be marked explicit
+// CHECK: :[[@LINE-6]]:4: error: unmatched 'NOLIN
+// CHECK: TEND' comment without a previous 'NOLIN
+// CHECK: TBEGIN' comment [clang-tidy-nolint]

diff  --git a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-mismatched-check-names.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-mismatched-check-names.cpp
index 8d7786fb8c712..957b0b341a3cc 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-mismatched-check-names.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-mismatched-check-names.cpp
@@ -16,3 +16,24 @@ auto Num = (unsigned int)(-1);
 // CHECK: :[[@LINE-10]]:4: error: unmatched 'NOLIN
 // CHECK: TEND' comment without a previous 'NOLIN
 // CHECK: TBEGIN' comment [clang-tidy-nolint]
+
+// NOLINTBEGIN(google-explicit-constructor,google-readability-casting)
+class B { B(int i); };
+// NOLINTEND(google-explicit-constructor)
+auto Num2 = (unsigned int)(-1);
+// NOLINTEND(google-readability-casting)
+
+// Note: the expected output has been split over several lines so that clang-tidy
+//       does not see the "no lint" suppression comment and mistakenly assume it
+//       is meant for itself.
+// CHECK: :[[@LINE-9]]:4: error: unmatched 'NOLIN
+// CHECK: TBEGIN' comment without a subsequent 'NOLIN
+// CHECK: TEND' comment [clang-tidy-nolint]
+// CHECK: :[[@LINE-11]]:11: warning: single-argument constructors must be marked explicit
+// CHECK: :[[@LINE-11]]:4: error: unmatched 'NOLIN
+// CHECK: TEND' comment without a previous 'NOLIN
+// CHECK: TBEGIN' comment [clang-tidy-nolint]
+// CHECK: :[[@LINE-13]]:13: warning: C-style casts are discouraged; use static_cast
+// CHECK: :[[@LINE-13]]:4: error: unmatched 'NOLIN
+// CHECK: TEND' comment without a previous 'NOLIN
+// CHECK: TBEGIN' comment [clang-tidy-nolint]

diff  --git a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend.cpp
index 562cf4fc6039d..8379128530180 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s google-explicit-constructor %t
+// RUN: %check_clang_tidy %s google-explicit-constructor,clang-diagnostic-unused-variable,cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays %t -- -extra-arg=-Wunused-variable
 
 class A { A(int i); };
 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
@@ -34,60 +34,54 @@ class B5 { B5(int i); };
 class C1 { C1(int i); };
 // NOLINTEND(google-explicit-constructor)
 
-// NOLINTBEGIN(*)
+// NOLINTBEGIN()
 class C2 { C2(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: single-argument constructors must be marked explicit
+// NOLINTEND()
+
+// NOLINTBEGIN(*)
+class C3 { C3(int i); };
 // NOLINTEND(*)
 
 // NOLINTBEGIN(some-other-check)
-class C3 { C3(int i); };
+class C4 { C4(int i); };
 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: single-argument constructors must be marked explicit
 // NOLINTEND(some-other-check)
 
 // NOLINTBEGIN(some-other-check, google-explicit-constructor)
-class C4 { C4(int i); };
-// NOLINTEND(some-other-check, google-explicit-constructor)
-
-// NOLINTBEGIN(some-other-check, google-explicit-constructor)
-// NOLINTEND(some-other-check)
 class C5 { C5(int i); };
-// NOLINTEND(google-explicit-constructor)
-
-// NOLINTBEGIN(some-other-check, google-explicit-constructor)
-// NOLINTEND(google-explicit-constructor)
-class C6 { C6(int i); };
-// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: single-argument constructors must be marked explicit
-// NOLINTEND(some-other-check)
+// NOLINTEND(some-other-check, google-explicit-constructor)
 
 // NOLINTBEGIN(google-explicit-constructor)
 // NOLINTBEGIN(some-other-check)
-class C7 { C7(int i); };
+class C6 { C6(int i); };
 // NOLINTEND(some-other-check)
 // NOLINTEND(google-explicit-constructor)
 
 // NOLINTBEGIN(google-explicit-constructor)
 // NOLINTBEGIN(some-other-check)
-class C8 { C8(int i); };
+class C7 { C7(int i); };
 // NOLINTEND(google-explicit-constructor)
 // NOLINTEND(some-other-check)
 
 // NOLINTBEGIN(google-explicit-constructor)
 // NOLINTBEGIN
-class C9 { C9(int i); };
+class C8 { C8(int i); };
 // NOLINTEND
 // NOLINTEND(google-explicit-constructor)
 
 // NOLINTBEGIN
 // NOLINTBEGIN(google-explicit-constructor)
-class C10 { C10(int i); };
+class C9 { C9(int i); };
 // NOLINTEND(google-explicit-constructor)
 // NOLINTEND
 
 // NOLINTBEGIN(not-closed-bracket-is-treated-as-skip-all
-class C11 { C11(int i); };
+class C10 { C10(int i); };
 // NOLINTEND(not-closed-bracket-is-treated-as-skip-all
 
 // NOLINTBEGIN without-brackets-skip-all, another-check
-class C12 { C12(int i); };
+class C11 { C11(int i); };
 // NOLINTEND without-brackets-skip-all, another-check
 
 #define MACRO(X) class X { X(int i); };
@@ -119,4 +113,45 @@ MACRO_WRAPPED_WITH_NO_LINT
 
 MACRO_NO_LINT_INSIDE_MACRO
 
-// CHECK-MESSAGES: Suppressed 18 warnings (18 NOLINT).
+// NOLINTBEGIN(google*)
+class C12 { C12(int i); };
+// NOLINTEND(google*)
+
+// NOLINTBEGIN(*explicit-constructor)
+class C15 { C15(int i); };
+// NOLINTEND(*explicit-constructor)
+
+// NOLINTBEGIN(*explicit*)
+class C16 { C16(int i); };
+// NOLINTEND(*explicit*)
+
+// NOLINTBEGIN(-explicit-constructor)
+class C17 { C17(int x); };
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: single-argument constructors must be marked explicit
+// NOLINTEND(-explicit-constructor)
+
+// NOLINTBEGIN(google*,-google*)
+class C18 { C18(int x); };
+// NOLINTEND(google*,-google*)
+
+// NOLINTBEGIN(*,-google*)
+class C19 { C19(int x); };
+// NOLINTEND(*,-google*)
+
+int array1[10];
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead [cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays]
+
+// NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays)
+int array2[10];
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead [modernize-avoid-c-arrays]
+// NOLINTEND(cppcoreguidelines-avoid-c-arrays)
+
+// NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
+int array3[10];
+// NOLINTEND(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
+
+// NOLINTBEGIN(*-avoid-c-arrays)
+int array4[10];
+// NOLINTEND(*-avoid-c-arrays)
+
+// CHECK-MESSAGES: Suppressed 27 warnings (27 NOLINT).

diff  --git a/clang-tools-extra/test/clang-tidy/infrastructure/nolintnextline.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/nolintnextline.cpp
index 0370621f7dddd..7b0a2c4374aa2 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/nolintnextline.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/nolintnextline.cpp
@@ -11,21 +11,25 @@ class C { C(int i); };
 class D { D(int i); };
 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
 
-// NOLINTNEXTLINE(*)
+// NOLINTNEXTLINE()
 class D1 { D1(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: single-argument constructors must be marked explicit
 
-// NOLINTNEXTLINE(not-closed-bracket-is-treated-as-skip-all
+// NOLINTNEXTLINE(*)
 class D2 { D2(int i); };
 
-// NOLINTNEXTLINE(google-explicit-constructor)
+// NOLINTNEXTLINE(not-closed-bracket-is-treated-as-skip-all
 class D3 { D3(int i); };
 
-// NOLINTNEXTLINE(some-check, google-explicit-constructor)
+// NOLINTNEXTLINE(google-explicit-constructor)
 class D4 { D4(int i); };
 
-// NOLINTNEXTLINE without-brackets-skip-all, another-check
+// NOLINTNEXTLINE(some-check, google-explicit-constructor)
 class D5 { D5(int i); };
 
+// NOLINTNEXTLINE without-brackets-skip-all, another-check
+class D6 { D6(int i); };
+
 // NOLINTNEXTLINE
 
 class E { E(int i); };
@@ -46,6 +50,38 @@ MACRO(H)
 // NOLINTNEXTLINE
 MACRO_NOARG
 
-// CHECK-MESSAGES: Suppressed 9 warnings (9 NOLINT)
+// NOLINTNEXTLINE(google*)
+class I1 { I1(int i); };
+
+// NOLINTNEXTLINE(*explicit-constructor)
+class I2 { I2(int i); };
+
+// NOLINTNEXTLINE(*explicit*)
+class I3 { I3(int i); };
+
+// NOLINTNEXTLINE(-explicit-constructor)
+class I4 { I4(int x); };
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: single-argument constructors must be marked explicit
+
+// NOLINTNEXTLINE(google*,-google*)
+class I5 { I5(int x); };
+
+// NOLINTNEXTLINE(*,-google*)
+class I6 { I6(int x); };
+
+int array1[10];
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead [cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays]
+
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
+int array2[10];
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead [modernize-avoid-c-arrays]
+
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
+int array3[10];
+
+// NOLINTNEXTLINE(*-avoid-c-arrays)
+int array4[10];
+
+// CHECK-MESSAGES: Suppressed 19 warnings (19 NOLINT)
 
-// RUN: %check_clang_tidy %s google-explicit-constructor %t --
+// RUN: %check_clang_tidy %s google-explicit-constructor,clang-diagnostic-unused-variable,cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays %t -- -extra-arg=-Wunused-variable


        


More information about the cfe-commits mailing list