This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: Objective-c prototype search cleanups


Hi,

Here is the message sending prototype search patch again, now against
mainline. Changes, from a user pov (similar, but not identical, to the
old version):


* The rules for the prototype search have been changed slightly (less
than before):

First, the compiler will search for a prototype based on the type of the
receiver (which may include a known class, and may include a list of
protocols, or may be nothing if the type is 'id' or 'Class').

If exactly one prototype is found, it is used.

If more than one prototype is found, the "derived-most" prototype will
be used, and a warning will be issued if the prototypes are
incompatible, unless you use the -Wno-conflicting-prototypes option.

If no prototype is found (which is always the case for plain 'id' and
'Class'), all known prototypes will be checked. If exactly one is found,
it's used. If no prototype is found, the fallback prototype is used and
a warning is issued. If more than one prototype is found, one will be
picked "randomly", and a warning is issued.


This is _almost_ identical to the old behavior. The difference is that
older versions would not always do the search among all prototypes if
the search based on type failed. Eg. given:

@interface Foo
@end
@interface Bar
-(void) quux;
@end
...
[(Foo *)receiver quux];

Previous versions would issue a warning and use the fallback prototype
in most cases, but would search all prototypes sometimes. The new
behavior is to always search all prototypes if no prototype is found
based on the receiver's type.

Since the code for this has now been cleaned up, I could fairly easily
change the behavior in any of the cases, if we can agree on what we
should change it to. :)


* When searching for a prototype for a class object with a known type,
and the class is a root class, and we're in an @implementation for that
class, and a matching instance method is found in the local
implementation, it will now be "found". This matches what the runtime
will do.


* When searching all known prototypes, instance methods of root classes
are included in the class methods. This matches what the runtime will
do.


* Warnings will now use a descriptive name of the type instead of just
the class name or "not implemented by protocols". Eg.:

"receiver of type `SomeClass <SomeProtocol>' may not respond to ..."

This allows developers to know exactly what the compiler is checking
against, and makes all the 'may not respond to...' warnings consistent.


* If a message is sent to a receiver with a type we have not seen an
interface for, a warning is issued:

"no interface seen for `SomeClass'"

Fairly often, I've spent time checking for typos and reading headers and
documentation trying to figure out why the compiler doesn't think some
class implements a method before realizing that I'd just forgotten to
include the header. This warning should put an end to that. :)

ChangeLog entry:

2003-09-29  Alexander Malmberg  <alexander@malmberg.org>

	* objc/objc-act.c: (lookup_method_static,
	lookup_method_in_protocol_list): Collect type-based prototype
	search functions in one place. Use new functions to handle
	prototypes that are found.
	(prototype_search_start, prototype_search_end, prototype_found):
	New functions. Deal with prototypes that are found and issue 
	warnings if -Wconflicting-prototypes is set.
	(finish_message_expr): Update for new prototype search machinery.
	When issuing warnings, use the full receiver type. If a message is
	sent to a receiver that is an instance of a class we haven't seen
	an interface for, issue a warning. If we're in an @implementation
	for a root class searching for a prototype for a class method in
	the same class, check instance methods in addition to class 
	methods. Always do the global prototype search if no prototype is
	found using the receiver's type.
	(add_method_to_hash_list): New function.
	(add_method): If an instance method is added to a root class, add
	the method to the class method hash list.
	(really_start_method): Update for new prototype search functions.
	* c-common.c, c-common.h, c-opts.c, c.opt: Add
	-Wno-conflicting-prototypes option.
	* doc/invoke.texi: Document it.

A couple of test cases are updated for the new wording, and there are a
6 new test cases.

Bootstrapped and tested (the objective-c test suite) on
i686-pc-linux-gnu. GNUstep compiles ok and there are no regressions in
its test suite, either.

I can't commit this to cvs myself. Also, I guess this is large enough to
bring in the copyright issue. What are my options, and whom do I
contact?

- Alexander Malmberg
? 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	26 Sep 2003 20:29:22 -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	26 Sep 2003 20:29:22 -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	26 Sep 2003 20:29:23 -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	26 Sep 2003 20:29:24 -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	26 Sep 2003 20:29:34 -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	26 Sep 2003 20:29:38 -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,76 @@
   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 1;
+    }
 
-      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 0;
+
+  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;
+
+  return 0;
 }
 
