diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-09-15 18:30:22 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-09-15 18:30:22 +0000 |
commit | 7d7ef8298d4711206772ff9eb51f5140536cbeab (patch) | |
tree | 5c675a2021900fcac27cec2fc2388618918c324d | |
parent | 74558b4c2f4136b0d89bbaa974df1070593b355a (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.cpp | 32 | ||||
-rw-r--r-- | test/SemaObjC/class-type-conversion.m | 46 |
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 |