Thread safety analysis: split warnings into two groups: attribute warnings

which are checked in the parser, and analysis warnings that require the
full analysis.  This allows attribute syntax to be checked independently
of the full thread safety analysis.  Also introduces a new warning for the
case where a string is used as a lock expression; this allows the analysis
to gracefully handle expressions that would otherwise cause a parse error.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155129 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
DeLesley Hutchins 2012-04-19 16:10:44 +00:00
Родитель dd9fe59a9a
Коммит ae519c42a1
4 изменённых файлов: 96 добавлений и 88 удалений

Просмотреть файл

@ -354,7 +354,10 @@ def Most : DiagGroup<"most", [
]>; ]>;
// Thread Safety warnings // Thread Safety warnings
def ThreadSafety : DiagGroup<"thread-safety">; def ThreadSafetyAttributes : DiagGroup<"thread-safety-attributes">;
def ThreadSafetyAnalysis : DiagGroup<"thread-safety-analysis">;
def ThreadSafety : DiagGroup<"thread-safety",
[ThreadSafetyAttributes, ThreadSafetyAnalysis]>;
// Note that putting warnings in -Wall will not disable them by default. If a // Note that putting warnings in -Wall will not disable them by default. If a
// warning should be active _only_ when -Wall is passed in, mark it as // warning should be active _only_ when -Wall is passed in, mark it as

Просмотреть файл

