Objective-C: Produce precise diagnostic when

'isa' ivar is accessed provided it is the first
ivar. Fixit hint will follow in another patch.
This is continuation of // rdar://13503456

llvm-svn: 178313
This commit is contained in:
Fariborz Jahanian 2013-03-28 23:39:11 +00:00
parent 5fff5c7b26
commit 3b602ce5a4
3 changed files with 43 additions and 20 deletions

View File

@ -450,6 +450,34 @@ static void CheckForNullPointerDereference(Sema &S, Expr *E) {
}
}
static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
bool IsAssign) {
const ObjCIvarDecl *IV = OIRE->getDecl();
if (!IV)
return;
DeclarationName MemberName = IV->getDeclName();
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
if (!Member || !Member->isStr("isa"))
return;
const Expr *Base = OIRE->getBase();
QualType BaseType = Base->getType();
if (OIRE->isArrow())
BaseType = BaseType->getPointeeType();
if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>())
if (ObjCInterfaceDecl *IDecl = OTy->getInterface()) {
ObjCInterfaceDecl *ClassDeclared = 0;
ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
if (!ClassDeclared->getSuperClass()
&& (*ClassDeclared->ivar_begin()) == IV) {
S.Diag(OIRE->getLocation(), IsAssign ? diag::warn_objc_isa_assign
: diag::warn_objc_isa_use);
S.Diag(IV->getLocation(), diag::note_ivar_decl);
}
}
}
ExprResult Sema::DefaultLvalueConversion(Expr *E) {
// Handle any placeholder expressions which made it here.
if (E->getType()->isPlaceholderType()) {
@ -503,7 +531,10 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
else
Diag(E->getExprLoc(), diag::warn_objc_isa_use);
}
else if (const ObjCIvarRefExpr *OIRE =
dyn_cast<ObjCIvarRefExpr>(E->IgnoreParenCasts()))
DiagnoseDirectIsaAccess(*this, OIRE, false);
// C++ [conv.lval]p1:
// [...] If T is a non-class type, the type of the prvalue is the
// cv-unqualified version of T. Otherwise, the type of the
@ -8561,7 +8592,10 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
else
Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign);
}
else if (const ObjCIvarRefExpr *OIRE =
dyn_cast<ObjCIvarRefExpr>(LHS.get()->IgnoreParenCasts()))
DiagnoseDirectIsaAccess(*this, OIRE, true);
if (CompResultTy.isNull())
return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc,
ResultTy, VK, OK, OpLoc,

View File

@ -1139,19 +1139,6 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
ObjCImpDecl, HasTemplateArgs);
goto fail;
}
else if (Member && Member->isStr("isa")) {
// If an ivar is (1) the first ivar in a root class and (2) named `isa`,
// then issue the same deprecated warning that id->isa gets.
ObjCInterfaceDecl *ClassDeclared = 0;
if (ObjCIvarDecl *IV =
IDecl->lookupInstanceVariable(Member, ClassDeclared)) {
if (!ClassDeclared->getSuperClass()
&& (*ClassDeclared->ivar_begin()) == IV) {
Diag(MemberLoc, diag::warn_objc_isa_use);
Diag(IV->getLocation(), diag::note_ivar_decl);
}
}
}
if (RequireCompleteType(OpLoc, BaseType, diag::err_typecheck_incomplete_tag,
BaseExpr.get()))

View File

@ -39,7 +39,7 @@ static void func() {
@interface BaseClass {
@public
Class isa; // expected-note 3 {{instance variable is declared here}}
Class isa; // expected-note 4 {{instance variable is declared here}}
}
@end
@ -70,12 +70,14 @@ static void func() {
Subclass *x;
SiblingClass *y;
OtherClass *z;
(void)v->isa; // expected-warning {{direct access to Objective-C's isa is deprecated}}
(void)w->isa; // expected-warning {{direct access to Objective-C's isa is deprecated}}
(void)x->isa; // expected-warning {{direct access to Objective-C's isa is deprecated}}
(void)y->isa; // expected-warning {{direct access to Objective-C's isa is deprecated}}
(void)v->isa; // expected-warning {{direct access to Objective-C's isa is deprecated in favor of object_getClass()}}
(void)w->isa; // expected-warning {{direct access to Objective-C's isa is deprecated in favor of object_getClass()}}
(void)x->isa; // expected-warning {{direct access to Objective-C's isa is deprecated in favor of object_getClass()}}
(void)y->isa; // expected-warning {{direct access to Objective-C's isa is deprecated in favor of object_getClass()}}
(void)z->isa;
(void)u->isa;
w->isa = 0; // expected-warning {{assignment to Objective-C's isa is deprecated in favor of object_setClass()}}
}
@end