r204350 - Replacing the exclusive_lock_function, shared_lock_function and unlock_function attributes with the acquire_capability and release_capability attributes. The old spellings will continue to work, but the underlying semantic attributes have been replaced.

Aaron Ballman aaron at aaronballman.com
Thu Mar 20 09:02:49 PDT 2014


Author: aaronballman
Date: Thu Mar 20 11:02:49 2014
New Revision: 204350

URL: http://llvm.org/viewvc/llvm-project?rev=204350&view=rev
Log:
Replacing the exclusive_lock_function, shared_lock_function and unlock_function attributes with the acquire_capability and release_capability attributes. The old spellings will continue to work, but the underlying semantic attributes have been replaced.

Downgraded the capability diagnostics from error to warning to match the desired behavior, and updated the existing test cases.

Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/lib/Analysis/ThreadSafety.cpp
    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=204350&r1=204349&r2=204350&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Thu Mar 20 11:02:49 2014
@@ -1335,9 +1335,10 @@ 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>;
+                   CXX11<"clang", "acquire_shared_capability">,
+                   GNU<"exclusive_lock_function">,
+                   GNU<"shared_lock_function">];
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
   let LateParsed = 1;
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
@@ -1345,7 +1346,8 @@ def AcquireCapability : InheritableAttr
   let Args = [VariadicExprArgument<"Args">];
   let Accessors = [Accessor<"isShared",
                     [GNU<"acquire_shared_capability">,
-                     CXX11<"clang", "acquire_shared_capability">]>];
+                     CXX11<"clang", "acquire_shared_capability">,
+                     GNU<"shared_lock_function">]>];
   let Documentation = [AcquireCapabilityDocs];
 }
 
@@ -1373,9 +1375,9 @@ def ReleaseCapability : InheritableAttr
                    GNU<"release_shared_capability">,
                    CXX11<"clang", "release_shared_capability">,
                    GNU<"release_generic_capability">,
-                   CXX11<"clang", "release_generic_capability">];
-  let Subjects = SubjectList<[Function, FunctionTemplate],
-                             ErrorDiag>;
+                   CXX11<"clang", "release_generic_capability">,
+                   GNU<"unlock_function">];
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
   let LateParsed = 1;
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
@@ -1463,28 +1465,6 @@ def AcquiredBefore : InheritableAttr {
   let Documentation = [Undocumented];
 }
 
-def ExclusiveLockFunction : InheritableAttr {
-  let Spellings = [GNU<"exclusive_lock_function">];
-  let Args = [VariadicExprArgument<"Args">];
-  let LateParsed = 1;
-  let TemplateDependent = 1;
-  let ParseArgumentsAsUnevaluated = 1;
-  let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[Function, FunctionTemplate]>;
-  let Documentation = [Undocumented];
-}
-
-def SharedLockFunction : InheritableAttr {
-  let Spellings = [GNU<"shared_lock_function">];
-  let Args = [VariadicExprArgument<"Args">];
-  let LateParsed = 1;
-  let TemplateDependent = 1;
-  let ParseArgumentsAsUnevaluated = 1;
-  let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[Function, FunctionTemplate]>;
-  let Documentation = [Undocumented];
-}
-
 def AssertExclusiveLock : InheritableAttr {
   let Spellings = [GNU<"assert_exclusive_lock">];
   let Args = [VariadicExprArgument<"Args">];
@@ -1528,17 +1508,6 @@ def SharedTrylockFunction : InheritableA
   let LateParsed = 1;
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
-  let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[Function, FunctionTemplate]>;
-  let Documentation = [Undocumented];
-}
-
-def UnlockFunction : InheritableAttr {
-  let Spellings = [GNU<"unlock_function">];
-  let Args = [VariadicExprArgument<"Args">];
-  let LateParsed = 1;
-  let TemplateDependent = 1;
-  let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
   let Subjects = SubjectList<[Function, FunctionTemplate]>;
   let Documentation = [Undocumented];

Modified: cfe/trunk/lib/Analysis/ThreadSafety.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ThreadSafety.cpp?rev=204350&r1=204349&r2=204350&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ThreadSafety.cpp (original)
+++ cfe/trunk/lib/Analysis/ThreadSafety.cpp Thu Mar 20 11:02:49 2014
@@ -1933,19 +1933,13 @@ void BuildLockset::handleCall(Expr *Exp,
   for(unsigned i = 0; i < ArgAttrs.size(); ++i) {
     Attr *At = const_cast<Attr*>(ArgAttrs[i]);
     switch (At->getKind()) {
-      // When we encounter an exclusive lock function, we need to add the lock
-      // to our lockset with kind exclusive.
-      case attr::ExclusiveLockFunction: {
-        ExclusiveLockFunctionAttr *A = cast<ExclusiveLockFunctionAttr>(At);
-        Analyzer->getMutexIDs(ExclusiveLocksToAdd, A, Exp, D, VD);
-        break;
-      }
-
-      // When we encounter a shared lock function, we need to add the lock
-      // to our lockset with kind shared.
-      case attr::SharedLockFunction: {
-        SharedLockFunctionAttr *A = cast<SharedLockFunctionAttr>(At);
-        Analyzer->getMutexIDs(SharedLocksToAdd, A, Exp, D, VD);
+      // When we encounter a lock function, we need to add the lock to our
+      // lockset.
+      case attr::AcquireCapability: {
+        auto *A = cast<AcquireCapabilityAttr>(At);
+        Analyzer->getMutexIDs(A->isShared() ? SharedLocksToAdd
+                                            : ExclusiveLocksToAdd,
+                              A, Exp, D, VD);
         break;
       }
 
@@ -1977,8 +1971,8 @@ void BuildLockset::handleCall(Expr *Exp,
 
       // When we encounter an unlock function, we need to remove unlocked
       // mutexes from the lockset, and flag a warning if they are not there.
-      case attr::UnlockFunction: {
-        UnlockFunctionAttr *A = cast<UnlockFunctionAttr>(At);
+      case attr::ReleaseCapability: {
+        auto *A = cast<ReleaseCapabilityAttr>(At);
         Analyzer->getMutexIDs(LocksToRemove, A, Exp, D, VD);
         break;
       }
@@ -2351,7 +2345,7 @@ void ThreadSafetyAnalyzer::runAnalysis(A
       if (RequiresCapabilityAttr *A = dyn_cast<RequiresCapabilityAttr>(Attr)) {
         getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A,
                     0, D);
-      } else if (UnlockFunctionAttr *A = dyn_cast<UnlockFunctionAttr>(Attr)) {
+      } else if (auto *A = dyn_cast<ReleaseCapabilityAttr>(Attr)) {
         // UNLOCK_FUNCTION() is used to hide the underlying lock implementation.
         // We must ignore such methods.
         if (A->args_size() == 0)
@@ -2359,16 +2353,12 @@ void ThreadSafetyAnalyzer::runAnalysis(A
         // FIXME -- deal with exclusive vs. shared unlock functions?
         getMutexIDs(ExclusiveLocksToAdd, A, (Expr*) 0, D);
         getMutexIDs(LocksReleased, A, (Expr*) 0, D);
-      } else if (ExclusiveLockFunctionAttr *A
-                   = dyn_cast<ExclusiveLockFunctionAttr>(Attr)) {
-        if (A->args_size() == 0)
-          return;
-        getMutexIDs(ExclusiveLocksAcquired, A, (Expr*) 0, D);
-      } else if (SharedLockFunctionAttr *A
-                   = dyn_cast<SharedLockFunctionAttr>(Attr)) {
+      } else if (auto *A = dyn_cast<AcquireCapabilityAttr>(Attr)) {
         if (A->args_size() == 0)
           return;
-        getMutexIDs(SharedLocksAcquired, A, (Expr*) 0, D);
+        getMutexIDs(A->isShared() ? SharedLocksAcquired
+                                  : ExclusiveLocksAcquired,
+                    A, nullptr, D);
       } else if (isa<ExclusiveTrylockFunctionAttr>(Attr)) {
         // Don't try to check trylock functions for now
         return;

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=204350&r1=204349&r2=204350&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Thu Mar 20 11:02:49 2014
@@ -599,33 +599,6 @@ static bool checkLockFunAttrCommon(Sema
   return true;
 }
 
-static void handleSharedLockFunctionAttr(Sema &S, Decl *D,
-                                         const AttributeList &Attr) {
-  SmallVector<Expr*, 1> Args;
-  if (!checkLockFunAttrCommon(S, D, Attr, Args))
-    return;
-
-  unsigned Size = Args.size();
-  Expr **StartArg = Size == 0 ? 0 : &Args[0];
-  D->addAttr(::new (S.Context)
-             SharedLockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size,
-                                    Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D,
-                                            const AttributeList &Attr) {
-  SmallVector<Expr*, 1> Args;
-  if (!checkLockFunAttrCommon(S, D, Attr, Args))
-    return;
-
-  unsigned Size = Args.size();
-  Expr **StartArg = Size == 0 ? 0 : &Args[0];
-  D->addAttr(::new (S.Context)
-             ExclusiveLockFunctionAttr(Attr.getRange(), S.Context,
-                                       StartArg, Size,
-                                       Attr.getAttributeSpellingListIndex()));
-}
-
 static void handleAssertSharedLockAttr(Sema &S, Decl *D,
                                        const AttributeList &Attr) {
   SmallVector<Expr*, 1> Args;
@@ -698,20 +671,6 @@ static void handleExclusiveTrylockFuncti
                                           Attr.getAttributeSpellingListIndex()));
 }
 
-static void handleUnlockFunAttr(Sema &S, Decl *D,
-                                const AttributeList &Attr) {
-  // zero or more arguments ok
-  // check that all arguments are lockable objects
-  SmallVector<Expr*, 1> Args;
-  checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
-  unsigned Size = Args.size();
-  Expr **StartArg = Size == 0 ? 0 : &Args[0];
-
-  D->addAttr(::new (S.Context)
-             UnlockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size,
-                                Attr.getAttributeSpellingListIndex()));
-}
-
 static void handleLockReturnedAttr(Sema &S, Decl *D,
                                    const AttributeList &Attr) {
   // check that the argument is lockable object
@@ -3912,12 +3871,7 @@ static void handleAssertCapabilityAttr(S
 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())
+  if (!checkLockFunAttrCommon(S, D, Attr, Args))
     return;
 
   D->addAttr(::new (S.Context) AcquireCapabilityAttr(Attr.getRange(),
@@ -3942,19 +3896,13 @@ static void handleTryAcquireCapabilityAt
 
 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;
+  SmallVector<Expr *, 1> Args;
+  checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, true);
 
-  D->addAttr(::new (S.Context) ReleaseCapabilityAttr(Attr.getRange(),
-                                                     S.Context,
-                                                     Args.data(), Args.size(),
-                                        Attr.getAttributeSpellingListIndex()));
+  D->addAttr(::new (S.Context) ReleaseCapabilityAttr(
+      Attr.getRange(), S.Context, Args.data(), Args.size(),
+      Attr.getAttributeSpellingListIndex()));
 }
 
 static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
@@ -4417,9 +4365,6 @@ static void ProcessDeclAttribute(Sema &S
   case AttributeList::AT_PtGuardedBy:
     handlePtGuardedByAttr(S, D, Attr);
     break;
-  case AttributeList::AT_ExclusiveLockFunction:
-    handleExclusiveLockFunctionAttr(S, D, Attr);
-    break;
   case AttributeList::AT_ExclusiveTrylockFunction:
     handleExclusiveTrylockFunctionAttr(S, D, Attr);
     break;
@@ -4429,15 +4374,9 @@ static void ProcessDeclAttribute(Sema &S
   case AttributeList::AT_LocksExcluded:
     handleLocksExcludedAttr(S, D, Attr);
     break;
-  case AttributeList::AT_SharedLockFunction:
-    handleSharedLockFunctionAttr(S, D, Attr);
-    break;
   case AttributeList::AT_SharedTrylockFunction:
     handleSharedTrylockFunctionAttr(S, D, Attr);
     break;
-  case AttributeList::AT_UnlockFunction:
-    handleUnlockFunAttr(S, D, Attr);
-    break;
   case AttributeList::AT_AcquiredBefore:
     handleAcquiredBeforeAttr(S, D, Attr);
     break;

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=204350&r1=204349&r2=204350&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Mar 20 11:02:49 2014
@@ -12597,19 +12597,13 @@ bool Sema::checkThisInStaticMemberFuncti
       Args = ArrayRef<Expr *>(AA->args_begin(), AA->args_size());
     else if (const auto *AB = dyn_cast<AcquiredBeforeAttr>(A))
       Args = ArrayRef<Expr *>(AB->args_begin(), AB->args_size());
-    else if (const auto *ELF  = dyn_cast<ExclusiveLockFunctionAttr>(A))
-      Args = ArrayRef<Expr *>(ELF->args_begin(), ELF->args_size());
-    else if (const auto *SLF  = dyn_cast<SharedLockFunctionAttr>(A))
-      Args = ArrayRef<Expr *>(SLF->args_begin(), SLF->args_size());
     else if (const auto *ETLF = dyn_cast<ExclusiveTrylockFunctionAttr>(A)) {
       Arg = ETLF->getSuccessValue();
       Args = ArrayRef<Expr *>(ETLF->args_begin(), ETLF->args_size());
     } else if (const auto *STLF = dyn_cast<SharedTrylockFunctionAttr>(A)) {
       Arg = STLF->getSuccessValue();
       Args = ArrayRef<Expr *>(STLF->args_begin(), STLF->args_size());
-    } else if (const auto *UF = dyn_cast<UnlockFunctionAttr>(A))
-      Args = ArrayRef<Expr *>(UF->args_begin(), UF->args_size());
-    else if (const auto *LR = dyn_cast<LockReturnedAttr>(A))
+    } else if (const auto *LR = dyn_cast<LockReturnedAttr>(A))
       Arg = LR->getArg();
     else if (const auto *LE = dyn_cast<LocksExcludedAttr>(A))
       Args = ArrayRef<Expr *>(LE->args_begin(), LE->args_size());

Modified: cfe/trunk/test/Sema/attr-capabilities.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-capabilities.c?rev=204350&r1=204349&r2=204350&view=diff
==============================================================================
--- cfe/trunk/test/Sema/attr-capabilities.c (original)
+++ cfe/trunk/test/Sema/attr-capabilities.c Thu Mar 20 11:02:49 2014
@@ -9,9 +9,9 @@ struct __attribute__((capability("wrong"
 
 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 Test3 __attribute__((acquire_capability("test3")));  // expected-warning {{'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}}
+int Test5 __attribute__((release_capability("test5"))); // expected-warning {{'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}}
@@ -39,17 +39,10 @@ void Func10(void) __attribute__((assert_
 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))) {}
 





More information about the cfe-commits mailing list