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