From: Steve Naroff Date: Tue, 14 Oct 2008 22:18:38 +0000 (+0000) Subject: Downgrade incompatibilities with objc qualified types (e.g. id

) to warnings. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=395790772565002c0ac03f2c8de9b0a6c7adcaf3;p=clang Downgrade incompatibilities with objc qualified types (e.g. id

) 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57529 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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 " = "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 )delegate; +- (id )delegate; + +@end + +@protocol NSTextStorageDelegate +@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'}} +} + +@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'}} + obj_p = obj_c; // expected-warning {{incompatible type assigning 'MyClass *', expected 'id'}} obj_p = obj_cp; /* Ok */ - obj_p = obj_C; // expected-error {{incompatible type assigning 'Class', expected 'id'}} + obj_p = obj_C; // expected-warning {{incompatible type assigning 'Class', expected 'id'}} /* Assigning to a 'MyOtherClass *' variable should always generate a warning, unless done from an 'id' or an 'id' (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 obj_ab = nil; id obj_ac = nil; - obj_a = obj_b; // expected-error {{incompatible type assigning 'id', expected 'id'}} + obj_a = obj_b; // expected-warning {{incompatible type assigning 'id', expected 'id'}} obj_a = obj_ab; /* Ok */ obj_a = obj_ac; /* Ok */ - obj_b = obj_a; // expected-error {{incompatible type assigning 'id', expected 'id'}} + obj_b = obj_a; // expected-warning {{incompatible type assigning 'id', expected 'id'}} obj_b = obj_ab; /* Ok */ - obj_b = obj_ac; // expected-error {{incompatible type assigning 'id', expected 'id'}} + obj_b = obj_ac; // expected-warning {{incompatible type assigning 'id', expected 'id'}} - obj_ab = obj_a; // expected-error {{incompatible type assigning 'id', expected 'id'}} - obj_ab = obj_b; // expected-error {{incompatible type assigning 'id', expected 'id'}} - obj_ab = obj_ac; // expected-error {{incompatible type assigning 'id', expected 'id'}} + obj_ab = obj_a; // expected-warning {{incompatible type assigning 'id', expected 'id'}} + obj_ab = obj_b; // expected-warning {{incompatible type assigning 'id', expected 'id'}} + obj_ab = obj_ac; // expected-warning {{incompatible type assigning 'id', expected 'id'}} - obj_ac = obj_a; // expected-error {{incompatible type assigning 'id', expected 'id'}} - obj_ac = obj_b; // expected-error {{incompatible type assigning 'id', expected 'id'}} - obj_ac = obj_ab; // expected-error {{incompatible type assigning 'id', expected 'id'}} + obj_ac = obj_a; // expected-warning {{incompatible type assigning 'id', expected 'id'}} + obj_ac = obj_b; // expected-warning {{incompatible type assigning 'id', expected 'id'}} + obj_ac = obj_ab; // expected-warning {{incompatible type assigning 'id', expected 'id'}} - if (obj_a == obj_b) foo (); // expected-error {{invalid operands to binary expression ('id' and 'id')}} - if (obj_b == obj_a) foo (); // expected-error {{invalid operands to binary expression ('id' and 'id')}} + if (obj_a == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id' and 'id')}} + if (obj_b == obj_a) foo (); // expected-warning {{invalid operands to binary expression ('id' and 'id')}} 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' and 'id')}} - if (obj_ac == obj_b) foo (); // expected-error {{invalid operands to binary expression ('id' and 'id')}} + if (obj_b == obj_ac) foo (); // expected-warning {{invalid operands to binary expression ('id' and 'id')}} + if (obj_ac == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id' and 'id')}} - if (obj_ab == obj_ac) foo (); // expected-error {{invalid operands to binary expression ('id' and 'id')}} - if (obj_ac == obj_ab) foo (); // expected-error {{invalid operands to binary expression ('id' and 'id')}} + if (obj_ab == obj_ac) foo (); // expected-warning {{invalid operands to binary expression ('id' and 'id')}} + if (obj_ac == obj_ab) foo (); // expected-warning {{invalid operands to binary expression ('id' and 'id')}} 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 *obj_c_super_p_q = nil; MyClass *obj_c_cat_p_q = nil; - obj_c_cat_p = obj_id_p; // expected-error {{incompatible type assigning 'id', expected 'MyClass *'}} - obj_c_super_p = obj_id_p; // expected-error {{incompatible type assigning 'id', expected 'MyOtherClass *'}} + obj_c_cat_p = obj_id_p; // expected-warning {{incompatible type assigning 'id', expected 'MyClass *'}} + obj_c_super_p = obj_id_p; // expected-warning {{incompatible type assigning 'id', 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'}} - obj_p = j; // expected-error {{incompatible type assigning 'int *', expected 'id'}} + obj_p = j; // expected-warning {{incompatible type assigning 'int *', expected 'id'}} 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', expected 'int *'}} + j = obj_p; // expected-warning {{incompatible type assigning 'id', 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 x) { - id l = x; // expected-error {{incompatible type initializing 'id', expected 'id'}} + id l = x; // expected-warning {{incompatible type initializing 'id', expected 'id'}} } void f3(A *a) { - id l = a; // expected-error {{incompatible type initializing 'A *', expected 'id'}} + id l = a; // expected-warning {{incompatible type initializing 'A *', expected 'id'}} } 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 ) outputStream { id nextOutputStream = [self nextOutputStream]; // GCC warns about both of these. - self = nextOutputStream; // expected-error {{incompatible type assigning 'id', expected 'DTFilterOutputStream2 *'}} + self = nextOutputStream; // expected-warning {{incompatible type assigning 'id', expected 'DTFilterOutputStream2 *'}} return nextOutputStream ? nextOutputStream : self; } @end @@ -38,7 +38,7 @@ - (id)initWithNextOutputStream:(id ) outputStream { id nextOutputStream = [self nextOutputStream]; // GCC warns about both of these as well (no errors). - self = nextOutputStream; // expected-error {{incompatible type assigning 'id', expected 'DTFilterOutputStream3 *'}} + self = nextOutputStream; // expected-warning {{incompatible type assigning 'id', 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 Func(INTF *p2) id Gunc2(id p2) { - Func(p2); // expected-error {{incompatible type passing 'id', expected 'INTF *'}} - return p2; // expected-error {{incompatible type returning 'id', expected 'id'}} + Func(p2); // expected-warning {{incompatible type passing 'id', expected 'INTF *'}} + return p2; // expected-warning {{incompatible type returning 'id', expected 'id'}} } id Gunc3(id p2) { - return p2; // expected-error {{incompatible type returning 'id', expected 'id'}} + return p2; // expected-warning {{incompatible type returning 'id', expected 'id'}} } @@ -61,13 +61,13 @@ INTF * Hunc1(id p2) INTF * Hunc2(id p2) { - Func(p2); // expected-error {{incompatible type passing 'id', expected 'INTF *'}} - return p2; // expected-error {{incompatible type returning 'id', expected 'INTF *'}} + Func(p2); // expected-warning {{incompatible type passing 'id', expected 'INTF *'}} + return p2; // expected-warning {{incompatible type returning 'id', expected 'INTF *'}} } INTF * Hunc3(id p2) { - return p2; // expected-error {{incompatible type returning 'id', expected 'INTF *'}} + return p2; // expected-warning {{incompatible type returning 'id', expected 'INTF *'}} }