diff options
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 4 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 14 | ||||
-rw-r--r-- | test/SemaObjC/compatible-protocol-qualified-types.m | 35 | ||||
-rw-r--r-- | test/SemaObjC/comptypes-1.m | 4 | ||||
-rw-r--r-- | test/SemaObjC/comptypes-3.m | 30 | ||||
-rw-r--r-- | test/SemaObjC/comptypes-5.m | 4 | ||||
-rw-r--r-- | test/SemaObjC/comptypes-7.m | 4 | ||||
-rw-r--r-- | test/SemaObjC/conditional-expr-3.m | 4 | ||||
-rw-r--r-- | test/SemaObjC/conditional-expr.m | 4 | ||||
-rw-r--r-- | test/SemaObjC/protocol-id-test-3.m | 12 |
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> *'}} } |