зеркало из 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<
|
def warn_arc_retained_assign : Warning<
|
||||||
"assigning retained object to %select{weak|unsafe_unretained}0 variable">,
|
"assigning retained object to %select{weak|unsafe_unretained}0 variable">,
|
||||||
InGroup<ARCUnsafeRetainedAssign>;
|
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<
|
def warn_arc_trivial_member_function_with_object_member : Warning<
|
||||||
"%0 cannot be shared between ARC and non-ARC "
|
"%0 cannot be shared between ARC and non-ARC "
|
||||||
"code; add a non-trivial %select{copy constructor|copy assignment operator|"
|
"code; add a non-trivial %select{copy constructor|copy assignment operator|"
|
||||||
|
|
|
@ -5644,9 +5644,13 @@ public:
|
||||||
void checkRetainCycles(ObjCMessageExpr *msg);
|
void checkRetainCycles(ObjCMessageExpr *msg);
|
||||||
void checkRetainCycles(Expr *receiver, Expr *argument);
|
void checkRetainCycles(Expr *receiver, Expr *argument);
|
||||||
|
|
||||||
/// checkWeakUnsafeAssigns - Check whether +1 expr is being assigned
|
/// checkUnsafeAssigns - Check whether +1 expr is being assigned
|
||||||
/// to weak/__unsafe_unretained.
|
/// to weak/__unsafe_unretained type.
|
||||||
void checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS);
|
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.
|
/// CheckMessageArgumentTypes - Check types in an Obj-C message send.
|
||||||
/// \param Method - May be null.
|
/// \param Method - May be null.
|
||||||
|
|
|
@ -3720,15 +3720,50 @@ void Sema::checkRetainCycles(Expr *receiver, Expr *argument) {
|
||||||
diagnoseRetainCycle(*this, capturer, owner);
|
diagnoseRetainCycle(*this, capturer, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sema::checkUnsafeAssigns(SourceLocation Loc,
|
bool Sema::checkUnsafeAssigns(SourceLocation Loc,
|
||||||
QualType LHS, Expr *RHS) {
|
QualType LHS, Expr *RHS) {
|
||||||
Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();
|
Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();
|
||||||
if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone)
|
if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone)
|
||||||
return;
|
return false;
|
||||||
if (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS))
|
// strip off any implicit cast added to get to the one arc-specific
|
||||||
if (cast->getCastKind() == CK_ObjCConsumeObject)
|
while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
|
||||||
|
if (cast->getCastKind() == CK_ObjCConsumeObject) {
|
||||||
Diag(Loc, diag::warn_arc_retained_assign)
|
Diag(Loc, diag::warn_arc_retained_assign)
|
||||||
<< (LT == Qualifiers::OCL_ExplicitNone)
|
<< (LT == Qualifiers::OCL_ExplicitNone)
|
||||||
<< RHS->getSourceRange();
|
<< 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 (ConvTy == Compatible) {
|
||||||
if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong)
|
if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong)
|
||||||
checkRetainCycles(LHS, RHS.get());
|
checkRetainCycles(LHS, RHS.get());
|
||||||
else
|
else if (getLangOptions().ObjCAutoRefCount)
|
||||||
checkUnsafeAssigns(Loc, LHSType, RHS.get());
|
checkUnsafeExprAssigns(Loc, LHS, RHS.get());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Compound assignment "x += y"
|
// 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
|
// rdar://9495837
|
||||||
@interface Test30
|
@interface Test30
|
||||||
- (id) new;
|
+ (id) new;
|
||||||
- (void)Meth;
|
- (void)Meth;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation Test30
|
@implementation Test30
|
||||||
- (id) new { return 0; }
|
+ (id) new { return 0; }
|
||||||
- (void) Meth {
|
- (void) Meth {
|
||||||
__weak id x = [Test30 new]; // expected-warning {{assigning retained object to weak variable}}
|
__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}}
|
id __unsafe_unretained u = [Test30 new]; // expected-warning {{assigning retained object to unsafe_unretained variable}}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче