Downgrade incompatibilities with objc qualified types (e.g. id <P>) to warnings.

Note: One day, we should consider moving the actual diags to ObjCQualifiedIdTypesAreCompatible(), since it has more information on the actual problem. GCC currently emits slightly more instructive errors for some cases involving protocols. I added a FIXME to the code.

llvm-svn: 57529
This commit is contained in:
Steve Naroff
2008-10-14 22:18:38 +00:00
parent 28106756af
commit 8afa98916a
11 changed files with 88 additions and 32 deletions

View File

@@ -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,

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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 *'}}

View File

@@ -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) {

View File

@@ -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

View File

@@ -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> *'}}
}