From: Steve Naroff Date: Tue, 14 Apr 2009 15:11:46 +0000 (+0000) Subject: ASTContext::mergeTypes(): Loosen up the type checking for 'Class' (treating it like... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d824c9c281c163ba86f3cc10c5572120234a2454;p=clang ASTContext::mergeTypes(): Loosen up the type checking for 'Class' (treating it like 'id'). This fixes XCDataTipsManager.m registers, observes notifications in class methods. The radar above is the result of clang typing 'self' in a class method as 'Class', which results in some spurious warnings (GCC types 'self' in a class method as 'id'). I considered changing the type of 'self' to 'id' (to conform to GCC), however this resulted in *many* test cases breaking. In addition, I really prefer a more strongly typed 'self'. All in all, this is the least obtrusive fix I could find for removing the spurious warnings (though we do loose some valid warnings). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69041 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7b357318e5..f0c2d2be48 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2964,17 +2964,17 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { const ObjCInterfaceType* LHSIface = LHS->getAsObjCInterfaceType(); const ObjCInterfaceType* RHSIface = RHS->getAsObjCInterfaceType(); - // ID acts sort of like void* for ObjC interfaces - if (LHSIface && isObjCIdStructType(RHS)) + // 'id' and 'Class' act sort of like void* for ObjC interfaces + if (LHSIface && (isObjCIdStructType(RHS) || isObjCClassStructType(RHS))) return LHS; - if (RHSIface && isObjCIdStructType(LHS)) + if (RHSIface && (isObjCIdStructType(LHS) || isObjCClassStructType(LHS))) return RHS; // ID is compatible with all qualified id types. if (LHS->isObjCQualifiedIdType()) { if (const PointerType *PT = RHS->getAsPointerType()) { QualType pType = PT->getPointeeType(); - if (isObjCIdStructType(pType)) + if (isObjCIdStructType(pType) || isObjCClassStructType(pType)) return LHS; // FIXME: need to use ObjCQualifiedIdTypesAreCompatible(LHS, RHS, true). // Unfortunately, this API is part of Sema (which we don't have access @@ -2987,7 +2987,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { if (RHS->isObjCQualifiedIdType()) { if (const PointerType *PT = LHS->getAsPointerType()) { QualType pType = PT->getPointeeType(); - if (isObjCIdStructType(pType)) + if (isObjCIdStructType(pType) || isObjCClassStructType(pType)) return RHS; // FIXME: need to use ObjCQualifiedIdTypesAreCompatible(LHS, RHS, true). // Unfortunately, this API is part of Sema (which we don't have access diff --git a/test/SemaObjC/class-method-self.m b/test/SemaObjC/class-method-self.m new file mode 100644 index 0000000000..d36bc8cbc9 --- /dev/null +++ b/test/SemaObjC/class-method-self.m @@ -0,0 +1,26 @@ +// RUN: clang-cc -verify %s + +typedef struct objc_class *Class; +@interface XX + +- (void)addObserver:(XX*)o; + +@end + +@interface YY + ++ (void)classMethod; + +@end + +@implementation YY + +static XX *obj; + ++ (void)classMethod { + [obj addObserver:self]; + Class whatever; + [obj addObserver:whatever]; // GCC warns about this. +} +@end + diff --git a/test/SemaObjC/comptypes-1.m b/test/SemaObjC/comptypes-1.m index aafd442fff..8717bd09eb 100644 --- a/test/SemaObjC/comptypes-1.m +++ b/test/SemaObjC/comptypes-1.m @@ -35,7 +35,7 @@ int main() warning, unless done from an 'id'. */ obj_c = obj; /* Ok */ obj_c = obj_cp; // // expected-warning {{incompatible pointer types assigning 'MyOtherClass *', expected 'MyClass *'}} - obj_c = obj_C; // expected-warning {{incompatible pointer types assigning 'Class', expected 'MyClass *'}} + obj_c = obj_C; /* Assigning to an 'id' variable should generate a warning if done from a 'MyClass *' (which doesn't implement @@ -52,7 +52,7 @@ int main() obj_cp = obj; /* Ok */ obj_cp = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *', expected 'MyOtherClass *'}} obj_cp = obj_p; /* Ok */ - obj_cp = obj_C; // expected-warning {{incompatible pointer types assigning 'Class', expected 'MyOtherClass *'}} + obj_cp = obj_C; /* Any comparison involving an 'id' must be without warnings. */ if (obj == obj_p) foo() ; /* Ok */ /*Bogus warning here in 2.95.4*/ @@ -73,8 +73,8 @@ int main() if (obj_c == obj_cp) foo() ; // expected-warning {{comparison of distinct pointer types ('MyClass *' and 'MyOtherClass *')}} if (obj_cp == obj_c) foo() ; // expected-warning {{comparison of distinct pointer types ('MyOtherClass *' and 'MyClass *')}} - if (obj_c == obj_C) foo() ; // expected-warning {{comparison of distinct pointer types ('MyClass *' and 'Class')}} - if (obj_C == obj_c) foo() ; // expected-warning {{comparison of distinct pointer types ('Class' and 'MyClass *')}} + if (obj_c == obj_C) foo() ; + if (obj_C == obj_c) foo() ; /* Any comparison between 'MyOtherClass *' (which implements MyProtocol) and an 'id' implementing MyProtocol are Ok. */ @@ -82,10 +82,10 @@ int main() if (obj_p == obj_cp) foo() ; /* Ok */ - if (obj_p == obj_C) foo() ; // expected-warning {{comparison of distinct pointer types ('id' and 'Class')}} - if (obj_C == obj_p) foo() ; // expected-warning {{comparison of distinct pointer types ('Class' and 'id')}} - if (obj_cp == obj_C) foo() ; // expected-warning {{comparison of distinct pointer types ('MyOtherClass *' and 'Class')}} - if (obj_C == obj_cp) foo() ; // expected-warning {{comparison of distinct pointer types ('Class' and 'MyOtherClass *')}} + if (obj_p == obj_C) foo() ; + if (obj_C == obj_p) foo() ; + if (obj_cp == obj_C) foo() ; + if (obj_C == obj_cp) foo() ; return 0; }