aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
authorDeLesley Hutchins <delesley@google.com>2012-05-02 22:18:42 +0000
committerDeLesley Hutchins <delesley@google.com>2012-05-02 22:18:42 +0000
commit60f2024b7df091fb0d8b7e37334bc83ac66a5c39 (patch)
tree5fe8232002c466298d62f4848e34a09e530ce8c6 /lib/Sema/SemaDeclAttr.cpp
parent914edfbb07c34d8cad8d0451193b4f9dd02a2d5a (diff)
Thread safety analysis: additional support for smart pointers in lock expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156030 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclAttr.cpp')
-rw-r--r--lib/Sema/SemaDeclAttr.cpp44
1 files changed, 28 insertions, 16 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 6b3f4f9734..3706bb8c8c 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -241,26 +241,23 @@ static bool isIntOrBool(Expr *Exp) {
// Check to see if the type is a smart pointer of some kind. We assume
// it's a smart pointer if it defines both operator-> and operator*.
-static bool threadSafetyCheckIsSmartPointer(Sema &S, const QualType QT) {
- if (const RecordType *RT = QT->getAs<RecordType>()) {
- DeclContextLookupConstResult Res1 = RT->getDecl()->lookup(
- S.Context.DeclarationNames.getCXXOperatorName(OO_Star));
- if (Res1.first == Res1.second)
- return false;
+static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
+ DeclContextLookupConstResult Res1 = RT->getDecl()->lookup(
+ S.Context.DeclarationNames.getCXXOperatorName(OO_Star));
+ if (Res1.first == Res1.second)
+ return false;
- DeclContextLookupConstResult Res2 = RT->getDecl()->lookup(
- S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow));
- if (Res2.first != Res2.second)
- return true;
- }
- return false;
+ DeclContextLookupConstResult Res2 = RT->getDecl()->lookup(
+ S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow));
+ if (Res2.first == Res2.second)
+ return false;
+
+ return true;
}
-///
/// \brief Check if passed in Decl is a pointer type.
/// Note that this function may produce an error message.
/// \return true if the Decl is a pointer type; false otherwise
-///
static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
const AttributeList &Attr) {
if (const ValueDecl *vd = dyn_cast<ValueDecl>(D)) {
@@ -268,8 +265,16 @@ static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
if (QT->isAnyPointerType())
return true;
- if (threadSafetyCheckIsSmartPointer(S, QT))
- return true;
+ if (const RecordType *RT = QT->getAs<RecordType>()) {
+ // If it's an incomplete type, it could be a smart pointer; skip it.
+ // (We don't want to force template instantiation if we can avoid it,
+ // since that would alter the order in which templates are instantiated.)
+ if (RT->isIncompleteType())
+ return true;
+
+ if (threadSafetyCheckIsSmartPointer(S, RT))
+ return true;
+ }
S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
<< Attr.getName()->getName() << QT;
@@ -305,9 +310,16 @@ static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr,
<< Attr.getName() << Ty.getAsString();
return;
}
+
// Don't check for lockable if the class hasn't been defined yet.
if (RT->isIncompleteType())
return;
+
+ // Allow smart pointers to be used as lockable objects.
+ // FIXME -- Check the type that the smart pointer points to.
+ 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)