mgehre updated this revision to Diff 72981. mgehre added a comment. | View Revision
Add additional gsl::suppress spelling, add test, add documentation
Files:
include/clang/Basic/Attr.td
include/clang/Basic/AttrDocs.td
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaStmtAttr.cpp
test/SemaCXX/suppress.cpp
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