-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 +6338,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 +6493,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 +6505,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 +7987,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	26 Sep 2003 20:29:44 -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	26 Sep 2003 20:29:44 -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	26 Sep 2003 20:29:44 -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	26 Sep 2003 20:29:44 -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	26 Sep 2003 20:29:44 -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 methods.  */
 /* 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	26 Sep 2003 20:29:44 -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	26 Sep 2003 20:29:44 -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	26 Sep 2003 20:29:44 -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" } */

/* Check that missing @interface warnings are reported properly. */
/* Contributed by Alexander Malmberg <alexander@malmberg.org>  */
/* { dg-do compile } */

@class SomeClass;

SomeClass *a;

@interface Foo
-(void) someMessage;
+(void) someMessage;
@end

void foo(void)
{
  [a someMessage]; /* { dg-warning "no interface seen for .SomeClass." } */
       /* { dg-warning "receiver of type .SomeClass  \\*. may not respond to .\\-someMessage." "" { target *-*-* } 16 } */
  [SomeClass someMessage]; /* { dg-warning "no interface seen for .SomeClass." } */
       /* { dg-warning "receiver of type .SomeClass. may not respond to .\\+someMessage." "" { target *-*-* } 18 } */
}


/* Check for finding the prototype
   when there is exactly one available. */
/* Contributed by David Ayers <d.ayers@inode.at>  */
/* { dg-do compile } */

#include <objc/Object.h>

struct _MyStruct
{
  unsigned long a;
  unsigned long b;
  unsigned long c;
};
typedef struct _MyStruct MyStruct;

/* Class declares method directly.  */
@interface Class1
+ (Class1 *)class1;
- (MyStruct)getStruct1;
@end

void foo1(void)
{
  MyStruct strct;
  Class1  *varClass1;
  id       varId;

  strct = [[Class1 class1] getStruct1];
  strct = [Class1 getStruct1];

  varClass1 = [Class1 class1];
  strct = [varClass1 getStruct1];

  varId = [Class1 class1];
  strct = [(Class1 *)varId getStruct1];
}

/* Superclass declares method.  */
@interface Class2 : Class1
+ (Class2 *)class2;
- (MyStruct)getStruct2;
@end

void foo2(void)
{
  MyStruct strct;
  Class2  *varClass2;
  id       varId;

  strct = [[Class2 class2] getStruct1];
  strct = [Class2 getStruct1];
  strct = [[Class2 class2] getStruct2];
  strct = [Class2 getStruct2]; /* { dg-warning "receiver of type .Class2. may not respond to .\\+getStruct2." } */
  /* { dg-warning "no prototype found for .\\+getStruct2." "" { target *-*-* } 53 } */
  /* { dg-warning "\\(Messages without a matching method prototype" "" { target *-*-* } 53 } */
  /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 53 } */
  /* { dg-warning ".\\.\\.\\.. as arguments\\.\\)" "" { target *-*-* } 53 } */
  /* { dg-error "incompatible types in assignment" "" { target *-*-* } 53 } */

  varClass2 = [Class2 class2];
  strct = [varClass2 getStruct1];
  strct = [varClass2 getStruct2];

  varId = [Class2 class2];
  strct = [(Class2 *)varId getStruct1];
  strct = [(Class2 *)varId getStruct2];
}

/* Protocol declares method.  */
@protocol Proto1
- (MyStruct)getStruct3;
@end

@interface Class0
@end

@interface Class3 <Proto1>
+ (Class3 *)class3;
+ (id<Proto1>)class3Proto1id;
+ (Class3<Proto1> *)class3Proto1Class3;
+ (Class0<Proto1> *)class3Proto1Class0;
@end

void foo3(void)
{
  MyStruct strct;
  Class3          *varClass3;
  id <Proto1>      varProto1;
  Class3 <Proto1> *varClass3Proto1;
  Class0 <Proto1> *varClass0Proto1;
  id               varId;

  strct = [[Class3 class3] getStruct3];
  strct = [Class3 getStruct3];

  strct = [[Class3 class3Proto1id] getStruct3];
  strct = [[Class3 class3Proto1Class3] getStruct3];

  varClass3 = [Class3 class3];
  strct = [varClass3 getStruct3];
  varProto1 = [Class3 class3Proto1id];
  strct = [varProto1 getStruct3];
  varClass3Proto1 = [Class3 class3Proto1Class3];
  strct = [varClass3Proto1 getStruct3];
  varClass0Proto1 = [Class3 class3Proto1Class0];
  strct = [varClass0Proto1 getStruct3];

  varId = [Class3 class3];
  strct = [(Class3 *)varId getStruct3];
  strct = [(id <Proto1>)varId getStruct3];
  strct = [(Class3 <Proto1> *)varId getStruct3];
  strct = [(Class0 <Proto1> *)varId getStruct3];
}

