diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 27980bd541f30401b294487641320dad9bfa8ea7..59c4373190eec1dae840ef6ab7182c4393152261 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -238,6 +238,24 @@ static bool isIntOrBool(Expr *Exp) { return QT->isBooleanType() || QT->isIntegerType(); } + +// 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; + + DeclContextLookupConstResult Res2 = RT->getDecl()->lookup( + S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow)); + if (Res2.first != Res2.second) + return true; + } + return false; +} + /// /// \brief Check if passed in Decl is a pointer type. /// Note that this function may produce an error message. @@ -249,6 +267,10 @@ static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D, QualType QT = vd->getType(); if (QT->isAnyPointerType()) return true; + + if (threadSafetyCheckIsSmartPointer(S, QT)) + return true; + S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer) << Attr.getName()->getName() << QT; } else { diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp index ac7737d4ac28d08fa1206eeb331ae1312e09d864..af02be1430bafbbe7516ba9737b117fc6bb39b1b 100644 --- a/test/SemaCXX/warn-thread-safety-parsing.cpp +++ b/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -1343,6 +1343,10 @@ class Foo { namespace PointerToMemberTest { +// Empty string should be ignored. +int testEmptyAttribute GUARDED_BY(""); +void testEmptyAttributeFunction() EXCLUSIVE_LOCKS_REQUIRED(""); + class Graph { public: Mu mu_; @@ -1356,5 +1360,31 @@ public: } + +namespace SmartPointerTest { + +template<class T> +class smart_ptr { + public: + smart_ptr(T* p) : ptr_(p) { }; + + T* operator->() { return ptr_; } + T& operator*() { return ptr_; } + + private: + T* ptr_; +}; + + +class MyClass { +public: + Mu mu_; + + smart_ptr<int> a PT_GUARDED_BY(mu_); +}; + +} + + } // end namespace TestMultiDecl