diff options
| -rw-r--r-- | clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h | 6 | ||||
| -rw-r--r-- | clang/lib/Analysis/ThreadSafetyCommon.cpp | 10 | ||||
| -rw-r--r-- | clang/test/SemaObjC/warn-thread-safety-analysis.m | 19 | 
3 files changed, 28 insertions, 7 deletions
diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h index 5ad8132e478..c01114fd862 100644 --- a/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h +++ b/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h @@ -193,8 +193,8 @@ public:    const CFG *getGraph() const { return CFGraph; }    CFG *getGraph() { return CFGraph; } -  const FunctionDecl *getDecl() const { -    return dyn_cast<FunctionDecl>(ACtx->getDecl()); +  const NamedDecl *getDecl() const { +    return dyn_cast<NamedDecl>(ACtx->getDecl());    }    const PostOrderCFGView *getSortedGraph() const { return SortedGraph; } @@ -326,7 +326,7 @@ private:    // We implement the CFGVisitor API    friend class CFGWalker; -  void enterCFG(CFG *Cfg, const FunctionDecl *D, const CFGBlock *First); +  void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First);    void enterCFGBlock(const CFGBlock *B);    bool visitPredecessors() { return true; }    void handlePredecessor(const CFGBlock *Pred); diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp index 0a6efebd311..fb96834b3e7 100644 --- a/clang/lib/Analysis/ThreadSafetyCommon.cpp +++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -14,6 +14,7 @@  #include "clang/Analysis/Analyses/ThreadSafetyCommon.h"  #include "clang/AST/Attr.h"  #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h"  #include "clang/AST/ExprCXX.h"  #include "clang/AST/StmtCXX.h"  #include "clang/Analysis/Analyses/PostOrderCFGView.h" @@ -634,8 +635,7 @@ void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock *Blk) {    }  } - -void SExprBuilder::enterCFG(CFG *Cfg, const FunctionDecl *FD, +void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D,                              const CFGBlock *First) {    // Perform initial setup operations.    unsigned NBlocks = Cfg->getNumBlockIDs(); @@ -649,10 +649,12 @@ void SExprBuilder::enterCFG(CFG *Cfg, const FunctionDecl *FD,      auto *BB = new (Arena) til::BasicBlock(Arena, 0, B->size());      BlockMap[B->getBlockID()] = BB;    } -  CallCtx.reset(new SExprBuilder::CallingContext(FD)); +  CallCtx.reset(new SExprBuilder::CallingContext(D));    CurrentBB = lookupBlock(&Cfg->getEntry()); -  for (auto *Pm : FD->parameters()) { +  auto Parms = isa<ObjCMethodDecl>(D) ? cast<ObjCMethodDecl>(D)->parameters() +                                      : cast<FunctionDecl>(D)->parameters(); +  for (auto *Pm : Parms) {      QualType T = Pm->getType();      if (!T.isTrivialType(Pm->getASTContext()))        continue; diff --git a/clang/test/SemaObjC/warn-thread-safety-analysis.m b/clang/test/SemaObjC/warn-thread-safety-analysis.m new file mode 100644 index 00000000000..0e29ff25352 --- /dev/null +++ b/clang/test/SemaObjC/warn-thread-safety-analysis.m @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -Wthread-safety-beta -Wno-objc-root-class %s + +struct __attribute__ ((lockable)) Mutex {}; + +struct Mutex mu1; + +int Foo_fun1(int i) __attribute__ ((exclusive_locks_required((mu1)))) { +  return i; +} + +@interface test +@end + +@implementation test +- (void) PR19541 { +  Foo_fun1(1); // expected-warning{{calling function 'Foo_fun1' requires holding mutex 'mu1' exclusively}} +} + +@end  | 