/* Protocol from Inherited class declares method.  */

@protocol Proto2
- (MyStruct)getStruct4;
@end

@interface Class4 : Class3 <Proto2>
+ (Class4 *)class4;
+ (id<Proto1>)class4Proto1id;
+ (id<Proto2>)class4Proto2id;
+ (Class4<Proto1> *)class4Proto1Class4;
+ (Class4<Proto2> *)class4Proto2Class4;
@end

void foo4(void)
{
  MyStruct strct;
  Class4          *varClass4;
  Class4 <Proto1> *varClass4Proto1;
  Class4 <Proto2> *varClass4Proto2;
  id              varId;

  strct = [[Class4 class4] getStruct3];
  strct = [Class4 getStruct3];
  strct = [[Class4 class4] getStruct4];
  strct = [Class4 getStruct4]; /* { dg-warning "receiver of type .Class4. may not respond to .\\+getStruct4." } */
  /* { dg-warning "no prototype found for .\\+getStruct4." "" { target *-*-* } 140 } */
  /* { dg-error "incompatible types in assignment" "" { target *-*-* } 140 } */

  strct = [[Class4 class4Proto1id] getStruct3];
  strct = [[Class4 class4Proto2id] getStruct4];
  strct = [[Class4 class4Proto1Class4] getStruct3];
  strct = [[Class4 class4Proto2Class4] getStruct4];

  varClass4 = [Class4 class4];
  strct = [varClass4 getStruct3];
  strct = [varClass4 getStruct4];

  varClass4Proto1 = [Class4 class4Proto1Class4];
  strct = [varClass4Proto1 getStruct3];
  strct = [varClass4Proto1 getStruct4];

  varClass4Proto2 = [Class4 class4Proto2Class4];
  strct = [varClass4Proto2 getStruct3];
  strct = [varClass4Proto2 getStruct4];

  varId = [Class4 class4];
  strct = [(Class4 *)varId getStruct3];
  strct = [(Class4 *)varId getStruct4];
  strct = [(id <Proto1>)varId getStruct3];
  strct = [(id <Proto1>)varId getStruct4]; /* { dg-warning "receiver of type .id \\<Proto1\\>. may not respond to .\\-getStruct4." } */
  strct = [(id <Proto2>)varId getStruct3]; /* { dg-warning "receiver of type .id \\<Proto2\\>. may not respond to .\\-getStruct3." } */
  strct = [(id <Proto2>)varId getStruct4];
  strct = [(Class4 <Proto1> *)varId getStruct3];
  strct = [(Class4 <Proto1> *)varId getStruct4];
  strct = [(Class4 <Proto2> *)varId getStruct3];
  strct = [(Class4 <Proto2> *)varId getStruct4];
}

/* Category declares method. */

@interface Class5
+ (Class5 *)class5;
@end
@interface Class5 (Category1)
- (MyStruct)getStruct5;
@end

void foo5(void)
{
  MyStruct strct;
  Class5  *varClass5;
  id       varId;

  strct = [[Class5 class5] getStruct5];
  strct = [Class5 getStruct5];

  varClass5 = [Class5 class5];
  strct = [varClass5 getStruct5];

  varId = [Class5 class5];
  strct = [(Class5 *)varId getStruct5];
}  

/* Category is inherited.  */
@interface Class6 : Class5
+ (Class6 *)class6;
@end
@interface Class6 (Category2)
- (MyStruct)getStruct6;
@end

void foo6(void)
{
  MyStruct strct;
  Class6  *varClass6;
  id       varId;

  strct = [[Class6 class6] getStruct5];
  strct = [Class6 getStruct5];
  strct = [[Class6 class6] getStruct6];
  strct = [Class6 getStruct6]; /* { dg-warning "receiver of type .Class6. may not respond to .\\+getStruct6." } */
  /* { dg-warning "no prototype found for .\\+getStruct6." "" { target *-*-* } 216 } */
  /* { dg-error "incompatible types in assignment" "" { target *-*-* } 216 } */

  varClass6 = [Class6 class6];
  strct = [varClass6 getStruct5];
  strct = [varClass6 getStruct6];

  varId = [Class6 class6];
  strct = [(Class6 *)varId getStruct5];
  strct = [(Class6 *)varId getStruct6];
}  

/* Category's protocol declares method. */

