[cfe-commits] r160018 - in /cfe/trunk: lib/Analysis/ThreadSafety.cpp test/SemaCXX/warn-thread-safety-analysis.cpp

DeLesley Hutchins delesley at google.com
Tue Jul 10 14:47:56 PDT 2012


Author: delesley
Date: Tue Jul 10 16:47:55 2012
New Revision: 160018

URL: http://llvm.org/viewvc/llvm-project?rev=160018&view=rev
Log:
Thread safety analysis: impove handling of trylock expressions.

Modified:
    cfe/trunk/lib/Analysis/ThreadSafety.cpp
    cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp

Modified: cfe/trunk/lib/Analysis/ThreadSafety.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ThreadSafety.cpp?rev=160018&r1=160017&r2=160018&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ThreadSafety.cpp (original)
+++ cfe/trunk/lib/Analysis/ThreadSafety.cpp Tue Jul 10 16:47:55 2012
@@ -1109,6 +1109,23 @@
 }
 
 
+bool getStaticBooleanValue(Expr* E, bool& TCond) {
+  if (isa<CXXNullPtrLiteralExpr>(E) || isa<GNUNullExpr>(E)) {
+    TCond = false;
+    return true;
+  } else if (CXXBoolLiteralExpr *BLE = dyn_cast<CXXBoolLiteralExpr>(E)) {
+    TCond = BLE->getValue();
+    return true;
+  } else if (IntegerLiteral *ILE = dyn_cast<IntegerLiteral>(E)) {
+    TCond = ILE->getValue().getBoolValue();
+    return true;
+  } else if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) {
+    return getStaticBooleanValue(CE->getSubExpr(), TCond);
+  }
+  return false;
+}
+
+
 // If Cond can be traced back to a function call, return the call expression.
 // The negate variable should be called with false, and will be set to true
 // if the function call is negated, e.g. if (!mu.tryLock(...))
@@ -1121,6 +1138,9 @@
   if (const CallExpr *CallExp = dyn_cast<CallExpr>(Cond)) {
     return CallExp;
   }
+  else if (const ParenExpr *PE = dyn_cast<ParenExpr>(Cond)) {
+    return getTrylockCallExpr(PE->getSubExpr(), C, Negate);
+  }
   else if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Cond)) {
     return getTrylockCallExpr(CE->getSubExpr(), C, Negate);
   }
@@ -1133,9 +1153,28 @@
       Negate = !Negate;
       return getTrylockCallExpr(UOP->getSubExpr(), C, Negate);
     }
+    return 0;
+  }
+  else if (const BinaryOperator *BOP = dyn_cast<BinaryOperator>(Cond)) {
+    if (BOP->getOpcode() == BO_EQ || BOP->getOpcode() == BO_NE) {
+      if (BOP->getOpcode() == BO_NE)
+        Negate = !Negate;
+
+      bool TCond = false;
+      if (getStaticBooleanValue(BOP->getRHS(), TCond)) {
+        if (!TCond) Negate = !Negate;
+        return getTrylockCallExpr(BOP->getLHS(), C, Negate);
+      }
+      else if (getStaticBooleanValue(BOP->getLHS(), TCond)) {
+        if (!TCond) Negate = !Negate;
+        return getTrylockCallExpr(BOP->getRHS(), C, Negate);
+      }
+      return 0;
+    }
+    return 0;
   }
   // FIXME -- handle && and || as well.
-  return NULL;
+  return 0;
 }
 
 

Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp?rev=160018&r1=160017&r2=160018&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Tue Jul 10 16:47:55 2012
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
-// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 %s
+
+// FIXME: should also run  %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
+// FIXME: should also run  %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
 
 #define LOCKABLE            __attribute__ ((lockable))
 #define SCOPED_LOCKABLE     __attribute__ ((scoped_lockable))
@@ -2932,5 +2934,128 @@
 
 
 
+namespace TryLockEqTest {
+
+class Foo {
+  Mutex mu_;
+  int a GUARDED_BY(mu_);
+  bool c;
+
+  int    tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
+  Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
+  void unlock() UNLOCK_FUNCTION(mu_);
+
+  void test1();
+  void test2();
+};
+
+
+void Foo::test1() {
+  if (tryLockMutexP() == 0) {
+    a = 0;  // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+    return;
+  }
+  a = 0;
+  unlock();
+
+  if (tryLockMutexP() != 0) {
+    a = 0;
+    unlock();
+  }
+
+  if (0 != tryLockMutexP()) {
+    a = 0;
+    unlock();
+  }
+
+  if (!(tryLockMutexP() == 0)) {
+    a = 0;
+    unlock();
+  }
+
+  if (tryLockMutexI() == 0) {
+    a = 0;   // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+    return;
+  }
+  a = 0;
+  unlock();
+
+  if (0 == tryLockMutexI()) {
+    a = 0;   // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+    return;
+  }
+  a = 0;
+  unlock();
+
+  if (tryLockMutexI() == 1) {
+    a = 0;
+    unlock();
+  }
+
+  if (mu_.TryLock() == false) {
+    a = 0;   // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+    return;
+  }
+  a = 0;
+  unlock();
+
+  if (mu_.TryLock() == true) {
+    a = 0;
+    unlock();
+  }
+  else {
+    a = 0;  // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+  }
+
+#if __has_feature(cxx_nullptr)
+  if (tryLockMutexP() == nullptr) {
+    a = 0;  // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
+    return;
+  }
+  a = 0;
+  unlock();
+#endif
+}
+
+
+void Foo::test2() {
+/* FIXME: these tests depend on changes to the CFG.
+ *
+  if (mu_.TryLock() && c) {
+    a = 0;
+    unlock();
+  }
+  else return;
+
+  if (c && mu_.TryLock()) {
+    a = 0;
+    unlock();
+  }
+  else return;
+
+  if (!(mu_.TryLock() && c))
+    return;
+  a = 0;
+  unlock();
+
+  if (!(c && mu_.TryLock()))
+    return;
+  a = 0;
+  unlock();
+
+  if (!(mu_.TryLock() == 0) && c) {
+    a = 0;
+    unlock();
+  }
+
+  if (!mu_.TryLock() || c)
+    return;
+  a = 0;
+  unlock();
+*/
+}
+
+
+} // end namespace TryLockEqTest
 
 





More information about the cfe-commits mailing list