From patchwork Fri Dec 31 11:15:33 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicola Pero X-Patchwork-Id: 77061 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 064F41007D4 for ; Fri, 31 Dec 2010 22:15:53 +1100 (EST) Received: (qmail 21928 invoked by alias); 31 Dec 2010 11:15:52 -0000 Received: (qmail 21913 invoked by uid 22791); 31 Dec 2010 11:15:50 -0000 X-SWARE-Spam-Status: No, hits=-1.4 required=5.0 tests=AWL, BAYES_00, TW_BJ, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from fencepost.gnu.org (HELO fencepost.gnu.org) (140.186.70.10) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 31 Dec 2010 11:15:43 +0000 Received: from eggs.gnu.org ([140.186.70.92]:50797) by fencepost.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1PYcxN-0002qI-DX for gcc-patches@gnu.org; Fri, 31 Dec 2010 06:15:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PYcxO-0005jR-Vy for gcc-patches@gnu.org; Fri, 31 Dec 2010 06:15:40 -0500 Received: from smtp141.iad.emailsrvr.com ([207.97.245.141]:51629) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PYcxO-0005jM-M7 for gcc-patches@gnu.org; Fri, 31 Dec 2010 06:15:38 -0500 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp34.relay.iad1a.emailsrvr.com (SMTP Server) with ESMTP id 060473805F0 for ; Fri, 31 Dec 2010 06:15:38 -0500 (EST) Received: by smtp34.relay.iad1a.emailsrvr.com (Authenticated sender: nicola.pero-AT-meta-innovation.com) with ESMTPA id 5F730380248 for ; Fri, 31 Dec 2010 06:15:37 -0500 (EST) Message-Id: From: Nicola Pero To: gcc-patches@gnu.org Mime-Version: 1.0 (Apple Message framework v936) Subject: ObjC/ObjC++: extend fix of PR objc/47076 ("Protocol referenced in @interface declarations should be defined") Date: Fri, 31 Dec 2010 12:15:33 +0100 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch is a sophistication of the fix to PR objc/47076, and fixes a slightly more complicated case. In objc/47076, we fixed the detection that a protocol was only forward- declared, ie, the testcase @protocol A; @interface MyClass @end this testcase should cause a warning, because protocol A is forward- declared, ie, it has been declared that A is a protocol without providing the list of methods required/ optional for it; but when A is used in the declaration of MyClass, the compiler needs the list of methods to properly process MyClass to do all the checks and things required. So, the compiler does (now) correctly warn in this case. What we didn't cover was the complication @protocol A; @protocol B - (void)method; @end @interface MyClass @end In this case, protocol B, which is directly referenced by MyClass, is a normal, declared protocol with a list of methods. But, it is also specified that B conforms to A, which is another protocol, this time forward-declared. So, again, the compiler won't have the full list of methods required/optional for the protocols that MyClass is declared to implement, and won't be able to perform all the expected checks and stuff on MyClass. It should, again, warn. But our fix to objc/ 47076 didn't cover this case; it only covered protocols directly referenced by the declaration. This patch extends the fix to these cases by doing the recursive check required, so we now warn in this case too. The warning/checks actually become much more useful in practice too :-). Testcases included. Ok to commit ? Thanks Index: objc/objc-act.c =================================================================== --- objc/objc-act.c (revision 168362) +++ objc/objc-act.c (working copy) @@ -10929,11 +10929,30 @@ add_protocol (tree protocol) return protocol_chain; } +/* Check that a protocol is defined, and, recursively, that all + protocols that this protocol conforms to are defined too. */ +static void +check_that_protocol_is_defined (tree protocol) +{ + if (!PROTOCOL_DEFINED (protocol)) + warning (0, "definition of protocol %qE not found", + PROTOCOL_NAME (protocol)); + + /* If the protocol itself conforms to other protocols, check them + too, recursively. */ + if (PROTOCOL_LIST (protocol)) + { + tree p; + + for (p = PROTOCOL_LIST (p); p; p = TREE_CHAIN (p)) + check_that_protocol_is_defined (TREE_VALUE (p)); + } +} + /* Looks up a protocol. If 'warn_if_deprecated' is true, a warning is emitted if the protocol is deprecated. If 'definition_required' is true, a warning is emitted if a full @protocol definition has not been seen. */ - static tree lookup_protocol (tree ident, bool warn_if_deprecated, bool definition_required) { @@ -10951,9 +10970,8 @@ lookup_protocol (tree ident, bool warn_i PROTOCOL_NAME (chain)); } - if (definition_required && !PROTOCOL_DEFINED (chain)) - warning (0, "definition of protocol %qE not found", - PROTOCOL_NAME (chain)); + if (definition_required) + check_that_protocol_is_defined (chain); return chain; } Index: objc/ChangeLog =================================================================== --- objc/ChangeLog (revision 168362) +++ objc/ChangeLog (working copy) @@ -1,3 +1,8 @@ +2010-12-31 Nicola Pero + + * objc-act.c (check_that_protocol_is_defined): New. + (lookup_protocol): Call check_that_protocol_is_defined. + 2010-12-30 Nicola Pero * objc-act.c (objc_types_are_equivalent): Fixed comparing protocol Index: testsuite/ChangeLog =================================================================== --- testsuite/ChangeLog (revision 168362) +++ testsuite/ChangeLog (working copy) @@ -1,3 +1,10 @@ +2010-12-31 Nicola Pero + + * objc.dg/protocol-forward-1.m: Removed TODO. + * objc.dg/protocol-forward-2.m: New. + * obj-c++.dg/protocol-forward-2.mm: Removed TODO. + * obj-c++.dg/protocol-forward-2.mm: New. + 2010-12-30 Nicola Pero * objc.dg/method-conflict-3.m: New. Index: testsuite/objc.dg/protocol-forward-2.m =================================================================== --- testsuite/objc.dg/protocol-forward-2.m (revision 0) +++ testsuite/objc.dg/protocol-forward-2.m (revision 0) @@ -0,0 +1,95 @@ +/* Contributed by Nicola Pero , December 2010. */ +/* { dg-do compile } */ + +/* Test that all protocols appearing in @interface declarations are + real (ie, we saw a full @protocol definition with list of methods), + and not just forward-references (ie, "@protocol NSObject;"). This + test checks protocols implemented by other protocols. */ + +#include + +@protocol MyProtocol; + +@interface MyClass /* { dg-warning "definition of protocol .MyProtocol. not found" } */ +@end + + +@protocol MyProtocol2 +- (int)method2; +@end + +@interface MyClass2 /* { dg-warning "definition of protocol .MyProtocol. not found" } */ +- (int)method2; +@end + + +@protocol MyProtocol3 +- (int)method3; +@end + +@interface MyClass3 /* { dg-warning "definition of protocol .MyProtocol. not found" } */ +- (int)method2; +- (int)method3; +@end + + +@protocol MyProtocol4 +- (int)method4; +@end + +@interface MyClass4 /* { dg-warning "definition of protocol .MyProtocol. not found" } */ +- (int)method2; +- (int)method3; +- (int)method4; +@end + + +@protocol MyProtocol5 +- (int)method5; +@end + +@interface MyClass5 /* Ok */ +- (int)method5; +@end + + +@protocol MyProtocol6 +- (int)method6; +@end + +@interface MyClass6 /* Ok */ +- (int)method5; +- (int)method6; +@end + + +@protocol MyProtocol7 +- (int)method7; +@end + +@interface MyClass7 /* { dg-warning "definition of protocol .MyProtocol. not found" } */ +- (int)method2; +- (int)method3; +- (int)method4; +- (int)method5; +- (int)method7; +@end + + +/* Now test that if we finally define MyProtocol, the warnings go away. */ +@protocol MyProtocol +- (int)method; +@end + +@protocol MyProtocol8 +- (int)method8; +@end +@interface MyClass8 /* Ok */ +- (int)method; +- (int)method2; +- (int)method3; +- (int)method4; +- (int)method5; +- (int)method8; +@end Index: testsuite/objc.dg/protocol-forward-1.m =================================================================== --- testsuite/objc.dg/protocol-forward-1.m (revision 168362) +++ testsuite/objc.dg/protocol-forward-1.m (working copy) @@ -24,7 +24,3 @@ @protocol MyProtocol3 /* Ok */ @end - -/* TODO: I guess if MyProtocol3 is now used in an @interface, we - should check that all the protocols it references are defined - too ? */ Index: testsuite/obj-c++.dg/protocol-forward-2.mm =================================================================== --- testsuite/obj-c++.dg/protocol-forward-2.mm (revision 0) +++ testsuite/obj-c++.dg/protocol-forward-2.mm (revision 0) @@ -0,0 +1,95 @@ +/* Contributed by Nicola Pero , December 2010. */ +/* { dg-do compile } */ + +/* Test that all protocols appearing in @interface declarations are + real (ie, we saw a full @protocol definition with list of methods), + and not just forward-references (ie, "@protocol NSObject;"). This + test checks protocols implemented by other protocols. */ + +#include + +@protocol MyProtocol; + +@interface MyClass /* { dg-warning "definition of protocol .MyProtocol. not found" } */ +@end + + +@protocol MyProtocol2 +- (int)method2; +@end + +@interface MyClass2 /* { dg-warning "definition of protocol .MyProtocol. not found" } */ +- (int)method2; +@end + + +@protocol MyProtocol3 +- (int)method3; +@end + +@interface MyClass3 /* { dg-warning "definition of protocol .MyProtocol. not found" } */ +- (int)method2; +- (int)method3; +@end + + +@protocol MyProtocol4 +- (int)method4; +@end + +@interface MyClass4 /* { dg-warning "definition of protocol .MyProtocol. not found" } */ +- (int)method2; +- (int)method3; +- (int)method4; +@end + + +@protocol MyProtocol5 +- (int)method5; +@end + +@interface MyClass5 /* Ok */ +- (int)method5; +@end + + +@protocol MyProtocol6 +- (int)method6; +@end + +@interface MyClass6 /* Ok */ +- (int)method5; +- (int)method6; +@end + + +@protocol MyProtocol7 +- (int)method7; +@end + +@interface MyClass7 /* { dg-warning "definition of protocol .MyProtocol. not found" } */ +- (int)method2; +- (int)method3; +- (int)method4; +- (int)method5; +- (int)method7; +@end + + +/* Now test that if we finally define MyProtocol, the warnings go away. */ +@protocol MyProtocol +- (int)method; +@end + +@protocol MyProtocol8 +- (int)method8; +@end + +@interface MyClass8 /* Ok */ +- (int)method; +- (int)method2; +- (int)method3; +- (int)method4; +- (int)method5; +- (int)method8; +@end Index: testsuite/obj-c++.dg/protocol-forward-1.mm =================================================================== --- testsuite/obj-c++.dg/protocol-forward-1.mm (revision 168362) +++ testsuite/obj-c++.dg/protocol-forward-1.mm (working copy) @@ -25,6 +25,3 @@ @protocol MyProtocol3 /* Ok */ @end -/* TODO: I guess if MyProtocol3 is now used in an @interface, we - should check that all the protocols it references are defined - too ? */