RFA: Objective-c prototype search cleanups

Alexander Malmberg alexander@malmberg.org
Mon Sep 29 20:20:00 GMT 2003


Alexander Malmberg wrote:
> Hi,
> 
> Here is the message sending prototype search patch again, now against
> mainline. 
[...]

And of course, I send an old diff. Sorry about that. A correct version
of the diff is attached. (The test cases were correct in the previous
mail.)

- Alexander Malmberg
-------------- next part --------------
? gcc/testsuite/objc.dg/missing-interface.m
? gcc/testsuite/objc.dg/prototype-1.m
? gcc/testsuite/objc.dg/prototype-2.m
? gcc/testsuite/objc.dg/prototype-3.m
? gcc/testsuite/objc.dg/prototype-4.m
? gcc/testsuite/objc.dg/prototype-5.m
Index: gcc/c-common.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.461
diff -u -r1.461 c-common.c
--- gcc/c-common.c	25 Sep 2003 01:25:43 -0000	1.461
+++ gcc/c-common.c	29 Sep 2003 19:48:25 -0000
@@ -497,6 +497,11 @@
 
 int warn_protocol = 1;
 
+/* Warn if multiple prototypes are found when sending a message to a receiver
+   with a known type.  */
+
+int warn_conflicting_prototypes = 1;
+
 
 /* C++ language option variables.  */
 
Index: gcc/c-common.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.209
diff -u -r1.209 c-common.h
--- gcc/c-common.h	25 Sep 2003 01:25:45 -0000	1.209
+++ gcc/c-common.h	29 Sep 2003 19:48:25 -0000
@@ -660,6 +660,11 @@
 
 extern int warn_protocol;
 
+/* Warn if multiple prototypes are found when sending a message to a receiver
+   with a known type.  */
+
+extern int warn_conflicting_prototypes;
+
 
 /* C++ language option variables.  */
 
Index: gcc/c-opts.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-opts.c,v
retrieving revision 1.90
diff -u -r1.90 c-opts.c
--- gcc/c-opts.c	25 Sep 2003 01:25:46 -0000	1.90
+++ gcc/c-opts.c	29 Sep 2003 19:48:27 -0000
@@ -406,6 +406,10 @@
       cpp_opts->warn_comments = value;
       break;
 
+    case OPT_Wconflicting_prototypes:
+      warn_conflicting_prototypes = value;
+      break;
+
     case OPT_Wconversion:
       warn_conversion = value;
       break;
Index: gcc/c.opt
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c.opt,v
retrieving revision 1.17
diff -u -r1.17 c.opt
--- gcc/c.opt	25 Sep 2003 01:25:50 -0000	1.17
+++ gcc/c.opt	29 Sep 2003 19:48:29 -0000
@@ -172,6 +172,10 @@
 C ObjC C++ ObjC++
 Synonym for -Wcomment
 
+Wconflicting-prototypes
+ObjC ObjC++
+Warn if multiple conflicting prototypes are found for a message to a typed receiver
+
 Wconversion
 C ObjC C++ ObjC++
 Warn about possibly confusing type conversions
Index: gcc/doc/invoke.texi
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.339
diff -u -r1.339 invoke.texi
--- gcc/doc/invoke.texi	25 Sep 2003 01:25:52 -0000	1.339
+++ gcc/doc/invoke.texi	29 Sep 2003 19:48:37 -0000
@@ -1954,6 +1954,15 @@
 compilation.  This also enforces the coding style convention
 that methods and selectors must be declared before being used.
 
+@item -Wno-conflicting-prototypes
+@opindex Wno-conflicting-prototypes
+When sending a message to a receiver whose type is known, that type is
+searched for a method prototype for the message.  If multiple conflicting
+prototypes are found, a warning is issued.  This can happen if, e.g., a class
+and its superclass both declare a method, but with different return or
+argument types.  If you use the @code{Wno-conflicting-prototypes} option, no
+warnings are issued.
+
 @c not documented because only avail via -Wp
 @c @item -print-objc-runtime-info
 
Index: gcc/objc/objc-act.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.194
diff -u -r1.194 objc-act.c
--- gcc/objc/objc-act.c	25 Sep 2003 17:53:41 -0000	1.194
+++ gcc/objc/objc-act.c	29 Sep 2003 19:48:41 -0000
@@ -182,7 +182,6 @@
 static hash hash_lookup (hash *, tree);
 static void hash_add_attr (hash, tree);
 static tree lookup_method (tree, tree);
-static tree lookup_method_static (tree, tree, int);
 static tree add_class (tree);
 static void add_category (tree, tree);
 
@@ -198,6 +197,29 @@
 static tree build_objc_string_decl (enum string_section);
 static tree build_selector_reference_decl (void);
 
+/* Searching for a prototype for a selector. */
+
+/* These methods are used to search for a suitable prototype for a receiver
+   of a known type.  Currently, these are used in finish_message_expr() and
+   really_start_method().  */
+
+/* The prototype found in the prototype search.  If multiple prototypes
+   were found, this will be the first found prototype.  */
+static GTY(()) tree current_found_prototype;
+static int num_found_prototypes;
+
+/* If warnings about conflicting prototypes are turned off, this will be set
+   to 1 as soon as a prototype is found, indicating that the search does not
+   need to proceed.  (Finding additional prototypes does no harm, but it's
+   a waste of time.)  */
+static int prototype_search_done;
+
+static void prototype_search_start (const char *);
+static void prototype_search_end (void);
+static void prototype_found (tree);
+static void lookup_method_static (tree, tree, int);
+static void lookup_method_in_protocol_list (tree, tree, int);
+
 /* Protocol additions.  */
 
 static tree add_protocol (tree);
@@ -239,7 +261,6 @@
 /* Everything else.  */
 
 static tree define_decl (tree, tree);
-static tree lookup_method_in_protocol_list (tree, tree, int);
 static tree lookup_protocol_in_reflist (tree, tree);
 static tree create_builtin_decl (enum tree_code, tree, const char *);
 static void setup_string_decl (void);
