diff options
-rw-r--r-- | clang/include/clang/Basic/Attr.td | 49 | ||||
-rw-r--r-- | clang/lib/Analysis/ThreadSafety.cpp | 38 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 73 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 8 | ||||
-rw-r--r-- | 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 f24d335df3f..c567cf29ebe 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 51f5e030691..cde19b531e0 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<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, 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<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(AnalysisDeclContext &AC) { 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(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<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; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 26d7ae96671..29aca3370dc 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<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 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<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(Sema &S, Decl *D, 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 handleTryAcquireCapabilityAttr(Sema &S, Decl *D, 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, 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 fc37727344c..5abaab8883a 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -12597,19 +12597,13 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) { 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()); diff --git a/clang/test/Sema/attr-capabilities.c b/clang/test/Sema/attr-capabilities.c index 6ce84dceabf..7a8cb35b0e3 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))) {}
|