xgsa updated this revision to Diff 125328.
https://reviews.llvm.org/D40671
Files:
clang-tidy/ClangTidyDiagnosticConsumer.cpp
docs/ReleaseNotes.rst
docs/clang-tidy/index.rst
test/clang-tidy/nolint.cpp
test/clang-tidy/nolintnextline.cpp
Index: docs/clang-tidy/index.rst
===================================================================
--- docs/clang-tidy/index.rst
+++ docs/clang-tidy/index.rst
@@ -250,6 +250,57 @@
value: 'some value'
...
+While :program:`clang-tidy` diagnostics are intended to call out code that does
+not adhere to a coding standard, or is otherwise problematic in some way, there
+are times when it is more appropriate to silence the diagnostic instead of
+changing the semantics of the code. The preferable way of doing this is using
+the check-specific ways to mute diagnostics, if they are available (e.g.
+bugprone-use-after-move can be silenced by re-initializing the variable after
+it has been moved out, misc-string-integer-assignment can be suppressed by
+explicitly casting the integer to char, readability-implicit-bool-conversion
+can also be suppressed by using explicit casts, etc.). Otherwise,
+the ``NOLINT`` or ``NOLINTNEXTLINE`` comments can be used to silence
+the diagnostic. For example:
+
+.. code-block:: c++
+
+ class Foo
+ {
+ // Skip all the diagnostics for the line
+ Foo(int param); // NOLINT
+
+ // Skip only the specified checks for the line
+ Foo(double param); // NOLINT(google-explicit-constructor, google-runtime-int)
+
+ // Skip only the specified diagnostics for the next line
+ // NOLINTNEXTLINE(google-explicit-constructor, google-runtime-int)
+ Foo(bool param);
+ };
+
+The formal syntax of ``NOLINT``/``NOLINTNEXTLINE`` is the following:
+
+.. parsed-literal::
+
+ lint-comment:
+ lint-command
+ lint-command lint-args
+
+ lint-args:
+ **(** check-name-list **)**
+
+ check-name-list:
+ *check-name*
+ check-name-list **,** *check-name*
+
+ lint-command:
+ **NOLINT**
+ **NOLINTNEXTLINE**
+
+Note that whitespaces between ``NOLINT``/``NOLINTNEXTLINE`` and the opening
+parenthesis are not allowed (in this case the comment will be treated just as
+``NOLINT``/``NOLINTNEXTLINE``), whereas in check names list (inside
+the parenthesis) whitespaces can be used and will be ignored.
+
.. _LibTooling: http://clang.llvm.org/docs/LibTooling.html
.. _How To Setup Tooling For LLVM: http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -256,6 +256,8 @@
- `hicpp-use-nullptr <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-use-nullptr.html>`_
- `hicpp-vararg <http://clang.llvm.org/extra/clang-tidy/checks/hicpp-vararg.html>`_
+- Added the ability to suppress specific checks (or all checks) in a ``NOLINT`` or ``NOLINTNEXTLINE`` comment.
+
Improvements to include-fixer
-----------------------------
Index: test/clang-tidy/nolint.cpp
===================================================================
--- test/clang-tidy/nolint.cpp
+++ test/clang-tidy/nolint.cpp
@@ -13,7 +13,18 @@
class B { B(int i); }; // NOLINT
-class C { C(int i); }; // NOLINT(we-dont-care-about-categories-yet)
+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 C2 { C2(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(some-check, google-explicit-constructor)
+
+class C5 { C5(int i); }; // NOLINT without-brackets-skip-all, another-check
void f() {
int i;
@@ -35,4 +46,4 @@
#define DOUBLE_MACRO MACRO(H) // NOLINT
DOUBLE_MACRO
-// CHECK-MESSAGES: Suppressed 8 warnings (8 NOLINT)
+// CHECK-MESSAGES: Suppressed 12 warnings (12 NOLINT)
Index: test/clang-tidy/nolintnextline.cpp
===================================================================
--- test/clang-tidy/nolintnextline.cpp
+++ test/clang-tidy/nolintnextline.cpp
@@ -4,8 +4,24 @@
// NOLINTNEXTLINE
class B { B(int i); };
-// NOLINTNEXTLINE(we-dont-care-about-categories-yet)
+// NOLINTNEXTLINE(for-some-other-check)
class C { C(int i); };
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: single-argument constructors must be marked explicit
+
+// NOLINTNEXTLINE(*)
+class C1 { C1(int i); };
+
+// NOLINTNEXTLINE(not-closed-bracket-is-treated-as-skip-all
+class C2 { C2(int i); };
+
+// NOLINTNEXTLINE(google-explicit-constructor)
+class C3 { C3(int i); };
+
+// NOLINTNEXTLINE(some-check, google-explicit-constructor)
+class C4 { C4(int i); };
+
+// NOLINTNEXTLINE without-brackets-skip-all, another-check
+class C5 { C5(int i); };
// NOLINTNEXTLINE
@@ -28,6 +44,6 @@
// NOLINTNEXTLINE
MACRO_NOARG
-// CHECK-MESSAGES: Suppressed 4 warnings (4 NOLINT)
+// CHECK-MESSAGES: Suppressed 8 warnings (8 NOLINT)
// RUN: %check_clang_tidy %s google-explicit-constructor %t --
Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp
===================================================================
--- clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/ASTDiagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/DiagnosticRenderer.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include <tuple>
#include <vector>
@@ -290,7 +291,38 @@
LastErrorPassesLineFilter = false;
}
-static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc) {
+static bool IsNOLINTFound(StringRef NolintDirectiveText, StringRef Line,
+ unsigned DiagID, const ClangTidyContext &Context) {
+ const size_t NolintIndex = Line.find(NolintDirectiveText);
+ if (NolintIndex == StringRef::npos)
+ return false;
+
+ size_t BracketIndex = NolintIndex + NolintDirectiveText.size();
+ // Check if the specific checks are specified in brackets.
+ if (BracketIndex < Line.size() && Line[BracketIndex] == '(') {
+ ++BracketIndex;
+ const size_t BracketEndIndex = Line.find(')', BracketIndex);
+ if (BracketEndIndex != StringRef::npos) {
+ StringRef ChecksStr =
+ Line.substr(BracketIndex, BracketEndIndex - BracketIndex);
+ // Allow disabling all the checks with "*".
+ if (ChecksStr != "*") {
+ StringRef CheckName = Context.getCheckName(DiagID);
+ // 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(); });
+ return llvm::find(Checks, CheckName) != Checks.end();
+ }
+ }
+ }
+ return true;
+}
+
+static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc,
+ unsigned DiagID,
+ const ClangTidyContext &Context) {
bool Invalid;
const char *CharacterData = SM.getCharacterData(Loc, &Invalid);
if (Invalid)
@@ -301,8 +333,7 @@
while (*P != '\0' && *P != '\r' && *P != '\n')
++P;
StringRef RestOfLine(CharacterData, P - CharacterData + 1);
- // FIXME: Handle /\bNOLINT\b(\([^)]*\))?/ as cpplint.py does.
- if (RestOfLine.find("NOLINT") != StringRef::npos)
+ if (IsNOLINTFound("NOLINT", RestOfLine, DiagID, Context))
return true;
// Check if there's a NOLINTNEXTLINE on the previous line.
@@ -329,16 +360,17 @@
--P;
RestOfLine = StringRef(P, LineEnd - P + 1);
- if (RestOfLine.find("NOLINTNEXTLINE") != StringRef::npos)
+ if (IsNOLINTFound("NOLINTNEXTLINE", RestOfLine, DiagID, Context))
return true;
return false;
}
-static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM,
- SourceLocation Loc) {
+static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM, SourceLocation Loc,
+ unsigned DiagID,
+ const ClangTidyContext &Context) {
while (true) {
- if (LineIsMarkedWithNOLINT(SM, Loc))
+ if (LineIsMarkedWithNOLINT(SM, Loc, DiagID, Context))
return true;
if (!Loc.isMacroID())
return false;
@@ -355,7 +387,8 @@
if (Info.getLocation().isValid() && DiagLevel != DiagnosticsEngine::Error &&
DiagLevel != DiagnosticsEngine::Fatal &&
LineIsMarkedWithNOLINTinMacro(Diags->getSourceManager(),
- Info.getLocation())) {
+ Info.getLocation(), Info.getID(),
+ Context)) {
++Context.Stats.ErrorsIgnoredNOLINT;
// Ignored a warning, should ignore related notes as well
LastErrorWasIgnored = true;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits