discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[objc-improvements] RFC: Message passing prototype search cleanup


From: Alexander Malmberg
Subject: [objc-improvements] RFC: Message passing prototype search cleanup
Date: Thu, 04 Sep 2003 03:42:24 +0200

Hi,

I've attached my patch (for objc-act.c), a patch for the existing test
cases, and a couple of new tests of the prototype search. The patch
cleans up the code in objc-act.c related to the prototype search, and
adds a bunch of comments. It also implements the new (but, in the end,
almost unchanged) behavior, cleans up a bunch of warnings, and adds a
few new warnings.

Details (from a user pov):

* The rules for the prototype search have been changes slightly:

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, one of them will be picked
"randomly" (in practice, the search is done in a specific order, so it
isn't really random; I don't think we want users to rely on that,
though). This is ugly from some povs, but it's compatible with previous
versions of gcc, and it does the right thing in most cases (when there
are slight prototype mismatches).

If no prototype is found (which is always the case for '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.

If more than one prototype is found, the fallback prototype is used, but
people do not seem to like this change. Earlier versions would pick one
randomly (but also had problems checking prototype equality, and thus
wouldn't detect all conflicts).

(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 receiver with a known type, the
search will not stop once it's found a prototype. Instead, it will
continue in order to catch any conflicting prototypes.

I guess this will be controversial, but IMHO, this is the right thing to
do. In GNUstep, this triggers in five basic cases. One is an obvious
unintended mismatch, one is a real library issue (after seeing the
warning, constructing a test case that caused a crash was trivial), and
one looks like a conflict with a really old compatibility method. I have
not looked closely at the remaining two yet. 

Fred Kiefer said in one of the discuss-gnustep threads:
> Even one correctly reported error would make this change worthwhile.

and I'm inclined to agree.


* 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. :)


Most of the changes to the existing tests are due to differently worded
warnings, but there are also updates for the new behavior in there. With
the patch, there are still two regressions in method-7.m. I've been
staring at them for a while, but I can't see any difference between the
expected warning and the warning reported:

objc.log:
output is:
...
/usr/local/src/gcc.objc/gcc/testsuite/objc.dg/method-7.m:8: warning:
could be using `-(void)setWindow:(Object *)wdw'
/usr/local/src/gcc.objc/gcc/testsuite/objc.dg/method-7.m:12: warning: or
`-(void)setWindow:(Class1 *)window'
...
FAIL: objc.dg/method-7.m  (test for warnings, line 8)
FAIL: objc.dg/method-7.m  (test for warnings, line 12)
PASS: objc.dg/method-7.m (test for excess errors)

method-7.m:
 /* { dg-warning "could be using .\\-\\(void\\)setWindow:\\(Object
\\*\\)wdw." "" { target *-*-* } 8 } */
 /* { dg-warning "or .\\-\\(void\\)setWindow:\\(Class1 \\*\\)window." ""
{ target *-*-* } 12 } */


I wrote the gcc patch, and David Ayers and I wrote and updated test
cases. Since it's late here, I won't comment any more until tomorrow
(after the first wave of flames :), but we have looked at all the test
changes, and we think they are correct.

- Alexander Malmberg
? ChangeLog
? diff_2003_08_25-2003_08_27
? objc-act.c.4-5.diff
? objc-act.c.5-6.diff
? objc-act.c.6-7.diff
? objc-act.c.alex
? objc-act.c.clean.7
? objc-act.c.log
? objc-act.h.1-2.diff
Index: objc-act.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.179.2.9
diff -u -r1.179.2.9 objc-act.c
--- objc-act.c  3 Sep 2003 00:14:27 -0000       1.179.2.9
+++ objc-act.c  4 Sep 2003 00:47:57 -0000
@@ -151,6 +151,7 @@
 static void build_selector_template            PARAMS ((void));
 static void build_category_template            PARAMS ((void));
 static tree lookup_method_in_hash_lists                PARAMS ((tree));
+static void add_method_to_hash_list            PARAMS ((hash *, tree));
 static void build_super_template               PARAMS ((void));
 static tree build_category_initializer         PARAMS ((tree, tree, tree,
                                                       tree, tree, tree));
@@ -188,7 +189,6 @@
 static hash hash_lookup                                PARAMS ((hash *, tree));
 static void hash_add_attr                      PARAMS ((hash, tree));
 static tree lookup_method                      PARAMS ((tree, tree));
-static tree lookup_method_static               PARAMS ((tree, tree, int));
 static tree add_class                          PARAMS ((tree));
 static void add_category                       PARAMS ((tree, tree));
 
@@ -206,6 +206,23 @@
 static tree build_objc_string_decl             PARAMS ((enum string_section));
 static tree build_selector_reference_decl      PARAMS ((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 tree current_found_prototype;
+static int num_found_prototypes;
+
+static void prototype_search_start             PARAMS ((const char *));
+static void prototype_search_end               PARAMS ((void));
+static void prototype_found                    PARAMS ((tree));
+static void lookup_method_static               PARAMS ((tree, tree, int));
+static void lookup_method_in_protocol_list     PARAMS ((tree, tree, int));
+
 /* Protocol additions.  */
 
 static tree add_protocol                       PARAMS ((tree));
@@ -248,7 +265,6 @@
 /* Everything else.  */
 
 static tree define_decl                                PARAMS ((tree, tree));
-static tree lookup_method_in_protocol_list     PARAMS ((tree, tree, int));
 static tree lookup_protocol_in_reflist         PARAMS ((tree, tree));
 static tree create_builtin_decl                        PARAMS ((enum tree_code,
                                                       tree, const char *));
@@ -574,41 +590,6 @@
 }
 
 static tree
-lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
-   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 (rproto_list, lproto)
      tree rproto_list;
      tree lproto;
@@ -5625,6 +5606,7 @@
   return meth;
 }
 
+
 /* If RECEIVER is a class reference, return the identifier node for
    the referenced class.  RECEIVER is created by get_class_reference,
    so we check the exact form created depending on which runtimes are
@@ -5785,6 +5767,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).  */
@@ -5805,12 +5791,22 @@
      @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).  */
+  /* 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) 
        {
@@ -5821,41 +5817,54 @@
              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))
-            : 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 one of them "randomly" (we use the
+     first one we find, so it's actually well defined; however, we don't
+     want users to rely on this).
+
+     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 the fallback prototype. */
+
+  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);
       /* Traverse typedef aliases */
@@ -5863,87 +5872,165 @@
             && 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) 
+         || 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 (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 (!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;
        }
-    }    
-
-  if (!method_prototype)
+    }
+  else if (rtype && IS_ID (rtype))
     {
-      static bool warn_missing_methods = false;
+      rprotos = TYPE_PROTOCOL_LIST (rtype);
+    }
 
-      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 ? '+' : '-'),
-                IDENTIFIER_POINTER (sel_name));
-      if (!warn_missing_methods)
-       {
-         warning ("(Messages without a matching method signature");
-         warning ("will be assumed to return `id' and accept");
-         warning ("`...' as arguments.)");
-         warn_missing_methods = true;
-       }
+  /* Now look in the protocol list.  */
+  if (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 (method_prototype == objc_ellipsis_node)
+  else if (num_found_prototypes > 1)
     {
       static bool warn_ambiguous_methods = false;
 
+      /* We found more than one. prototype_found() will already have issued
+        warnings. We set method_prototype to the first one and, if this is
+        the first conflict in this unit, issue another warning to explain
+        what we'll do. */
+      method_prototype = current_found_prototype;
+
       if (!warn_ambiguous_methods)
        {
-         warning ("(Messages matching multiple method signatures");
-         warning ("will be assumed to return `id' and accept");
-         warning ("`...' as arguments.)");
+         warning ("(When multiple prototypes are found for a receiver type, 
one");
+         warning ("of them will be picked randomly (but deterministically).)");
          warn_ambiguous_methods = true;
        }
-      method_prototype = NULL_TREE;
+    }
+  else
+    {
+      /* The type information didn't give us any prototypes. Thus, we check if
+        there are any known prototypes at all. */
+
+      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));
+
+      method_prototype
+       = (is_class
+          ? check_duplicates (hash_lookup (cls_method_hash_list, sel_name))
+          : lookup_method_in_hash_lists (sel_name));
+
+      if (!method_prototype)
+       {
+         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;
+           }
+       }
+      else if (method_prototype == objc_ellipsis_node)
+       {
+         /* More than one prototype was found. */
+         static bool warn_ambiguous_methods = false;
+
+         if (!warn_ambiguous_methods)
+           {
+             warning ("(Messages matching multiple method prototypes");
+             warning ("will be assumed to return `id' and accept");
+             warning ("`...' as arguments.)");
+             warn_ambiguous_methods = true;
+           }
+         method_prototype = NULL_TREE;
+       }
     }
 
   /* Save the selector name for printing error messages.  */
@@ -6325,29 +6412,64 @@
   entry->list = obj;           /* append to front */
 }
 
-static tree
-lookup_method (mchain, method)
-     tree mchain;
-     tree method;
+static 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 (type)
+    const char *type;
 {
-  tree key;
+  prototype_search_type = type;
+  num_found_prototypes = 0;
+  current_found_prototype = 0;
+}
 
-  if (TREE_CODE (method) == IDENTIFIER_NODE)
-    key = method;
-  else
-    key = METHOD_SEL_NAME (method);
+static void
+prototype_search_end ()
+{
+  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 (prototype)
+    tree prototype;
+{
+  /* If we've found exactly one prototype, and the new prototype is
+     identical, do nothing. */
+  if (num_found_prototypes == 1
+      && comp_proto_with_proto (prototype, current_found_prototype))
+    return;
+
+  num_found_prototypes++;
+  if (num_found_prototypes > 1)
     {
-      if (METHOD_SEL_NAME (mchain) == key)
-       return mchain;
+      char type = (TREE_CODE (prototype) == INSTANCE_METHOD_DECL) ? '-' : '+';
 
-      mchain = TREE_CHAIN (mchain);
+      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 (interface, ident, is_class)
      tree interface;
      tree ident;
@@ -6361,47 +6483,127 @@
       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);
 
-      /* 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);
 
-         /* 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 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);
        }
 
-      /* 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 (rproto_list, sel_name, class_meth)
+   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);
+             }
+           /* Check the protocols this protocol inherits from. */
+           if (PROTOCOL_LIST (p))
+             lookup_method_in_protocol_list (PROTOCOL_LIST (p),
+                                                   sel_name, class_meth);
+         }
+     }
+}
+
+static tree
+lookup_method (mchain, 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_list, method)
+  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
@@ -6411,7 +6613,6 @@
      int is_class;
 {
   tree mth;
-  hash hsh;
 
   if (!(mth = lookup_method (is_class ? CLASS_CLS_METHODS (class) : 
CLASS_NST_METHODS (class), method)))
     {
@@ -6429,10 +6630,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))
@@ -6440,23 +6642,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;
 }
 
@@ -7994,17 +8194,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 any prototypes, check that the implementation matches
+        the first one (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);
        }
     }
 }
? duplicate-implemenations.m
? missing-interface.m
? prototype-1.m
? prototype-2.m
? prototype-3.m
? prototype-4.m
? prototype-5.m
? prototype-6.m
Index: call-super-2.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/Attic/call-super-2.m,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 call-super-2.m
--- call-super-2.m      26 Aug 2003 23:33:25 -0000      1.1.2.2
+++ call-super-2.m      4 Sep 2003 01:30:49 -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: desig-init-1.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/desig-init-1.m,v
retrieving revision 1.1.34.1
diff -u -r1.1.34.1 desig-init-1.m
--- desig-init-1.m      26 Aug 2003 23:33:25 -0000      1.1.34.1
+++ desig-init-1.m      4 Sep 2003 01:30:49 -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: method-2.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/method-2.m,v
retrieving revision 1.1.60.2
diff -u -r1.1.60.2 method-2.m
--- method-2.m  26 Aug 2003 23:33:25 -0000      1.1.60.2
+++ method-2.m  4 Sep 2003 01:30:49 -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: method-5.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/Attic/method-5.m,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 method-5.m
--- method-5.m  26 Aug 2003 23:33:25 -0000      1.1.2.2
+++ method-5.m  4 Sep 2003 01:30:49 -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: method-6.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/Attic/method-6.m,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 method-6.m
--- method-6.m  26 Aug 2003 23:33:25 -0000      1.1.2.2
+++ method-6.m  4 Sep 2003 01:30:49 -0000
@@ -5,22 +5,38 @@
 #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 "could be using .\\-\\(unsigned\\)port1." "" { target 
*-*-* } 8 } */
+       /* { dg-warning "or .\\-\\(Protocol \\*\\)port1." "" { target *-*-* } 
14 } */
+       /* { dg-warning "\\(Messages matching multiple method prototypes" "" { 
target *-*-* } 22 } */
+       /* { dg-warning "will be assumed to return .id. and accept" "" { target 
*-*-* } 22 } */
+       /* { dg-warning ".\.\.\.. as arguments\.\\)" "" { 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 *-*-* } 29 } */
+       /* { dg-warning "will be assumed to return .id. and accept" "" { target 
*-*-* } 29 } */
+       /* { dg-warning ".\.\.\.. as arguments\.\\)" "" { target *-*-* } 29 } */
+  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 } */
+       /* { dg-warning "\\(When multiple prototypes are found for a receiver 
type\\, one" "" { target *-*-* } 35 } */
+       /* { dg-warning "" "" { target *-*-* } 35 } */
+  p2 = [Derived port2];  /* No warning, using class method */
+  return p1;
 }
Index: method-7.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/Attic/method-7.m,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 method-7.m
--- method-7.m  26 Aug 2003 23:33:25 -0000      1.1.2.2
+++ method-7.m  4 Sep 2003 01:30:49 -0000
@@ -15,16 +15,16 @@
 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 } */
+  [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 "could be using .\\-\\(void\\)setWindow:\\(Object 
\\*\\)wdw." "" { target *-*-* } 8 } */
+       /* { dg-warning "or .\\-\\(void\\)setWindow:\\(Class1 \\*\\)window." "" 
{ target *-*-* } 12 } */
+       /* { dg-warning "Messages matching multiple method prototypes" "" { 
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" } */
        /* { dg-warning "could be using .\\-\\(void\\)setWindow:\\(Object 
\\*\\)wdw." "" { target *-*-* } 8 } */
        /* { dg-warning "or .\\-\\(void\\)setWindow:\\(Class1 \\*\\)window." "" 
{ target *-*-* } 12 } */
-       /* { dg-warning "Messages matching multiple method signatures" "" { 
target *-*-* } 22 } */
-       /* { dg-warning "will be assumed to return .id. and accept" "" { target 
*-*-* } 22 } */
-       /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 22 } */
 
   return obj;
 }
Index: method-9.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/Attic/method-9.m,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 method-9.m
--- method-9.m  26 Aug 2003 23:33:25 -0000      1.1.2.2
+++ method-9.m  4 Sep 2003 01:30:49 -0000
@@ -35,7 +35,7 @@
      /* { dg-warning "could be using .\\-\\(id\\)initWithData:\\(Object 
\\*\\)data." "" { target *-*-* } 9 } */
      /* { dg-warning "or .\\-\\(id\\)initWithData:\\(id <MyObject, 
MyCoding>\\)data." "" { target *-*-* } 17 } */
      /* { dg-warning "or .\\-\\(id\\)initWithData:\\(int\\)data." "" { target 
*-*-* } 13 } */
-     /* { dg-warning "\\(Messages matching multiple method signatures" "" { 
target *-*-* } 33 } */
+     /* { dg-warning "\\(Messages matching multiple method prototypes" "" { 
target *-*-* } 33 } */
      /* { dg-warning "will be assumed to return .id. and accept" "" { target 
*-*-* } 33 } */
      /* { dg-warning ".\.\.\.. as arguments\.\\)" "" { target *-*-* } 33 } */
 
