View Revision
mgehre updated this revision to Diff 72981.
mgehre added a comment.

Add additional gsl::suppress spelling, add test, add documentation


https://reviews.llvm.org/D24886

Files:
include/clang/Basic/Attr.td
include/clang/Basic/AttrDocs.td
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaStmtAttr.cpp
test/SemaCXX/suppress.cpp

Index: test/SemaCXX/suppress.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/suppress.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -verify
+
+[[clang::suppress("globally")]];
+
+namespace N {
+  [[clang::suppress("in-a-namespace")]];
+}
+
+[[clang::suppress("readability-identifier-naming")]]
+void f_() {
+  int *aVar_Name;
+  [[gsl::suppress("type", "bounds")]] {
+    aVar_Name = reinterpret_cast<int*>(7);
+  }
+
+  [[clang::suppress]] int x; // expected-error {{'suppress' attribute takes at least 1 argument}}
+  [[clang::suppress()]] int y; // expected-error {{'suppress' attribute takes at least 1 argument}}
+  int [[clang::suppress("r")]] z; // expected-error {{'suppress' attribute cannot be applied to types}}
+  [[clang::suppress(f_)]] float f; // expected-error {{'suppress' attribute requires a string}}
+}
+
+union [[gsl::suppress("type.1")]] U {
+  int i;
+  float f;
+};
Index: lib/Sema/SemaStmtAttr.cpp
===================================================================
--- lib/Sema/SemaStmtAttr.cpp
+++ lib/Sema/SemaStmtAttr.cpp
@@ -53,6 +53,28 @@
   return ::new (S.Context) auto(Attr);
 }
 
+static Attr *handleSuppressAttr(Sema &S, Stmt *St, const AttributeList &A,
+                                SourceRange Range) {
+  if (A.getNumArgs() < 1) {
+    S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments) << A.getName() << 1;
+    return nullptr;
+  }
+
+  std::vector<StringRef> Rules;
+  for (unsigned I = 0, E = A.getNumArgs(); I != E; ++I) {
+    StringRef RuleName;
+    SourceLocation LiteralLoc;
+
+    if (!S.checkStringLiteralArgumentAttr(A, I, RuleName, &LiteralLoc))
+      return nullptr;
+
+    Rules.push_back(RuleName);
+  }
+
+  return ::new (S.Context) SuppressAttr(A.getRange(), S.Context, Rules.data(), Rules.size(),
+                    A.getAttributeSpellingListIndex());
+}
+
 static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
                                 SourceRange) {
   IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0);
@@ -283,6 +305,8 @@
     return handleLoopHintAttr(S, St, A, Range);
   case AttributeList::AT_OpenCLUnrollHint:
     return handleOpenCLUnrollHint(S, St, A, Range);
+  case AttributeList::AT_Suppress:
+    return handleSuppressAttr(S, St, A, Range);
   default:
     // if we're here, then we parsed a known attribute, but didn't recognize
     // it as a statement attribute => it is declaration attribute
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -3838,6 +3838,26 @@
   }
 }
 
+static void handleSuppressAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+    return;
+
+  std::vector<StringRef> Rules;
+  for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) {
+    StringRef RuleName;
+    SourceLocation LiteralLoc;
+
+    if (!S.checkStringLiteralArgumentAttr(Attr, I, RuleName, &LiteralLoc))
+      return;
+
+    Rules.push_back(RuleName);
+  }
+  D->addAttr(::new (S.Context) SuppressAttr(
+      Attr.getRange(), S.Context, Rules.data(), Rules.size(),
+      Attr.getAttributeSpellingListIndex()));
+}
+
+
 bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, 
                                 const FunctionDecl *FD) {
   if (attr.isInvalid())
@@ -5830,6 +5850,9 @@
   case AttributeList::AT_PreserveAll:
     handleCallConvAttr(S, D, Attr);
     break;
+  case AttributeList::AT_Suppress:
+    handleSuppressAttr(S, D, Attr);
+    break;
   case AttributeList::AT_OpenCLKernel:
     handleSimpleAttribute<OpenCLKernelAttr>(S, D, Attr);
     break;
Index: include/clang/Basic/AttrDocs.td
===================================================================
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -2501,6 +2501,33 @@
   }];
 }
 
+def SuppressDocs : Documentation {
+  let Category = DocCatStmt;
+  let Content = [{
+The ``[[clang::suppress]]`` and ``[[gsl::suppress]]`` attributes can be used
+to suppress specific clang-tidy warnings. They can be attached to a scope,
+statement or type. The ``[[gsl::suppress]]`` is an alias of ``[[clang::suppress]]``
+which is intended to be used for suppressing rules of the C++ Core Guidelines_
+in a portable way. The attribute can be attached to declarations, statements,
+and on namespace scope.
+
+.. code-block: c++
+  [[clang::suppress("readability-identifier-naming")]]
+  void f_() {
+    int *aVar_Name;
+    [[gsl::suppress("type")]] {
+      aVar_Name = reinterpret-cast<int*>(7);
+    }
+  }
+  namespace N {
+    [[clang::suppress("type", "bounds")]];
+    ...
+  }
+
+.. Guidelines_: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#inforce-enforcement
+  }];
+}
+
 def AbiTagsDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -1464,6 +1464,12 @@
   let Documentation = [SwiftIndirectResultDocs];
 }
 
+def Suppress : StmtAttr {
+  let Spellings = [CXX11<"clang", "suppress">, CXX11<"gsl", "suppress">];
+  let Args = [VariadicStringArgument<"Rules">];
+  let Documentation = [SuppressDocs];
+}
+
 def SysVABI : InheritableAttr {
   let Spellings = [GCC<"sysv_abi">];
 //  let Subjects = [Function, ObjCMethod];
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to