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.

Delesley Hutchins delesley at google.com
Thu Mar 20 15:48:27 PDT 2014


The analysis currently has a single unlock_function attribute, which
will unlock both exclusive and shared locks.  There's a feature
request to add shared_unlock_function and exclusive_unlock_function
attributes.  (These should issue a warning if they are used to unlock
the wrong kind of capability.) Any chance you could wrap those up into
the unlock_capability attribute?

  -DeLesley


On Thu, Mar 20, 2014 at 9:02 AM, Aaron Ballman <aaron at aaronballman.com> wrote:
> 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))) {}
>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



-- 
DeLesley Hutchins | Software Engineer | delesley at google.com | 505-206-0315



More information about the cfe-commits mailing list