diff options
| -rw-r--r-- | clang/lib/Analysis/ThreadSafety.cpp | 10 | ||||
| -rw-r--r-- | clang/test/SemaCXX/warn-thread-safety-analysis.cpp | 45 | 
2 files changed, 51 insertions, 4 deletions
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index 77785d3e29f..b89a83c8817 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -300,8 +300,9 @@ private:      } else if (CXXMemberCallExpr *CMCE = dyn_cast<CXXMemberCallExpr>(Exp)) {        // When calling a function with a lock_returned attribute, replace        // the function call with the expression in lock_returned. -      if (LockReturnedAttr* At = -            CMCE->getMethodDecl()->getAttr<LockReturnedAttr>()) { +      CXXMethodDecl* MD = +        cast<CXXMethodDecl>(CMCE->getMethodDecl()->getMostRecentDecl()); +      if (LockReturnedAttr* At = MD->getAttr<LockReturnedAttr>()) {          CallingContext LRCallCtx(CMCE->getMethodDecl());          LRCallCtx.SelfArg = CMCE->getImplicitObjectArgument();          LRCallCtx.SelfArrow = @@ -330,8 +331,9 @@ private:        NodeVec[Root].setSize(Sz + 1);        return Sz + 1;      } else if (CallExpr *CE = dyn_cast<CallExpr>(Exp)) { -      if (LockReturnedAttr* At = -            CE->getDirectCallee()->getAttr<LockReturnedAttr>()) { +      FunctionDecl* FD = +        cast<FunctionDecl>(CE->getDirectCallee()->getMostRecentDecl()); +      if (LockReturnedAttr* At = FD->getAttr<LockReturnedAttr>()) {          CallingContext LRCallCtx(CE->getDirectCallee());          LRCallCtx.NumArgs = CE->getNumArgs();          LRCallCtx.FunArgs = CE->getArgs(); diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp index 2a362064ab7..7d0d6430d9b 100644 --- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -3145,3 +3145,48 @@ public:  } // end namespace StringIgnoreTest +namespace LockReturnedScopeFix { + +class Base { +protected: +  struct Inner; +  bool c; + +  const Mutex& getLock(const Inner* i); + +  void lockInner  (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i)); +  void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i)); +  void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i)); + +  void bar(Inner* i); +}; + + +struct Base::Inner { +  Mutex lock_; +  void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_); +}; + + +const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) { +  return i->lock_; +} + + +void Base::foo(Inner* i) { +  i->doSomething(); +} + +void Base::bar(Inner* i) { +  if (c) { +    i->lock_.Lock(); +    unlockInner(i); +  } +  else { +    lockInner(i); +    i->lock_.Unlock(); +  } +} + +} // end namespace LockReturnedScopeFix +  | 