@@ -559,39 +580,6 @@
 }
 
 static tree
-lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
-				int class_meth)
-{
-   tree rproto, p;
-   tree fnd = 0;
-
-   for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
-     {
-        p = TREE_VALUE (rproto);
-
-	if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
-	  {
-	    if ((fnd = lookup_method (class_meth
-				      ? PROTOCOL_CLS_METHODS (p)
-				      : PROTOCOL_NST_METHODS (p), sel_name)))
-	      ;
-	    else if (PROTOCOL_LIST (p))
-	      fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
-						    sel_name, class_meth);
-	  }
-	else
-          {
-	    ; /* An identifier...if we could not find a protocol.  */
-          }
-
-	if (fnd)
-	  return fnd;
-     }
-
-   return 0;
-}
-
-static tree
 lookup_protocol_in_reflist (tree rproto_list, tree lproto)
 {
   tree rproto, p;
@@ -5663,6 +5651,10 @@
   tree selector, retval, is_class;
   int self, super, have_cast;
 
+  /* A description of the receiver's type we use when reporting
+     errors/warnings. Currently, will always point at errbuf.  */
+  char *report_type;
+
   /* Extract the receiver of the message, as well as its type
      (where the latter may take the form of a cast or be inferred
      from the implementation context).  */
@@ -5680,15 +5672,25 @@
 		   && !IS_SUPER (rtype)));
 
   /* If the receiver is a class object, retrieve the corresponding
-     @interface, if one exists. */
+     @interface, if one exists.  */
   is_class = receiver_is_class_object (receiver, self, super);
-
-  /* Now determine the receiver type (if an explicit cast has not been
-     provided).  */
-  if (!have_cast)
+  
+  /* Now determine the receiver type if an explicit cast has not been
+     provided.  Generate a description of the receiver's type and place
+     it in report_type.  */
+  if (!have_cast)   
     {
       if (is_class)
-	rtype = lookup_interface (is_class);
+	{
+	  rtype = lookup_interface (is_class);
+	  if (!rtype)
+	    warning ("no interface seen for `%s'",
+		     IDENTIFIER_POINTER (is_class));
+
+	  report_type = errbuf;
+	  sprintf (report_type, "%s",
+		   IDENTIFIER_POINTER (is_class));
+	}
       /* Handle `self' and `super'.  */
       else if (super)
 	{
@@ -5699,40 +5701,51 @@
 	      return error_mark_node;
 	    }
 	  rtype = lookup_interface (CLASS_SUPER_NAME (implementation_template));
+
+	  report_type = errbuf;
+	  sprintf (report_type, "%s",
+		   IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)));
 	}
       else if (self)
-	rtype = lookup_interface (CLASS_NAME (implementation_template));
-    }
-
-  /* If receiver is of type `id' or `Class' (or if the @interface for a
-     class is not visible), we shall be satisfied with the existence of
-     any instance or class method. */
-  if (!rtype || IS_ID (rtype)
-	|| TREE_TYPE (rtype) == TREE_TYPE (objc_class_type))
-    {
-      if (!rtype)
-	rtype = xref_tag (RECORD_TYPE, is_class);
-      else if (IS_ID (rtype))
 	{
-	  rprotos = TYPE_PROTOCOL_LIST (rtype);
-	  rtype = NULL_TREE;
+	  rtype = lookup_interface (CLASS_NAME (implementation_template));
+
+	  report_type = errbuf;
+	  sprintf (report_type, "%s",
+		   IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
 	}
       else
-	is_class = TYPE_NAME (rtype) = get_identifier ("Class");
-
-      if (rprotos)
-	method_prototype
-	  = lookup_method_in_protocol_list (rprotos, sel_name,
-					    is_class != NULL_TREE);
-      if (!method_prototype && !rprotos)
-	method_prototype
-	  = (is_class
-	     ? check_duplicates (hash_lookup (cls_method_hash_list, sel_name), 1)
-	     : lookup_method_in_hash_lists (sel_name));
+	report_type = gen_declaration (rtype, errbuf);
     }
   else
+    report_type = gen_declaration (rtype, errbuf);
+
+  /* Search for a suitable prototype.  If we can't find one, we use our
+     fallback prototype: id (*)(id,SEL,...).
+
+     First we check if the type information known for the receiver gives any
+     prototypes.  If this gives us a unique prototype, we use it.  If it gives
+     several prototypes, we warn and use the "derived-most" prototype.
+
+     If the type information does not provide any prototypes, we search for
+     one among all known prototypes.  However, if the receiver is a class
+     object according to the type information, we only search among prototypes
+     for class methods, and instance methods in root classes.
+
+     If this gives us one unique prototype, we use it.  If the receiver wasn't
+     of type 'id' or 'Class', we issue a warning.
+
+     If this gives us more than one prototype, or no prototype, we issue an
+     appropriate warning and use one of them.  */
+
+  prototype_search_start (report_type);
+
+  /* Search for a prototype given by the class part of the receiver's type,
+     if any.  */
+  if (rtype && !IS_ID (rtype)
+      && TREE_TYPE (rtype) != TREE_TYPE (objc_class_type))
     {
-      tree orig_rtype = rtype, saved_rtype;
+      tree saved_rtype;
 
       if (TREE_CODE (rtype) == POINTER_TYPE)
 	rtype = TREE_TYPE (rtype);
@@ -5741,73 +5754,141 @@
 	     && TREE_CODE (TYPE_NAME (rtype)) == TYPE_DECL
 	     && DECL_ORIGINAL_TYPE (TYPE_NAME (rtype)))
 	rtype = DECL_ORIGINAL_TYPE (TYPE_NAME (rtype));
+
       saved_rtype = rtype;
       if (TYPED_OBJECT (rtype))
 	{
 	  rprotos = TYPE_PROTOCOL_LIST (rtype);
 	  rtype = lookup_interface (OBJC_TYPE_NAME (rtype));
 	}
+
       /* If we could not find an @interface declaration, we must have
 	 only seen a @class declaration; so, we cannot say anything
 	 more intelligent about which methods the receiver will
 	 understand. */
       if (!rtype)
-	rtype = saved_rtype;
+ 	{
+	  rtype = saved_rtype;
+	  warning ("no interface seen for `%s'",
+		   IDENTIFIER_POINTER (OBJC_TYPE_NAME (rtype)));
+	}
       else if (TREE_CODE (rtype) == CLASS_INTERFACE_TYPE
 	  || TREE_CODE (rtype) == CLASS_IMPLEMENTATION_TYPE)
 	{
 	  /* We have a valid ObjC class name.  Look up the method name
-	     in the published @interface for the class (and its
+	     in the published @interface(s) for the class (and its
 	     superclasses). */
-	  method_prototype
-	    = lookup_method_static (rtype, sel_name, is_class != NULL_TREE);
+	  lookup_method_static (rtype, sel_name, is_class != NULL_TREE);
 
-	  /* If the method was not found in the @interface, it may still
-	     exist locally as part of the @implementation.  */
-	  if (!method_prototype && objc_implementation_context
+	  /* The method may also exist locally as part of the
+	     @implementation.  */
+	  if (!prototype_search_done
+	     && objc_implementation_context
 	     && CLASS_NAME (objc_implementation_context)
-		== OBJC_TYPE_NAME (rtype))			
-	    method_prototype
-	      = lookup_method
-		((is_class
-		  ? CLASS_CLS_METHODS (objc_implementation_context)
-		  : CLASS_NST_METHODS (objc_implementation_context)),
-		  sel_name);
-
-	  /* If we haven't found a candidate method by now, try looking for
-	     it in the protocol list.  */
-	  if (!method_prototype && rprotos)
-	    method_prototype
-	      = lookup_method_in_protocol_list (rprotos, sel_name,
-						is_class != NULL_TREE);
+		== OBJC_TYPE_NAME (rtype))
+	    {
+	      tree possible_prototype;
+
+	      if (is_class)
+		{
+		  possible_prototype
+		    = lookup_method
+		      (CLASS_CLS_METHODS (objc_implementation_context),
+		       sel_name);
+		  if (possible_prototype)
+		    prototype_found (possible_prototype);
+
+		  /* If we are a root class, the instance methods also apply
+		     to the class.  */
+		  if (!prototype_search_done && !CLASS_SUPER_NAME (rtype))
+		    {
+		      possible_prototype
+			= lookup_method
+			  (CLASS_NST_METHODS (objc_implementation_context),
+			   sel_name);
+		      if (possible_prototype)
+			prototype_found (possible_prototype);
+		    }
+		}
+	      else
+		{
+		  possible_prototype
+		    = lookup_method
+		      (CLASS_NST_METHODS (objc_implementation_context),
+		       sel_name);
+		  if (possible_prototype)
+		    prototype_found (possible_prototype);
+		}
+	    }
 	}
       else
 	{
-	  warning ("invalid receiver type `%s'",
-		   gen_declaration (orig_rtype, errbuf));
-	  rtype = rprotos = NULL_TREE;
+	  warning ("invalid receiver type `%s'", report_type);
+	  rtype = rprotos = is_class = NULL_TREE;
 	}
-    }	
+    }
+  else if (rtype && IS_ID (rtype))
+    {
+      rprotos = TYPE_PROTOCOL_LIST (rtype);
+    }
 
-  if (!method_prototype)
+  /* Now look in the protocol list.  */
+  if (!prototype_search_done && rprotos)
+    lookup_method_in_protocol_list (rprotos, sel_name,
+				    is_class != NULL_TREE);
+
+  prototype_search_end ();
+
+  if (num_found_prototypes == 1)
+    {
+      /* We found exactly one. Use it. */
+      method_prototype = current_found_prototype;
+    }
+  else if (num_found_prototypes > 1)
+    {
+      /* We found more than one.  prototype_found() will already have issued
+	 warnings.  We set method_prototype to the first one, which will
+	 be the "derived-most" prototype.  */
+      method_prototype = current_found_prototype;
+    }
+  else
     {
-      static bool warn_missing_methods = false;
+      /* The type information didn't give us any prototypes.  Thus, we check
+	 if there are any known prototypes at all.  */
 
-      if (rtype)
-	warning ("`%s' may not respond to `%c%s'",
-		 IDENTIFIER_POINTER (OBJC_TYPE_NAME (rtype)),
-		 (is_class ? '+' : '-'),
-		 IDENTIFIER_POINTER (sel_name));
-      if (rprotos)
-	warning ("`%c%s' not implemented by protocol(s)",
-		 (is_class ? '+' : '-'),
+      if (rtype && TREE_TYPE (rtype) == TREE_TYPE (objc_class_type)
+	  && !IS_ID (rtype))
+	is_class = get_identifier ("Class");
+
+      /* If the object is "typed", ie. not just 'id' or 'Class', issue a
+	 warning.  */
+      if (rprotos || !rtype
+	  || (!IS_ID (rtype)
+	      && TREE_TYPE (rtype) != TREE_TYPE (objc_class_type)))
+	warning ("receiver of type `%s' may not respond to `%c%s'",
+		 report_type, (is_class ? '+' : '-'),
 		 IDENTIFIER_POINTER (sel_name));
-      if (!warn_missing_methods)
+
+      method_prototype
+	= (is_class
+	   ? check_duplicates (hash_lookup (cls_method_hash_list, sel_name), 1)
+	   : lookup_method_in_hash_lists (sel_name));
+
+      if (!method_prototype)
 	{
-	  warning ("(Messages without a matching method signature");
-	  warning ("will be assumed to return `id' and accept");
-	  warning ("`...' as arguments.)");
-	  warn_missing_methods = true;
+	  static bool warn_missing_methods = false;
+
+	  warning ("no prototype found for `%c%s'",
+		   (is_class ? '+' : '-'),
+		   IDENTIFIER_POINTER (sel_name));
+
+	  if (!warn_missing_methods)
+	    {
+	      warning ("(Messages without a matching method prototype");
+	      warning ("will be assumed to return `id' and accept");
+	      warning ("`...' as arguments.)");
+	      warn_missing_methods = true;
+	    }
 	}
     }
 
@@ -6177,27 +6258,74 @@
   entry->list = obj;		/* append to front */
 }
 
-static tree
-lookup_method (tree mchain, tree method)
+static GTY(()) const char *prototype_search_type;
+
+/* Start a prototype search. type is a string describing the receiver's
+   type, and is used when issuing warnings. */
+static void
+prototype_search_start (const char *type)
 {
-  tree key;
+  prototype_search_type = type;
+  num_found_prototypes = 0;
+  current_found_prototype = 0;
+  prototype_search_done = 0;
+}
 
-  if (TREE_CODE (method) == IDENTIFIER_NODE)
-    key = method;
-  else
-    key = METHOD_SEL_NAME (method);
+static void
+prototype_search_end (void)
+{
+  prototype_search_type = 0;
+}
 
-  while (mchain)
+/* Called when a prototype is found.  Will check if it's compatible with
+   the prototype already found, issue warnings if necessary, and update
+   current_found_prototype and num_found_prototypes as necessary. */
+static void
+prototype_found (tree prototype)
+{
+  if (!warn_conflicting_prototypes)
     {
-      if (METHOD_SEL_NAME (mchain) == key)
-	return mchain;
+      /* This might be called several times even if warnings are turned off.
+	 If so, we ignore all calls except the first.  */
+      if (num_found_prototypes == 0)
+	current_found_prototype = prototype;
+      num_found_prototypes = 1;
+      prototype_search_done = 1;
+      return;
+    }
 
-      mchain = TREE_CHAIN (mchain);
+  /* If we've found exactly one prototype, and the new prototype is
+     compatible, do nothing.  */
+  if (num_found_prototypes == 1
+      && comp_proto_with_proto (prototype, current_found_prototype))
+    return;
+
+  num_found_prototypes++;
+  if (num_found_prototypes > 1)
+    {
+      char type = (TREE_CODE (prototype) == INSTANCE_METHOD_DECL) ? '-' : '+';
+
+      if (num_found_prototypes == 2)
+	{
+	  warning ("multiple methods named `%c%s' found for receiver of type `%s'",
+		   type,
+		   IDENTIFIER_POINTER (METHOD_SEL_NAME (prototype)),
+		   prototype_search_type);
+	  warn_with_method ("using", type,
+			    current_found_prototype);
+	  warn_with_method ("instead of", type, prototype);
+	}
+      else
+	warn_with_method ("or", type, prototype);
     }
-  return NULL_TREE;
+  else
+    current_found_prototype = prototype;
 }
 
-static tree
+/* Look for prototypes for a selector in an interface (including all
+   categories and protocols, and then all superclasses, for that interface).
+   Any prototypes found are passed to prototype_found().  */
+static void
 lookup_method_static (tree interface, tree ident, int is_class)
 {
   tree meth = NULL_TREE, root_inter = NULL_TREE;
@@ -6208,54 +6336,144 @@
       tree chain = is_class ? CLASS_CLS_METHODS (inter) : CLASS_NST_METHODS (inter);
       tree category = inter;
 
-      /* First, look up the method in the class itself.  */
+      /* Look up the method in the class itself.  */
       if ((meth = lookup_method (chain, ident)))
-	return meth;
+	{
+	  prototype_found (meth);
+	  if (prototype_search_done)
+	    return;
+	}
 
-      /* Failing that, look for the method in each category of the class.  */
+      /* Look for the method in each category of the class.  */
       while ((category = CLASS_CATEGORY_LIST (category)))
 	{
 	  chain = is_class ? CLASS_CLS_METHODS (category) : CLASS_NST_METHODS (category);
 
 	  /* Check directly in each category.  */
 	  if ((meth = lookup_method (chain, ident)))
-	    return meth;
+	    {
+	      prototype_found (meth);
+	      if (prototype_search_done)
+		return;
+	    }
 
-	  /* Failing that, check in each category's protocols.  */
+	  /* Check in each category's protocols.  */
 	  if (CLASS_PROTOCOL_LIST (category))
 	    {
-	      if ((meth = (lookup_method_in_protocol_list
-			   (CLASS_PROTOCOL_LIST (category), ident, is_class))))
-		return meth;
+	      lookup_method_in_protocol_list
+		(CLASS_PROTOCOL_LIST (category), ident, is_class);
+	      if (prototype_search_done)
+		return;
 	    }
 	}
 
-      /* If not found in categories, check in protocols of the main class.  */
+      /* Check in protocols of the main class.  */
       if (CLASS_PROTOCOL_LIST (inter))
 	{
-	  if ((meth = (lookup_method_in_protocol_list
-		       (CLASS_PROTOCOL_LIST (inter), ident, is_class))))
-	    return meth;
+	  lookup_method_in_protocol_list
+	    (CLASS_PROTOCOL_LIST (inter), ident, is_class);
+	  if (prototype_search_done)
+	    return;
 	}
 
-      /* Failing that, climb up the inheritance hierarchy.  */
+      /* Climb up the inheritance hierarchy.  */
       root_inter = inter;
       inter = lookup_interface (CLASS_SUPER_NAME (inter));
     }
   while (inter);
 
-  /* If no class (factory) method was found, check if an _instance_
+  /* If the receiver is a class object, check if an _instance_
      method of the same name exists in the root class.  This is what
-     the Objective-C runtime will do.  If an instance method was not
-     found, return 0.  */
-  return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
+     the Objective-C runtime will do. */
+  if (is_class)
+    lookup_method_static (root_inter, ident, 0);
+}
+
+/* Look for prototypes for a selector in a set of protocols (including
+   protocols the protocols inherit from).  Any prototypes that are found
+   will be passed to prototype_found().  */
+static void
+lookup_method_in_protocol_list (tree rproto_list, tree sel_name, int class_meth)
+{
+   tree rproto, p;
+   tree fnd;
+
+   for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
+     {
+        p = TREE_VALUE (rproto);
+
+	if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
+	  {
+	    /* Check the protocol itself.  */
+	    if ((fnd = lookup_method (class_meth
+				      ? PROTOCOL_CLS_METHODS (p)
+				      : PROTOCOL_NST_METHODS (p), sel_name)))
+	      {
+		prototype_found (fnd);
+		if (prototype_search_done)
+		  return;
+	      }
+	    /* Check the protocols this protocol inherits from.  */
+	    if (PROTOCOL_LIST (p))
+	      {
+	        lookup_method_in_protocol_list (PROTOCOL_LIST (p),
+						sel_name, class_meth);
+		if (prototype_search_done)
+		  return;
+	      }
+	  }
+     }
+}
+
+static tree
+lookup_method (tree mchain, tree method)
+{
+  tree key;
+
+  if (TREE_CODE (method) == IDENTIFIER_NODE)
+    key = method;
+  else
+    key = METHOD_SEL_NAME (method);
+
+  while (mchain)
+    {
+      if (METHOD_SEL_NAME (mchain) == key)
+	return mchain;
+
+      mchain = TREE_CHAIN (mchain);
+    }
+  return NULL_TREE;
+}
+
+
+/* Add the method to the hash list if it doesn't contain an identical
+   method already. */
+static void
+add_method_to_hash_list (hash *hash_list, tree method)
+{
+  hash hsh;
+
+  if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
+    {
+      /* Install on a global chain.  */
+      hash_enter (hash_list, method);
+    }
+  else
+    {
+      /* Check types against those; if different, add to a list.  */
+      attr loop;
+      int already_there = comp_proto_with_proto (method, hsh->key);
+      for (loop = hsh->list; !already_there && loop; loop = loop->next)
+	already_there |= comp_proto_with_proto (method, loop->value);
+      if (!already_there)
+	hash_add_attr (hsh, method);
+    }
 }
 
 tree
 add_method (tree class, tree method, int is_class)
 {
   tree mth;
-  hash hsh;
 
   if (!(mth = lookup_method (is_class ? CLASS_CLS_METHODS (class) : CLASS_NST_METHODS (class), method)))
     {
@@ -6273,10 +6491,11 @@
     }
   else
     {
-      /* When processing an @interface for a class or category, give hard errors on methods with
-	 identical selectors but differing argument and/or return types. We do not do this for
-	 @implementations, because C/C++ will do it for us (i.e., there will be
-	 duplicate function definition errors).  */
+      /* When processing an @interface for a class or category, give hard
+	 errors on methods with identical selectors but differing argument
+	 and/or return types. We do not do this for @implementations, because
+	 C/C++ will do it for us (i.e., there will be duplicate function
+	 definition errors).  */
       if ((TREE_CODE (class) == CLASS_INTERFACE_TYPE
 	   || TREE_CODE (class) == CATEGORY_INTERFACE_TYPE)
 	  && !comp_proto_with_proto (method, mth))
@@ -6284,23 +6503,21 @@
 		is_class ? '+' : '-', IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
     }
 
-  if (!(hsh = hash_lookup (is_class
-			   ? cls_method_hash_list
-			   : nst_method_hash_list, METHOD_SEL_NAME (method))))
-    {
-      /* Install on a global chain.  */
-      hash_enter (is_class ? cls_method_hash_list : nst_method_hash_list, method);
-    }
+  if (is_class)
+    add_method_to_hash_list (cls_method_hash_list, method);
   else
     {
-      /* Check types against those; if different, add to a list.  */
-      attr loop;
-      int already_there = comp_proto_with_proto (method, hsh->key);
-      for (loop = hsh->list; !already_there && loop; loop = loop->next)
-	already_there |= comp_proto_with_proto (method, loop->value);
-      if (!already_there)
-	hash_add_attr (hsh, method);
+      add_method_to_hash_list (nst_method_hash_list, method);
+
+      /* Instance methods in root classes are inherited by class objects,
+	 so we add those methods to the class method list, too.
+
+	 TODO: We should do this for categories of root classes as well. */
+      if (TREE_CODE (class) == CLASS_INTERFACE_TYPE
+	  && !CLASS_SUPER_NAME (class))
+	add_method_to_hash_list (cls_method_hash_list, method);
     }
+
   return method;
 }
 
@@ -7768,17 +7985,24 @@
 
   if (implementation_template != objc_implementation_context)
     {
-      tree proto
-	= lookup_method_static (implementation_template,
-				METHOD_SEL_NAME (method),
-				TREE_CODE (method) == CLASS_METHOD_DECL);
-
-      if (proto && ! comp_method_with_proto (method, proto))
+      prototype_search_start
+ 	(IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
+      lookup_method_static (implementation_template,
+			    METHOD_SEL_NAME (method),
+			    TREE_CODE (method) == CLASS_METHOD_DECL);
+      prototype_search_end ();
+
+      /* If we found exactly one prototype, check that the implementation
+	 matches it (if there's more than one, warnings will already have
+	 been issued during the search). */
+      if (num_found_prototypes == 1
+	  && !comp_method_with_proto (method, current_found_prototype))
 	{
 	  char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
 
 	  warn_with_method ("conflicting types for", type, method);
-	  warn_with_method ("previous declaration of", type, proto);
+	  warn_with_method ("previous declaration of", type,
+			    current_found_prototype);
 	}
     }
 }
