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