diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index fd9e686485552..cff1f12b94999 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3803,7 +3803,9 @@ def Capability : InheritableAttr { def AssertCapability : InheritableAttr { let Spellings = [Clang<"assert_capability", 0>, - Clang<"assert_shared_capability", 0>]; + Clang<"assert_shared_capability", 0>, + GNU<"assert_exclusive_lock">, + GNU<"assert_shared_lock">]; let Subjects = SubjectList<[Function]>; let LateParsed = LateAttrParseStandard; let TemplateDependent = 1; @@ -3811,7 +3813,8 @@ def AssertCapability : InheritableAttr { let InheritEvenIfAlreadyPresent = 1; let Args = [VariadicExprArgument<"Args">]; let Accessors = [Accessor<"isShared", - [Clang<"assert_shared_capability", 0>]>]; + [Clang<"assert_shared_capability", 0>, + GNU<"assert_shared_lock">]>]; let Documentation = [AssertCapabilityDocs]; } @@ -3834,16 +3837,18 @@ def AcquireCapability : InheritableAttr { def TryAcquireCapability : InheritableAttr { let Spellings = [Clang<"try_acquire_capability", 0>, - Clang<"try_acquire_shared_capability", 0>]; - let Subjects = SubjectList<[Function], - ErrorDiag>; + Clang<"try_acquire_shared_capability", 0>, + GNU<"exclusive_trylock_function">, + GNU<"shared_trylock_function">]; + let Subjects = SubjectList<[Function]>; let LateParsed = LateAttrParseStandard; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let InheritEvenIfAlreadyPresent = 1; let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; let Accessors = [Accessor<"isShared", - [Clang<"try_acquire_shared_capability", 0>]>]; + [Clang<"try_acquire_shared_capability", 0>, + GNU<"shared_trylock_function">]>]; let Documentation = [TryAcquireCapabilityDocs]; } @@ -3933,54 +3938,6 @@ def AcquiredBefore : InheritableAttr { let Documentation = [Undocumented]; } -def AssertExclusiveLock : InheritableAttr { - let Spellings = [GNU<"assert_exclusive_lock">]; - let Args = [VariadicExprArgument<"Args">]; - let LateParsed = LateAttrParseStandard; - let TemplateDependent = 1; - let ParseArgumentsAsUnevaluated = 1; - let InheritEvenIfAlreadyPresent = 1; - let Subjects = SubjectList<[Function]>; - let Documentation = [Undocumented]; -} - -def AssertSharedLock : InheritableAttr { - let Spellings = [GNU<"assert_shared_lock">]; - let Args = [VariadicExprArgument<"Args">]; - let LateParsed = LateAttrParseStandard; - let TemplateDependent = 1; - let ParseArgumentsAsUnevaluated = 1; - let InheritEvenIfAlreadyPresent = 1; - let Subjects = SubjectList<[Function]>; - let Documentation = [Undocumented]; -} - -// The first argument is an integer or boolean value specifying the return value -// of a successful lock acquisition. -def ExclusiveTrylockFunction : InheritableAttr { - let Spellings = [GNU<"exclusive_trylock_function">]; - let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; - let LateParsed = LateAttrParseStandard; - let TemplateDependent = 1; - let ParseArgumentsAsUnevaluated = 1; - let InheritEvenIfAlreadyPresent = 1; - let Subjects = SubjectList<[Function]>; - let Documentation = [Undocumented]; -} - -// The first argument is an integer or boolean value specifying the return value -// of a successful lock acquisition. -def SharedTrylockFunction : InheritableAttr { - let Spellings = [GNU<"shared_trylock_function">]; - let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; - let LateParsed = LateAttrParseStandard; - let TemplateDependent = 1; - let ParseArgumentsAsUnevaluated = 1; - let InheritEvenIfAlreadyPresent = 1; - let Subjects = SubjectList<[Function]>; - let Documentation = [Undocumented]; -} - def LockReturned : InheritableAttr { let Spellings = [GNU<"lock_returned">]; let Args = [ExprArgument<"Arg">]; diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 8c91cce22f78e..3a475f43a601d 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -9420,34 +9420,6 @@ Expected ASTImporter::Import(const Attr *FromAttr) { From->args_size()); break; } - case attr::AssertExclusiveLock: { - const auto *From = cast(FromAttr); - AI.importAttr(From, - AI.importArrayArg(From->args(), From->args_size()).value(), - From->args_size()); - break; - } - case attr::AssertSharedLock: { - const auto *From = cast(FromAttr); - AI.importAttr(From, - AI.importArrayArg(From->args(), From->args_size()).value(), - From->args_size()); - break; - } - case attr::ExclusiveTrylockFunction: { - const auto *From = cast(FromAttr); - AI.importAttr(From, AI.importArg(From->getSuccessValue()).value(), - AI.importArrayArg(From->args(), From->args_size()).value(), - From->args_size()); - break; - } - case attr::SharedTrylockFunction: { - const auto *From = cast(FromAttr); - AI.importAttr(From, AI.importArg(From->getSuccessValue()).value(), - AI.importArrayArg(From->args(), From->args_size()).value(), - From->args_size()); - break; - } case attr::LockReturned: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArg(From->getArg()).value()); diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index 6b5b49377fa08..42fb0fe7dcdaa 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -1511,38 +1511,17 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result, return; auto *FunDecl = dyn_cast_or_null(Exp->getCalleeDecl()); - if(!FunDecl || !FunDecl->hasAttrs()) + if (!FunDecl || !FunDecl->hasAttr()) return; CapExprSet ExclusiveLocksToAdd; CapExprSet SharedLocksToAdd; // If the condition is a call to a Trylock function, then grab the attributes - for (const auto *Attr : FunDecl->attrs()) { - switch (Attr->getKind()) { - case attr::TryAcquireCapability: { - auto *A = cast(Attr); - getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A, - Exp, FunDecl, PredBlock, CurrBlock, A->getSuccessValue(), - Negate); - break; - }; - case attr::ExclusiveTrylockFunction: { - const auto *A = cast(Attr); - getMutexIDs(ExclusiveLocksToAdd, A, Exp, FunDecl, PredBlock, CurrBlock, - A->getSuccessValue(), Negate); - break; - } - case attr::SharedTrylockFunction: { - const auto *A = cast(Attr); - getMutexIDs(SharedLocksToAdd, A, Exp, FunDecl, PredBlock, CurrBlock, - A->getSuccessValue(), Negate); - break; - } - default: - break; - } - } + for (const auto *Attr : FunDecl->specific_attrs()) + getMutexIDs(Attr->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, Attr, + Exp, FunDecl, PredBlock, CurrBlock, Attr->getSuccessValue(), + Negate); // Add and remove locks. SourceLocation Loc = Exp->getExprLoc(); @@ -1882,29 +1861,6 @@ void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D, // An assert will add a lock to the lockset, but will not generate // a warning if it is already there, and will not generate a warning // if it is not removed. - case attr::AssertExclusiveLock: { - const auto *A = cast(At); - - CapExprSet AssertLocks; - Analyzer->getMutexIDs(AssertLocks, A, Exp, D, Self); - for (const auto &AssertLock : AssertLocks) - Analyzer->addLock( - FSet, std::make_unique( - AssertLock, LK_Exclusive, Loc, FactEntry::Asserted)); - break; - } - case attr::AssertSharedLock: { - const auto *A = cast(At); - - CapExprSet AssertLocks; - Analyzer->getMutexIDs(AssertLocks, A, Exp, D, Self); - for (const auto &AssertLock : AssertLocks) - Analyzer->addLock( - FSet, std::make_unique( - AssertLock, LK_Shared, Loc, FactEntry::Asserted)); - break; - } - case attr::AssertCapability: { const auto *A = cast(At); CapExprSet AssertLocks; @@ -2499,12 +2455,6 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) { getMutexIDs(A->isShared() ? SharedLocksAcquired : ExclusiveLocksAcquired, A, nullptr, D); - } else if (isa(Attr)) { - // Don't try to check trylock functions for now. - return; - } else if (isa(Attr)) { - // Don't try to check trylock functions for now. - return; } 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 d76afe9d6464d..d39164aa32a2d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -536,29 +536,6 @@ static bool checkLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, return true; } -static void handleAssertSharedLockAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - SmallVector Args; - if (!checkLockFunAttrCommon(S, D, AL, Args)) - return; - - unsigned Size = Args.size(); - Expr **StartArg = Size == 0 ? nullptr : &Args[0]; - D->addAttr(::new (S.Context) - AssertSharedLockAttr(S.Context, AL, StartArg, Size)); -} - -static void handleAssertExclusiveLockAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - SmallVector Args; - if (!checkLockFunAttrCommon(S, D, AL, Args)) - return; - - unsigned Size = Args.size(); - Expr **StartArg = Size == 0 ? nullptr : &Args[0]; - D->addAttr(::new (S.Context) - AssertExclusiveLockAttr(S.Context, AL, StartArg, Size)); -} - /// Checks to be sure that the given parameter number is in bounds, and /// is an integral type. Will emit appropriate diagnostics if this returns /// false. @@ -638,26 +615,6 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, return true; } -static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - SmallVector Args; - if (!checkTryLockFunAttrCommon(S, D, AL, Args)) - return; - - D->addAttr(::new (S.Context) SharedTrylockFunctionAttr( - S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size())); -} - -static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - SmallVector Args; - if (!checkTryLockFunAttrCommon(S, D, AL, Args)) - return; - - D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr( - S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size())); -} - static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // check that the argument is lockable object SmallVector Args; @@ -7535,12 +7492,6 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, break; // Thread safety attributes: - case ParsedAttr::AT_AssertExclusiveLock: - handleAssertExclusiveLockAttr(S, D, AL); - break; - case ParsedAttr::AT_AssertSharedLock: - handleAssertSharedLockAttr(S, D, AL); - break; case ParsedAttr::AT_PtGuardedVar: handlePtGuardedVarAttr(S, D, AL); break; @@ -7556,18 +7507,12 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_PtGuardedBy: handlePtGuardedByAttr(S, D, AL); break; - case ParsedAttr::AT_ExclusiveTrylockFunction: - handleExclusiveTrylockFunctionAttr(S, D, AL); - break; case ParsedAttr::AT_LockReturned: handleLockReturnedAttr(S, D, AL); break; case ParsedAttr::AT_LocksExcluded: handleLocksExcludedAttr(S, D, AL); break; - case ParsedAttr::AT_SharedTrylockFunction: - handleSharedTrylockFunctionAttr(S, D, AL); - break; case ParsedAttr::AT_AcquiredBefore: handleAcquiredBeforeAttr(S, D, AL); break; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index b86f7118e0b34..76903d4dee037 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -19060,13 +19060,7 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) { Args = llvm::ArrayRef(AA->args_begin(), AA->args_size()); else if (const auto *AB = dyn_cast(A)) Args = llvm::ArrayRef(AB->args_begin(), AB->args_size()); - else if (const auto *ETLF = dyn_cast(A)) { - Arg = ETLF->getSuccessValue(); - Args = llvm::ArrayRef(ETLF->args_begin(), ETLF->args_size()); - } else if (const auto *STLF = dyn_cast(A)) { - Arg = STLF->getSuccessValue(); - Args = llvm::ArrayRef(STLF->args_begin(), STLF->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 = llvm::ArrayRef(LE->args_begin(), LE->args_size()); @@ -19074,9 +19068,10 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) { Args = llvm::ArrayRef(RC->args_begin(), RC->args_size()); else if (const auto *AC = dyn_cast(A)) Args = llvm::ArrayRef(AC->args_begin(), AC->args_size()); - else if (const auto *AC = dyn_cast(A)) + else if (const auto *AC = dyn_cast(A)) { + Arg = AC->getSuccessValue(); Args = llvm::ArrayRef(AC->args_begin(), AC->args_size()); - else if (const auto *RC = dyn_cast(A)) + } else if (const auto *RC = dyn_cast(A)) Args = llvm::ArrayRef(RC->args_begin(), RC->args_size()); if (Arg && !Finder.TraverseStmt(Arg)) diff --git a/clang/test/Sema/attr-capabilities.c b/clang/test/Sema/attr-capabilities.c index 5138803bd5eb7..12b18b687803e 100644 --- a/clang/test/Sema/attr-capabilities.c +++ b/clang/test/Sema/attr-capabilities.c @@ -14,7 +14,7 @@ struct __attribute__((capability("custom"))) CustomName {}; int Test1 __attribute__((capability("test1"))); // expected-error {{'capability' attribute only applies to structs, unions, classes, and typedefs}} int Test2 __attribute__((shared_capability("test2"))); // expected-error {{'shared_capability' attribute only applies to structs, unions, classes, and typedefs}} 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 Test4 __attribute__((try_acquire_capability("test4"))); // expected-warning {{'try_acquire_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 {{expected string literal as argument of 'capability' attribute}} diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 40e1197bc21f1..4192faee1af80 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -7977,42 +7977,6 @@ TEST_P(ImportAttributes, ImportAcquiredBefore) { checkImportVariadicArg(FromAttr->args(), ToAttr->args()); } -TEST_P(ImportAttributes, ImportAssertExclusiveLock) { - AssertExclusiveLockAttr *FromAttr, *ToAttr; - importAttr("void test(int A1, int A2) " - "__attribute__((assert_exclusive_lock(A1, A2)));", - FromAttr, ToAttr); - checkImportVariadicArg(FromAttr->args(), ToAttr->args()); -} - -TEST_P(ImportAttributes, ImportAssertSharedLock) { - AssertSharedLockAttr *FromAttr, *ToAttr; - importAttr( - "void test(int A1, int A2) __attribute__((assert_shared_lock(A1, A2)));", - FromAttr, ToAttr); - checkImportVariadicArg(FromAttr->args(), ToAttr->args()); -} - -TEST_P(ImportAttributes, ImportExclusiveTrylockFunction) { - ExclusiveTrylockFunctionAttr *FromAttr, *ToAttr; - importAttr( - "void test(int A1, int A2) __attribute__((exclusive_trylock_function(1, " - "A1, A2)));", - FromAttr, ToAttr); - checkImported(FromAttr->getSuccessValue(), ToAttr->getSuccessValue()); - checkImportVariadicArg(FromAttr->args(), ToAttr->args()); -} - -TEST_P(ImportAttributes, ImportSharedTrylockFunction) { - SharedTrylockFunctionAttr *FromAttr, *ToAttr; - importAttr( - "void test(int A1, int A2) __attribute__((shared_trylock_function(1, A1, " - "A2)));", - FromAttr, ToAttr); - checkImported(FromAttr->getSuccessValue(), ToAttr->getSuccessValue()); - checkImportVariadicArg(FromAttr->args(), ToAttr->args()); -} - TEST_P(ImportAttributes, ImportLockReturned) { LockReturnedAttr *FromAttr, *ToAttr; importAttr(