@protocol Proto3
- (MyStruct)getStruct7;
@end
@interface Class7
+ (Class7 *)class7;
+ (id<Proto3>)class7Proto3;
+ (Class7<Proto3> *)class7Proto3Class7;
@end
@interface Class7 (Category3) <Proto3>
@end

void foo7(void)
{
  MyStruct        strct;
  Class7         *varClass7;
  id<Proto3>      varProto3;
  Class7<Proto3> *varClass7Proto3;
  id              varId;

  strct = [[Class7 class7] getStruct7];
  strct = [Class7 getStruct7];

  strct = [[Class7 class7] getStruct7];
  strct = [[Class7 class7Proto3] getStruct7];
  strct = [[Class7 class7Proto3Class7] getStruct7];

  varClass7 = [Class7 class7];
  strct = [varClass7 getStruct7];
  varProto3 = [Class7 class7Proto3];
  strct = [varProto3 getStruct7];
  varClass7Proto3 = [Class7 class7Proto3Class7];
  strct = [varClass7Proto3 getStruct7];

  varId = [Class7 class7];
  strct = [(Class7 *)varId getStruct7];
  strct = [(id<Proto3>)varId getStruct7];
  strct = [(Class7<Proto3>*)varId getStruct7];
}  

/* Inherited category's protocol declares method. */

@interface Class8 : Class7
+ (Class8 *)class8;
+ (Class8 <Proto3> *)class8Proto3Class7;
@end

void foo8(void)
{
  MyStruct        strct;
  Class8         *varClass8;
  Class8<Proto3> *varClass8Proto3;
  id              varId;

  strct = [[Class8 class8] getStruct7];
  strct = [Class8 getStruct7];

  strct = [[Class8 class8] getStruct7];
  strct = [[Class8 class8Proto3Class7] getStruct7];

  varClass8 = [Class8 class8];
  strct = [varClass8 getStruct7];
  varClass8Proto3 = [Class8 class8Proto3Class7];
  strct = [varClass8Proto3 getStruct7];

  varId = [Class8 class8];
  strct = [(Class8 *)varId getStruct7];
  strct = [(Class8<Proto3>*)varId getStruct7];
}  

/* Inherited Protocol declares method.  */

@protocol Proto4 <Proto3>
- (MyStruct)getStruct9;
@end

@interface Class9 <Proto4>
+ (Class9 *)class9;
+ (id<Proto4>)class9Proto4id;
+ (Class9<Proto4> *)class9Proto4Class9;
+ (Class0<Proto4> *)class9Proto4Class0;
@end

void foo9(void)
{
  MyStruct strct;
  Class9          *varClass9;
  id <Proto4>      varProto4;
  Class9 <Proto4> *varClass9Proto4;
  Class0 <Proto4> *varClass0Proto4;
  id              varId;

  strct = [[Class9 class9] getStruct7];
  strct = [Class9 getStruct9];

  strct = [[Class9 class9Proto4id] getStruct7];
  strct = [[Class9 class9Proto4Class9] getStruct7];
  strct = [[Class9 class9Proto4Class0] getStruct7];

  varClass9 = [Class9 class9];
  strct = [varClass9 getStruct7];

  varProto4 = [Class9 class9Proto4id];
  strct = [varProto4 getStruct7];

  varClass9Proto4 = [Class9 class9Proto4Class9];
  strct = [varClass9Proto4 getStruct7];

  varClass0Proto4 = [Class9 class9Proto4Class0];
  strct = [varClass0Proto4 getStruct7];

  varId = [Class9 class9];
  strct = [(Class9 *)varId getStruct7];
  strct = [(id <Proto4>)varId getStruct7];
  strct = [(Class9 <Proto4> *)varId getStruct7];
  strct = [(Class0 <Proto4> *)varId getStruct7];
}

/* Implicit local declaraions in class.  */

@interface Class10
@end
@implementation Class10
-(MyStruct)getStruct10
{
  MyStruct strct = { 1UL, 1UL, 1UL };
  return strct;
}
-(void)useInInstance10
{
  MyStruct strct;
  Class10 *varClass10 = self;
  id       varId = self;

  strct = [self getStruct10];
  strct = [varClass10 getStruct10];
  strct = [(Class10 *)varId getStruct10];
}
+(void)useInClass10
{
  MyStruct strct;
  strct = [self getStruct10];
}
@end

/* Implicit local declaraions in category.  */

