]> granicus.if.org Git - clang/commitdiff
Downgrade incompatibilities with objc qualified types (e.g. id <P>) to warnings.
authorSteve Naroff <snaroff@apple.com>
Tue, 14 Oct 2008 22:18:38 +0000 (22:18 +0000)
committerSteve Naroff <snaroff@apple.com>
Tue, 14 Oct 2008 22:18:38 +0000 (22:18 +0000)
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

include/clang/Basic/DiagnosticKinds.def
lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
test/SemaObjC/compatible-protocol-qualified-types.m
test/SemaObjC/comptypes-1.m
test/SemaObjC/comptypes-3.m
test/SemaObjC/comptypes-5.m
test/SemaObjC/comptypes-7.m
test/SemaObjC/conditional-expr-3.m
test/SemaObjC/conditional-expr.m
test/SemaObjC/protocol-id-test-3.m

index 9cae8efaf2837b7237a27e6e689bd1e78bcd5291..fc2b7f6088ef1f96e13754f1311fc5b265058406 100644 (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,
index 313b9aa7016af18c4edfde4c307935c7239d741f..e9e1ad15689078f87c3f81d48dc841c655d0346f 100644 (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
index a6197dd2b75edf3e777a08c791dea16cf9ebb460..c8610da6bd9e89eb1dbf01dbe1041ec55f94c3b7 100644 (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;
index 2e7eb6c43b82c1ddab482ae9a7c7984c6dfea1ab..583acb065622b31ab871eeabde25ffd0f43f4681 100644 (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
index e47bc63565fc3b6ef9c41d5505381e888321a289..ec0e38052116f80306206d3f812ce49ec57915b6 100644 (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
index 1e271c8340ebab680869b95029312752e175bed7..b47c96078649cb03846d57989334b6ccc4c76a7d 100644 (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;
 }
index f12fa9ab5d4411a07c8c4e6ec22f02a2224b480b..9905fc4298a57ffb603aabb005803037b488cdd5 100644 (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 */
 
index ef3a7790a3d3b952ec20512212e52108ed5c6678..ce0391ea07a503633a7a378c8b6de9e75ec1e556 100644 (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 *'}}
   
index de7b828a980781842a1bd2853216fcd6b962fba0..f5b04339e837a7c7497ba276d81b1c220df9e5fb 100644 (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) {
index 2884fb4c988b5276a69075397deedfa40445ef18..c607178a57cd51f292e0ebee30bf59ecdf8b504e 100644 (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
index 8c2beee989c74d55cd2cf4db2c03e883868b7643..a4be20b4a5c59312813ba70fe5cf078edcd9658c 100644 (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> *'}}
 }