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; }
// 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);
#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"
}
}
-
-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();
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;
--- /dev/null
+// 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