Index: gcc/testsuite/objc.dg/call-super-2.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/call-super-2.m,v
retrieving revision 1.2
diff -u -r1.2 call-super-2.m
--- gcc/testsuite/objc.dg/call-super-2.m	25 Sep 2003 01:26:00 -0000	1.2
+++ gcc/testsuite/objc.dg/call-super-2.m	29 Sep 2003 19:48:48 -0000
@@ -44,11 +44,8 @@
 @implementation Derived
 + (int) class_func1
 {
-   int i = (int)[self class_func0];       /* { dg-warning ".Derived. may not respond to .\\+class_func0." } */
-       /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 47 } */
-       /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 47 } */
-       /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 47 } */
-   return i + (int)[super class_func0];   /* { dg-warning ".Object. may not respond to .\\+class_func0." } */
+   int i = (int)[self class_func0];       /* { dg-warning "receiver of type .Derived. may not respond to .\\+class_func0." } */
+   return i + (int)[super class_func0];   /* { dg-warning "receiver of type .Object. may not respond to .\\+class_func0." } */
 }
 + (int) class_func2
 {
@@ -65,12 +62,12 @@
 }   
 + (int) class_func5
 {
-   int i = (int)[Derived class_func0];    /* { dg-warning ".Derived. may not respond to .\\+class_func0." } */
-   return i + (int)[Object class_func0];  /* { dg-warning ".Object. may not respond to .\\+class_func0." } */
+   int i = (int)[Derived class_func0];    /* { dg-warning "receiver of type .Derived. may not respond to .\\+class_func0." } */
+   return i + (int)[Object class_func0];  /* { dg-warning "receiver of type .Object. may not respond to .\\+class_func0." } */
 }
 + (int) class_func6
 {
-   return (int)[OBJC_GETCLASS("Object") class_func1];  /* { dg-warning ".Object. may not respond to .\\+class_func1." } */
+   return (int)[OBJC_GETCLASS("Object") class_func1];  /* { dg-warning "receiver of type .Object. may not respond to .\\+class_func1." } */
 }
 + (int) class_func7
 {
@@ -78,8 +75,8 @@
 }
 - (int) instance_func1
 {
-   int i = (int)[self instance_func0];     /* { dg-warning ".Derived. may not respond to .\\-instance_func0." } */
-   return i + (int)[super instance_func0]; /* { dg-warning ".Object. may not respond to .\\-instance_func0." } */
+   int i = (int)[self instance_func0];     /* { dg-warning "receiver of type .Derived. may not respond to .\\-instance_func0." } */
+   return i + (int)[super instance_func0]; /* { dg-warning "receiver of type .Object. may not respond to .\\-instance_func0." } */
 }
 - (int) instance_func2
 {
@@ -95,12 +92,17 @@
 }   
 - (int) instance_func5
 {
-   int i = (int)[Derived instance_func1]; /* { dg-warning ".Derived. may not respond to .\\+instance_func1." } */
-   return i + (int)[Object instance_func1]; /* { dg-warning ".Object. may not respond to .\\+instance_func1." } */
+   int i = (int)[Derived instance_func1]; /* { dg-warning "receiver of type .Derived. may not respond to .\\+instance_func1." } */
+       /* { dg-warning "no prototype found for .\\+instance_func1." "" { target *-*-* } 95 } */
+       /* { dg-warning "\\(Messages without a matching method prototype" "" { target *-*-* } 95 } */
+       /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 95 } */
+       /* { dg-warning ".\.\.\.. as arguments\.\\)" "" { target *-*-* } 95 } */
+   return i + (int)[Object instance_func1]; /* { dg-warning "receiver of type .Object. may not respond to .\\+instance_func1." } */
+       /* { dg-warning "no prototype found for .\\+instance_func1." "" { target *-*-* } 100 } */
 }
 - (int) instance_func6
 {
-   return (int)[OBJC_GETCLASS("Object") class_func1]; /* { dg-warning ".Object. may not respond to .\\+class_func1." } */
+   return (int)[OBJC_GETCLASS("Object") class_func1]; /* { dg-warning "receiver of type .Object. may not respond to .\\+class_func1." } */
 }
 - (int) instance_func7
 {
@@ -111,11 +113,12 @@
 @implementation Derived (Categ)
 + (int) categ_class_func1
 {
-   int i = (int)[self class_func0];       /* { dg-warning ".Derived. may not respond to .\\+class_func0." } */
+   int i = (int)[self class_func0];       /* { dg-warning "receiver of type .Derived. may not respond to .\\+class_func0." } */
    i += [self class_func1];
    i += [self categ_class_func2];
-   i += (int)[self categ_instance_func1]; /* { dg-warning ".Derived. may not respond to .\\+categ_instance_func1." } */
-   return i + (int)[super class_func0];   /* { dg-warning ".Object. may not respond to .\\+class_func0." } */
+   i += (int)[self categ_instance_func1]; /* { dg-warning "receiver of type .Derived. may not respond to .\\+categ_instance_func1." } */
+       /* { dg-warning "no prototype found for .\\+categ_instance_func1." "" { target *-*-* } 119 } */
+   return i + (int)[super class_func0];   /* { dg-warning "receiver of type .Object. may not respond to .\\+class_func0." } */
 }
 + (int) categ_class_func2
 {
@@ -124,13 +127,12 @@
 }
 - (int) categ_instance_func1
 {
-   int i = (int)[self instance_func0];    /* { dg-warning ".Derived. may not respond to .\\-instance_func0." } */
+   int i = (int)[self instance_func0];    /* { dg-warning "receiver of type .Derived. may not respond to .\\-instance_func0." } */
    i += [(Derived <Func> *)self categ_instance_func2];
-   i += (int)[(Object <Func> *)self categ_instance_func2]; /* { dg-warning ".Object. may not respond to .\\-categ_instance_func2." } */
-   /* { dg-warning ".\\-categ_instance_func2. not implemented by protocol" "" { target *-*-* } 129 } */
-   i += (int)[(id <Func>)self categ_instance_func2];  /* { dg-warning ".\\-categ_instance_func2. not implemented by protocol" } */
+   i += (int)[(Object <Func> *)self categ_instance_func2]; /* { dg-warning "receiver of type .Object <Func>  \\*. may not respond to .\\-categ_instance_func2." } */
+   i += (int)[(id <Func>)self categ_instance_func2];  /* { dg-warning "receiver of type .id <Func>. may not respond to .\\-categ_instance_func2." } */
    i += [(id)self categ_instance_func2];
-   return i + (int)[super instance_func0];   /* { dg-warning ".Object. may not respond to .\\-instance_func0." } */
+   return i + (int)[super instance_func0];   /* { dg-warning "receiver of type .Object. may not respond to .\\-instance_func0." } */
 }
 - (int) categ_instance_func2
 {
Index: gcc/testsuite/objc.dg/desig-init-1.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/desig-init-1.m,v
retrieving revision 1.2
diff -u -r1.2 desig-init-1.m
--- gcc/testsuite/objc.dg/desig-init-1.m	25 Sep 2003 01:26:00 -0000	1.2
+++ gcc/testsuite/objc.dg/desig-init-1.m	29 Sep 2003 19:48:48 -0000
@@ -22,10 +22,8 @@
     0, 
     [Cls meth1], 
     [2 + 1] = 3, 
-    [2 * 2 ... 5] = (int)[0 meth2], /* { dg-warning "invalid receiver type" } */ 
-       /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 25 } */
-       /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 25 } */
-       /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 25 } */
+    [2 * 2 ... 5] = (int)[0 meth2], /* { dg-warning "invalid receiver type .int ." } */
+       /* { dg-warning "receiver of type .int . may not respond to .\\-meth2." "" { target *-*-* } 25 } */
     [2] [Cls meth2]
   };
 
