aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/AST/ASTContext.cpp18
-rw-r--r--lib/Sema/SemaExpr.cpp14
-rw-r--r--test/SemaObjC/comptypes-legal.m37
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 *'}}
+}