forked from OSchip/llvm-project
Thread safety analysis: Handle ObjCIvarRefExpr in SExprBuilder::translate
Summary: This imitates the code for MemberExpr. Fixes PR38896. Reviewers: aaron.ballman, delesley, lukasza, rjmccall Reviewed By: delesley Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D52200 llvm-svn: 342600
This commit is contained in:
parent
8d6ac8f689
commit
b081f44e17
|
@ -397,6 +397,8 @@ private:
|
|||
CallingContext *Ctx) ;
|
||||
til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx);
|
||||
til::SExpr *translateMemberExpr(const MemberExpr *ME, CallingContext *Ctx);
|
||||
til::SExpr *translateObjCIVarRefExpr(const ObjCIvarRefExpr *IVRE,
|
||||
CallingContext *Ctx);
|
||||
til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx,
|
||||
const Expr *SelfE = nullptr);
|
||||
til::SExpr *translateCXXMemberCallExpr(const CXXMemberCallExpr *ME,
|
||||
|
|
|
@ -211,6 +211,8 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
|
|||
return translateCXXThisExpr(cast<CXXThisExpr>(S), Ctx);
|
||||
case Stmt::MemberExprClass:
|
||||
return translateMemberExpr(cast<MemberExpr>(S), Ctx);
|
||||
case Stmt::ObjCIvarRefExprClass:
|
||||
return translateObjCIVarRefExpr(cast<ObjCIvarRefExpr>(S), Ctx);
|
||||
case Stmt::CallExprClass:
|
||||
return translateCallExpr(cast<CallExpr>(S), Ctx);
|
||||
case Stmt::CXXMemberCallExprClass:
|
||||
|
@ -311,9 +313,9 @@ static const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static bool hasCppPointerType(const til::SExpr *E) {
|
||||
static bool hasAnyPointerType(const til::SExpr *E) {
|
||||
auto *VD = getValueDeclFromSExpr(E);
|
||||
if (VD && VD->getType()->isPointerType())
|
||||
if (VD && VD->getType()->isAnyPointerType())
|
||||
return true;
|
||||
if (const auto *C = dyn_cast<til::Cast>(E))
|
||||
return C->castOpcode() == til::CAST_objToPtr;
|
||||
|
@ -344,7 +346,20 @@ til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME,
|
|||
D = getFirstVirtualDecl(VD);
|
||||
|
||||
til::Project *P = new (Arena) til::Project(E, D);
|
||||
if (hasCppPointerType(BE))
|
||||
if (hasAnyPointerType(BE))
|
||||
P->setArrow(true);
|
||||
return P;
|
||||
}
|
||||
|
||||
til::SExpr *SExprBuilder::translateObjCIVarRefExpr(const ObjCIvarRefExpr *IVRE,
|
||||
CallingContext *Ctx) {
|
||||
til::SExpr *BE = translate(IVRE->getBase(), Ctx);
|
||||
til::SExpr *E = new (Arena) til::SApply(BE);
|
||||
|
||||
const auto *D = cast<ObjCIvarDecl>(IVRE->getDecl()->getCanonicalDecl());
|
||||
|
||||
til::Project *P = new (Arena) til::Project(E, D);
|
||||
if (hasAnyPointerType(BE))
|
||||
P->setArrow(true);
|
||||
return P;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -Wthread-safety-beta -Wno-objc-root-class %s
|
||||
|
||||
class __attribute__((lockable)) Lock {
|
||||
public:
|
||||
void Acquire() __attribute__((exclusive_lock_function())) {}
|
||||
void Release() __attribute__((unlock_function())) {}
|
||||
};
|
||||
|
||||
class __attribute__((scoped_lockable)) AutoLock {
|
||||
public:
|
||||
AutoLock(Lock &lock) __attribute__((exclusive_lock_function(lock)))
|
||||
: lock_(lock) {
|
||||
lock.Acquire();
|
||||
}
|
||||
~AutoLock() __attribute__((unlock_function())) { lock_.Release(); }
|
||||
|
||||
private:
|
||||
Lock &lock_;
|
||||
};
|
||||
|
||||
@interface MyInterface {
|
||||
@private
|
||||
Lock lock_;
|
||||
int value_;
|
||||
}
|
||||
|
||||
- (void)incrementValue;
|
||||
- (void)decrementValue;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MyInterface
|
||||
|
||||
- (void)incrementValue {
|
||||
AutoLock lock(lock_);
|
||||
value_ += 1;
|
||||
}
|
||||
|
||||
- (void)decrementValue {
|
||||
lock_.Acquire(); // expected-note{{mutex acquired here}}
|
||||
value_ -= 1;
|
||||
} // expected-warning{{mutex 'self->lock_' is still held at the end of function}}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue