mgehre created this revision.
mgehre added reviewers: alexfh, aaron.ballman.
mgehre added a subscriber: cfe-commits.
Herald added a subscriber: nemanjai.

This is a proof-of-concept how the [[clang::suppress(tags,...)]] attribute can
work with suppressing clang-tidy warnings.

The list of tags that can be used to suppress a specific warnings comes
from [1]. It is the group that the cppcoreguidelines check belongs to
("type"), the name of the check there ("type.1") and the clang-tidy
name ("cppcoreguidelines-pro-type-reinterpret-cast").

I envision to put this into all cppcoreguidelines checks. Alternatively,
this could go into clang-tidy core, to have this automatically for all
checks.

I'm looking forward to your comments!

Depends on: D24886

[1] 
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#inforce-enforcement

https://reviews.llvm.org/D24888

Files:
  clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp
  clang-tidy/cppcoreguidelines/Suppression.h
  docs/clang-tidy/checks/cppcoreguidelines-pro-type-reinterpret-cast.rst
  test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp

Index: test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp
===================================================================
--- test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp
+++ test/clang-tidy/cppcoreguidelines-pro-type-reinterpret-cast.cpp
@@ -4,3 +4,14 @@
 void *j;
 void f() { j = reinterpret_cast<void *>(i); }
 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast]
+
+[[clang::suppress("cppcoreguidelines-pro-type-reinterpret-cast")]]
+void suppress_f() { j = reinterpret_cast<void *>(i); }
+
+void suppress_f2() {
+    [[clang::suppress("type")]] j = reinterpret_cast<void *>(i);
+    [[clang::suppress("type.1")]] {
+        i = 1;
+        j = reinterpret_cast<void *>(i);
+    }
+}
Index: docs/clang-tidy/checks/cppcoreguidelines-pro-type-reinterpret-cast.rst
===================================================================
--- docs/clang-tidy/checks/cppcoreguidelines-pro-type-reinterpret-cast.rst
+++ docs/clang-tidy/checks/cppcoreguidelines-pro-type-reinterpret-cast.rst
@@ -11,3 +11,7 @@
 
 This rule is part of the "Type safety" profile of the C++ Core Guidelines, see
 https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-type-reinterpretcast.
+
+Warnings of this check can be suppressed by using the C++11 attribute
+``[[clang::suppress("tag")]]`` with a tag of either "type", "type.1" or
+"cppcoreguidelines-pro-type-reinterpret-cast".
Index: clang-tidy/cppcoreguidelines/Suppression.h
===================================================================
--- /dev/null
+++ clang-tidy/cppcoreguidelines/Suppression.h
@@ -0,0 +1,87 @@
+//===--- Suppression.h - clang-tidy------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SUPPRESSION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SUPPRESSION_H
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, AttributedStmt> attributedStmt;
+
+AST_MATCHER(Decl, hasAttrs) {
+  return Node.hasAttrs();
+}
+
+#if 0
+/// Returns true if the Node has a suppress attribute (like [[suppress(rule1,rule2)]])
+/// where the given rule appears in the rule list.
+/// If called on a Decl, assumes that hasAttrs() is true!
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(hasSuppressAttr,
+                                   AST_POLYMORPHIC_SUPPORTED_TYPES(Decl,
+                                                                   AttributedStmt),
+                                   std::string, Rule, 0) {
+  if (const auto *Suppress = getSpecificAttr<const SuppressAttr>(Node.getAttrs())) {
+    auto It = std::find_if(Suppress->rules_begin(),
+                           Suppress->rules_end(),
+                           [this](const std::string &R) {
+                             return R == this->Rule;
+                           });
+    return It != Suppress->rules_end();
+  }
+  return false;
+}
+#endif
+
+// If called on a Decl, assumes that hasAttrs() is true!
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(hasSuppressAttr,
+                                   AST_POLYMORPHIC_SUPPORTED_TYPES(Decl,
+                                                                   AttributedStmt),
+                                   std::vector<StringRef>, Rules, 0) {
+  llvm::outs() << "hasSuppressAttr called\n";
+  if (const auto *Suppress = getSpecificAttr<const SuppressAttr>(Node.getAttrs())) {
+    for(const auto& Rule : Rules) {
+      auto It = std::find_if(Suppress->rules_begin(),
+                             Suppress->rules_end(),
+                             [Rule](const std::string &R) {
+                               llvm::outs() << "Rule " << R << "\n";
+                               return R == Rule;
+                             });
+      if(It != Suppress->rules_end())
+        return true;
+    }
+  }
+  return false;
+}
+
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(hasSuppressAttr,
+                                   AST_POLYMORPHIC_SUPPORTED_TYPES(Decl,
+                                                                   AttributedStmt),
+                                   StringRef, Rule, 1) {
+  std::vector<StringRef> Rules(1, Rule);
+  return ast_matchers::internal::Matcher<NodeType>(hasSuppressAttr(Rules)).matches(Node, Finder, Builder);
+}
+
+AST_POLYMORPHIC_MATCHER_P(isSuppressed,
+                          AST_POLYMORPHIC_SUPPORTED_TYPES(Decl,
+                                                          Stmt),
+                          std::vector<StringRef>, Rules) {
+  using namespace clang::ast_matchers;
+  return ast_matchers::internal::Matcher<NodeType>(
+           anyOf(hasAncestor(attributedStmt(hasSuppressAttr(Rules))),
+                 hasAncestor(decl(hasAttrs(), hasSuppressAttr(Rules)))))
+           .matches(Node, Finder, Builder);
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_SUPPRESSION_H
Index: clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp
===================================================================
--- clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp
+++ clang-tidy/cppcoreguidelines/ProTypeReinterpretCastCheck.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "ProTypeReinterpretCastCheck.h"
+#include "Suppression.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 
@@ -21,7 +22,8 @@
   if (!getLangOpts().CPlusPlus)
     return;
 
-  Finder->addMatcher(cxxReinterpretCastExpr().bind("cast"), this);
+  std::vector<StringRef> Rules{"type", "type.1", "cppcoreguidelines-pro-type-reinterpret-cast"};
+  Finder->addMatcher(cxxReinterpretCastExpr(unless(isSuppressed(Rules))).bind("cast"), this);
 }
 
 void ProTypeReinterpretCastCheck::check(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to