@implementation Class10 (Category4)
-(MyStruct)getStruct11
{
  MyStruct strct = { 1UL, 1UL, 1UL };
  return strct;
}
-(void)useInInstance11
{
  MyStruct strct;
  Class10 *varClass10 = self;
  id       varId = self;

  strct = [self getStruct11];
  strct = [varClass10 getStruct11];
  strct = [(Class10 *)varId getStruct11];
}
+(void)useInClass11
{
  MyStruct strct;
  strct = [self getStruct11];
}
@end


/* Check for finding the prototype
   when there multiple identical available. */
/* Contributed by David Ayers <d.ayers@inode.at>
and Alexander Malmberg <alexander@malmberg.org> */
/* { dg-do compile } */

#include <objc/Object.h>

struct _MyStruct
{
  unsigned long a;
  unsigned long b;
  unsigned long c;
};
typedef struct _MyStruct MyStruct;

/* Protocol from Inherited class declares method.  */

@protocol Proto1
- (MyStruct)getStruct;
@end

/* Class declares method directly.  */
@interface Class1 <Proto1>
- (MyStruct)getStruct;
@end

/* Protocol declares method.  */
@protocol Proto2
- (MyStruct)getStruct;
@end

/* Superclass declares method.  */
@interface Class2 : Class1 <Proto2>
- (MyStruct)getStruct;
+ (Class2 *)class2;
@end

@interface Class2 (Category1)
- (MyStruct)getStruct;
@end

/* Category is inherited.  */
@interface Class1 (Category2)
- (MyStruct)getStruct;
@end

/* Category's protocol declares method. */

@protocol Proto3
- (MyStruct)getStruct;
@end
@interface Class2 (Category3) <Proto3>
@end

/* Inherited category's protocol declares method. */

@protocol Proto4
- (MyStruct)getStruct;
@end
@interface Class1 (Category4) <Proto4>
@end

/* Implicit local declaraions in class.  */

@implementation Class2
+(Class2 *)class2
{
  return nil;
}
-(MyStruct)getStruct
{
  MyStruct strct = { 1UL, 1UL, 1UL };
  return strct;
}
-(void)useInInstance
{
  MyStruct strct;
  strct = [self getStruct];
}
@end

/* Implicit local declaraions in category.  */

@implementation Class2 (Category5)
-(MyStruct)getStruct
{
  MyStruct strct = { 1UL, 1UL, 1UL };
  return strct;
}
-(void)useInInstance2
{
  MyStruct strct;
  strct = [self getStruct];
}
@end

void foo1(void)
{
  MyStruct strct;
  Class2  *varClass2;
  id       varId;

  strct = [[Class2 class2] getStruct];
  strct = [Class2 getStruct];

  varClass2 = [Class2 class2];
  strct = [varClass2 getStruct];

  varId = [Class2 class2];
  strct = [(Class2 *)varId getStruct];
}



/* Check for finding the prototype
   when there multiple conflicting available. */
/* Contributed by David Ayers <d.ayers@inode.at>
and Alexander Malmberg <alexander@malmberg.org> */
/* { dg-do compile } */

#include <objc/Object.h>

typedef struct { unsigned long a1; } MyStruct1;
typedef struct { unsigned long a1; } MyStruct2;
typedef struct { unsigned long a1; } MyStruct3;
typedef struct { unsigned long a1; } MyStruct4;
typedef struct { unsigned long a1; } MyStruct5;
typedef struct { unsigned long a1; } MyStruct6;
typedef struct { unsigned long a1; } MyStruct7;
typedef struct { unsigned long a1; } MyStruct8;
typedef struct { unsigned long a1; } MyStruct9;
typedef struct { unsigned long a1; } MyStruct10;
typedef struct { unsigned long a1; } MyStruct11;

/* Protocol from Inherited class declares method.  */

@protocol Proto1
- (MyStruct1)getStruct1;
@end

/* Class declares method directly.  */
@interface Class1 <Proto1>
+ (Class1 *)class1;
- (MyStruct2)getStruct1;
@end

/* Protocol declares method.  */
@protocol Proto2
- (MyStruct3)getStruct1;
@end

/* Superclass declares method.  */
@interface Class2 : Class1 <Proto2>
- (MyStruct4)getStruct1;
@end

@interface Class2 (Category1)
- (MyStruct5)getStruct1;
@end

/* Category is inherited.  */
@interface Class1 (Category2)
- (MyStruct6)getStruct1;
@end

/* Category's protocol declares method. */

@protocol Proto3
- (MyStruct7)getStruct1;
@end
@interface Class2 (Category3) <Proto3>
@end

/* Inherited category's protocol declares method. */

@protocol Proto4
- (MyStruct8)getStruct1;
@end
@interface Class1 (Category4) <Proto4>
@end

