]> granicus.if.org Git - clang/commitdiff
Adding role-based capability attributes that allow you to express role management...
authorAaron Ballman <aaron@aaronballman.com>
Fri, 21 Feb 2014 21:05:14 +0000 (21:05 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Fri, 21 Feb 2014 21:05:14 +0000 (21:05 +0000)
This functionality should be considered a WIP.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201890 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Attr.td
include/clang/Basic/AttrDocs.td
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaDeclCXX.cpp
test/Sema/attr-capabilities.c

index 3b70c4cc3e58d0a56a6620720da5005bfdcb1d41..148de472063f00016a0a9a2f1345856cf5b20d11 100644 (file)
@@ -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">,
index a2476e43ac08a976d0349fbceb24931e4645f73e..c0f0fbcea13cf955cdf50f0d2fc441ccf822cb26 100644 (file)
@@ -77,6 +77,37 @@ that appears to be capable of returning to its caller.
   }];
 }
 
+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 = [{
index ef19a0b992ad28d266d2df7a03b3c8457ba849af..19b79555489e59b7c337b1df93d005ba140c29d8 100644 (file)
@@ -3905,6 +3905,61 @@ static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
                                         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, Scope *scope, Decl *D,
   case AttributeList::AT_Capability:
   case AttributeList::AT_Lockable:
     handleCapabilityAttr(S, D, Attr); break;
-  case AttributeList::AT_RequiresCapability:\r
-    handleRequiresCapabilityAttr(S, D, Attr); break;\r
+  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:
index e4967f899e22999de68b91d2c480c40002d0d242..d98a01d33fa171cba3e437ebdcc304fe87209a00 100644 (file)
@@ -12752,6 +12752,13 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
     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;
index fa3a3fab2562d563c07f95bb6963de97d6be970f..7a83403934fd9a2e06c98f00ab9685dc8c348add 100644 (file)
@@ -6,6 +6,9 @@ struct NotACapability {};
 \r
 int Test1 __attribute__((capability("test1")));  // expected-error {{'capability' attribute only applies to structs}}\r
 int Test2 __attribute__((shared_capability("test2"))); // expected-error {{'shared_capability' attribute only applies to structs}}\r
+int Test3 __attribute__((acquire_capability("test3")));  // expected-error {{'acquire_capability' attribute only applies to functions}}\r
+int Test4 __attribute__((try_acquire_capability("test4"))); // expected-error {{'try_acquire_capability' attribute only applies to functions}}\r
+int Test5 __attribute__((release_capability("test5"))); // expected-error {{'release_capability' attribute only applies to functions}}\r
 \r
 struct __attribute__((capability(12))) Test3 {}; // expected-error {{'capability' attribute requires a string}}\r
 struct __attribute__((shared_capability(Test2))) Test4 {}; // expected-error {{'shared_capability' attribute requires a string}}\r
@@ -23,3 +26,32 @@ void Func4(void) __attribute__((requires_shared_capability)) {}  // expected-err
 \r
 void Func5(void) __attribute__((requires_capability(1))) {}  // expected-warning {{'requires_capability' attribute requires arguments that are class type or point to class type}}\r
 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'}}\r
+\r
+void Func7(void) __attribute__((assert_capability(GUI))) {}\r
+void Func8(void) __attribute__((assert_shared_capability(GUI))) {}\r
+\r
+void Func9(void) __attribute__((assert_capability())) {} // expected-error {{'assert_capability' attribute takes one argument}}\r
+void Func10(void) __attribute__((assert_shared_capability())) {} // expected-error {{'assert_shared_capability' attribute takes one argument}}\r
+\r
+void Func11(void) __attribute__((acquire_capability(GUI))) {}\r
+void Func12(void) __attribute__((acquire_shared_capability(GUI))) {}\r
+\r
+void Func13(void) __attribute__((acquire_capability())) {} // expected-error {{'acquire_capability' attribute takes at least 1 argument}}\r
+void Func14(void) __attribute__((acquire_shared_capability())) {} // expected-error {{'acquire_shared_capability' attribute takes at least 1 argument}}\r
+\r
+void Func15(void) __attribute__((release_capability(GUI))) {}\r
+void Func16(void) __attribute__((release_shared_capability(GUI))) {}\r
+void Func17(void) __attribute__((release_generic_capability(GUI))) {}\r
+\r
+void Func18(void) __attribute__((release_capability())) {} // expected-error {{'release_capability' attribute takes at least 1 argument}}\r
+void Func19(void) __attribute__((release_shared_capability())) {} // expected-error {{'release_shared_capability' attribute takes at least 1 argument}}\r
+void Func20(void) __attribute__((release_generic_capability())) {} // expected-error {{'release_generic_capability' attribute takes at least 1 argument}}\r
+\r
+void Func21(void) __attribute__((try_acquire_capability(1))) {}\r
+void Func22(void) __attribute__((try_acquire_shared_capability(1))) {}\r
+\r
+void Func23(void) __attribute__((try_acquire_capability(1, GUI))) {}\r
+void Func24(void) __attribute__((try_acquire_shared_capability(1, GUI))) {}\r
+\r
+void Func25(void) __attribute__((try_acquire_capability())) {} // expected-error {{'try_acquire_capability' attribute takes at least 1 argument}}\r
+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