@ -1656,72 +1656,79 @@ def warn_availability_version_ordering : Warning<
"attribute ignored">; "attribute ignored">;
// Thread Safety Attributes // Thread Safety Attributes
// Errors when parsing the attributes def warn_thread_attribute_ignored : Warning<
"ignoring %0 attribute because its argument is invalid">,
InGroup<ThreadSafetyAttributes>, DefaultIgnore;
def warn_thread_attribute_argument_not_lockable : Warning<
"%0 attribute requires arguments whose type is annotated "
"with 'lockable' attribute; type here is '%1'">,
InGroup<ThreadSafetyAttributes>, 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<ThreadSafetyAttributes>, DefaultIgnore;
def warn_thread_attribute_decl_not_lockable : Warning<
"%0 attribute can only be applied in a context annotated "
"with 'lockable' attribute">,
InGroup<ThreadSafetyAttributes>, DefaultIgnore;
def warn_thread_attribute_decl_not_pointer : Warning<
"'%0' only applies to pointer types; type here is %1">,
InGroup<ThreadSafetyAttributes>, DefaultIgnore;
def err_attribute_argument_out_of_range : Error< def err_attribute_argument_out_of_range : Error<
"%0 attribute parameter %1 is out of bounds: " "%0 attribute parameter %1 is out of bounds: "
"%plural{0:no parameters to index into|" "%plural{0:no parameters to index into|"
"1:can only be 1, since there is one parameter|" "1:can only be 1, since there is one parameter|"
":must be between 1 and %2}2">; ":must be between 1 and %2}2">;
def warn_attribute_argument_not_lockable : Warning<
"%0 attribute requires arguments whose type is annotated " // Thread Safety Analysis
"with 'lockable' attribute; type here is '%1'">,
InGroup<ThreadSafety>, DefaultIgnore;
def warn_attribute_decl_not_lockable : Warning<
"%0 attribute can only be applied in a context annotated "
"with 'lockable' attribute">,
InGroup<ThreadSafety>, DefaultIgnore;
def warn_attribute_argument_not_class : Warning<
"%0 attribute requires arguments that are class type or point to"
" class type; type here is '%1'">,
InGroup<ThreadSafety>, DefaultIgnore;
def warn_unlock_but_no_lock : Warning< def warn_unlock_but_no_lock : Warning<
"unlocking '%0' that was not locked">, "unlocking '%0' that was not locked">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_double_lock : Warning< def warn_double_lock : Warning<
"locking '%0' that is already locked">, "locking '%0' that is already locked">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_no_unlock : Warning< def warn_no_unlock : Warning<
"mutex '%0' is still locked at the end of function">, "mutex '%0' is still locked at the end of function">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
// FIXME: improve the error message about locks not in scope // FIXME: improve the error message about locks not in scope
def warn_lock_some_predecessors : Warning< def warn_lock_some_predecessors : Warning<
"mutex '%0' is not locked on every path through here">, "mutex '%0' is not locked on every path through here">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_expecting_lock_held_on_loop : Warning< def warn_expecting_lock_held_on_loop : Warning<
"expecting mutex '%0' to be locked at start of each loop">, "expecting mutex '%0' to be locked at start of each loop">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def note_locked_here : Note<"mutex acquired here">; def note_locked_here : Note<"mutex acquired here">;
def warn_lock_exclusive_and_shared : Warning< def warn_lock_exclusive_and_shared : Warning<
"mutex '%0' is locked exclusively and shared in the same scope">, "mutex '%0' is locked exclusively and shared in the same scope">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def note_lock_exclusive_and_shared : Note< def note_lock_exclusive_and_shared : Note<
"the other lock of mutex '%0' is here">, "the other lock of mutex '%0' is here">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_variable_requires_lock : Warning< def warn_variable_requires_lock : Warning<
"%select{reading|writing}2 variable '%0' requires locking " "%select{reading|writing}2 variable '%0' requires locking "
"%select{'%1'|'%1' exclusively}2">, "%select{'%1'|'%1' exclusively}2">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_var_deref_requires_lock : Warning< def warn_var_deref_requires_lock : Warning<
"%select{reading|writing}2 the value pointed to by '%0' requires locking " "%select{reading|writing}2 the value pointed to by '%0' requires locking "
"%select{'%1'|'%1' exclusively}2">, "%select{'%1'|'%1' exclusively}2">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_variable_requires_any_lock : Warning< def warn_variable_requires_any_lock : Warning<
"%select{reading|writing}1 variable '%0' requires locking " "%select{reading|writing}1 variable '%0' requires locking "
"%select{any mutex|any mutex exclusively}1">, "%select{any mutex|any mutex exclusively}1">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_var_deref_requires_any_lock : Warning< def warn_var_deref_requires_any_lock : Warning<
"%select{reading|writing}1 the value pointed to by '%0' requires locking " "%select{reading|writing}1 the value pointed to by '%0' requires locking "
"%select{any mutex|any mutex exclusively}1">, "%select{any mutex|any mutex exclusively}1">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_fun_requires_lock : Warning< def warn_fun_requires_lock : Warning<
"calling function '%0' requires %select{shared|exclusive}2 lock on '%1'">, "calling function '%0' requires %select{shared|exclusive}2 lock on '%1'">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_fun_excludes_mutex : Warning< def warn_fun_excludes_mutex : Warning<
"cannot call function '%0' while mutex '%1' is locked">, "cannot call function '%0' while mutex '%1' is locked">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_cannot_resolve_lock : Warning< def warn_cannot_resolve_lock : Warning<
"cannot resolve lock expression">, "cannot resolve lock expression">,
InGroup<ThreadSafety>, DefaultIgnore; InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_impcast_vector_scalar : Warning< def warn_impcast_vector_scalar : Warning<

Просмотреть файл