@protocol Proto5 <Proto4>
- (MyStruct9)getStruct1;
@end

/* Implicit local declaraions in class.  */

@implementation Class2
-(MyStruct10)getStruct1
{ /* { dg-warning "multiple methods named .\\-getStruct1. found for receiver of type .Class2." } */
/* { dg-warning "using .\\-\\(MyStruct4\\)getStruct1." "" { target *-*-* } 40 } */
/* { dg-warning "instead of .\\-\\(MyStruct7\\)getStruct1." "" { target *-*-* } 55 } */
/* { dg-warning "or .\\-\\(MyStruct5\\)getStruct1." "" { target *-*-* } 44 } */
/* { dg-warning "or .\\-\\(MyStruct3\\)getStruct1." "" { target *-*-* } 35 } */
/* { dg-warning "or .\\-\\(MyStruct2\\)getStruct1." "" { target *-*-* } 30 } */
/* { dg-warning "or .\\-\\(MyStruct8\\)getStruct1." "" { target *-*-* } 63 } */
/* { dg-warning "or .\\-\\(MyStruct6\\)getStruct1." "" { target *-*-* } 49 } */
/* { dg-warning "or .\\-\\(MyStruct1\\)getStruct1." "" { target *-*-* } 24 } */
  MyStruct10 strct = { 1UL };
  return strct;
}
-(void)useInInstance
{
  MyStruct1 strct;
  strct = [self getStruct1]; /* { dg-warning "multiple methods named .\\-getStruct1. found for receiver of type .Class2." } */
/* { dg-warning "or .\\-\\(MyStruct10\\)getStruct1." "" { target *-*-* } 76 } */
/* { dg-error "incompatible types in assignment" "" { target *-*-* } 91 } */
}
@end

/* Implicit local declaraions in category.  */

@implementation Class1 (Category5)
-(MyStruct11)getStruct1
{ /* { dg-warning "multiple methods named .\\-getStruct1. found for receiver of type .Class1." } */
/* { dg-warning "using .\\-\\(MyStruct2\\)getStruct1." "" { target *-*-* } 30 } */
/* { dg-warning "instead of .\\-\\(MyStruct8\\)getStruct1." "" { target *-*-* } 63 } */
  MyStruct11 strct = { 1UL };
  return strct;
}
-(void)useInInstance2
{
  MyStruct1 strct;
  strct = [self getStruct1]; /* { dg-warning "multiple methods named .\\-getStruct1. found for receiver of type .Class1." } */
/* { dg-warning "or .\\-\\(MyStruct11\\)getStruct1." "" { target *-*-* } 101 } */
/* { dg-error "incompatible types in assignment" "" { target *-*-* } 110 } */
}
@end

void foo1(void)
{
  MyStruct1 strct;
  Class1  *varClass1;
  id       varId;

  strct = [[Class1 class1] getStruct1]; /* { dg-warning "multiple methods named .\\-getStruct1. found for receiver of type .Class1." } */
/* { dg-error "incompatible types in assignment" "" { target *-*-* } 122 } */

  strct = [Class1 getStruct1]; /* { dg-warning "multiple methods named .\\-getStruct1. found for receiver of type .Class1." } */
/* { dg-error "incompatible types in assignment" "" { target *-*-* } 125 } */

  varClass1 = [Class1 class1];
  strct = [varClass1 getStruct1]; /* { dg-warning "multiple methods named .\\-getStruct1. found for receiver of type .Class1." } */
/* { dg-error "incompatible types in assignment" "" { target *-*-* } 129 } */


  varId = [Class1 class1];
  strct = [(Class1 *)varId getStruct1]; /* { dg-warning "multiple methods named .\\-getStruct1. found for receiver of type .Class1." } */
/* { dg-error "incompatible types in assignment" "" { target *-*-* } 134 } */
}


/* Check for finding the prototype
   when there multiple conflicting available. */
/* Contributed by David Ayers <d.ayers@inode.at>
and Alexander Malmberg <alexander@malmberg.org> */
/* { dg-do compile } */

#include <objc/Object.h>

@class ClassA;
@class ClassB;

@interface Class1
- (ClassA *)getObject;
+ (Class1 *)class1;
+ (id)new;
@end

@interface Class2
- (ClassB *)getObject;
+ (Class2 *)class2;
+ (id)new;
@end

