From: Aaron Ballman Date: Mon, 24 Mar 2014 19:29:19 +0000 (+0000) Subject: Capability attributes can now be declared on a typedef declaration as well as a struc... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3fd557c273e9c2256f0ca2c672e972da3c3d1f30;p=clang Capability attributes can now be declared on a typedef declaration as well as a structure declaration. This allows for C code to use Boolean expressions on a capability as part of another attribute. Eg) __attribute__((requires_capability(!SomeCapability))) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@204657 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 3eb5d4e0f3..afc038c15f 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -1302,7 +1302,8 @@ def Capability : InheritableAttr { let Spellings = [GNU<"capability">, CXX11<"clang", "capability">, GNU<"shared_capability">, CXX11<"clang", "shared_capability">]; - let Subjects = SubjectList<[Struct], ErrorDiag, "ExpectedStruct">; + let Subjects = SubjectList<[Struct, TypedefName], ErrorDiag, + "ExpectedStructOrTypedef">; let Args = [StringArgument<"Name">]; let Accessors = [Accessor<"isShared", [GNU<"shared_capability">, diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 179c605aeb..105974b6c1 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2102,7 +2102,7 @@ def warn_attribute_wrong_decl_type : Warning< "struct or union|struct, union or class|types|" "Objective-C instance methods|init methods of interface or class extension declarations|" "variables, functions and classes|Objective-C protocols|" - "functions and global variables}1">, + "functions and global variables|structs or typedefs}1">, InGroup; def err_attribute_wrong_decl_type : Error; def warn_type_attribute_wrong_type : Warning< @@ -2180,10 +2180,6 @@ def warn_thread_attribute_argument_not_lockable : Warning< "%0 attribute requires arguments whose type is annotated " "with 'capability' attribute; type here is %1">, InGroup, DefaultIgnore; -def warn_thread_attribute_argument_not_class : Warning< - "%0 attribute requires arguments that are class type or point to" - " class type; type here is %1">, - InGroup, DefaultIgnore; def warn_thread_attribute_decl_not_lockable : Warning< "%0 attribute can only be applied in a context annotated " "with 'capability(\"mutex\")' attribute">, diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 43e8d35fd4..171f9f9b9f 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -838,7 +838,8 @@ enum AttributeDeclKind { ExpectedObjCInterfaceDeclInitMethod, ExpectedFunctionVariableOrClass, ExpectedObjectiveCProtocol, - ExpectedFunctionGlobalVarMethodOrProperty + ExpectedFunctionGlobalVarMethodOrProperty, + ExpectedStructOrTypedef }; } // end namespace clang diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 29aca3370d..f4d16af6d3 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -363,63 +363,78 @@ static const RecordType *getRecordType(QualType QT) { return 0; } - -static bool checkBaseClassIsLockableCallback(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, void *Unused) { - const RecordType *RT = Specifier->getType()->getAs(); - return RT->getDecl()->hasAttr(); -} - - -/// \brief Thread Safety Analysis: Checks that the passed in RecordType -/// resolves to a lockable object. -static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr, - QualType Ty) { +static bool checkRecordTypeForCapability(Sema &S, const AttributeList &Attr, + QualType Ty) { const RecordType *RT = getRecordType(Ty); - // Warn if could not get record type for this argument. - if (!RT) { - S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_class) - << Attr.getName() << Ty; - return; - } + if (!RT) + return false; - // Don't check for lockable if the class hasn't been defined yet. + // Don't check for the capability if the class hasn't been defined yet. if (RT->isIncompleteType()) - return; + return true; - // Allow smart pointers to be used as lockable objects. + // Allow smart pointers to be used as capability objects. // FIXME -- Check the type that the smart pointer points to. if (threadSafetyCheckIsSmartPointer(S, RT)) - return; + return true; - // Check if the type is lockable. + // Check if the record itself has a capability. RecordDecl *RD = RT->getDecl(); if (RD->hasAttr()) - return; + return true; - // Else check if any base classes are lockable. + // Else check if any base classes have a capability. if (CXXRecordDecl *CRD = dyn_cast(RD)) { CXXBasePaths BPaths(false, false); - if (CRD->lookupInBases(checkBaseClassIsLockableCallback, 0, BPaths)) - return; + if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &P, + void *) { + return BS->getType()->getAs() + ->getDecl()->hasAttr(); + }, 0, BPaths)) + return true; } + return false; +} + +static bool checkTypedefTypeForCapability(Sema &S, const AttributeList &Attr, + QualType Ty) { + const auto *TD = Ty->getAs(); + if (!TD) + return false; + + TypedefNameDecl *TN = TD->getDecl(); + if (!TN) + return false; + + return TN->hasAttr(); +} + +/// \brief Checks that the passed in type is qualified as a capability. This +/// type can either be a struct, or a typedef to a built-in type (such as int). +static void checkForCapability(Sema &S, const AttributeList &Attr, + QualType Ty) { + if (checkTypedefTypeForCapability(S, Attr, Ty)) + return; + + if (checkRecordTypeForCapability(S, Attr, Ty)) + return; S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable) << Attr.getName() << Ty; } -/// \brief Thread Safety Analysis: Checks that all attribute arguments, starting -/// from Sidx, resolve to a lockable object. +/// \brief Checks that all attribute arguments, starting from Sidx, resolve to +/// a capability object. /// \param Sidx The attribute argument index to start checking with. /// \param ParamIdxOk Whether an argument can be indexing into a function /// parameter list. -static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D, - const AttributeList &Attr, - SmallVectorImpl &Args, - int Sidx = 0, - bool ParamIdxOk = false) { - for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { +static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, + const AttributeList &Attr, + SmallVectorImpl &Args, + int Sidx = 0, + bool ParamIdxOk = false) { + for (unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { Expr *ArgExp = Attr.getArgAsExpr(Idx); if (ArgExp->isTypeDependent()) { @@ -455,7 +470,7 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D, if (DRE->getDecl()->isCXXInstanceMember()) ArgTy = DRE->getDecl()->getType(); - // First see if we can just cast to record type, or point to record type. + // First see if we can just cast to record type, or pointer to record type. const RecordType *RT = getRecordType(ArgTy); // Now check if we index into a record type function param. @@ -476,7 +491,7 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D, } } - checkForLockableRecord(S, D, Attr, ArgTy); + checkForCapability(S, Attr, ArgTy); Args.push_back(ArgExp); } @@ -505,7 +520,7 @@ static bool checkGuardedByAttrCommon(Sema &S, Decl *D, Expr* &Arg) { SmallVector Args; // check that all arguments are lockable objects - checkAttrArgsAreLockableObjs(S, D, Attr, Args); + checkAttrArgsAreCapabilityObjs(S, D, Attr, Args); unsigned Size = Args.size(); if (Size != 1) return false; @@ -556,7 +571,7 @@ static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, } // Check that all arguments are lockable objects. - checkAttrArgsAreLockableObjs(S, D, Attr, Args); + checkAttrArgsAreCapabilityObjs(S, D, Attr, Args); if (Args.empty()) return false; @@ -594,7 +609,7 @@ static bool checkLockFunAttrCommon(Sema &S, Decl *D, SmallVectorImpl &Args) { // zero or more arguments ok // check that all arguments are lockable objects - checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true); + checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true); return true; } @@ -640,7 +655,7 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, } // check that all arguments are lockable objects - checkAttrArgsAreLockableObjs(S, D, Attr, Args, 1); + checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 1); return true; } @@ -675,7 +690,7 @@ static void handleLockReturnedAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check that the argument is lockable object SmallVector Args; - checkAttrArgsAreLockableObjs(S, D, Attr, Args); + checkAttrArgsAreCapabilityObjs(S, D, Attr, Args); unsigned Size = Args.size(); if (Size == 0) return; @@ -692,7 +707,7 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D, // check that all arguments are lockable objects SmallVector Args; - checkAttrArgsAreLockableObjs(S, D, Attr, Args); + checkAttrArgsAreCapabilityObjs(S, D, Attr, Args); unsigned Size = Args.size(); if (Size == 0) return; @@ -3898,7 +3913,7 @@ static void handleReleaseCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Check that all arguments are lockable objects. SmallVector Args; - checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, true); + checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, true); D->addAttr(::new (S.Context) ReleaseCapabilityAttr( Attr.getRange(), S.Context, Args.data(), Args.size(), @@ -3912,7 +3927,7 @@ static void handleRequiresCapabilityAttr(Sema &S, Decl *D, // check that all arguments are lockable objects SmallVector Args; - checkAttrArgsAreLockableObjs(S, D, Attr, Args); + checkAttrArgsAreCapabilityObjs(S, D, Attr, Args); if (Args.empty()) return; diff --git a/test/Sema/attr-capabilities.c b/test/Sema/attr-capabilities.c index 1c8645a021..e6f123f25a 100644 --- a/test/Sema/attr-capabilities.c +++ b/test/Sema/attr-capabilities.c @@ -1,14 +1,14 @@ // RUN: %clang_cc1 -fsyntax-only -Wthread-safety -verify %s -struct __attribute__((capability("role"))) ThreadRole {}; +typedef int __attribute__((capability("role"))) ThreadRole; struct __attribute__((shared_capability("mutex"))) Mutex {}; struct NotACapability {}; // Test an invalid capability name struct __attribute__((capability("wrong"))) IncorrectName {}; // expected-warning {{invalid capability name 'wrong'; capability name must be 'mutex' or 'role'}} -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 Test1 __attribute__((capability("test1"))); // expected-error {{'capability' attribute only applies to structs or typedefs}} +int Test2 __attribute__((shared_capability("test2"))); // expected-error {{'shared_capability' attribute only applies to structs or 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 Test5 __attribute__((release_capability("test5"))); // expected-warning {{'release_capability' attribute only applies to functions}} @@ -20,14 +20,14 @@ struct __attribute__((capability)) Test5 {}; // expected-error {{'capability' at struct __attribute__((shared_capability("test1", 12))) Test6 {}; // expected-error {{'shared_capability' attribute takes one argument}} struct NotACapability BadCapability; -struct ThreadRole GUI, Worker; +ThreadRole GUI, Worker; void Func1(void) __attribute__((requires_capability(GUI))) {} void Func2(void) __attribute__((requires_shared_capability(Worker))) {} void Func3(void) __attribute__((requires_capability)) {} // expected-error {{'requires_capability' attribute takes at least 1 argument}} void Func4(void) __attribute__((requires_shared_capability)) {} // expected-error {{'requires_shared_capability' attribute takes at least 1 argument}} -void Func5(void) __attribute__((requires_capability(1))) {} // expected-warning {{'requires_capability' attribute requires arguments that are class type or point to class type}} +void Func5(void) __attribute__((requires_capability(1))) {} // expected-warning {{'requires_capability' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} void Func6(void) __attribute__((requires_shared_capability(BadCapability))) {} // expected-warning {{'requires_shared_capability' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'struct NotACapability'}} void Func7(void) __attribute__((assert_capability(GUI))) {} diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp index a27818692c..6d4ad39c0c 100644 --- a/test/SemaCXX/warn-thread-safety-parsing.cpp +++ b/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -353,11 +353,11 @@ int gb_var_arg_8 GUARDED_BY(muPointer); // illegal attribute arguments int gb_var_arg_bad_1 GUARDED_BY(1); // \ - // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'int'}} + // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} int gb_var_arg_bad_2 GUARDED_BY("mu"); // \ // expected-warning {{ignoring 'guarded_by' attribute because its argument is invalid}} int gb_var_arg_bad_3 GUARDED_BY(muDoublePointer); // \ - // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'Mutex **'}} + // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int gb_var_arg_bad_4 GUARDED_BY(umu); // \ // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'UnlockableMu'}} @@ -424,11 +424,11 @@ int * pgb_var_arg_8 PT_GUARDED_BY(muPointer); // illegal attribute arguments int * pgb_var_arg_bad_1 PT_GUARDED_BY(1); // \ - // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} int * pgb_var_arg_bad_2 PT_GUARDED_BY("mu"); // \ // expected-warning {{ignoring 'pt_guarded_by' attribute because its argument is invalid}} int * pgb_var_arg_bad_3 PT_GUARDED_BY(muDoublePointer); // \ - // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int * pgb_var_arg_bad_4 PT_GUARDED_BY(umu); // \ // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -485,11 +485,11 @@ Mutex aa_var_arg_8 ACQUIRED_AFTER(muPointer); // illegal attribute arguments Mutex aa_var_arg_bad_1 ACQUIRED_AFTER(1); // \ - // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} Mutex aa_var_arg_bad_2 ACQUIRED_AFTER("mu"); // \ // expected-warning {{ignoring 'acquired_after' attribute because its argument is invalid}} Mutex aa_var_arg_bad_3 ACQUIRED_AFTER(muDoublePointer); // \ - // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} Mutex aa_var_arg_bad_4 ACQUIRED_AFTER(umu); // \ // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'capability' attribute}} UnlockableMu aa_var_arg_bad_5 ACQUIRED_AFTER(mu_aa); // \ @@ -548,11 +548,11 @@ Mutex ab_var_arg_8 ACQUIRED_BEFORE(muPointer); // illegal attribute arguments Mutex ab_var_arg_bad_1 ACQUIRED_BEFORE(1); // \ - // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} Mutex ab_var_arg_bad_2 ACQUIRED_BEFORE("mu"); // \ // expected-warning {{ignoring 'acquired_before' attribute because its argument is invalid}} Mutex ab_var_arg_bad_3 ACQUIRED_BEFORE(muDoublePointer); // \ - // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} Mutex ab_var_arg_bad_4 ACQUIRED_BEFORE(umu); // \ // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'capability' attribute}} UnlockableMu ab_var_arg_bad_5 ACQUIRED_BEFORE(mu_ab); // \ @@ -617,7 +617,7 @@ int elf_function_9(Mutex x, Mutex y) EXCLUSIVE_LOCK_FUNCTION(1,2); int elf_function_bad_2() EXCLUSIVE_LOCK_FUNCTION("mu"); // \ // expected-warning {{ignoring 'exclusive_lock_function' attribute because its argument is invalid}} int elf_function_bad_3() EXCLUSIVE_LOCK_FUNCTION(muDoublePointer); // \ - // expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int elf_function_bad_4() EXCLUSIVE_LOCK_FUNCTION(umu); // \ // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -689,7 +689,7 @@ int slf_function_9(Mutex x, Mutex y) SHARED_LOCK_FUNCTION(1,2); int slf_function_bad_2() SHARED_LOCK_FUNCTION("mu"); // \ // expected-warning {{ignoring 'shared_lock_function' attribute because its argument is invalid}} int slf_function_bad_3() SHARED_LOCK_FUNCTION(muDoublePointer); // \ - // expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int slf_function_bad_4() SHARED_LOCK_FUNCTION(umu); // \ // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -771,7 +771,7 @@ int etf_function_bad_3() EXCLUSIVE_TRYLOCK_FUNCTION(muDoublePointer); // \ int etf_function_bad_4() EXCLUSIVE_TRYLOCK_FUNCTION(1, "mu"); // \ // expected-warning {{ignoring 'exclusive_trylock_function' attribute because its argument is invalid}} int etf_function_bad_5() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoublePointer); // \ - // expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int etf_function_bad_6() EXCLUSIVE_TRYLOCK_FUNCTION(1, umu); // \ // expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -845,7 +845,7 @@ int stf_function_bad_3() SHARED_TRYLOCK_FUNCTION(muDoublePointer); // \ int stf_function_bad_4() SHARED_TRYLOCK_FUNCTION(1, "mu"); // \ // expected-warning {{ignoring 'shared_trylock_function' attribute because its argument is invalid}} int stf_function_bad_5() SHARED_TRYLOCK_FUNCTION(1, muDoublePointer); // \ - // expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int stf_function_bad_6() SHARED_TRYLOCK_FUNCTION(1, umu); // \ // expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -908,7 +908,7 @@ int uf_function_9(Mutex x, Mutex y) UNLOCK_FUNCTION(1,2); int uf_function_bad_2() UNLOCK_FUNCTION("mu"); // \ // expected-warning {{ignoring 'unlock_function' attribute because its argument is invalid}} int uf_function_bad_3() UNLOCK_FUNCTION(muDoublePointer); // \ - // expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int uf_function_bad_4() UNLOCK_FUNCTION(umu); // \ // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -980,11 +980,11 @@ int lr_function_8() LOCK_RETURNED(muPointer); // illegal attribute arguments int lr_function_bad_1() LOCK_RETURNED(1); // \ - // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} int lr_function_bad_2() LOCK_RETURNED("mu"); // \ // expected-warning {{ignoring 'lock_returned' attribute because its argument is invalid}} int lr_function_bad_3() LOCK_RETURNED(muDoublePointer); // \ - // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int lr_function_bad_4() LOCK_RETURNED(umu); // \ // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -1047,11 +1047,11 @@ int le_function_8() LOCKS_EXCLUDED(muPointer); // illegal attribute arguments int le_function_bad_1() LOCKS_EXCLUDED(1); // \ - // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} int le_function_bad_2() LOCKS_EXCLUDED("mu"); // \ // expected-warning {{ignoring 'locks_excluded' attribute because its argument is invalid}} int le_function_bad_3() LOCKS_EXCLUDED(muDoublePointer); // \ - // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int le_function_bad_4() LOCKS_EXCLUDED(umu); // \ // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -1114,11 +1114,11 @@ int elr_function_8() EXCLUSIVE_LOCKS_REQUIRED(muPointer); // illegal attribute arguments int elr_function_bad_1() EXCLUSIVE_LOCKS_REQUIRED(1); // \ - // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} int elr_function_bad_2() EXCLUSIVE_LOCKS_REQUIRED("mu"); // \ // expected-warning {{ignoring 'exclusive_locks_required' attribute because its argument is invalid}} int elr_function_bad_3() EXCLUSIVE_LOCKS_REQUIRED(muDoublePointer); // \ - // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int elr_function_bad_4() EXCLUSIVE_LOCKS_REQUIRED(umu); // \ // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -1182,11 +1182,11 @@ int slr_function_8() SHARED_LOCKS_REQUIRED(muPointer); // illegal attribute arguments int slr_function_bad_1() SHARED_LOCKS_REQUIRED(1); // \ - // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} int slr_function_bad_2() SHARED_LOCKS_REQUIRED("mu"); // \ // expected-warning {{ignoring 'shared_locks_required' attribute because its argument is invalid}} int slr_function_bad_3() SHARED_LOCKS_REQUIRED(muDoublePointer); // \ - // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int slr_function_bad_4() SHARED_LOCKS_REQUIRED(umu); // \ // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute}}