aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2011-09-15 18:30:22 +0000
committerFariborz Jahanian <fjahanian@apple.com>2011-09-15 18:30:22 +0000
commit7d7ef8298d4711206772ff9eb51f5140536cbeab (patch)
tree5c675a2021900fcac27cec2fc2388618918c324d
parent74558b4c2f4136b0d89bbaa974df1070593b355a (diff)
Objective-c: Conversion from type Class to any root class type is allowed
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
-rw-r--r--lib/Sema/SemaExpr.cpp32
-rw-r--r--test/SemaObjC/class-type-conversion.m46
2 files changed, 76 insertions, 2 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index bb31507c23..35b38b101a 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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
index 0000000000..a009ebe8c4
--- /dev/null
+++ b/test/SemaObjC/class-type-conversion.m
@@ -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