void foo1(void)
{
  Class1 *varClass1;
  Class2 *varClassB;
  id      varId = nil;

  ClassA *objA;
  ClassB *objB;
  id      objId;

  varClass1 = [Class1 class1];
  objA = [[Class1 class1] getObject];
  objA = [[Class1 new] getObject]; /* { dg-warning "multiple methods named .\\-getObject. found" } */
/* { dg-warning "using .\\-\\(ClassA \\*\\)getObject." "" { target *-*-* } 13 } */
/* { dg-warning "also found .\\-\\(ClassB \\*\\)getObject." "" { target *-*-* } 19 } */
  objA = [Class1 getObject];
  objA = [varClass1 getObject];

  varClassB = [Class2 class2];
  objB = [[Class2 class2] getObject];
  objB = [[Class2 new] getObject]; /* { dg-warning "multiple methods named .\\-getObject. found" } */
/* { dg-warning "assignment from incompatible pointer type"  "" { target *-*-* } 44 } */
  objB = [Class2 getObject];
  objB = [varClassB getObject];

  objId = [varId getObject]; /* { dg-warning "multiple methods named .\\-getObject. found" } */
  objId = [(Class1 *)varId getObject];
  objId = [(Class2 *)varId getObject];

  objA = [varClassB getObject]; /* { dg-warning "assignment from incompatible pointer type" } */
  objB = [varClass1 getObject]; /* { dg-warning "assignment from incompatible pointer type" } */
  objA = [(Class1 *)varClassB getObject];
  objB = [(Class2 *)varClass1 getObject];

}

@class ClassC;

@interface Class3 : Class1
- (ClassC *)getObject;
+ (Class3 *)class3;
@end

void foo2(void)
{
  ClassA   *varClassA;
  ClassC   *varClassC;
  id        varId = nil;

  id        objId;

  varClassA = [[Class3 class3] getObject]; /* { dg-warning "multiple methods named .\\-getObject. found for receiver of type .Class3  \\*." } */
/* { dg-warning "using .\\-\\(ClassC \\*\\)getObject." "" { target *-*-* } 63 } */
/* { dg-warning "instead of .\\-\\(ClassA \\*\\)getObject." "" { target *-*-* } 13 } */
/* { dg-warning "assignment from incompatible pointer type"  "" { target *-*-* } 75 } */
  varClassC = [[Class3 class3] getObject]; /* { dg-warning "multiple methods named .\\-getObject. found for receiver of type .Class3  \\*." } */
  objId = [[Class3 class3] getObject];  /* { dg-warning "multiple methods named .\\-getObject. found for receiver of type .Class3  \\*." } */

  varClassA = [[Class3 new] getObject]; /* { dg-warning "multiple methods named .\\-getObject. found" } */
/* { dg-warning "also found .\\-\\(ClassC \\*\\)getObject." "" { target *-*-* } 63 } */
  varClassC = [[Class3 new] getObject]; /* { dg-warning "multiple methods named .\\-getObject. found" } */
/* { dg-warning "assignment from incompatible pointer type"  "" { target *-*-* } 84 } */
  objId = [[Class3 new] getObject];  /* { dg-warning "multiple methods named .\\-getObject. found" } */

  varClassA = [Class3 getObject];
  varClassC = [Class3 getObject];  /* { dg-warning "assignment from incompatible pointer type" } */
  objId = [Class3 getObject];

  varClassA = [(Class3 *)varId getObject];  /* { dg-warning "multiple methods named .\\-getObject. found for receiver of type .Class3  \\*." } */
/* { dg-warning "assignment from incompatible pointer type"  "" { target *-*-* } 92 } */
  varClassC = [(Class3 *)varId getObject];  /* { dg-warning "multiple methods named .\\-getObject. found for receiver of type .Class3  \\*." } */

  /* Test Random/merged selection. */
  varClassA = [varId getObject];  /* { dg-warning "multiple methods named .\\-getObject. found" } */
  varClassC = [varId getObject];  /* { dg-warning "multiple methods named .\\-getObject. found" } */
/* { dg-warning "assignment from incompatible pointer type"  "" { target *-*-* } 98 } */
}

@protocol Proto1
-(id<Proto1>)getObject;
@end

@interface Class4 : Class2 <Proto1>
+ (Class4 *)class4;
@end

