]> granicus.if.org Git - clang/commitdiff
Objective-c: Conversion from type Class to any root class type is allowed
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 15 Sep 2011 18:30:22 +0000 (18:30 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 15 Sep 2011 18:30:22 +0000 (18:30 +0000)
in class methods with no warning. //rdar://10109725

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139818 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/SemaObjC/class-type-conversion.m [new file with mode: 0644]

index bb31507c236981608de39cb1189fe28339904cae..35b38b101a3f9f7263d7e6ad31452a783a0cb4ee 100644 (file)
@@ -5227,6 +5227,35 @@ checkBlockPointerTypesForAssignment(Sema &S, QualType LHSType,
   return ConvTy;
 }
 
+static Sema::AssignConvertType
+checkObjCPointerTypesForAssignment(Sema &S, QualType LHSType,
+                                   QualType RHSType);
+/// checkClassTypes - Routine checks for conversion of "Class" type.
+// Conversion from type Class to any root class type in a class method
+// is allowed.
+static Sema::AssignConvertType
+checkClassTypes(Sema &S, QualType LHSType) {
+  // Conversion from type Class to any root class type is allowed.
+  DeclContext *DC = S.CurContext;
+  while (isa<BlockDecl>(DC))
+    DC = DC->getParent();
+  ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(DC);
+  if (MD && MD->isClassMethod()) {
+    ObjCInterfaceDecl *Root = 0;
+      if (ObjCInterfaceDecl * IDecl = MD->getClassInterface())
+        do
+          Root = IDecl;
+        while ((IDecl = IDecl->getSuperClass()));
+      if (Root){
+        QualType RHSType = 
+          S.Context.getObjCObjectPointerType(
+                                 S.Context.getObjCInterfaceType(Root));
+        return checkObjCPointerTypesForAssignment(S, LHSType, RHSType);
+      }
+  }
+  return Sema::IncompatiblePointer;
+}
+
 /// checkObjCPointerTypesForAssignment - Compares two objective-c pointer types
 /// for assignment compatibility.
 static Sema::AssignConvertType
@@ -5243,10 +5272,9 @@ checkObjCPointerTypesForAssignment(Sema &S, QualType LHSType,
     return Sema::Compatible;
   }
   if (RHSType->isObjCBuiltinType()) {
-    // Class is not compatible with ObjC object pointers.
     if (RHSType->isObjCClassType() && !LHSType->isObjCBuiltinType() &&
         !LHSType->isObjCQualifiedClassType())
-      return Sema::IncompatiblePointer;
+      return checkClassTypes(S, LHSType);
     return Sema::Compatible;
   }
   QualType lhptee = LHSType->getAs<ObjCObjectPointerType>()->getPointeeType();
diff --git a/test/SemaObjC/class-type-conversion.m b/test/SemaObjC/class-type-conversion.m
new file mode 100644 (file)
index 0000000..a009ebe
--- /dev/null
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// rdar://10109725
+
+@interface NSObject {
+    Class isa;
+}
+- (id)addObserver:(NSObject *)observer; // expected-note 2 {{passing argument to parameter 'observer' here}}
+@end
+
+@interface MyClass : NSObject {
+}
+@end
+
+@implementation NSObject
++ (void)initialize
+{
+        NSObject *obj = 0;
+        [obj addObserver:self];
+        [obj addObserver:(Class)0];
+}
+
+- init
+{
+        NSObject *obj = 0;
+        [obj addObserver:self];
+        return [obj addObserver:(Class)0]; // expected-warning {{incompatible pointer types sending 'Class' to parameter of type 'NSObject *'}}
+}
+- (id)addObserver:(NSObject *)observer { return 0; }
+@end
+
+@implementation MyClass
+
++ (void)initialize
+{
+        NSObject *obj = 0;
+        [obj addObserver:self];
+        [obj addObserver:(Class)0];
+}
+
+- init
+{
+        NSObject *obj = 0;
+        [obj addObserver:self];
+        return [obj addObserver:(Class)0]; // expected-warning {{incompatible pointer types sending 'Class' to parameter of type 'NSObject *'}}
+}
+@end