Index: gcc/testsuite/objc.dg/method-2.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/method-2.m,v
retrieving revision 1.2
diff -u -r1.2 method-2.m
--- gcc/testsuite/objc.dg/method-2.m	25 Sep 2003 01:26:01 -0000	1.2
+++ gcc/testsuite/objc.dg/method-2.m	29 Sep 2003 19:48:48 -0000
@@ -22,11 +22,13 @@
     [self rootInstanceMethod];            /* class is searched for an instance method  */
     [MyIntermediate rootInstanceMethod];  /* with the same name.                       */
 
-    [self instanceMethod];   /* { dg-warning ".MyDerived. may not respond to .\\+instanceMethod." } */
-       /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 25 } */
+    [self instanceMethod];   /* { dg-warning "receiver of type .MyDerived. may not respond to .\\+instanceMethod." } */
+       /* { dg-warning "no prototype found for .\\+instanceMethod." "" { target *-*-* } 25 } */
+       /* { dg-warning "\\(Messages without a matching method prototype" "" { target *-*-* } 25 } */
        /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 25 } */
-       /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 25 } */
+       /* { dg-warning ".\.\.\.. as arguments\\.\\)" "" { target *-*-* } 25 } */
     [MyDerived instanceMethod];   /* { dg-warning ".MyDerived. may not respond to .\\+instanceMethod." } */
+       /* { dg-warning "no prototype found for .\\+instanceMethod." "" { target *-*-* } 30 } */
 }
 @end
 
Index: gcc/testsuite/objc.dg/method-5.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/method-5.m,v
retrieving revision 1.2
diff -u -r1.2 method-5.m
--- gcc/testsuite/objc.dg/method-5.m	25 Sep 2003 01:26:01 -0000	1.2
+++ gcc/testsuite/objc.dg/method-5.m	29 Sep 2003 19:48:48 -0000
@@ -8,11 +8,17 @@
 } NotAClass;
 
 void foo(UnderSpecified *u, NotAClass *n) {
-  [n nonexistent_method];    /* { dg-warning "invalid receiver type" } */
-       /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 11 } */
+  [n nonexistent_method];    /* { dg-warning "invalid receiver type .untagged struct  \\*." } */
+       /* { dg-warning "receiver of type .untagged struct  \\*. may not respond to .\\-nonexistent_method." "" { target *-*-* } 11 } */
+       /* { dg-warning "no prototype found for .\\-nonexistent_method." "" { target *-*-* } 11 } */
+       /* { dg-warning "\\(Messages without a matching method prototype" "" { target *-*-* } 11 } */
        /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 11 } */
-       /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 11 } */
+       /* { dg-warning ".\.\.\.. as arguments\\.\\)" "" { target *-*-* } 11 } */
   [NotAClass nonexistent_method]; /* { dg-error ".NotAClass. is not an Objective\\-C class name or alias" } */
-  [u nonexistent_method]; /* { dg-warning ".UnderSpecified. may not respond to .\\-nonexistent_method." } */
-  [UnderSpecified nonexistent_method]; /* { dg-warning ".UnderSpecified. may not respond to .\\+nonexistent_method." } */
+  [u nonexistent_method];  /* { dg-warning "no interface seen for .UnderSpecified." } */
+       /* { dg-warning "receiver of type .UnderSpecified  \\*. may not respond to .\\-nonexistent_method." "" { target *-*-* } 18 } */
+       /* { dg-warning "no prototype found for .\\-nonexistent_method." "" { target *-*-* } 18 } */
+  [UnderSpecified nonexistent_method]; /* { dg-warning "no interface seen for .UnderSpecified." } */
+       /* { dg-warning "receiver of type .UnderSpecified. may not respond to .\\+nonexistent_method." "" { target *-*-* } 21 } */
+       /* { dg-warning "no prototype found for .\\+nonexistent_method." "" { target *-*-* } 21 } */
 }
Index: gcc/testsuite/objc.dg/method-6.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/method-6.m,v
retrieving revision 1.2
diff -u -r1.2 method-6.m
--- gcc/testsuite/objc.dg/method-6.m	25 Sep 2003 01:26:01 -0000	1.2
+++ gcc/testsuite/objc.dg/method-6.m	29 Sep 2003 19:48:48 -0000
@@ -1,26 +1,38 @@
-/* Check that sending messages to variables of type 'Class' does not involve instance methods.  */
+/* Check that sending messages to variables of type 'Class' does not involve instance methods not in root classes.  */
 /* Author: Ziemowit Laski <zlaski@apple.com>  */
 /* { dg-do compile } */
 
 #include <objc/Protocol.h>
 
 @interface Base
-- (unsigned)port;
+- (unsigned)port1;
 - (id)starboard;
 @end
 
 @interface Derived: Base
