From 18d85aed3974564dc636b2fba6215ade85a00370 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 20 Mar 2014 16:02:49 +0000 Subject: [PATCH] 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. llvm-svn: 204350 --- clang/include/clang/Basic/Attr.td | 49 +++++-------------------- clang/lib/Analysis/ThreadSafety.cpp | 38 +++++++------------ clang/lib/Sema/SemaDeclAttr.cpp | 73 +++---------------------------------- clang/lib/Sema/SemaDeclCXX.cpp | 8 +--- clang/test/Sema/attr-capabilities.c | 11 +----- 5 files changed, 32 insertions(+), 147 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index f24d335..c567cf2 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -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">]; @@ -1533,17 +1513,6 @@ def SharedTrylockFunction : InheritableAttr { 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]; -} - def LockReturned : InheritableAttr { let Spellings = [GNU<"lock_returned">]; let Args = [ExprArgument<"Arg">]; diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index 51f5e03..cde19b5 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -1933,19 +1933,13 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) { for(unsigned i = 0; i < ArgAttrs.size(); ++i) { Attr *At = const_cast(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(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(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(At); + Analyzer->getMutexIDs(A->isShared() ? SharedLocksToAdd + : ExclusiveLocksToAdd, + A, Exp, D, VD); break; } @@ -1977,8 +1971,8 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) { // 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(At); + case attr::ReleaseCapability: { + auto *A = cast(At); Analyzer->getMutexIDs(LocksToRemove, A, Exp, D, VD); break; } @@ -2351,7 +2345,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) { if (RequiresCapabilityAttr *A = dyn_cast(Attr)) { getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A, 0, D); - } else if (UnlockFunctionAttr *A = dyn_cast(Attr)) { + } else if (auto *A = dyn_cast(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(AnalysisDeclContext &AC) { // 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(Attr)) { - if (A->args_size() == 0) - return; - getMutexIDs(ExclusiveLocksAcquired, A, (Expr*) 0, D); - } else if (SharedLockFunctionAttr *A - = dyn_cast(Attr)) { + } else if (auto *A = dyn_cast(Attr)) { if (A->args_size() == 0) return; - getMutexIDs(SharedLocksAcquired, A, (Expr*) 0, D); + getMutexIDs(A->isShared() ? SharedLocksAcquired + : ExclusiveLocksAcquired, + A, nullptr, D); } else if (isa(Attr)) { // Don't try to check trylock functions for now return; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 26d7ae9..29aca33 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -599,33 +599,6 @@ static bool checkLockFunAttrCommon(Sema &S, Decl *D, return true; } -static void handleSharedLockFunctionAttr(Sema &S, Decl *D, - const AttributeList &Attr) { - SmallVector 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 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 Args; @@ -698,20 +671,6 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, 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 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(Sema &S, Decl *D, static void handleAcquireCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { SmallVector 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 handleTryAcquireCapabilityAttr(Sema &S, Decl *D, static void handleReleaseCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { - SmallVector Args; - if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) - return; - // Check that all arguments are lockable objects. - checkAttrArgsAreLockableObjs(S, D, Attr, Args); - if (Args.empty()) - return; + SmallVector 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, Scope *scope, Decl *D, 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, Scope *scope, Decl *D, 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; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index fc37727..5abaab8 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -12597,19 +12597,13 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) { Args = ArrayRef(AA->args_begin(), AA->args_size()); else if (const auto *AB = dyn_cast(A)) Args = ArrayRef(AB->args_begin(), AB->args_size()); - else if (const auto *ELF = dyn_cast(A)) - Args = ArrayRef(ELF->args_begin(), ELF->args_size()); - else if (const auto *SLF = dyn_cast(A)) - Args = ArrayRef(SLF->args_begin(), SLF->args_size()); else if (const auto *ETLF = dyn_cast(A)) { Arg = ETLF->getSuccessValue(); Args = ArrayRef(ETLF->args_begin(), ETLF->args_size()); } else if (const auto *STLF = dyn_cast(A)) { Arg = STLF->getSuccessValue(); Args = ArrayRef(STLF->args_begin(), STLF->args_size()); - } else if (const auto *UF = dyn_cast(A)) - Args = ArrayRef(UF->args_begin(), UF->args_size()); - else if (const auto *LR = dyn_cast(A)) + } else if (const auto *LR = dyn_cast(A)) Arg = LR->getArg(); else if (const auto *LE = dyn_cast(A)) Args = ArrayRef(LE->args_begin(), LE->args_size()); diff --git a/clang/test/Sema/attr-capabilities.c b/clang/test/Sema/attr-capabilities.c index 6ce84dc..7a8cb35 100644 --- a/clang/test/Sema/attr-capabilities.c +++ b/clang/test/Sema/attr-capabilities.c @@ -9,9 +9,9 @@ struct __attribute__((capability("wrong"))) IncorrectName {}; // expected-warnin 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_shared_capability())) {} // expected-err 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))) {} -- 2.7.4