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 |

