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 <[email protected]> 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 > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits -- DeLesley Hutchins | Software Engineer | [email protected] | 505-206-0315 _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