@ -243,12 +243,13 @@ static bool isIntOrBool(Expr *Exp) {
/// Note that this function may produce an error message. /// Note that this function may produce an error message.
/// \return true if the Decl is a pointer type; false otherwise /// \return true if the Decl is a pointer type; false otherwise
/// ///
static bool checkIsPointer(Sema &S, const Decl *D, const AttributeList &Attr) { static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
const AttributeList &Attr) {
if (const ValueDecl *vd = dyn_cast<ValueDecl>(D)) { if (const ValueDecl *vd = dyn_cast<ValueDecl>(D)) {
QualType QT = vd->getType(); QualType QT = vd->getType();
if (QT->isAnyPointerType()) if (QT->isAnyPointerType())
return true; return true;
S.Diag(Attr.getLoc(), diag::warn_pointer_attribute_wrong_type) S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
<< Attr.getName()->getName() << QT; << Attr.getName()->getName() << QT;
} else { } else {
S.Diag(Attr.getLoc(), diag::err_attribute_can_be_applied_only_to_value_decl) S.Diag(Attr.getLoc(), diag::err_attribute_can_be_applied_only_to_value_decl)
@ -271,14 +272,14 @@ static const RecordType *getRecordType(QualType QT) {
} }
/// \brief Thread Safety Analysis: Checks that the passed in RecordType /// \brief Thread Safety Analysis: Checks that the passed in RecordType
/// resolves to a lockable object. May flag an error. /// resolves to a lockable object.
static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr, static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr,
QualType Ty) { QualType Ty) {
const RecordType *RT = getRecordType(Ty); const RecordType *RT = getRecordType(Ty);
// Warn if could not get record type for this argument. // Warn if could not get record type for this argument.
if (!RT) { if (!RT) {
S.Diag(Attr.getLoc(), diag::warn_attribute_argument_not_class) S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_class)
<< Attr.getName() << Ty.getAsString(); << Attr.getName() << Ty.getAsString();
return; return;
} }
@ -287,18 +288,18 @@ static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr,
return; return;
// Warn if the type is not lockable. // Warn if the type is not lockable.
if (!RT->getDecl()->getAttr<LockableAttr>()) { if (!RT->getDecl()->getAttr<LockableAttr>()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_argument_not_lockable) S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
<< Attr.getName() << Ty.getAsString(); << Attr.getName() << Ty.getAsString();
return; return;
} }
} }
/// \brief Thread Safety Analysis: Checks that all attribute arguments, starting /// \brief Thread Safety Analysis: Checks that all attribute arguments, starting
/// from Sidx, resolve to a lockable object. May flag an error. /// from Sidx, resolve to a lockable object.
/// \param Sidx The attribute argument index to start checking with. /// \param Sidx The attribute argument index to start checking with.
/// \param ParamIdxOk Whether an argument can be indexing into a function /// \param ParamIdxOk Whether an argument can be indexing into a function
/// parameter list. /// parameter list.
static bool checkAttrArgsAreLockableObjs(Sema &S, Decl *D, static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
const AttributeList &Attr, const AttributeList &Attr,
SmallVectorImpl<Expr*> &Args, SmallVectorImpl<Expr*> &Args,
int Sidx = 0, int Sidx = 0,
@ -307,11 +308,19 @@ static bool checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
Expr *ArgExp = Attr.getArg(Idx); Expr *ArgExp = Attr.getArg(Idx);
if (ArgExp->isTypeDependent()) { if (ArgExp->isTypeDependent()) {
// FIXME -- need to processs this again on template instantiation // FIXME -- need to check this again on template instantiation
Args.push_back(ArgExp); Args.push_back(ArgExp);
continue; continue;
} }
if (isa<StringLiteral>(ArgExp)) {
// We allow constant strings to be used as a placeholder for expressions
// that are not valid C++ syntax, but warn that they are ignored.
S.Diag(Attr.getLoc(), diag::warn_thread_attribute_ignored) <<
Attr.getName();
continue;
}
QualType ArgTy = ArgExp->getType(); QualType ArgTy = ArgExp->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 point to record type.
@ -329,7 +338,7 @@ static bool checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
if(!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) { if(!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range) S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range)
<< Attr.getName() << Idx + 1 << NumParams; << Attr.getName() << Idx + 1 << NumParams;
return false; continue;
} }
ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType(); ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType();
} }
@ -339,7 +348,6 @@ static bool checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
Args.push_back(ArgExp); Args.push_back(ArgExp);
} }
return true;
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -364,7 +372,7 @@ static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr,
return; return;
} }
if (pointer && !checkIsPointer(S, D, Attr)) if (pointer && !threadSafetyCheckIsPointer(S, D, Attr))
return; return;
if (pointer) if (pointer)
@ -380,8 +388,6 @@ static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr,
if (!checkAttributeNumArgs(S, Attr, 1)) if (!checkAttributeNumArgs(S, Attr, 1))
return; return;
Expr *Arg = Attr.getArg(0);
// D must be either a member field or global (potentially shared) variable. // D must be either a member field or global (potentially shared) variable.
if (!mayBeSharedVariable(D)) { if (!mayBeSharedVariable(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
@ -389,12 +395,16 @@ static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr,
return; return;
} }
if (pointer && !checkIsPointer(S, D, Attr)) if (pointer && !threadSafetyCheckIsPointer(S, D, Attr))
return; return;
if (!Arg->isTypeDependent()) { SmallVector<Expr*, 1> Args;
checkForLockableRecord(S, D, Attr, Arg->getType()); // check that all arguments are lockable objects
} checkAttrArgsAreLockableObjs(S, D, Attr, Args);
unsigned Size = Args.size();
if (Size != 1)
return;
Expr *Arg = Args[0];
if (pointer) if (pointer)
D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(), D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(),
@ -442,7 +452,7 @@ static void handleNoThreadSafetyAttr(Sema &S, Decl *D,
} }
static void handleNoAddressSafetyAttr(Sema &S, Decl *D, static void handleNoAddressSafetyAttr(Sema &S, Decl *D,
const AttributeList &Attr) { const AttributeList &Attr) {
assert(!Attr.isInvalid()); assert(!Attr.isInvalid());
if (!checkAttributeNumArgs(S, Attr, 0)) if (!checkAttributeNumArgs(S, Attr, 0))
@ -473,25 +483,24 @@ static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr,
return; return;
} }
// Check that this attribute only applies to lockable types // Check that this attribute only applies to lockable types.
QualType QT = VD->getType(); QualType QT = VD->getType();
if (!QT->isDependentType()) { if (!QT->isDependentType()) {
const RecordType *RT = getRecordType(QT); const RecordType *RT = getRecordType(QT);
if (!RT || !RT->getDecl()->getAttr<LockableAttr>()) { if (!RT || !RT->getDecl()->getAttr<LockableAttr>()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_decl_not_lockable) S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
<< Attr.getName(); << Attr.getName();
return; return;
} }
} }
SmallVector<Expr*, 1> Args; SmallVector<Expr*, 1> Args;
// check that all arguments are lockable objects // Check that all arguments are lockable objects.
if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args)) checkAttrArgsAreLockableObjs(S, D, Attr, Args);
return;
unsigned Size = Args.size(); unsigned Size = Args.size();
assert(Size == Attr.getNumArgs()); if (Size == 0)
Expr **StartArg = Size == 0 ? 0 : &Args[0]; return;
Expr **StartArg = &Args[0];
if (before) if (before)
D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getRange(), S.Context, D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getRange(), S.Context,
@ -516,11 +525,8 @@ static void handleLockFunAttr(Sema &S, Decl *D, const AttributeList &Attr,
// check that all arguments are lockable objects // check that all arguments are lockable objects
SmallVector<Expr*, 1> Args; SmallVector<Expr*, 1> Args;
if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true)) checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
return;
unsigned Size = Args.size(); unsigned Size = Args.size();
assert(Size == Attr.getNumArgs());
Expr **StartArg = Size == 0 ? 0 : &Args[0]; Expr **StartArg = Size == 0 ? 0 : &Args[0];
if (exclusive) if (exclusive)
@ -540,7 +546,6 @@ static void handleTrylockFunAttr(Sema &S, Decl *D, const AttributeList &Attr,
if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return; return;
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod; << Attr.getName() << ExpectedFunctionOrMethod;
@ -555,9 +560,7 @@ static void handleTrylockFunAttr(Sema &S, Decl *D, const AttributeList &Attr,
SmallVector<Expr*, 2> Args; SmallVector<Expr*, 2> Args;
// check that all arguments are lockable objects // check that all arguments are lockable objects
if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args, 1)) checkAttrArgsAreLockableObjs(S, D, Attr, Args, 1);
return;
unsigned Size = Args.size(); unsigned Size = Args.size();
Expr **StartArg = Size == 0 ? 0 : &Args[0]; Expr **StartArg = Size == 0 ? 0 : &Args[0];
@ -588,12 +591,11 @@ static void handleLocksRequiredAttr(Sema &S, Decl *D, const AttributeList &Attr,
// check that all arguments are lockable objects // check that all arguments are lockable objects
SmallVector<Expr*, 1> Args; SmallVector<Expr*, 1> Args;
if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args)) checkAttrArgsAreLockableObjs(S, D, Attr, Args);
return;
unsigned Size = Args.size(); unsigned Size = Args.size();
assert(Size == Attr.getNumArgs()); if (Size == 0)
Expr **StartArg = Size == 0 ? 0 : &Args[0]; return;
Expr **StartArg = &Args[0];
if (exclusive) if (exclusive)
D->addAttr(::new (S.Context) ExclusiveLocksRequiredAttr(Attr.getRange(), D->addAttr(::new (S.Context) ExclusiveLocksRequiredAttr(Attr.getRange(),
@ -619,11 +621,8 @@ static void handleUnlockFunAttr(Sema &S, Decl *D,
// check that all arguments are lockable objects // check that all arguments are lockable objects
SmallVector<Expr*, 1> Args; SmallVector<Expr*, 1> Args;
if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true)) checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
return;
unsigned Size = Args.size(); unsigned Size = Args.size();
assert(Size == Attr.getNumArgs());
Expr **StartArg = Size == 0 ? 0 : &Args[0]; Expr **StartArg = Size == 0 ? 0 : &Args[0];
D->addAttr(::new (S.Context) UnlockFunctionAttr(Attr.getRange(), S.Context, D->addAttr(::new (S.Context) UnlockFunctionAttr(Attr.getRange(), S.Context,
@ -668,12 +667,11 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D,
// check that all arguments are lockable objects // check that all arguments are lockable objects
SmallVector<Expr*, 1> Args; SmallVector<Expr*, 1> Args;
if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args)) checkAttrArgsAreLockableObjs(S, D, Attr, Args);
return;
unsigned Size = Args.size(); unsigned Size = Args.size();
assert(Size == Attr.getNumArgs()); if (Size == 0)
Expr **StartArg = Size == 0 ? 0 : &Args[0]; return;
Expr **StartArg = &Args[0];
D->addAttr(::new (S.Context) LocksExcludedAttr(Attr.getRange(), S.Context, D->addAttr(::new (S.Context) LocksExcludedAttr(Attr.getRange(), S.Context,
StartArg, Size)); StartArg, Size));

Просмотреть файл

@ -343,7 +343,7 @@ int gb_var_arg_8 __attribute__((guarded_by(muPointer)));
int gb_var_arg_bad_1 __attribute__((guarded_by(1))); // \ int gb_var_arg_bad_1 __attribute__((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 that are class type or point to class type; type here is 'int'}}
int gb_var_arg_bad_2 __attribute__((guarded_by("mu"))); // \ int gb_var_arg_bad_2 __attribute__((guarded_by("mu"))); // \
// expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'const char [3]'}} // expected-warning {{ignoring 'guarded_by' attribute because its argument is invalid}}
int gb_var_arg_bad_3 __attribute__((guarded_by(muDoublePointer))); // \ int gb_var_arg_bad_3 __attribute__((guarded_by(muDoublePointer))); // \
// expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'class Mu **'}} // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'class Mu **'}}
int gb_var_arg_bad_4 __attribute__((guarded_by(umu))); // \ int gb_var_arg_bad_4 __attribute__((guarded_by(umu))); // \
@ -414,7 +414,7 @@ int * pgb_var_arg_8 __attribute__((pt_guarded_by(muPointer)));
int * pgb_var_arg_bad_1 __attribute__((pt_guarded_by(1))); // \ int * pgb_var_arg_bad_1 __attribute__((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 that are class type or point to class type}}
int * pgb_var_arg_bad_2 __attribute__((pt_guarded_by("mu"))); // \ int * pgb_var_arg_bad_2 __attribute__((pt_guarded_by("mu"))); // \
// expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} // expected-warning {{ignoring 'pt_guarded_by' attribute because its argument is invalid}}
int * pgb_var_arg_bad_3 __attribute__((pt_guarded_by(muDoublePointer))); // \ int * pgb_var_arg_bad_3 __attribute__((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 that are class type or point to class type}}
int * pgb_var_arg_bad_4 __attribute__((pt_guarded_by(umu))); // \ int * pgb_var_arg_bad_4 __attribute__((pt_guarded_by(umu))); // \
@ -475,7 +475,7 @@ Mu aa_var_arg_8 __attribute__((acquired_after(muPointer)));
Mu aa_var_arg_bad_1 __attribute__((acquired_after(1))); // \ Mu aa_var_arg_bad_1 __attribute__((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 that are class type or point to class type}}
Mu aa_var_arg_bad_2 __attribute__((acquired_after("mu"))); // \ Mu aa_var_arg_bad_2 __attribute__((acquired_after("mu"))); // \
// expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} // expected-warning {{ignoring 'acquired_after' attribute because its argument is invalid}}
Mu aa_var_arg_bad_3 __attribute__((acquired_after(muDoublePointer))); // \ Mu aa_var_arg_bad_3 __attribute__((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 that are class type or point to class type}}
Mu aa_var_arg_bad_4 __attribute__((acquired_after(umu))); // \ Mu aa_var_arg_bad_4 __attribute__((acquired_after(umu))); // \
@ -538,7 +538,7 @@ Mu ab_var_arg_8 __attribute__((acquired_before(muPointer)));
Mu ab_var_arg_bad_1 __attribute__((acquired_before(1))); // \ Mu ab_var_arg_bad_1 __attribute__((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 that are class type or point to class type}}
Mu ab_var_arg_bad_2 __attribute__((acquired_before("mu"))); // \ Mu ab_var_arg_bad_2 __attribute__((acquired_before("mu"))); // \
// expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} // expected-warning {{ignoring 'acquired_before' attribute because its argument is invalid}}
Mu ab_var_arg_bad_3 __attribute__((acquired_before(muDoublePointer))); // \ Mu ab_var_arg_bad_3 __attribute__((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 that are class type or point to class type}}
Mu ab_var_arg_bad_4 __attribute__((acquired_before(umu))); // \ Mu ab_var_arg_bad_4 __attribute__((acquired_before(umu))); // \
@ -603,7 +603,7 @@ int elf_function_9(Mu x, Mu y) __attribute__((exclusive_lock_function(1,2)));
// illegal attribute arguments // illegal attribute arguments
int elf_function_bad_2() __attribute__((exclusive_lock_function("mu"))); // \ int elf_function_bad_2() __attribute__((exclusive_lock_function("mu"))); // \
// expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}} // expected-warning {{ignoring 'exclusive_lock_function' attribute because its argument is invalid}}
int elf_function_bad_3() __attribute__((exclusive_lock_function(muDoublePointer))); // \ int elf_function_bad_3() __attribute__((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 that are class type or point to class type}}
int elf_function_bad_4() __attribute__((exclusive_lock_function(umu))); // \ int elf_function_bad_4() __attribute__((exclusive_lock_function(umu))); // \
@ -675,7 +675,7 @@ int slf_function_9(Mu x, Mu y) __attribute__((shared_lock_function(1,2)));
// illegal attribute arguments // illegal attribute arguments
int slf_function_bad_2() __attribute__((shared_lock_function("mu"))); // \ int slf_function_bad_2() __attribute__((shared_lock_function("mu"))); // \
// expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}} // expected-warning {{ignoring 'shared_lock_function' attribute because its argument is invalid}}
int slf_function_bad_3() __attribute__((shared_lock_function(muDoublePointer))); // \ int slf_function_bad_3() __attribute__((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 that are class type or point to class type}}
int slf_function_bad_4() __attribute__((shared_lock_function(umu))); // \ int slf_function_bad_4() __attribute__((shared_lock_function(umu))); // \
@ -757,7 +757,7 @@ int etf_function_bad_3() __attribute__((exclusive_trylock_function(muDoublePoint
// expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}} // expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}}
int etf_function_bad_4() __attribute__((exclusive_trylock_function(1, "mu"))); // \ int etf_function_bad_4() __attribute__((exclusive_trylock_function(1, "mu"))); // \
// expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}} // expected-warning {{ignoring 'exclusive_trylock_function' attribute because its argument is invalid}}
int etf_function_bad_5() __attribute__((exclusive_trylock_function(1, muDoublePointer))); // \ int etf_function_bad_5() __attribute__((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 that are class type or point to class type}}
int etf_function_bad_6() __attribute__((exclusive_trylock_function(1, umu))); // \ int etf_function_bad_6() __attribute__((exclusive_trylock_function(1, umu))); // \
@ -831,7 +831,7 @@ int stf_function_bad_3() __attribute__((shared_trylock_function(muDoublePointer)
// expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}} // expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}}
int stf_function_bad_4() __attribute__((shared_trylock_function(1, "mu"))); // \ int stf_function_bad_4() __attribute__((shared_trylock_function(1, "mu"))); // \
// expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}} // expected-warning {{ignoring 'shared_trylock_function' attribute because its argument is invalid}}
int stf_function_bad_5() __attribute__((shared_trylock_function(1, muDoublePointer))); // \ int stf_function_bad_5() __attribute__((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 that are class type or point to class type}}
int stf_function_bad_6() __attribute__((shared_trylock_function(1, umu))); // \ int stf_function_bad_6() __attribute__((shared_trylock_function(1, umu))); // \
@ -894,7 +894,7 @@ int uf_function_9(Mu x, Mu y) __attribute__((unlock_function(1,2)));
// illegal attribute arguments // illegal attribute arguments
int uf_function_bad_2() __attribute__((unlock_function("mu"))); // \ int uf_function_bad_2() __attribute__((unlock_function("mu"))); // \
// expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}} // expected-warning {{ignoring 'unlock_function' attribute because its argument is invalid}}
int uf_function_bad_3() __attribute__((unlock_function(muDoublePointer))); // \ int uf_function_bad_3() __attribute__((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 that are class type or point to class type}}
int uf_function_bad_4() __attribute__((unlock_function(umu))); // \ int uf_function_bad_4() __attribute__((unlock_function(umu))); // \
@ -1037,7 +1037,7 @@ int le_function_8() __attribute__((locks_excluded(muPointer)));
int le_function_bad_1() __attribute__((locks_excluded(1))); // \ int le_function_bad_1() __attribute__((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 that are class type or point to class type}}
int le_function_bad_2() __attribute__((locks_excluded("mu"))); // \ int le_function_bad_2() __attribute__((locks_excluded("mu"))); // \
// expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} // expected-warning {{ignoring 'locks_excluded' attribute because its argument is invalid}}
int le_function_bad_3() __attribute__((locks_excluded(muDoublePointer))); // \ int le_function_bad_3() __attribute__((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 that are class type or point to class type}}
int le_function_bad_4() __attribute__((locks_excluded(umu))); // \ int le_function_bad_4() __attribute__((locks_excluded(umu))); // \
@ -1104,7 +1104,7 @@ int elr_function_8() __attribute__((exclusive_locks_required(muPointer)));
int elr_function_bad_1() __attribute__((exclusive_locks_required(1))); // \ int elr_function_bad_1() __attribute__((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 that are class type or point to class type}}
int elr_function_bad_2() __attribute__((exclusive_locks_required("mu"))); // \ int elr_function_bad_2() __attribute__((exclusive_locks_required("mu"))); // \
// expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} // expected-warning {{ignoring 'exclusive_locks_required' attribute because its argument is invalid}}
int elr_function_bad_3() __attribute__((exclusive_locks_required(muDoublePointer))); // \ int elr_function_bad_3() __attribute__((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 that are class type or point to class type}}
int elr_function_bad_4() __attribute__((exclusive_locks_required(umu))); // \ int elr_function_bad_4() __attribute__((exclusive_locks_required(umu))); // \
@ -1172,7 +1172,7 @@ int slr_function_8() __attribute__((shared_locks_required(muPointer)));
int slr_function_bad_1() __attribute__((shared_locks_required(1))); // \ int slr_function_bad_1() __attribute__((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 that are class type or point to class type}}
int slr_function_bad_2() __attribute__((shared_locks_required("mu"))); // \ int slr_function_bad_2() __attribute__((shared_locks_required("mu"))); // \
// expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} // expected-warning {{ignoring 'shared_locks_required' attribute because its argument is invalid}}
int slr_function_bad_3() __attribute__((shared_locks_required(muDoublePointer))); // \ int slr_function_bad_3() __attribute__((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 that are class type or point to class type}}
int slr_function_bad_4() __attribute__((shared_locks_required(umu))); // \ int slr_function_bad_4() __attribute__((shared_locks_required(umu))); // \