r343902 - Thread safety analysis: Handle conditional expression in getTrylockCallExpr

Aaron Puchert via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 5 18:09:28 PDT 2018


Author: aaronpuchert
Date: Fri Oct  5 18:09:28 2018
New Revision: 343902

URL: http://llvm.org/viewvc/llvm-project?rev=343902&view=rev
Log:
Thread safety analysis: Handle conditional expression in getTrylockCallExpr

Summary:
We unwrap conditional expressions containing try-lock functions.

Additionally we don't acquire on conditional expression branches, since
that is usually not helpful. When joining the branches we would almost
certainly get a warning then.

Hopefully fixes an issue that was raised in D52398.

Reviewers: aaron.ballman, delesley, hokein

Reviewed By: aaron.ballman

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D52888

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=343902&r1=343901&r2=343902&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ThreadSafety.cpp (original)
+++ cfe/trunk/lib/Analysis/ThreadSafety.cpp Fri Oct  5 18:09:28 2018
@@ -1435,6 +1435,17 @@ const CallExpr* ThreadSafetyAnalyzer::ge
     if (BOP->getOpcode() == BO_LOr)
       return getTrylockCallExpr(BOP->getRHS(), C, Negate);
     return nullptr;
+  } else if (const auto *COP = dyn_cast<ConditionalOperator>(Cond)) {
+    bool TCond, FCond;
+    if (getStaticBooleanValue(COP->getTrueExpr(), TCond) &&
+        getStaticBooleanValue(COP->getFalseExpr(), FCond)) {
+      if (TCond && !FCond)
+        return getTrylockCallExpr(COP->getCond(), C, Negate);
+      if (!TCond && FCond) {
+        Negate = !Negate;
+        return getTrylockCallExpr(COP->getCond(), C, Negate);
+      }
+    }
   }
   return nullptr;
 }
@@ -1449,7 +1460,8 @@ void ThreadSafetyAnalyzer::getEdgeLockse
   Result = ExitSet;
 
   const Stmt *Cond = PredBlock->getTerminatorCondition();
-  if (!Cond)
+  // We don't acquire try-locks on ?: branches, only when its result is used.
+  if (!Cond || isa<ConditionalOperator>(PredBlock->getTerminator()))
     return;
 
   bool Negate = false;

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=343902&r1=343901&r2=343902&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Fri Oct  5 18:09:28 2018
@@ -1873,6 +1873,23 @@ struct TestTryLock {
    int i = a;
    mu.Unlock();
   }
+
+  // Test with conditional operator
+  void foo13() {
+    if (mu.TryLock() ? 1 : 0)
+      mu.Unlock();
+  }
+
+  void foo14() {
+    if (mu.TryLock() ? 0 : 1)
+      return;
+    mu.Unlock();
+  }
+
+  void foo15() {
+    if (mu.TryLock() ? 0 : 1) // expected-note{{mutex acquired here}}
+      mu.Unlock();            // expected-warning{{releasing mutex 'mu' that was not held}}
+  }                           // expected-warning{{mutex 'mu' is not held on every path through here}}
 };  // end TestTrylock
 
 } // end namespace TrylockTest




More information about the cfe-commits mailing list