diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 54f08a250bffce09bb5bd43f0424e3970aa9ba5d..dd4814891a720473b158d9136a292e320f2bbad7 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,9 @@
+2010-11-17  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* objc-act.c (lookup_method_in_protocol_list): Search methods in
+	PROTOCOL_OPTIONAL_CLS_METHODS / PROTOCOL_OPTIONAL_NST_METHODS if
+	they are not found in PROTOCOL_CLS_METHODS / PROTOCOL_NST_METHODS.
+
 2010-11-15  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	* objc-act.c (objc_build_setter_call): New.
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index bfff1d2f110eb347f17e1338fe86cc6091656a48..96a3998221a72f0080ffeeb4b273a0cf38e2a400 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -649,30 +649,44 @@ static tree
 lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
 				int is_class)
 {
-   tree rproto, p;
-   tree fnd = 0;
+  tree rproto, p, m;
 
    for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto))
      {
-        p = TREE_VALUE (rproto);
+       p = TREE_VALUE (rproto);
+       m = NULL_TREE;
 
 	if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
 	  {
-	    if ((fnd = lookup_method (is_class
-				      ? 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, is_class);
+	    /* First, search the @required protocol methods.  */
+	    if (is_class)
+	      m = lookup_method (PROTOCOL_CLS_METHODS (p),  sel_name);
+	    else
+	      m = lookup_method (PROTOCOL_NST_METHODS (p), sel_name);
+
+	    if (m)
+	      return m;
+
+	    /* If still not found, search the @optional protocol methods.  */
+	    if (is_class)
+	      m = lookup_method (PROTOCOL_OPTIONAL_CLS_METHODS (p), sel_name);
+	    else
+	      m = lookup_method (PROTOCOL_OPTIONAL_NST_METHODS (p), sel_name);
+
+	    if (m)
+	      return m;
+
+	    /* If still not found, search the attached protocols.  */
+	    if (PROTOCOL_LIST (p))
+	      m = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
+						  sel_name, is_class);
+	    if (m)
+	      return m;
 	  }
 	else
           {
 	    ; /* An identifier...if we could not find a protocol.  */
           }
-
-	if (fnd)
-	  return fnd;
      }
 
    return 0;
@@ -8642,7 +8656,10 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional)
 {
   tree mth;
 
-  /* @optional methods are added to protocol's OPTIONAL list */
+  /* @optional methods are added to protocol's OPTIONAL list.  Note
+     that this disables checking that the methods are implemented by
+     classes implementing the protocol, since these checks only use
+     the CLASS_CLS_METHODS and CLASS_NST_METHODS.  */
   if (is_optional)
     {
       gcc_assert (TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 599a5f2f16ab573dd822aa85d8afd9884f70735a..01c6cb189c2bfde5da6e42cb54b42d02e15822f3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-11-17  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* objc.dg/protocol-optional-1.m: New.
+	* obj-c++.dg/protocol-optional-1.mm: New.
+
 2010-11-16  Richard Henderson  <rth@redhat.com>
 
 	* gcc.target/powerpc/ppc-fma-2.c: Use -ffp-contract=off.
diff --git a/gcc/testsuite/obj-c++.dg/protocol-optional-1.mm b/gcc/testsuite/obj-c++.dg/protocol-optional-1.mm
new file mode 100644
index 0000000000000000000000000000000000000000..bc4a3d07e978081000dcb89328bcf2bbda1c256c
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/protocol-optional-1.mm
@@ -0,0 +1,48 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+/* Test that @optional for @protocol works.  */
+
+@protocol MyProtocol
++ (int)classMethod;
+- (int)method;
+@optional
++ (int)optionalClassMethod;
+- (int)optionalMethod;
+@end
+
+@interface MyRootClass <MyProtocol>
+@end
+
+/* The implementation implements both the @required methods, but none
+   of the @optional ones.  There should be no warnings as the
+   @optional methods are optional. ;-)  */
+@implementation MyRootClass
++ (int)classMethod
+{
+  return 20;
+}
+- (int)method
+{
+  return 11;
+}
+@end
+
+int function (id <MyProtocol> object1,
+	      MyRootClass *object2)
+{
+  /* Test that there are no warnings if you try to use an @optional
+     method with an object of the class.  */
+  int i = 0;
+
+  i += [object1 method];
+  i += [object2 method];
+  i += [MyRootClass classMethod];
+  i += [object1 optionalMethod];
+  i += [object2 optionalMethod];
+  i += [MyRootClass optionalClassMethod];
+
+  return i;
+}
diff --git a/gcc/testsuite/objc.dg/protocol-optional-1.m b/gcc/testsuite/objc.dg/protocol-optional-1.m
new file mode 100644
index 0000000000000000000000000000000000000000..bc4a3d07e978081000dcb89328bcf2bbda1c256c
--- /dev/null
+++ b/gcc/testsuite/objc.dg/protocol-optional-1.m
@@ -0,0 +1,48 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
+/* { dg-do compile } */
+
+#include <objc/objc.h>
+
+/* Test that @optional for @protocol works.  */
+
+@protocol MyProtocol
++ (int)classMethod;
+- (int)method;
+@optional
++ (int)optionalClassMethod;
+- (int)optionalMethod;
+@end
+
+@interface MyRootClass <MyProtocol>
+@end
+
+/* The implementation implements both the @required methods, but none
+   of the @optional ones.  There should be no warnings as the
+   @optional methods are optional. ;-)  */
+@implementation MyRootClass
++ (int)classMethod
+{
+  return 20;
+}
+- (int)method
+{
+  return 11;
+}
+@end
+
+int function (id <MyProtocol> object1,
+	      MyRootClass *object2)
+{
+  /* Test that there are no warnings if you try to use an @optional
+     method with an object of the class.  */
+  int i = 0;
+
+  i += [object1 method];
+  i += [object2 method];
+  i += [MyRootClass classMethod];
+  i += [object1 optionalMethod];
+  i += [object2 optionalMethod];
+  i += [MyRootClass optionalClassMethod];
+
+  return i;
+}