Capabilities are required to pass a name specifying what type of capability is being annotated. There are currently only two supported names: mutex and role. Adding functionality to check for the capability name and diagnose when it's unexpected.
Note that for backwards compatibility, an unnamed capability will default to being a "mutex." This allows the deprecated lockable attribute to continue to function. llvm-svn: 203012
This commit is contained in:
parent
d44807ca67
commit
6c8100748f
|
@ -1306,6 +1306,10 @@ def Capability : InheritableAttr {
|
|||
[GNU<"shared_capability">,
|
||||
CXX11<"clang","shared_capability">]>];
|
||||
let Documentation = [Undocumented];
|
||||
let AdditionalMembers = [{
|
||||
bool isMutex() const { return getName().equals_lower("mutex"); }
|
||||
bool isRole() const { return getName().equals_lower("role"); }
|
||||
}];
|
||||
}
|
||||
|
||||
def AssertCapability : InheritableAttr {
|
||||
|
|
|
@ -2153,6 +2153,9 @@ def note_overridden_method : Note<
|
|||
"overridden method is here">;
|
||||
|
||||
// Thread Safety Attributes
|
||||
def warn_invalid_capability_name : Warning<
|
||||
"invalid capability name '%0'; capability name must be 'mutex' or 'role'">,
|
||||
InGroup<ThreadSafetyAttributes>, DefaultIgnore;
|
||||
def warn_thread_attribute_ignored : Warning<
|
||||
"ignoring %0 attribute because its argument is invalid">,
|
||||
InGroup<ThreadSafetyAttributes>, DefaultIgnore;
|
||||
|
|
|
@ -3892,12 +3892,20 @@ static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|||
// parameters. However, semantically, both attributes represent the same
|
||||
// concept, and so they use the same semantic attribute. Eventually, the
|
||||
// lockable attribute will be removed.
|
||||
StringRef N;
|
||||
//
|
||||
// For backwards compatibility, any capability which has no specified string
|
||||
// literal will be considered a "mutex."
|
||||
StringRef N("mutex");
|
||||
SourceLocation LiteralLoc;
|
||||
if (Attr.getKind() == AttributeList::AT_Capability &&
|
||||
!S.checkStringLiteralArgumentAttr(Attr, 0, N, &LiteralLoc))
|
||||
return;
|
||||
|
||||
// Currently, there are only two names allowed for a capability: role and
|
||||
// mutex (case insensitive). Diagnose other capability names.
|
||||
if (!N.equals_lower("mutex") && !N.equals_lower("role"))
|
||||
S.Diag(LiteralLoc, diag::warn_invalid_capability_name) << N;
|
||||
|
||||
D->addAttr(::new (S.Context) CapabilityAttr(Attr.getRange(), S.Context, N,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -Wthread-safety -verify %s
|
||||
|
||||
struct __attribute__((capability("thread role"))) ThreadRole {};
|
||||
struct __attribute__((capability("role"))) ThreadRole {};
|
||||
struct __attribute__((shared_capability("mutex"))) Mutex {};
|
||||
struct NotACapability {};
|
||||
|
||||
// Test an invalid capability name
|
||||
struct __attribute__((capability("wrong"))) IncorrectName {}; // expected-warning {{invalid capability name 'wrong'; capability name must be 'mutex' or 'role'}}
|
||||
|
||||
int Test1 __attribute__((capability("test1"))); // expected-error {{'capability' attribute only applies to structs}}
|
||||
int Test2 __attribute__((shared_capability("test2"))); // expected-error {{'shared_capability' attribute only applies to structs}}
|
||||
int Test3 __attribute__((acquire_capability("test3"))); // expected-error {{'acquire_capability' attribute only applies to functions}}
|
||||
|
|
Loading…
Reference in New Issue