-- (Object *)port;
-+ (Protocol *)port;
+- (Object *)port1;
++ (Protocol *)port1;
+- (Object *)port2;
++ (Protocol *)port2;
+- (Object *)port3;
 @end
 
 id foo(void) {
   Class receiver;
-  id p = [receiver port];  /* there should be no warnings here! */
-  p = [receiver starboard];  /* { dg-warning ".Class. may not respond to .\\+starboard." } */
-       /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 20 } */
-       /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 20 } */
-       /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 20 } */
-  p = [Class port];  /* { dg-error ".Class. is not an Objective\\-C class name or alias" } */
-  return p;
+  id p1 = [receiver port1];  /* { dg-warning "multiple methods named .\\-port1. found" } */
+       /* { dg-warning "using .\\-\\(unsigned\\)port1." "" { target *-*-* } 8 } */
+       /* { dg-warning "also found .\\-\\(Protocol \\*\\)port1." "" { target *-*-* } 14 } */
+       /* { dg-warning "initialization makes pointer from integer without a cast" "" { target *-*-* } 22 } */
+  id p2 = [receiver port2];  /* there should be no warnings here! */
+  id p3 = [receiver port3];  /* { dg-warning "no prototype found for .\\+port3." } */
+       /* { dg-warning "\\(Messages without a matching method prototype" "" { target *-*-* } 27 } */
+       /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 27 } */
+       /* { dg-warning ".\.\.\.. as arguments\.\\)" "" { target *-*-* } 27 } */
+  p1 = [receiver starboard];  /* No warning here as Class is treated like id (i.e. all class methods are matched) */
+  p1 = [Base port1];  /* { dg-warning "assignment makes pointer from integer without a cast" } */
+  p1 = [Derived port1];  /* { dg-warning "multiple methods named .\\-port1. found for receiver of type .Derived." } */
+       /* { dg-warning "using .\\-\\(Protocol \\*\\)port1." "" { target *-*-* } 14 } */
+       /* { dg-warning "instead of .\\-\\(unsigned\\)port1." "" { target *-*-* } 8 } */
+  p2 = [Derived port2];  /* No warning, using class method */
+  return p1;
 }
Index: gcc/testsuite/objc.dg/method-7.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/method-7.m,v
retrieving revision 1.2
diff -u -r1.2 method-7.m
--- gcc/testsuite/objc.dg/method-7.m	25 Sep 2003 01:26:01 -0000	1.2
+++ gcc/testsuite/objc.dg/method-7.m	29 Sep 2003 19:48:48 -0000
@@ -15,13 +15,11 @@
 id foo(void) {
   Object *obj = [[Object alloc] init];
   id obj2 = obj;
-  [obj setWindow:nil];  /* { dg-warning ".Object. may not respond to .\\-setWindow:." } */
-       /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 18 } */
-       /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 18 } */
-       /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 18 } */
-  [obj2 setWindow:nil]; /* { dg-warning "multiple methods named .\\-setWindow:. found" } */
+  [obj setWindow:nil];  /* { dg-warning "receiver of type .Object  \\*. may not respond to .\\-setWindow:." } */
+       /* { dg-warning "multiple methods named .\\-setWindow:. found" "" { target *-*-* } 18 } */
        /* { dg-warning "using .\\-\\(void\\)setWindow:\\(Object \\*\\)wdw." "" { target *-*-* } 8 } */
        /* { dg-warning "also found .\\-\\(void\\)setWindow:\\(Class1 \\*\\)window." "" { target *-*-* } 12 } */
+  [obj2 setWindow:nil]; /* { dg-warning "multiple methods named .\\-setWindow:. found" } */
 
   return obj;
 }
Index: gcc/testsuite/objc.dg/proto-hier-1.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/proto-hier-1.m,v
retrieving revision 1.2
diff -u -r1.2 proto-hier-1.m
--- gcc/testsuite/objc.dg/proto-hier-1.m	25 Sep 2003 01:26:01 -0000	1.2
+++ gcc/testsuite/objc.dg/proto-hier-1.m	29 Sep 2003 19:48:49 -0000
@@ -48,8 +48,9 @@
   id<Booing, Fooing> stupidVar;
   [stupidVar boo];
   [stupidVar foo];
-  [stupidVar anotherMsg]; /* { dg-warning ".\-anotherMsg. not implemented by protocol" } */
-       /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 51 } */
+  [stupidVar anotherMsg]; /* { dg-warning "receiver of type .id <Booing, Fooing>. may not respond to .\-anotherMsg." } */
+       /* { dg-warning "no prototype found for .\-anotherMsg." "" { target *-*-* } 51 } */
+       /* { dg-warning "Messages without a matching method prototype" "" { target *-*-* } 51 } */
        /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 51 } */
        /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 51 } */
   return 0;
Index: gcc/testsuite/objc.dg/proto-lossage-1.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/proto-lossage-1.m,v
retrieving revision 1.2
diff -u -r1.2 proto-lossage-1.m
--- gcc/testsuite/objc.dg/proto-lossage-1.m	25 Sep 2003 01:26:01 -0000	1.2
+++ gcc/testsuite/objc.dg/proto-lossage-1.m	29 Sep 2003 19:48:49 -0000
@@ -35,11 +35,7 @@
   return (id <NSObject>)plate1; /* { dg-bogus "does not conform" } */
 }
 - (int) getValue {
-  int i = [plate1 someValue];   /* { dg-warning ".\\-someValue. not implemented by protocol\\(s\\)" } */
-     /* { dg-warning "\\(Messages without a matching method signature" "" { target *-*-* } 38 } */
-     /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 38 } */
-     /* { dg-warning ".\.\.\.. as arguments\.\\)" "" { target *-*-* } 38 } */
-     /* { dg-warning "initialization makes integer from pointer without a cast" "" { target *-*-* } 38 } */
+  int i = [plate1 someValue];   /* { dg-warning "receiver of type .id <PlateMethods>. may not respond to .\\-someValue." } */
 
   int j = [(id <NSObject>)plate1 someValue];  /* { dg-bogus "not implemented by protocol" } */
   int k = [(id)plate1 someValue]; /* { dg-bogus "not implemented by protocol" } */


More information about the Gcc-patches mailing list