void foo3(void)
{
  ClassA *varClassA;
  ClassB *varClassB;
  id <Proto1> varProto1;
  id          varId = nil;
  id objId;

  varClassA = [[Class4 class4] getObject];  /* { dg-warning "multiple methods named .\\-getObject. found for receiver of type .Class4  \\*." } */
/* { dg-warning "using .\\-\\(id \\<Proto1\\>\\)getObject."  "" { target *-*-* } 103 } */
/* { dg-warning "instead of .\\-\\(ClassB \\*\\)getObject."  "" { target *-*-* } 19 } */
/* { dg-warning "assignment from incompatible pointer type"  "" { target *-*-* } 118 } */
  varClassB = [[Class4 class4] getObject];  /* { dg-warning "multiple methods named .\\-getObject. found for receiver of type .Class4  \\*." } */
/* { dg-warning "assignment from incompatible pointer type" "" { target *-*-* } 122 } */
  varProto1 = [[Class4 class4] getObject];  /* { dg-warning "multiple methods named .\\-getObject. found for receiver of type .Class4  \\*." } */
  objId = [[Class4 class4] getObject];  /* { dg-warning "multiple methods named .\\-getObject. found for receiver of type .Class4  \\*." } */

  varClassA = [[Class4 new] getObject];  /* { dg-warning "multiple methods named .\\-getObject. found" } */
/* { dg-warning "also found .\\-\\(id \\<Proto1\\>\\)getObject." "" { target *-*-* } 103 } */
  varClassB = [[Class4 new] getObject];  /* { dg-warning "multiple methods named .\\-getObject. found" } */
/* { dg-warning "assignment from incompatible pointer type"  "" { target *-*-* } 129 } */
  varProto1 = [[Class4 new] getObject];  /* { dg-warning "multiple methods named .\\-getObject. found" } */
/* { dg-warning "class .ClassA. does not implement the .Proto1. protocol"  "" { target *-*-* } 131 } */
  objId = [[Class4 new] getObject];  /* { dg-warning "multiple methods named .\\-getObject. found" } */

  varClassA = [Class4 getObject]; /* { dg-warning "assignment from incompatible pointer type" } */
  varClassB = [Class4 getObject];
  varProto1 = [Class4 getObject]; /* { dg-warning "class .ClassB. does not implement the .Proto1. protocol" } */
  objId = [Class4 getObject];

  varClassA = [(Class4 *)varId getObject]; /* { dg-warning "multiple methods named .\\-getObject. found" } */
/* { dg-warning "assignment from incompatible pointer type" "" { target *-*-* } 140 } */
  varClassB = [(Class4 *)varId getObject]; /* { dg-warning "multiple methods named .\\-getObject. found" } */
/* { dg-warning "assignment from incompatible pointer type" "" { target *-*-* } 142 } */
  varProto1 = [(Class4 *)varId getObject]; /* { dg-warning "multiple methods named .\\-getObject. found" } */
  objId = [(Class4 *)varId getObject]; /* { dg-warning "multiple methods named .\\-getObject. found" } */

  varClassA = [(id <Proto1>)varId getObject]; /* { dg-warning "assignment from incompatible pointer type" } */
  varClassB = [(id <Proto1>)varId getObject]; /* { dg-warning "assignment from incompatible pointer type" } */
  varProto1 = [(id <Proto1>)varId getObject];
  objId = [(id <Proto1>)varId getObject];

}




/* Check that instance methods in root classes are searched when sending
   messages to class objects. */
/* Contributed by Alexander Malmberg <alexander@malmberg.org>  */
/* { dg-do compile } */

#include <objc/Object.h>

@protocol Quux
-(void) protocolInstanceMethod;
+(void) protocolClassMethod;
@end

@protocol Baz
-(void) rootProtocolInstanceMethod;
@end

@interface Foo <Baz>
+(void) classMethod;
-(void) rootInstanceMethod;
@end

@interface Foo (aCategory)
-(void) rootCategoryInstanceMethod;
@end

@interface Bar : Foo
-(void) instanceMethod;
@end


Class c;
void foo(void)
{
  [c classMethod];
  [c instanceMethod];  /* { dg-warning "no prototype found for .\\+instanceMethod." } */
       /* { dg-warning "\\(Messages without a matching method prototype" "" { target *-*-* } 35 } */
       /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 35 } */
       /* { dg-warning ".\.\.\.. as arguments\.\\)" "" { target *-*-* } 35 } */
  [c rootInstanceMethod];
  [c rootCategoryInstanceMethod];  /* { dg-warning "no prototype found for .\\+rootCategoryInstanceMethod." } */
  [c protocolClassMethod];
  [c protocolInstanceMethod];  /* { dg-warning "no prototype found for .\\+protocolInstanceMethod." } */
  [c rootProtocolInstanceMethod];  /* { dg-warning "no prototype found for .\\+rootProtocolInstanceMethod." } */
}



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]