]> granicus.if.org Git - clang/commitdiff
Objective-C: Produce precise diagnostic when
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 28 Mar 2013 23:39:11 +0000 (23:39 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 28 Mar 2013 23:39:11 +0000 (23:39 +0000)
'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

lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprMember.cpp
test/SemaObjC/warn-isa-ref.m

index 238d833c389e5203f837d626d1876c0c292c3421..c6882908c2400deb759a228df2af30e9d0e3a3e5 100644 (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,
index 481c22135e9c037cc5308e8de42055646b55ee0b..54190edf37d9f36309370becea6a2e9e6f45764a 100644 (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()))
index 0d924e872c547a2519c427e58176b3c5011a8828..b1ffb4fc9008e4c871c949d58db9697f7882b148 100644 (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