r201890 - Adding role-based capability attributes that allow you to express role management: asserting a capability is held, acquiring a capability and releasing a capability. Also includes some skeleton documentation for these new attributes.
Aaron Ballman
aaron at aaronballman.com
Fri Feb 21 13:05:15 PST 2014
Author: aaronballman
Date: Fri Feb 21 15:05:14 2014
New Revision: 201890
URL: http://llvm.org/viewvc/llvm-project?rev=201890&view=rev
Log:
Adding role-based capability attributes that allow you to express role management: asserting a capability is held, acquiring a capability and releasing a capability. Also includes some skeleton documentation for these new attributes.
This functionality should be considered a WIP.
Modified:
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Basic/AttrDocs.td
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/Sema/attr-capabilities.c
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=201890&r1=201889&r2=201890&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Fri Feb 21 15:05:14 2014
@@ -1302,6 +1302,82 @@ def Capability : InheritableAttr {
let Documentation = [Undocumented];
}
+def AssertCapability : InheritableAttr {
+ let Spellings = [GNU<"assert_capability">,
+ CXX11<"clang", "assert_capability">,
+ GNU<"assert_shared_capability">,
+ CXX11<"clang", "assert_shared_capability">];
+ let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Args = [ExprArgument<"Expr">];
+ let Accessors = [Accessor<"isShared",
+ [GNU<"assert_shared_capability">,
+ CXX11<"clang", "assert_shared_capability">]>];
+ let Documentation = [AssertCapabilityDocs];
+}
+
+def AcquireCapability : InheritableAttr {
+ let Spellings = [GNU<"acquire_capability">,
+ CXX11<"clang", "acquire_capability">,
+ GNU<"acquire_shared_capability">,
+ CXX11<"clang", "acquire_shared_capability">];
+ let Subjects = SubjectList<[Function, FunctionTemplate],
+ ErrorDiag>;
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Args = [VariadicExprArgument<"Args">];
+ let Accessors = [Accessor<"isShared",
+ [GNU<"acquire_shared_capability">,
+ CXX11<"clang", "acquire_shared_capability">]>];
+ let Documentation = [AcquireCapabilityDocs];
+}
+
+def TryAcquireCapability : InheritableAttr {
+ let Spellings = [GNU<"try_acquire_capability">,
+ CXX11<"clang", "try_acquire_capability">,
+ GNU<"try_acquire_shared_capability">,
+ CXX11<"clang", "try_acquire_shared_capability">];
+ let Subjects = SubjectList<[Function, FunctionTemplate],
+ ErrorDiag>;
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
+ let Accessors = [Accessor<"isShared",
+ [GNU<"try_acquire_shared_capability">,
+ CXX11<"clang", "try_acquire_shared_capability">]>];
+ let Documentation = [TryAcquireCapabilityDocs];
+}
+
+def ReleaseCapability : InheritableAttr {
+ let Spellings = [GNU<"release_capability">,
+ CXX11<"clang", "release_capability">,
+ GNU<"release_shared_capability">,
+ CXX11<"clang", "release_shared_capability">,
+ GNU<"release_generic_capability">,
+ CXX11<"clang", "release_generic_capability">];
+ let Subjects = SubjectList<[Function, FunctionTemplate],
+ ErrorDiag>;
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Args = [VariadicExprArgument<"Args">];
+ let Accessors = [Accessor<"isShared",
+ [GNU<"release_shared_capability">,
+ CXX11<"clang", "release_shared_capability">]>,
+ Accessor<"isGeneric",
+ [GNU<"release_generic_capability">,
+ CXX11<"clang", "release_generic_capability">]>];
+ let Documentation = [ReleaseCapabilityDocs];
+}
+
def RequiresCapability : InheritableAttr {
let Spellings = [GNU<"requires_capability">,
CXX11<"clang", "requires_capability">,
Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=201890&r1=201889&r2=201890&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Fri Feb 21 15:05:14 2014
@@ -77,6 +77,37 @@ that appears to be capable of returning
}];
}
+def AssertCapabilityDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Marks a function that dynamically tests whether a capability is held, and halts
+the program if it is not held.
+ }];
+}
+
+def AcquireCapabilityDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Marks a function as acquiring a capability.
+ }];
+}
+
+def TryAcquireCapabilityDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Marks a function that attemps to aquire a capability. This function may fail to
+actually acquire the capability; they accept a Boolean value determining
+whether acquiring the capability means success (true), or failing to acquire
+the capability means success (false).
+ }];
+}
+
+def ReleaseCapabilityDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Marks a function as releasing a capability.
+ }];
+}
def EnableIfDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=201890&r1=201889&r2=201890&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Feb 21 15:05:14 2014
@@ -3905,6 +3905,61 @@ static void handleCapabilityAttr(Sema &S
Attr.getAttributeSpellingListIndex()));
}
+static void handleAssertCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ D->addAttr(::new (S.Context) AssertCapabilityAttr(Attr.getRange(), S.Context,
+ Attr.getArgAsExpr(0),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleAcquireCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ SmallVector<Expr*, 1> Args;
+ if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ return;
+
+ // Check that all arguments are lockable objects.
+ checkAttrArgsAreLockableObjs(S, D, Attr, Args);
+ if (Args.empty())
+ return;
+
+ D->addAttr(::new (S.Context) AcquireCapabilityAttr(Attr.getRange(),
+ S.Context,
+ Args.data(), Args.size(),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ SmallVector<Expr*, 2> Args;
+ if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
+ return;
+
+ D->addAttr(::new (S.Context) TryAcquireCapabilityAttr(Attr.getRange(),
+ S.Context,
+ Attr.getArgAsExpr(0),
+ Args.data(),
+ Args.size(),
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleReleaseCapabilityAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ SmallVector<Expr*, 1> Args;
+ if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
+ return;
+
+ // Check that all arguments are lockable objects.
+ checkAttrArgsAreLockableObjs(S, D, Attr, Args);
+ if (Args.empty())
+ return;
+
+ D->addAttr(::new (S.Context) ReleaseCapabilityAttr(Attr.getRange(),
+ S.Context,
+ Args.data(), Args.size(),
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
@@ -4275,8 +4330,17 @@ static void ProcessDeclAttribute(Sema &S
case AttributeList::AT_Capability:
case AttributeList::AT_Lockable:
handleCapabilityAttr(S, D, Attr); break;
- case AttributeList::AT_RequiresCapability:
- handleRequiresCapabilityAttr(S, D, Attr); break;
+ case AttributeList::AT_RequiresCapability:
+ handleRequiresCapabilityAttr(S, D, Attr); break;
+
+ case AttributeList::AT_AssertCapability:
+ handleAssertCapabilityAttr(S, D, Attr); break;
+ case AttributeList::AT_AcquireCapability:
+ handleAcquireCapabilityAttr(S, D, Attr); break;
+ case AttributeList::AT_ReleaseCapability:
+ handleReleaseCapabilityAttr(S, D, Attr); break;
+ case AttributeList::AT_TryAcquireCapability:
+ handleTryAcquireCapabilityAttr(S, D, Attr); break;
// Consumed analysis attributes.
case AttributeList::AT_Consumable:
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=201890&r1=201889&r2=201890&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Feb 21 15:05:14 2014
@@ -12752,6 +12752,13 @@ bool Sema::checkThisInStaticMemberFuncti
else if (RequiresCapabilityAttr *RC
= dyn_cast<RequiresCapabilityAttr>(*A))
Args = ArrayRef<Expr *>(RC->args_begin(), RC->args_size());
+ else if (AcquireCapabilityAttr *AC = dyn_cast<AcquireCapabilityAttr>(*A))
+ Args = ArrayRef<Expr *>(AC->args_begin(), AC->args_size());
+ else if (TryAcquireCapabilityAttr *AC
+ = dyn_cast<TryAcquireCapabilityAttr>(*A))
+ Args = ArrayRef<Expr *>(AC->args_begin(), AC->args_size());
+ else if (ReleaseCapabilityAttr *RC = dyn_cast<ReleaseCapabilityAttr>(*A))
+ Args = ArrayRef<Expr *>(RC->args_begin(), RC->args_size());
if (Arg && !Finder.TraverseStmt(Arg))
return true;
Modified: cfe/trunk/test/Sema/attr-capabilities.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-capabilities.c?rev=201890&r1=201889&r2=201890&view=diff
==============================================================================
--- cfe/trunk/test/Sema/attr-capabilities.c (original)
+++ cfe/trunk/test/Sema/attr-capabilities.c Fri Feb 21 15:05:14 2014
@@ -6,6 +6,9 @@ struct NotACapability {};
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}}
+int Test4 __attribute__((try_acquire_capability("test4"))); // expected-error {{'try_acquire_capability' attribute only applies to functions}}
+int Test5 __attribute__((release_capability("test5"))); // expected-error {{'release_capability' attribute only applies to functions}}
struct __attribute__((capability(12))) Test3 {}; // expected-error {{'capability' attribute requires a string}}
struct __attribute__((shared_capability(Test2))) Test4 {}; // expected-error {{'shared_capability' attribute requires a string}}
@@ -23,3 +26,32 @@ void Func4(void) __attribute__((requires
void Func5(void) __attribute__((requires_capability(1))) {} // expected-warning {{'requires_capability' attribute requires arguments that are class type or point to class type}}
void Func6(void) __attribute__((requires_shared_capability(BadCapability))) {} // expected-warning {{'requires_shared_capability' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'struct NotACapability'}}
+
+void Func7(void) __attribute__((assert_capability(GUI))) {}
+void Func8(void) __attribute__((assert_shared_capability(GUI))) {}
+
+void Func9(void) __attribute__((assert_capability())) {} // expected-error {{'assert_capability' attribute takes one argument}}
+void Func10(void) __attribute__((assert_shared_capability())) {} // expected-error {{'assert_shared_capability' attribute takes one argument}}
+
+void Func11(void) __attribute__((acquire_capability(GUI))) {}
+void Func12(void) __attribute__((acquire_shared_capability(GUI))) {}
+
+void Func13(void) __attribute__((acquire_capability())) {} // expected-error {{'acquire_capability' attribute takes at least 1 argument}}
+void Func14(void) __attribute__((acquire_shared_capability())) {} // expected-error {{'acquire_shared_capability' attribute takes at least 1 argument}}
+
+void Func15(void) __attribute__((release_capability(GUI))) {}
+void Func16(void) __attribute__((release_shared_capability(GUI))) {}
+void Func17(void) __attribute__((release_generic_capability(GUI))) {}
+
+void Func18(void) __attribute__((release_capability())) {} // expected-error {{'release_capability' attribute takes at least 1 argument}}
+void Func19(void) __attribute__((release_shared_capability())) {} // expected-error {{'release_shared_capability' attribute takes at least 1 argument}}
+void Func20(void) __attribute__((release_generic_capability())) {} // expected-error {{'release_generic_capability' attribute takes at least 1 argument}}
+
+void Func21(void) __attribute__((try_acquire_capability(1))) {}
+void Func22(void) __attribute__((try_acquire_shared_capability(1))) {}
+
+void Func23(void) __attribute__((try_acquire_capability(1, GUI))) {}
+void Func24(void) __attribute__((try_acquire_shared_capability(1, GUI))) {}
+
+void Func25(void) __attribute__((try_acquire_capability())) {} // expected-error {{'try_acquire_capability' attribute takes at least 1 argument}}
+void Func26(void) __attribute__((try_acquire_shared_capability())) {} // expected-error {{'try_acquire_shared_capability' attribute takes at least 1 argument}}
\ No newline at end of file
More information about the cfe-commits
mailing list