mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
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:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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 *'}}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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> *'}}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user