зеркало из https://github.com/microsoft/clang-1.git
objc-arc: Check on a variety of unsafe assignment of retained
objects. // rdar://9495837 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133806 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
f58de90e20
Коммит
921c143229
|
@ -2603,6 +2603,9 @@ def warn_arc_non_pod_class_with_object_member : Warning<
|
|||
def warn_arc_retained_assign : Warning<
|
||||
"assigning retained object to %select{weak|unsafe_unretained}0 variable">,
|
||||
InGroup<ARCUnsafeRetainedAssign>;
|
||||
def warn_arc_retained_property_assign : Warning<
|
||||
"assigning retained object to unsafe property">,
|
||||
InGroup<ARCUnsafeRetainedAssign>;
|
||||
def warn_arc_trivial_member_function_with_object_member : Warning<
|
||||
"%0 cannot be shared between ARC and non-ARC "
|
||||
"code; add a non-trivial %select{copy constructor|copy assignment operator|"
|
||||
|
|
|
@ -5644,9 +5644,13 @@ public:
|
|||
void checkRetainCycles(ObjCMessageExpr *msg);
|
||||
void checkRetainCycles(Expr *receiver, Expr *argument);
|
||||
|
||||
/// checkWeakUnsafeAssigns - Check whether +1 expr is being assigned
|
||||
/// to weak/__unsafe_unretained.
|
||||
void checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS);
|
||||
/// checkUnsafeAssigns - Check whether +1 expr is being assigned
|
||||
/// to weak/__unsafe_unretained type.
|
||||
bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS);
|
||||
|
||||
/// checkUnsafeExprAssigns - Check whether +1 expr is being assigned
|
||||
/// to weak/__unsafe_unretained expression.
|
||||
void checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS);
|
||||
|
||||
/// CheckMessageArgumentTypes - Check types in an Obj-C message send.
|
||||
/// \param Method - May be null.
|
||||
|
|
|
@ -3720,15 +3720,50 @@ void Sema::checkRetainCycles(Expr *receiver, Expr *argument) {
|
|||
diagnoseRetainCycle(*this, capturer, owner);
|
||||
}
|
||||
|
||||
void Sema::checkUnsafeAssigns(SourceLocation Loc,
|
||||
bool Sema::checkUnsafeAssigns(SourceLocation Loc,
|
||||
QualType LHS, Expr *RHS) {
|
||||
Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();
|
||||
if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone)
|
||||
return;
|
||||
if (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS))
|
||||
if (cast->getCastKind() == CK_ObjCConsumeObject)
|
||||
return false;
|
||||
// strip off any implicit cast added to get to the one arc-specific
|
||||
while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
|
||||
if (cast->getCastKind() == CK_ObjCConsumeObject) {
|
||||
Diag(Loc, diag::warn_arc_retained_assign)
|
||||
<< (LT == Qualifiers::OCL_ExplicitNone)
|
||||
<< RHS->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
RHS = cast->getSubExpr();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
|
||||
Expr *LHS, Expr *RHS) {
|
||||
QualType LHSType = LHS->getType();
|
||||
if (checkUnsafeAssigns(Loc, LHSType, RHS))
|
||||
return;
|
||||
Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();
|
||||
// FIXME. Check for other life times.
|
||||
if (LT != Qualifiers::OCL_None)
|
||||
return;
|
||||
|
||||
if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(LHS)) {
|
||||
if (PRE->isImplicitProperty())
|
||||
return;
|
||||
const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
|
||||
if (!PD)
|
||||
return;
|
||||
|
||||
unsigned Attributes = PD->getPropertyAttributes();
|
||||
if (Attributes & ObjCPropertyDecl::OBJC_PR_assign)
|
||||
while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
|
||||
if (cast->getCastKind() == CK_ObjCConsumeObject) {
|
||||
Diag(Loc, diag::warn_arc_retained_property_assign)
|
||||
<< RHS->getSourceRange();
|
||||
return;
|
||||
}
|
||||
RHS = cast->getSubExpr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6735,8 +6735,8 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, ExprResult &RHS,
|
|||
if (ConvTy == Compatible) {
|
||||
if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong)
|
||||
checkRetainCycles(LHS, RHS.get());
|
||||
else
|
||||
checkUnsafeAssigns(Loc, LHSType, RHS.get());
|
||||
else if (getLangOptions().ObjCAutoRefCount)
|
||||
checkUnsafeExprAssigns(Loc, LHS, RHS.get());
|
||||
}
|
||||
} else {
|
||||
// Compound assignment "x += y"
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-nonfragile-abi -fsyntax-only -fobjc-arc -verify %s
|
||||
// rdar://9495837
|
||||
|
||||
@interface Foo {
|
||||
__unsafe_unretained id unsafe_ivar;
|
||||
}
|
||||
|
||||
@property (assign,nonatomic) id unsafe_prop;
|
||||
|
||||
- (id)init;
|
||||
+ (id)new;
|
||||
+ (id)alloc;
|
||||
|
||||
-(void)Meth;
|
||||
@end
|
||||
|
||||
@implementation Foo
|
||||
@synthesize unsafe_prop;
|
||||
-(id)init { return self; }
|
||||
+(id)new { return 0; }
|
||||
+(id)alloc { return 0; }
|
||||
|
||||
-(void)Meth {
|
||||
self.unsafe_prop = [Foo new]; // expected-warning {{assigning retained object to unsafe property}}
|
||||
self->unsafe_ivar = [Foo new]; // expected-warning {{assigning retained object to unsafe_unretained}}
|
||||
self.unsafe_prop = [[Foo alloc] init]; // expected-warning {{assigning retained object to unsafe property}}
|
||||
self->unsafe_ivar = [[Foo alloc] init]; // expected-warning {{assigning retained object to unsafe_unretained}}
|
||||
|
||||
__unsafe_unretained id unsafe_var;
|
||||
unsafe_var = [Foo new]; // expected-warning {{assigning retained object to unsafe_unretained}}
|
||||
unsafe_var = [[Foo alloc] init]; // expected-warning {{assigning retained object to unsafe_unretained}}
|
||||
}
|
||||
@end
|
||||
|
||||
void bar(Foo *f) {
|
||||
f.unsafe_prop = [Foo new]; // expected-warning {{assigning retained object to unsafe property}}
|
||||
|
||||
__unsafe_unretained id unsafe_var;
|
||||
unsafe_var = [Foo new]; // expected-warning {{assigning retained object to unsafe_unretained}}
|
||||
unsafe_var = [[Foo alloc] init]; // expected-warning {{assigning retained object to unsafe_unretained}}
|
||||
}
|
|
@ -518,12 +518,12 @@ typedef struct Bark Bark;
|
|||
|
||||
// rdar://9495837
|
||||
@interface Test30
|
||||
- (id) new;
|
||||
+ (id) new;
|
||||
- (void)Meth;
|
||||
@end
|
||||
|
||||
@implementation Test30
|
||||
- (id) new { return 0; }
|
||||
+ (id) new { return 0; }
|
||||
- (void) Meth {
|
||||
__weak id x = [Test30 new]; // expected-warning {{assigning retained object to weak variable}}
|
||||
id __unsafe_unretained u = [Test30 new]; // expected-warning {{assigning retained object to unsafe_unretained variable}}
|
||||
|
|
Загрузка…
Ссылка в новой задаче