Objective-C: Issue more precise warning when user
is accessing 'isa' as an object pointer.
// rdar://13503456. FixIt to follow in another patch.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178179 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 398471c..0e1baeb 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -187,6 +187,7 @@
 def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">;
 def ObjCReadonlyPropertyHasSetter : DiagGroup<"objc-readonly-with-setter-property">;
 def ObjCRootClass : DiagGroup<"objc-root-class">;
+def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
 def Packed : DiagGroup<"packed">;
 def Padded : DiagGroup<"padded">;
 def PointerArith : DiagGroup<"pointer-arith">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index de761ae..4fda498 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -634,9 +634,11 @@
   "'assign' is assumed">,
   InGroup<ObjCPropertyNoAttribute>;
 def warn_objc_isa_use : Warning<
-  "direct access to Objective-C's isa is deprecated "
-  "in favor of object_setClass() and object_getClass()">,
-  InGroup<DiagGroup<"deprecated-objc-isa-usage">>;
+  "direct access to Objective-C's isa is deprecated in favor of "
+  "object_getClass()">, InGroup<DeprecatedObjCIsaUsage>;
+def warn_objc_isa_assign : Warning<
+  "assignemt to Objective-C's isa is deprecated in favor of "
+  "object_setClass()">, InGroup<DeprecatedObjCIsaUsage>;
 def warn_objc_property_default_assign_on_object : Warning<
   "default property attribute 'assign' not appropriate for non-GC object">,
   InGroup<ObjCPropertyNoAttribute>;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index c0b1ad1..54422e8 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -491,6 +491,8 @@
   }
 
   CheckForNullPointerDereference(*this, E);
+  if (isa<ObjCIsaExpr>(E->IgnoreParens()))
+    Diag(E->getExprLoc(), diag::warn_objc_isa_use);
 
   // C++ [conv.lval]p1:
   //   [...] If T is a non-class type, the type of the prvalue is the
@@ -8535,6 +8537,9 @@
   CheckArrayAccess(LHS.get());
   CheckArrayAccess(RHS.get());
 
+  if (isa<ObjCIsaExpr>(LHS.get()->IgnoreParens()))
+    Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign);
+
   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 7b016c6..e41a2e9 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -1130,12 +1130,9 @@
       // There's an implicit 'isa' ivar on all objects.
       // But we only actually find it this way on objects of type 'id',
       // apparently.
-      if (OTy->isObjCId() && Member->isStr("isa")) {
-        Diag(MemberLoc, diag::warn_objc_isa_use);
+      if (OTy->isObjCId() && Member->isStr("isa"))
         return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc,
                                                Context.getObjCClassType()));
-      }
-
       if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr))
         return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
                                 ObjCImpDecl, HasTemplateArgs);
diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m
index bb22c25..8881db0 100644
--- a/test/Analysis/misc-ps-region-store.m
+++ b/test/Analysis/misc-ps-region-store.m
@@ -920,7 +920,7 @@
 
 void pr6302(id x, Class y) {
   // This previously crashed the analyzer (reported in PR 6302)
-  x->isa  = y; // expected-warning {{direct access to Objective-C's isa is deprecated in favor of object_setClass() and object_getClass()}}
+  x->isa  = y; // expected-warning {{assignemt to Objective-C's isa is deprecated in favor of object_setClass()}}
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/test/SemaObjC/warn-isa-ref.m b/test/SemaObjC/warn-isa-ref.m
index 39a5e45..0d924e8 100644
--- a/test/SemaObjC/warn-isa-ref.m
+++ b/test/SemaObjC/warn-isa-ref.m
@@ -18,8 +18,8 @@
   id x;
 
   // rdar://8290002
-  [(*x).isa self]; // expected-warning {{direct access to Objective-C's isa is deprecated in favor of object_setClass() and object_getClass()}}
-  [x->isa self]; // expected-warning {{direct access to Objective-C's isa is deprecated in favor of object_setClass() and object_getClass()}}
+  [(*x).isa self]; // expected-warning {{direct access to Objective-C's isa is deprecated in favor of object_getClass()}}
+  [x->isa self]; // expected-warning {{direct access to Objective-C's isa is deprecated in favor of object_getClass()}}
   
   Whatever *y;
 
diff --git a/test/SemaObjCXX/instantiate-expr.mm b/test/SemaObjCXX/instantiate-expr.mm
index 071bf6b..e9d296d 100644
--- a/test/SemaObjCXX/instantiate-expr.mm
+++ b/test/SemaObjCXX/instantiate-expr.mm
@@ -21,7 +21,7 @@
   get_an_A(N)->ivar = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}}
   get_an_A(N).prop = value2; // expected-error{{assigning to 'int' from incompatible type 'double *'}}
   T c = get_an_id(N)->isa; // expected-error{{cannot initialize a variable of type 'int' with an lvalue of type 'Class'}} \
-                           // expected-warning 5 {{direct access to Objective-C's isa is deprecated in favor of object_setClass() and object_getClass()}}
+                           // expected-warning 3 {{direct access to Objective-C's isa is deprecated in favor of object_getClass()}}
 }
 
 template void f<6, Class>(int, int); // expected-note{{in instantiation of}}
@@ -46,7 +46,7 @@
 template<typename T, typename U>
 void f3(U ptr) {
   T c = ptr->isa; // expected-error{{cannot initialize a variable of type 'int' with an lvalue of type 'Class'}} \
-                  // expected-warning 2 {{direct access to Objective-C's isa is deprecated in favor of object_setClass() and object_getClass()}}
+                  // expected-warning 1 {{direct access to Objective-C's isa is deprecated in favor of object_getClass()}}
 }
 
 template void f3<Class>(id); // expected-note{{in instantiation of}}