diff options
author | Matthias Gehre <M.Gehre@gmx.de> | 2017-03-27 19:45:24 +0000 |
---|---|---|
committer | Matthias Gehre <M.Gehre@gmx.de> | 2017-03-27 19:45:24 +0000 |
commit | 8d45096ff7505d762c4f0d6c9907d7f3e7a0812d (patch) | |
tree | 97e900e86780596557e89934da3ae7b783afb01b /lib/Sema/SemaStmtAttr.cpp | |
parent | eec6cbfc8d18f8777ba9478f65d4ad5291180d38 (diff) | |
download | clang-8d45096ff7505d762c4f0d6c9907d7f3e7a0812d.tar.gz |
Add [[clang::suppress(rule, ...)]] attribute
Summary:
This patch implements parsing of [[clang::suppress(rule, ...)]]
and [[gsl::suppress(rule, ...)]] attributes.
C++ Core Guidelines depend heavily on tool support for
rule enforcement. They also propose a way to suppress
warnings [1] which is by annotating any ancestor in AST
with the C++11 attribute [[gsl::suppress(rule1,...)]].
To have a mechanism to suppress non-C++ Core
Guidelines specific, an additional spelling of [[clang::suppress]]
is defined.
For example, to suppress the warning cppcoreguidelines-slicing,
one could do
```
[[clang::suppress("cppcoreguidelines-slicing")]]
void f() { ... code that does slicing ... }
```
or
```
void g() {
Derived b;
[[clang::suppress("cppcoreguidelines-slicing")]]
Base a{b};
[[clang::suppress("cppcoreguidelines-slicing")]] {
doSomething();
Base a2{b};
}
}
```
This parsing can then be used by clang-tidy, which includes multiple
C++ Core Guidelines rules, to suppress warnings (see
https://reviews.llvm.org/D24888).
For the exact naming of the rule in the attribute, there
are different possibilities, which will be defined in the
corresponding clang-tidy patch.
Currently, clang-tidy supports suppressing of warnings through "//
NOLINT" comments. There are some advantages that the attribute has:
- Suppressing specific warnings instead of all warnings
- Suppressing warnings in a block (namespace, function, compound
statement)
- Code formatting may split a statement into multiple lines,
thus a "// NOLINT" comment may be on the wrong line
I'm looking forward to your comments!
[1] https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#inforce-enforcement
Reviewers: alexfh, aaron.ballman, rsmith
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D24886
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@298880 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmtAttr.cpp')
-rw-r--r-- | lib/Sema/SemaStmtAttr.cpp | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp index 01fa856132..4ee3412170 100644 --- a/lib/Sema/SemaStmtAttr.cpp +++ b/lib/Sema/SemaStmtAttr.cpp @@ -53,6 +53,31 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A, 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> DiagnosticIdentifiers; + for (unsigned I = 0, E = A.getNumArgs(); I != E; ++I) { + StringRef RuleName; + + if (!S.checkStringLiteralArgumentAttr(A, I, RuleName, nullptr)) + return nullptr; + + // FIXME: Warn if the rule name is unknown. This is tricky because only + // clang-tidy knows about available rules. + DiagnosticIdentifiers.push_back(RuleName); + } + + return ::new (S.Context) SuppressAttr( + A.getRange(), S.Context, DiagnosticIdentifiers.data(), + DiagnosticIdentifiers.size(), A.getAttributeSpellingListIndex()); +} + static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, SourceRange) { IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0); @@ -279,6 +304,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A, 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 |