}
}
+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()) {
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
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,
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()))
@interface BaseClass {
@public
- Class isa; // expected-note 3 {{instance variable is declared here}}
+ Class isa; // expected-note 4 {{instance variable is declared here}}
}
@end
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