зеркало из https://github.com/microsoft/clang-1.git
Thread safety analysis: check for LOCKABLE attribute on base classes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156175 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
8775485350
Коммит
bbba25fa8e
|
@ -14,6 +14,7 @@
|
|||
#include "clang/Sema/SemaInternal.h"
|
||||
#include "TargetAttributesSema.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/CXXInheritance.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
|
@ -298,6 +299,16 @@ static const RecordType *getRecordType(QualType QT) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool checkBaseClassIsLockableCallback(const CXXBaseSpecifier *Specifier,
|
||||
CXXBasePath &Path, void *UserData) {
|
||||
const RecordType *RT = Specifier->getType()->getAs<RecordType>();
|
||||
if (RT->getDecl()->getAttr<LockableAttr>())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// \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,
|
||||
|
@ -320,12 +331,20 @@ static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr,
|
|||
if (threadSafetyCheckIsSmartPointer(S, RT))
|
||||
return;
|
||||
|
||||
// Warn if the type is not lockable.
|
||||
if (!RT->getDecl()->getAttr<LockableAttr>()) {
|
||||
S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
|
||||
<< Attr.getName() << Ty.getAsString();
|
||||
// Check if the type is lockable.
|
||||
RecordDecl *RD = RT->getDecl();
|
||||
if (RD->getAttr<LockableAttr>())
|
||||
return;
|
||||
|
||||
// Else check if any base classes are lockable.
|
||||
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
|
||||
CXXBasePaths BPaths(false, false);
|
||||
if (CRD->lookupInBases(checkBaseClassIsLockableCallback, 0, BPaths))
|
||||
return;
|
||||
}
|
||||
|
||||
S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
|
||||
<< Attr.getName() << Ty.getAsString();
|
||||
}
|
||||
|
||||
/// \brief Thread Safety Analysis: Checks that all attribute arguments, starting
|
||||
|
|
|
@ -1319,6 +1319,8 @@ private:
|
|||
Mutex mu_;
|
||||
};
|
||||
|
||||
} // end namespace TestMultiDecl
|
||||
|
||||
|
||||
namespace NestedClassLateDecl {
|
||||
|
||||
|
@ -1393,5 +1395,38 @@ public:
|
|||
}
|
||||
|
||||
|
||||
} // end namespace TestMultiDecl
|
||||
namespace InheritanceTest {
|
||||
|
||||
class LOCKABLE Base {
|
||||
public:
|
||||
void lock() EXCLUSIVE_LOCK_FUNCTION();
|
||||
void unlock() UNLOCK_FUNCTION();
|
||||
};
|
||||
|
||||
class Base2 { };
|
||||
|
||||
class Derived1 : public Base { };
|
||||
|
||||
class Derived2 : public Base2, public Derived1 { };
|
||||
|
||||
class Derived3 : public Base2 { };
|
||||
|
||||
class Foo {
|
||||
Derived1 mu1_;
|
||||
Derived2 mu2_;
|
||||
Derived3 mu3_;
|
||||
int a GUARDED_BY(mu1_);
|
||||
int b GUARDED_BY(mu2_);
|
||||
int c GUARDED_BY(mu3_); // \
|
||||
// expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute; type here is 'class InheritanceTest::Derived3'}}
|
||||
|
||||
void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1_, mu2_) {
|
||||
a = 0;
|
||||
b = 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче