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:
DeLesley Hutchins 2012-05-04 16:28:38 +00:00
Родитель 8775485350
Коммит bbba25fa8e
2 изменённых файлов: 59 добавлений и 5 удалений

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

@ -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;
}
};
}