]> granicus.if.org Git - clang/commitdiff
Thread Safety Analysis: handle expressions involving temporaries,
authorDeLesley Hutchins <delesley@google.com>
Tue, 3 Jul 2012 18:25:56 +0000 (18:25 +0000)
committerDeLesley Hutchins <delesley@google.com>
Tue, 3 Jul 2012 18:25:56 +0000 (18:25 +0000)
e.g. ExprWithCleanups.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159674 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ThreadSafety.cpp
test/SemaCXX/warn-thread-safety-analysis.cpp

index f9d93ee0dfad03d8d2d4e7e8ea3bca4013b88aa6..238a888194b80082b50a0c243b24cab4404ca25d 100644 (file)
@@ -206,15 +206,17 @@ class MutexID {
       buildMutexID(CE->getSubExpr(), CallCtx);
     } else if (ParenExpr *PE = dyn_cast<ParenExpr>(Exp)) {
       buildMutexID(PE->getSubExpr(), CallCtx);
+    } else if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Exp)) {
+      buildMutexID(EWC->getSubExpr(), CallCtx);
     } else if (isa<CharacterLiteral>(Exp) ||
-             isa<CXXNullPtrLiteralExpr>(Exp) ||
-             isa<GNUNullExpr>(Exp) ||
-             isa<CXXBoolLiteralExpr>(Exp) ||
-             isa<FloatingLiteral>(Exp) ||
-             isa<ImaginaryLiteral>(Exp) ||
-             isa<IntegerLiteral>(Exp) ||
-             isa<StringLiteral>(Exp) ||
-             isa<ObjCStringLiteral>(Exp)) {
+               isa<CXXNullPtrLiteralExpr>(Exp) ||
+               isa<GNUNullExpr>(Exp) ||
+               isa<CXXBoolLiteralExpr>(Exp) ||
+               isa<FloatingLiteral>(Exp) ||
+               isa<ImaginaryLiteral>(Exp) ||
+               isa<IntegerLiteral>(Exp) ||
+               isa<StringLiteral>(Exp) ||
+               isa<ObjCStringLiteral>(Exp)) {
       return;  // FIXME: Ignore literals for now
     } else {
       // Ignore.  FIXME: mark as invalid expression?
@@ -1523,6 +1525,10 @@ void BuildLockset::VisitDeclStmt(DeclStmt *S) {
     Decl *D = *I;
     if (VarDecl *VD = dyn_cast_or_null<VarDecl>(D)) {
       Expr *E = VD->getInit();
+      // handle constructors that involve temporaries
+      if (ExprWithCleanups *EWC = dyn_cast_or_null<ExprWithCleanups>(E))
+        E = EWC->getSubExpr();
+
       if (CXXConstructExpr *CE = dyn_cast_or_null<CXXConstructExpr>(E)) {
         NamedDecl *CtorD = dyn_cast_or_null<NamedDecl>(CE->getConstructor());
         if (!CtorD || !CtorD->hasAttrs())
index 2bf9ed40796bcc388ab1ee64b9232c590929bf04..de3f3213792d236721346d2670bba999faf6437a 100644 (file)
@@ -57,6 +57,23 @@ class SCOPED_LOCKABLE ReleasableMutexLock {
   void Release() UNLOCK_FUNCTION();
 };
 
+
+template<class T>
+class SmartPtr {
+public:
+  SmartPtr(T* p) : ptr_(p) { }
+  SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
+  ~SmartPtr();
+
+  T* get()        const { return ptr_; }
+  T* operator->() const { return ptr_; }
+  T& operator*()  const { return ptr_; }
+
+private:
+  T* ptr_;
+};
+
+
 Mutex sls_mu;
 
 Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
@@ -2535,3 +2552,26 @@ class Foo {
 
 } // end namespace FoolishScopedLockableBug
 
+
+namespace TemporaryCleanupExpr {
+
+class Foo {
+  int a GUARDED_BY(getMutexPtr().get());
+
+  SmartPtr<Mutex> getMutexPtr();
+
+  void test();
+};
+
+
+void Foo::test() {
+  {
+    ReaderMutexLock lock(getMutexPtr().get());
+    int b = a;
+  }           // FIXME: handle smart pointers better.
+  int b = a;  // expected-warning {{reading variable 'a' requires locking 'get'}}
+}
+
+} // end namespace TemporaryCleanupExpr
+
+