Index: proto-hier-1.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/proto-hier-1.m,v
retrieving revision 1.1.64.2
diff -u -r1.1.64.2 proto-hier-1.m
--- proto-hier-1.m      26 Aug 2003 23:33:25 -0000      1.1.64.2
+++ proto-hier-1.m      4 Sep 2003 01:30: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: proto-lossage-1.m
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/testsuite/objc.dg/proto-lossage-1.m,v
retrieving revision 1.1.32.1
diff -u -r1.1.32.1 proto-lossage-1.m
--- proto-lossage-1.m   26 Aug 2003 23:33:25 -0000      1.1.32.1
+++ proto-lossage-1.m   4 Sep 2003 01:30: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" 
} */
/* Check that missing @interface warnings are reported properly. */
/* Contributed by Alexander Malmberg <address@hidden>  */
/* { 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 <address@hidden>  */
/* { 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 <address@hidden>
and Alexander Malmberg <address@hidden> */
/* { 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 <address@hidden>
and Alexander Malmberg <address@hidden> */
/* { 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-warning "\\(When multiple prototypes are found for a receiver type\\, 
one" "" { target *-*-* } 91 } */
/* { dg-warning "of them will be picked randomly \\(but 
deterministically\\)\\.\\)" "" { target *-*-* } 91 } */
/* { 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 *-*-* } 103 } 
*/
/* { dg-error "incompatible types in assignment" "" { target *-*-* } 112 } */
}
@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 *-*-* } 124 } */

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

  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 *-*-* } 131 } */


  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 *-*-* } 136 } */
}

/* Check for finding the prototype
   when there multiple conflicting available. */
/* Contributed by David Ayers <address@hidden>
and Alexander Malmberg <address@hidden> */
/* { 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 "could be using .\\-\\(ClassA \\*\\)getObject." "" { target 
*-*-* } 13 } */
/* { dg-warning "or .\\-\\(ClassB \\*\\)getObject." "" { target *-*-* } 19 } */
/* { dg-warning "\\(Messages matching multiple method prototypes" "" { target 
*-*-* } 36 } */
/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 
36 } */
/* { dg-warning ".\\.\\.\\.. as arguments\\.\\)" "" { target *-*-* } 36 } */
  objA = [Class1 getObject];
  objA = [varClass1 getObject];

  varClassB = [Class2 class2];
  objB = [[Class2 class2] getObject];
  objB = [[Class2 new] getObject]; /* { dg-warning "multiple methods named 
.\\-getObject. found" } */
  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 *-*-* } 65 } 
*/
/* { dg-warning "instead of .\\-\\(ClassA \\*\\)getObject." "" { target *-*-* } 
13 } */
/* { dg-warning "\\(When multiple prototypes are found for a receiver type\\, 
one" "" { target *-*-* } 77 } */
/* { dg-warning "of them will be picked randomly \\(but 
deterministically\\)\\.\\)" "" { target *-*-* } 77 }*/
/* { dg-warning "assignment from incompatible pointer type"  "" { target *-*-* 
} 77 } */
  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 "or .\\-\\(ClassC \\*\\)getObject." "" { target *-*-* } 65 } */
  varClassC = [[Class3 new] getObject]; /* { dg-warning "multiple methods named 
.\\-getObject. found" } */
  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 *-*-* 
} 95 } */
  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" } */

} 

@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 *-*-* 
} 106 } */
/* { dg-warning "instead of .\\-\\(ClassB \\*\\)getObject."  "" { target *-*-* 
} 19 } */
/* { dg-warning "assignment from incompatible pointer type"  "" { target *-*-* 
} 121 } */
  varClassB = [[Class4 class4] getObject];  /* { dg-warning "multiple methods 
named .\\-getObject. found for receiver of type .Class4  \\*." } */
/* { dg-warning "assignment from incompatible pointer type" "" { target *-*-* } 
125 } */
  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 "or .\\-\\(id \\<Proto1\\>\\)getObject." "" { target *-*-* } 
106 } */
  varClassB = [[Class4 new] getObject];  /* { dg-warning "multiple methods 
named .\\-getObject. found" } */
  varProto1 = [[Class4 new] getObject];  /* { dg-warning "multiple methods 
named .\\-getObject. found" } */
  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 *-*-* } 
141 } */
  varClassB = [(Class4 *)varId getObject]; /* { dg-warning "multiple methods 
named .\\-getObject. found" } */
/* { dg-warning "assignment from incompatible pointer type" "" { target *-*-* } 
143 } */
  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 <address@hidden>  */
/* { 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." } */
}


reply via email to

[Prev in Thread] Current Thread [Next in Thread]