aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticKinds.def4
-rw-r--r--lib/Sema/Sema.h5
-rw-r--r--lib/Sema/SemaExpr.cpp14
-rw-r--r--test/SemaObjC/compatible-protocol-qualified-types.m35
-rw-r--r--test/SemaObjC/comptypes-1.m4
-rw-r--r--test/SemaObjC/comptypes-3.m30
-rw-r--r--test/SemaObjC/comptypes-5.m4
-rw-r--r--test/SemaObjC/comptypes-7.m4
-rw-r--r--test/SemaObjC/conditional-expr-3.m4
-rw-r--r--test/SemaObjC/conditional-expr.m4
-rw-r--r--test/SemaObjC/protocol-id-test-3.m12
11 files changed, 88 insertions, 32 deletions
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 9cae8efaf2..fc2b7f6088 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -1045,6 +1045,10 @@ DIAG(err_typecheck_bool_condition, ERROR,
// assignment related diagnostics (also for argument passing, returning, etc).
DIAG(err_typecheck_convert_incompatible, ERROR,
"incompatible type %2 '%1', expected '%0'")
+DIAG(warn_incompatible_qualified_id, WARNING,
+ "incompatible type %2 '%1', expected '%0'")
+DIAG(warn_incompatible_qualified_id_operands, WARNING,
+ "invalid operands to binary expression ('%0' and '%1')")
DIAG(ext_typecheck_convert_pointer_int, EXTWARN,
"incompatible pointer to integer conversion %2 '%1', expected '%0'")
DIAG(ext_typecheck_convert_int_pointer, EXTWARN,
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 313b9aa701..e9e1ad1568 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -924,6 +924,11 @@ private:
/// void*, we accept for now.
BlockVoidPointer,
+ /// IncompatibleObjCQualifiedId - The assignment is between a qualified
+ /// id type and something else (that is incompatible with it). For example,
+ /// "id <XXX>" = "Foo *", where "Foo *" doesn't implement the XXX protocol.
+ IncompatibleObjCQualifiedId,
+
/// Incompatible - We reject this conversion outright, it is invalid to
/// represent it in the AST.
Incompatible
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index a6197dd2b7..c8610da6bd 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1587,7 +1587,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
return IntToPointer;
if (lhsType->isIntegerType())
return PointerToInt;
- return Incompatible;
+ return IncompatibleObjCQualifiedId;
}
if (lhsType->isVectorType() || rhsType->isVectorType()) {
@@ -2034,6 +2034,13 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation loc,
if (ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) {
ImpCastExprToType(rex, lType);
return Context.IntTy;
+ } else {
+ if ((lType->isObjCQualifiedIdType() && rType->isObjCQualifiedIdType())) {
+ Diag(loc, diag::warn_incompatible_qualified_id_operands,
+ lex->getType().getAsString(), rex->getType().getAsString(),
+ lex->getSourceRange(), rex->getSourceRange());
+ return QualType();
+ }
}
}
if ((lType->isPointerType() || lType->isObjCQualifiedIdType()) &&
@@ -3078,6 +3085,11 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
case BlockVoidPointer:
DiagKind = diag::ext_typecheck_convert_pointer_void_block;
break;
+ case IncompatibleObjCQualifiedId:
+ // FIXME: Diagnose the problem in ObjCQualifiedIdTypesAreCompatible, since
+ // it can give a more specific diagnostic.
+ DiagKind = diag::warn_incompatible_qualified_id;
+ break;
case Incompatible:
DiagKind = diag::err_typecheck_convert_incompatible;
isInvalid = true;
diff --git a/test/SemaObjC/compatible-protocol-qualified-types.m b/test/SemaObjC/compatible-protocol-qualified-types.m
index 2e7eb6c43b..583acb0656 100644
--- a/test/SemaObjC/compatible-protocol-qualified-types.m
+++ b/test/SemaObjC/compatible-protocol-qualified-types.m
@@ -38,3 +38,38 @@ extern NSString * const XCActiveSelectionLevel;
[[[XCActionManager defaultActionManager] selectionAtLevel:XCActiveSelectionLevel] source];
}
@end
+
+@protocol NSTextStorageDelegate;
+@class NSNotification;
+
+@interface NSTextStorage : NSObject
+
+- (void)setDelegate:(id <NSTextStorageDelegate>)delegate;
+- (id <NSTextStorageDelegate>)delegate;
+
+@end
+
+@protocol NSTextStorageDelegate <NSObject>
+@optional
+
+- (void)textStorageWillProcessEditing:(NSNotification *)notification;
+- (void)textStorageDidProcessEditing:(NSNotification *)notification;
+
+@end
+
+@interface SKTText : NSObject {
+ @private
+
+
+ NSTextStorage *_contents;
+}
+@end
+
+@implementation SKTText
+
+
+- (NSTextStorage *)contents {
+ [_contents setDelegate:self]; // expected-warning {{incompatible type sending 'SKTText *', expected 'id<NSTextStorageDelegate>'}}
+}
+
+@end
diff --git a/test/SemaObjC/comptypes-1.m b/test/SemaObjC/comptypes-1.m
index e47bc63565..ec0e380521 100644
--- a/test/SemaObjC/comptypes-1.m
+++ b/test/SemaObjC/comptypes-1.m
@@ -42,9 +42,9 @@ int main()
MyProtocol), but not from an 'id' or from a 'MyOtherClass *'
(which implements MyProtocol). */
obj_p = obj; /* Ok */
- obj_p = obj_c; // expected-error {{incompatible type assigning 'MyClass *', expected 'id<MyProtocol>'}}
+ obj_p = obj_c; // expected-warning {{incompatible type assigning 'MyClass *', expected 'id<MyProtocol>'}}
obj_p = obj_cp; /* Ok */
- obj_p = obj_C; // expected-error {{incompatible type assigning 'Class', expected 'id<MyProtocol>'}}
+ obj_p = obj_C; // expected-warning {{incompatible type assigning 'Class', expected 'id<MyProtocol>'}}
/* Assigning to a 'MyOtherClass *' variable should always generate
a warning, unless done from an 'id' or an 'id<MyProtocol>' (since
diff --git a/test/SemaObjC/comptypes-3.m b/test/SemaObjC/comptypes-3.m
index 1e271c8340..b47c960786 100644
--- a/test/SemaObjC/comptypes-3.m
+++ b/test/SemaObjC/comptypes-3.m
@@ -26,24 +26,24 @@ int main()
id<MyProtocolAB> obj_ab = nil;
id<MyProtocolAC> obj_ac = nil;
- obj_a = obj_b; // expected-error {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolA>'}}
+ obj_a = obj_b; // expected-warning {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolA>'}}
obj_a = obj_ab; /* Ok */
obj_a = obj_ac; /* Ok */
- obj_b = obj_a; // expected-error {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolB>'}}
+ obj_b = obj_a; // expected-warning {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolB>'}}
obj_b = obj_ab; /* Ok */
- obj_b = obj_ac; // expected-error {{incompatible type assigning 'id<MyProtocolAC>', expected 'id<MyProtocolB>'}}
+ obj_b = obj_ac; // expected-warning {{incompatible type assigning 'id<MyProtocolAC>', expected 'id<MyProtocolB>'}}
- obj_ab = obj_a; // expected-error {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolAB>'}}
- obj_ab = obj_b; // expected-error {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolAB>'}}
- obj_ab = obj_ac; // expected-error {{incompatible type assigning 'id<MyProtocolAC>', expected 'id<MyProtocolAB>'}}
+ obj_ab = obj_a; // expected-warning {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolAB>'}}
+ obj_ab = obj_b; // expected-warning {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolAB>'}}
+ obj_ab = obj_ac; // expected-warning {{incompatible type assigning 'id<MyProtocolAC>', expected 'id<MyProtocolAB>'}}
- obj_ac = obj_a; // expected-error {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolAC>'}}
- obj_ac = obj_b; // expected-error {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolAC>'}}
- obj_ac = obj_ab; // expected-error {{incompatible type assigning 'id<MyProtocolAB>', expected 'id<MyProtocolAC>'}}
+ obj_ac = obj_a; // expected-warning {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolAC>'}}
+ obj_ac = obj_b; // expected-warning {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolAC>'}}
+ obj_ac = obj_ab; // expected-warning {{incompatible type assigning 'id<MyProtocolAB>', expected 'id<MyProtocolAC>'}}
- if (obj_a == obj_b) foo (); // expected-error {{invalid operands to binary expression ('id<MyProtocolA>' and 'id<MyProtocolB>')}}
- if (obj_b == obj_a) foo (); // expected-error {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolA>')}}
+ if (obj_a == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolA>' and 'id<MyProtocolB>')}}
+ if (obj_b == obj_a) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolA>')}}
if (obj_a == obj_ab) foo (); /* Ok */
if (obj_ab == obj_a) foo (); /* Ok */
@@ -54,11 +54,11 @@ int main()
if (obj_b == obj_ab) foo (); /* Ok */
if (obj_ab == obj_b) foo (); /* Ok */
- if (obj_b == obj_ac) foo (); // expected-error {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolAC>')}}
- if (obj_ac == obj_b) foo (); // expected-error {{invalid operands to binary expression ('id<MyProtocolAC>' and 'id<MyProtocolB>')}}
+ if (obj_b == obj_ac) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolAC>')}}
+ if (obj_ac == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAC>' and 'id<MyProtocolB>')}}
- if (obj_ab == obj_ac) foo (); // expected-error {{invalid operands to binary expression ('id<MyProtocolAB>' and 'id<MyProtocolAC>')}}
- if (obj_ac == obj_ab) foo (); // expected-error {{invalid operands to binary expression ('id<MyProtocolAC>' and 'id<MyProtocolAB>')}}
+ if (obj_ab == obj_ac) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAB>' and 'id<MyProtocolAC>')}}
+ if (obj_ac == obj_ab) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAC>' and 'id<MyProtocolAB>')}}
return 0;
}
diff --git a/test/SemaObjC/comptypes-5.m b/test/SemaObjC/comptypes-5.m
index f12fa9ab5d..9905fc4298 100644
--- a/test/SemaObjC/comptypes-5.m
+++ b/test/SemaObjC/comptypes-5.m
@@ -26,8 +26,8 @@ int main()
MyOtherClass<MyProtocol> *obj_c_super_p_q = nil;
MyClass<MyProtocol> *obj_c_cat_p_q = nil;
- obj_c_cat_p = obj_id_p; // expected-error {{incompatible type assigning 'id<MyProtocol>', expected 'MyClass *'}}
- obj_c_super_p = obj_id_p; // expected-error {{incompatible type assigning 'id<MyProtocol>', expected 'MyOtherClass *'}}
+ obj_c_cat_p = obj_id_p; // expected-warning {{incompatible type assigning 'id<MyProtocol>', expected 'MyClass *'}}
+ obj_c_super_p = obj_id_p; // expected-warning {{incompatible type assigning 'id<MyProtocol>', expected 'MyOtherClass *'}}
obj_id_p = obj_c_cat_p; /* Ok */
obj_id_p = obj_c_super_p; /* Ok */
diff --git a/test/SemaObjC/comptypes-7.m b/test/SemaObjC/comptypes-7.m
index ef3a7790a3..ce0391ea07 100644
--- a/test/SemaObjC/comptypes-7.m
+++ b/test/SemaObjC/comptypes-7.m
@@ -28,7 +28,7 @@ int main()
obj = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'id'}}
obj_p = i; // expected-warning {{incompatible integer to pointer conversion assigning 'int', expected 'id<MyProtocol>'}}
- obj_p = j; // expected-error {{incompatible type assigning 'int *', expected 'id<MyProtocol>'}}
+ obj_p = j; // expected-warning {{incompatible type assigning 'int *', expected 'id<MyProtocol>'}}
obj_c = i; // expected-warning {{incompatible integer to pointer conversion assigning 'int', expected 'MyClass *'}}
obj_c = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'MyClass *'}}
@@ -42,7 +42,7 @@ int main()
i = obj_C; // expected-warning {{incompatible pointer to integer conversion assigning 'Class', expected 'int'}}
j = obj; // expected-warning {{incompatible pointer types assigning 'id', expected 'int *'}}
- j = obj_p; // expected-error {{incompatible type assigning 'id<MyProtocol>', expected 'int *'}}
+ j = obj_p; // expected-warning {{incompatible type assigning 'id<MyProtocol>', expected 'int *'}}
j = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *', expected 'int *'}}
j = obj_C; // expected-warning {{incompatible pointer types assigning 'Class', expected 'int *'}}
diff --git a/test/SemaObjC/conditional-expr-3.m b/test/SemaObjC/conditional-expr-3.m
index de7b828a98..f5b04339e8 100644
--- a/test/SemaObjC/conditional-expr-3.m
+++ b/test/SemaObjC/conditional-expr-3.m
@@ -27,11 +27,11 @@ void f1(id x, A *a) {
}
void f2(id<P1> x) {
- id<P0> l = x; // expected-error {{incompatible type initializing 'id<P1>', expected 'id<P0>'}}
+ id<P0> l = x; // expected-warning {{incompatible type initializing 'id<P1>', expected 'id<P0>'}}
}
void f3(A *a) {
- id<P1> l = a; // expected-error {{incompatible type initializing 'A *', expected 'id<P1>'}}
+ id<P1> l = a; // expected-warning {{incompatible type initializing 'A *', expected 'id<P1>'}}
}
void f4(int cond, id x, A *a) {
diff --git a/test/SemaObjC/conditional-expr.m b/test/SemaObjC/conditional-expr.m
index 2884fb4c98..c607178a57 100644
--- a/test/SemaObjC/conditional-expr.m
+++ b/test/SemaObjC/conditional-expr.m
@@ -28,7 +28,7 @@
- (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream {
id <DTOutputStreams> nextOutputStream = [self nextOutputStream];
// GCC warns about both of these.
- self = nextOutputStream; // expected-error {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream2 *'}}
+ self = nextOutputStream; // expected-warning {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream2 *'}}
return nextOutputStream ? nextOutputStream : self;
}
@end
@@ -38,7 +38,7 @@
- (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream {
id <DTOutputStreams> nextOutputStream = [self nextOutputStream];
// GCC warns about both of these as well (no errors).
- self = nextOutputStream; // expected-error {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream3 *'}}
+ self = nextOutputStream; // expected-warning {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream3 *'}}
return nextOutputStream ? nextOutputStream : self;
}
@end
diff --git a/test/SemaObjC/protocol-id-test-3.m b/test/SemaObjC/protocol-id-test-3.m
index 8c2beee989..a4be20b4a5 100644
--- a/test/SemaObjC/protocol-id-test-3.m
+++ b/test/SemaObjC/protocol-id-test-3.m
@@ -29,15 +29,15 @@ id<MyProto1> Func(INTF <MyProto1, MyProto2> *p2)
id<MyProto1, MyProto2> Gunc2(id <MyProto1>p2)
{
- Func(p2); // expected-error {{incompatible type passing 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}}
- return p2; // expected-error {{incompatible type returning 'id<MyProto1>', expected 'id<MyProto1,MyProto2>'}}
+ Func(p2); // expected-warning {{incompatible type passing 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}}
+ return p2; // expected-warning {{incompatible type returning 'id<MyProto1>', expected 'id<MyProto1,MyProto2>'}}
}
id<MyProto1> Gunc3(id <MyProto2>p2)
{
- return p2; // expected-error {{incompatible type returning 'id<MyProto2>', expected 'id<MyProto1>'}}
+ return p2; // expected-warning {{incompatible type returning 'id<MyProto2>', expected 'id<MyProto1>'}}
}
@@ -61,13 +61,13 @@ INTF<MyProto1> * Hunc1(id <MyProto1, MyProto2>p2)
INTF<MyProto1, MyProto2> * Hunc2(id <MyProto1>p2)
{
- Func(p2); // expected-error {{incompatible type passing 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}}
- return p2; // expected-error {{incompatible type returning 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}}
+ Func(p2); // expected-warning {{incompatible type passing 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}}
+ return p2; // expected-warning {{incompatible type returning 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}}
}
INTF<MyProto1> * Hunc3(id <MyProto2>p2)
{
- return p2; // expected-error {{incompatible type returning 'id<MyProto2>', expected 'INTF<MyProto1> *'}}
+ return p2; // expected-warning {{incompatible type returning 'id<MyProto2>', expected 'INTF<MyProto1> *'}}
}