зеркало из https://github.com/microsoft/clang-1.git
Thread safety analysis: downgraded requirement that mutex expressions refer to a lockable type from error to warning.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154198 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
b0f245ccce
Коммит
83cad4544f
|
@ -1650,12 +1650,18 @@ def err_attribute_argument_out_of_range : Error<
|
|||
"%plural{0:no parameters to index into|"
|
||||
"1:can only be 1, since there is one parameter|"
|
||||
":must be between 1 and %2}2">;
|
||||
def err_attribute_argument_not_lockable : Error<
|
||||
def warn_attribute_argument_not_lockable : Warning<
|
||||
"%0 attribute requires arguments whose type is annotated "
|
||||
"with 'lockable' attribute">;
|
||||
def err_attribute_decl_not_lockable : Error<
|
||||
"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">;
|
||||
"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<
|
||||
"unlocking '%0' that was not locked">,
|
||||
InGroup<ThreadSafety>, DefaultIgnore;
|
||||
|
|
|
@ -272,24 +272,25 @@ static const RecordType *getRecordType(QualType QT) {
|
|||
|
||||
/// \brief Thread Safety Analysis: Checks that the passed in RecordType
|
||||
/// resolves to a lockable object. May flag an error.
|
||||
static bool checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr,
|
||||
const RecordType *RT) {
|
||||
// Flag error if could not get record type for this argument.
|
||||
static void checkForLockableRecord(Sema &S, Decl *D, 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::err_attribute_argument_not_class)
|
||||
<< Attr.getName();
|
||||
return false;
|
||||
S.Diag(Attr.getLoc(), diag::warn_attribute_argument_not_class)
|
||||
<< Attr.getName() << Ty.getAsString();
|
||||
return;
|
||||
}
|
||||
// Don't check for lockable if the class hasn't been defined yet.
|
||||
if (RT->isIncompleteType())
|
||||
return true;
|
||||
// Flag error if the type is not lockable.
|
||||
return;
|
||||
// Warn if the type is not lockable.
|
||||
if (!RT->getDecl()->getAttr<LockableAttr>()) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_lockable)
|
||||
<< Attr.getName();
|
||||
return false;
|
||||
S.Diag(Attr.getLoc(), diag::warn_attribute_argument_not_lockable)
|
||||
<< Attr.getName() << Ty.getAsString();
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Thread Safety Analysis: Checks that all attribute arguments, starting
|
||||
|
@ -331,12 +332,10 @@ static bool checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
|
|||
return false;
|
||||
}
|
||||
ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType();
|
||||
RT = getRecordType(ArgTy);
|
||||
}
|
||||
}
|
||||
|
||||
if (!checkForLockableRecord(S, D, Attr, RT))
|
||||
return false;
|
||||
checkForLockableRecord(S, D, Attr, ArgTy);
|
||||
|
||||
Args.push_back(ArgExp);
|
||||
}
|
||||
|
@ -394,9 +393,7 @@ static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr,
|
|||
return;
|
||||
|
||||
if (!Arg->isTypeDependent()) {
|
||||
if (!checkForLockableRecord(S, D, Attr, getRecordType(Arg->getType())))
|
||||
return;
|
||||
// FIXME -- semantic checks for dependent attributes
|
||||
checkForLockableRecord(S, D, Attr, Arg->getType());
|
||||
}
|
||||
|
||||
if (pointer)
|
||||
|
@ -481,7 +478,7 @@ static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr,
|
|||
if (!QT->isDependentType()) {
|
||||
const RecordType *RT = getRecordType(QT);
|
||||
if (!RT || !RT->getDecl()->getAttr<LockableAttr>()) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_decl_not_lockable)
|
||||
S.Diag(Attr.getLoc(), diag::warn_attribute_decl_not_lockable)
|
||||
<< Attr.getName();
|
||||
return;
|
||||
}
|
||||
|
@ -651,8 +648,7 @@ static void handleLockReturnedAttr(Sema &S, Decl *D,
|
|||
return;
|
||||
|
||||
// check that the argument is lockable object
|
||||
if (!checkForLockableRecord(S, D, Attr, getRecordType(Arg->getType())))
|
||||
return;
|
||||
checkForLockableRecord(S, D, Attr, Arg->getType());
|
||||
|
||||
D->addAttr(::new (S.Context) LockReturnedAttr(Attr.getRange(), S.Context, Arg));
|
||||
}
|
||||
|
|
|
@ -341,13 +341,13 @@ int gb_var_arg_8 __attribute__((guarded_by(muPointer)));
|
|||
|
||||
// illegal attribute arguments
|
||||
int gb_var_arg_bad_1 __attribute__((guarded_by(1))); // \
|
||||
// expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}}
|
||||
// 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"))); // \
|
||||
// expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}}
|
||||
// expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'const char [3]'}}
|
||||
int gb_var_arg_bad_3 __attribute__((guarded_by(muDoublePointer))); // \
|
||||
// expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}}
|
||||
// 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))); // \
|
||||
// expected-error {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute; type here is 'class UnlockableMu'}}
|
||||
|
||||
//3.
|
||||
// Thread Safety analysis tests
|
||||
|
@ -412,13 +412,13 @@ int * pgb_var_arg_8 __attribute__((pt_guarded_by(muPointer)));
|
|||
|
||||
// illegal attribute arguments
|
||||
int * pgb_var_arg_bad_1 __attribute__((pt_guarded_by(1))); // \
|
||||
// expected-error {{'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"))); // \
|
||||
// expected-error {{'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_3 __attribute__((pt_guarded_by(muDoublePointer))); // \
|
||||
// expected-error {{'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))); // \
|
||||
// expected-error {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
|
||||
|
||||
//-----------------------------------------//
|
||||
|
@ -473,15 +473,15 @@ Mu aa_var_arg_8 __attribute__((acquired_after(muPointer)));
|
|||
|
||||
// illegal attribute arguments
|
||||
Mu aa_var_arg_bad_1 __attribute__((acquired_after(1))); // \
|
||||
// expected-error {{'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"))); // \
|
||||
// expected-error {{'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_3 __attribute__((acquired_after(muDoublePointer))); // \
|
||||
// expected-error {{'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))); // \
|
||||
// expected-error {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
UnlockableMu aa_var_arg_bad_5 __attribute__((acquired_after(mu_aa))); // \
|
||||
// expected-error {{'acquired_after' attribute can only be applied in a context annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'acquired_after' attribute can only be applied in a context annotated with 'lockable' attribute}}
|
||||
|
||||
//-----------------------------------------//
|
||||
// Acquired Before (ab)
|
||||
|
@ -536,15 +536,15 @@ Mu ab_var_arg_8 __attribute__((acquired_before(muPointer)));
|
|||
|
||||
// illegal attribute arguments
|
||||
Mu ab_var_arg_bad_1 __attribute__((acquired_before(1))); // \
|
||||
// expected-error {{'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"))); // \
|
||||
// expected-error {{'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_3 __attribute__((acquired_before(muDoublePointer))); // \
|
||||
// expected-error {{'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))); // \
|
||||
// expected-error {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
UnlockableMu ab_var_arg_bad_5 __attribute__((acquired_before(mu_ab))); // \
|
||||
// expected-error {{'acquired_before' attribute can only be applied in a context annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'acquired_before' attribute can only be applied in a context annotated with 'lockable' attribute}}
|
||||
|
||||
|
||||
//-----------------------------------------//
|
||||
|
@ -603,11 +603,11 @@ int elf_function_9(Mu x, Mu y) __attribute__((exclusive_lock_function(1,2)));
|
|||
|
||||
// illegal attribute arguments
|
||||
int elf_function_bad_2() __attribute__((exclusive_lock_function("mu"))); // \
|
||||
// expected-error {{'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_3() __attribute__((exclusive_lock_function(muDoublePointer))); // \
|
||||
// expected-error {{'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))); // \
|
||||
// expected-error {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
|
||||
int elf_function_bad_1() __attribute__((exclusive_lock_function(1))); // \
|
||||
// expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
|
||||
|
@ -675,11 +675,11 @@ int slf_function_9(Mu x, Mu y) __attribute__((shared_lock_function(1,2)));
|
|||
|
||||
// illegal attribute arguments
|
||||
int slf_function_bad_2() __attribute__((shared_lock_function("mu"))); // \
|
||||
// expected-error {{'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_3() __attribute__((shared_lock_function(muDoublePointer))); // \
|
||||
// expected-error {{'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))); // \
|
||||
// expected-error {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
|
||||
int slf_function_bad_1() __attribute__((shared_lock_function(1))); // \
|
||||
// expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
|
||||
|
@ -757,11 +757,11 @@ 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}}
|
||||
|
||||
int etf_function_bad_4() __attribute__((exclusive_trylock_function(1, "mu"))); // \
|
||||
// expected-error {{'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_5() __attribute__((exclusive_trylock_function(1, muDoublePointer))); // \
|
||||
// expected-error {{'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))); // \
|
||||
// expected-error {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
|
||||
|
||||
//-----------------------------------------//
|
||||
|
@ -831,11 +831,11 @@ 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}}
|
||||
|
||||
int stf_function_bad_4() __attribute__((shared_trylock_function(1, "mu"))); // \
|
||||
// expected-error {{'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_5() __attribute__((shared_trylock_function(1, muDoublePointer))); // \
|
||||
// expected-error {{'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))); // \
|
||||
// expected-error {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
|
||||
|
||||
//-----------------------------------------//
|
||||
|
@ -894,11 +894,11 @@ int uf_function_9(Mu x, Mu y) __attribute__((unlock_function(1,2)));
|
|||
|
||||
// illegal attribute arguments
|
||||
int uf_function_bad_2() __attribute__((unlock_function("mu"))); // \
|
||||
// expected-error {{'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_3() __attribute__((unlock_function(muDoublePointer))); // \
|
||||
// expected-error {{'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))); // \
|
||||
// expected-error {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
|
||||
int uf_function_bad_1() __attribute__((unlock_function(1))); // \
|
||||
// expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
|
||||
|
@ -968,13 +968,13 @@ int lr_function_8() __attribute__((lock_returned(muPointer)));
|
|||
|
||||
// illegal attribute arguments
|
||||
int lr_function_bad_1() __attribute__((lock_returned(1))); // \
|
||||
// expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}}
|
||||
// expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}}
|
||||
int lr_function_bad_2() __attribute__((lock_returned("mu"))); // \
|
||||
// expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}}
|
||||
// expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}}
|
||||
int lr_function_bad_3() __attribute__((lock_returned(muDoublePointer))); // \
|
||||
// expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}}
|
||||
// expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}}
|
||||
int lr_function_bad_4() __attribute__((lock_returned(umu))); // \
|
||||
// expected-error {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
|
||||
|
||||
|
||||
|
@ -1035,13 +1035,13 @@ int le_function_8() __attribute__((locks_excluded(muPointer)));
|
|||
|
||||
// illegal attribute arguments
|
||||
int le_function_bad_1() __attribute__((locks_excluded(1))); // \
|
||||
// expected-error {{'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"))); // \
|
||||
// expected-error {{'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_3() __attribute__((locks_excluded(muDoublePointer))); // \
|
||||
// expected-error {{'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))); // \
|
||||
// expected-error {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
|
||||
|
||||
|
||||
|
@ -1102,13 +1102,13 @@ int elr_function_8() __attribute__((exclusive_locks_required(muPointer)));
|
|||
|
||||
// illegal attribute arguments
|
||||
int elr_function_bad_1() __attribute__((exclusive_locks_required(1))); // \
|
||||
// expected-error {{'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"))); // \
|
||||
// expected-error {{'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_3() __attribute__((exclusive_locks_required(muDoublePointer))); // \
|
||||
// expected-error {{'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))); // \
|
||||
// expected-error {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
|
||||
|
||||
|
||||
|
@ -1170,13 +1170,13 @@ int slr_function_8() __attribute__((shared_locks_required(muPointer)));
|
|||
|
||||
// illegal attribute arguments
|
||||
int slr_function_bad_1() __attribute__((shared_locks_required(1))); // \
|
||||
// expected-error {{'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"))); // \
|
||||
// expected-error {{'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_3() __attribute__((shared_locks_required(muDoublePointer))); // \
|
||||
// expected-error {{'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))); // \
|
||||
// expected-error {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
// expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
|
||||
|
||||
|
||||
//-----------------------------------------//
|
||||
|
|
Загрузка…
Ссылка в новой задаче