diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2013-03-28 23:39:11 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2013-03-28 23:39:11 +0000 |
commit | 99a72d2d875321b4d91e6aef4e20b289f3d05db4 (patch) | |
tree | cd9a388a4f2207bbcfb2b43eac4257c02a23c7ff | |
parent | 123243cfd80f790a27edd1b829cd190a85f6c006 (diff) |
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
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178313 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 38 | ||||
-rw-r--r-- | lib/Sema/SemaExprMember.cpp | 13 | ||||
-rw-r--r-- | test/SemaObjC/warn-isa-ref.m | 12 |
3 files changed, 43 insertions, 20 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 238d833c38..c6882908c2 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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, diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 481c22135e..54190edf37 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -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())) diff --git a/test/SemaObjC/warn-isa-ref.m b/test/SemaObjC/warn-isa-ref.m index 0d924e872c..b1ffb4fc90 100644 --- a/test/SemaObjC/warn-isa-ref.m +++ b/test/SemaObjC/warn-isa-ref.m @@ -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 |