diff options
-rw-r--r-- | lib/AST/ASTContext.cpp | 18 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 14 | ||||
-rw-r--r-- | test/SemaObjC/comptypes-legal.m | 37 |
3 files changed, 53 insertions, 16 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 9ed6251089..e24de53314 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2680,6 +2680,15 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { // If the canonical type classes don't match. if (LHSClass != RHSClass) { + const ObjCInterfaceType* LHSIface = LHS->getAsObjCInterfaceType(); + const ObjCInterfaceType* RHSIface = RHS->getAsObjCInterfaceType(); + + // ID acts sort of like void* for ObjC interfaces + if (LHSIface && isObjCIdStructType(RHS)) + return LHS; + if (RHSIface && isObjCIdStructType(LHS)) + return RHS; + // ID is compatible with all qualified id types. if (LHS->isObjCQualifiedIdType()) { if (const PointerType *PT = RHS->getAsPointerType()) { @@ -2808,8 +2817,13 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { return LHS; return QualType(); case Type::ObjCInterface: - // Distinct ObjC interfaces are not compatible; see canAssignObjCInterfaces - // for checking assignment/comparison safety + // Check if the interfaces are assignment compatible. + const ObjCInterfaceType* LHSIface = LHS->getAsObjCInterfaceType(); + const ObjCInterfaceType* RHSIface = RHS->getAsObjCInterfaceType(); + if (LHSIface && RHSIface && + canAssignObjCInterfaces(LHSIface, RHSIface)) + return LHS; + return QualType(); case Type::ObjCQualifiedId: // Distinct qualified id's are not compatible. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c95b5ee52d..c390f769f5 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2546,20 +2546,6 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) { assert(lhptee->isFunctionType()); return FunctionVoidPointer; } - - // Check for ObjC interfaces - const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType(); - const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType(); - if (LHSIface && RHSIface && - Context.canAssignObjCInterfaces(LHSIface, RHSIface)) - return ConvTy; - - // ID acts sort of like void* for ObjC interfaces - if (LHSIface && Context.isObjCIdStructType(rhptee)) - return ConvTy; - if (RHSIface && Context.isObjCIdStructType(lhptee)) - return ConvTy; - // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or // unqualified versions of compatible types, ... if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), diff --git a/test/SemaObjC/comptypes-legal.m b/test/SemaObjC/comptypes-legal.m new file mode 100644 index 0000000000..71a2b29747 --- /dev/null +++ b/test/SemaObjC/comptypes-legal.m @@ -0,0 +1,37 @@ +// RUN: clang -fsyntax-only -verify -pedantic %s + +@protocol NSObject +@end +@interface NSObject <NSObject> { +} +@end +@interface NSString : NSObject +@end +void __setRetained(id *ivar, id value, NSObject **o) { + *ivar = value; +} +static NSString *_logProcessPrefix = 0; +void func() { + __setRetained(&_logProcessPrefix, _logProcessPrefix, &_logProcessPrefix); +} +@implementation NSObject (ScopeAdditions) ++ (void)setObjectLogProcessPrefix:(NSString *)processPrefix { + __setRetained(&_logProcessPrefix, processPrefix, &_logProcessPrefix); +} +@end + +@class Derived; + +NSObject *ExternFunc (NSObject *filePath, NSObject *key); +typedef id FuncSignature (NSObject *arg1, Derived *arg2); + +@interface Derived: NSObject ++ (void)registerFunc:(FuncSignature *)function; +@end + +void foo(void) +{ + // GCC currently allows this (it has some fiarly new support for covariant return types and contravariant argument types). + // Since registerFunc: expects a Derived object as it's second argument, I don't know why this would be legal. + [Derived registerFunc: ExternFunc]; // expected-warning{{incompatible pointer types sending 'NSObject *(NSObject *, NSObject *)', expected 'FuncSignature *'}} +} |