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


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

[RFC/RFA] [ObjC] Class <protocol> support I


Hello,

This adds support for qualifying Objective-C 'Class' references with a
protocol list.  It also removes 'id' keyword and therefor invalidates
the gcc/testsuite/objc.dg/id-1.m test case.  I've also attached a new
test case which checks the most important aspects of the feature.

The only non-obvious semantics are that instance methods of protocols
declared by root classes are also considered when searching for class
method prototypes (as this reflects the runtime semantics).  It also
registers those prototypes in the global class method list.

Bootstrapped and tested on i686-pc-linux-gnu.  (Only failure is the
above mentioned id-1.m test case.  It would fail differently if an
#include <objc/objc.h> were added, but redefining types is already
tested in the C front end.  I would think that the test case could
simply be removed.)

Next up, (objc_)comptypes support.

Cheers,
David Ayers

PS: An adapted patch for the objc-improvements-branch (which will
include the previous renaming patches) is being bootstrapped and tested
now.  (2 bootstraps a 2.8 hours + 2 test runs  a 2.6 hours = 10.8 hours,
and those times are without objc++ so don't expect that until tomorrow
if everything goes well.)

PPS: May I also use this opportunity to ping:
http://gcc.gnu.org/ml/gcc-patches/2004-06/msg00385.html

Oh, and here's the ChangeLog for the test suite:

2004-06-29  David Ayers  <d.ayers@inode.at>

        * objc.dg/class-protocol-1.m: New test.
        * objc.dg/id-1.m: Remove test.

2004-06-29  David Ayers  <d.ayers@inode.at>

	* c-common.h (rid): Remove RID_ID.
	* c-parse.in: Remove OBJECTNAME and references to RID_ID.
	(typespec_reserved_attr): Add rule for TYPENAME
	non_empty_protocolrefs.  Update calls to get_static_reference and
	get_protocol_reference.
	(yylexname) Remove special handling of RID_ID.
	* objc/objc-act.h (get_static_reference) Remove.
	(get_protocol_reference): Update prototype.
	(PROTOCOL_DECLARED_BY_ROOT): New macro.
	(OCTI_ID_ID): Rename to OCTI_TYPE_ID_ID.
	(OCTI_TYPE_CLS_ID): New macro.
	(objc_id_id): Rename to objc_type_id_id.
	(objc_type_class_id): New macro.
	
	* objc/objc-act.c (mark_protocols_declared_by_root_class)
	(instance_prototype_of_root_protocol): Add new functions.
	(TYPE_CLASS): New macro.
	(get_static_reference): Remove.
	(get_protocol_reference): Add parameters for type or class
	reference and flag to identify class references.
	Add and merge diagnostics for invalid 'Class' type.
	(synth_module_prologue): Initialize objc_type_id_id and
	objc_type_class_id.
	(finish_message_expr): Extend prototype search for protocol
	qualified classes.
	(start_class): Call mark_protocols_declared_by_root_class if
	processing a root class with protocol references.
	(finish_protocol): Register instance prototypes as class
	prototypes if protocol has previously been referenced by a root
	class.

	(lookup_and_install_protocols) Update documentation.

Index: gcc/c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.246
diff -u -r1.246 c-common.h
--- gcc/c-common.h	25 Jun 2004 21:24:21 -0000	1.246
+++ gcc/c-common.h	27 Jun 2004 11:18:46 -0000
@@ -92,7 +92,7 @@
   RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
 
   /* Objective-C */
-  RID_ID,          RID_AT_ENCODE,    RID_AT_END,
+  RID_AT_ENCODE,   RID_AT_END,
   RID_AT_CLASS,    RID_AT_ALIAS,     RID_AT_DEFS,
   RID_AT_PRIVATE,  RID_AT_PROTECTED, RID_AT_PUBLIC,
   RID_AT_PROTOCOL, RID_AT_SELECTOR,  
Index: gcc/c-parse.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parse.in,v
retrieving revision 1.220
diff -u -r1.220 c-parse.in
--- gcc/c-parse.in	24 Jun 2004 23:12:27 -0000	1.220
+++ gcc/c-parse.in	27 Jun 2004 11:18:47 -0000
@@ -176,7 +176,7 @@
    Objective C, so that the token codes are the same in both.  */
 %token AT_INTERFACE AT_IMPLEMENTATION AT_END AT_SELECTOR AT_DEFS AT_ENCODE
 %token CLASSNAME AT_PUBLIC AT_PRIVATE AT_PROTECTED AT_PROTOCOL 
-%token OBJECTNAME AT_CLASS AT_ALIAS
+%token AT_CLASS AT_ALIAS
 %token AT_THROW AT_TRY AT_CATCH AT_FINALLY AT_SYNCHRONIZED
 %token OBJC_STRING
 
@@ -250,7 +250,7 @@
 %type <ttype> selectorarg keywordnamelist keywordname objcencodeexpr
 %type <ttype> non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
 
-%type <ttype> CLASSNAME OBJECTNAME OBJC_STRING
+%type <ttype> CLASSNAME OBJC_STRING
 
 %type <ttype> superclass
 @@end_ifobjc
@@ -436,7 +436,6 @@
 	IDENTIFIER
 	| TYPENAME
 @@ifobjc
-	| OBJECTNAME
 	| CLASSNAME
 @@end_ifobjc
 	;
@@ -1321,14 +1320,14 @@
 		  $$ = lookup_name ($1); }
 @@ifobjc
 	| CLASSNAME protocolrefs
-		{ $$ = get_static_reference ($1, $2); }
-	| OBJECTNAME protocolrefs
-		{ $$ = get_protocol_reference ($2); }
+		{ $$ = get_protocol_reference ($1, $2, 1); }
+	| TYPENAME non_empty_protocolrefs
+		{ $$ = get_protocol_reference ($1, $2, 0); }
 
 /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>"
    - nisse@lysator.liu.se */
         | non_empty_protocolrefs
-                { $$ = get_protocol_reference ($1); }
+                { $$ = get_protocol_reference (NULL_TREE, $1, 0); }
 @@end_ifobjc
 	| typeof '(' expr ')'
 		{ skip_evaluation--;
@@ -1590,9 +1589,6 @@
 	| '*' maybe_type_quals_attrs after_type_declarator  %prec UNARY
 		{ $$ = make_pointer_declarator ($2, $3); }
 	| TYPENAME
-@@ifobjc
-	| OBJECTNAME
-@@end_ifobjc
 	;
 
 /* Kinds of declarator that can appear in a parameter list
@@ -1610,9 +1606,6 @@
 	| parm_declarator_starttypename array_declarator  %prec '.'
 		{ $$ = set_array_declarator_type ($2, $1, 0); }
 	| TYPENAME
-@@ifobjc
-	| OBJECTNAME
-@@end_ifobjc
 	;
 
 parm_declarator_nostarttypename:
@@ -2996,7 +2989,6 @@
 	  IDENTIFIER
 	| TYPENAME
 	| CLASSNAME
-	| OBJECTNAME
 	| reservedwords
 	;
 
@@ -3234,7 +3226,6 @@
   { "volatile",		RID_VOLATILE,	0 },
   { "while",		RID_WHILE,	0 },
 @@ifobjc
-  { "id",		RID_ID,			D_OBJC },
 
   /* These objc keywords are recognized only immediately after
      an '@'.  */
@@ -3380,7 +3371,6 @@
   /* RID_STATCAST */	0,
 
   /* Objective C */
-  /* RID_ID */			OBJECTNAME,
   /* RID_AT_ENCODE */		AT_ENCODE,
   /* RID_AT_END */		AT_END,
   /* RID_AT_CLASS */		AT_CLASS,
@@ -3449,15 +3439,6 @@
       enum rid rid_code = C_RID_CODE (yylval.ttype);
 
 @@ifobjc
-      /* Turn non-typedefed refs to "id" into plain identifiers; this
-	 allows constructs like "void foo(id id);" to work.  */
-      if (rid_code == RID_ID)
-      {
-	decl = lookup_name (yylval.ttype);
-	if (decl == NULL_TREE || TREE_CODE (decl) != TYPE_DECL)
-	  return IDENTIFIER;
-      }
-
       if (!OBJC_IS_AT_KEYWORD (rid_code)
 	  && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
 @@end_ifobjc
@@ -3620,7 +3601,6 @@
     {
     case IDENTIFIER:
     case TYPENAME:
-    case OBJECTNAME:
     case TYPESPEC:
     case TYPE_QUAL:
     case SCSPEC:
Index: gcc/objc/objc-act.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.228
diff -u -r1.228 objc-act.c
--- gcc/objc/objc-act.c	24 Jun 2004 23:12:30 -0000	1.228
+++ gcc/objc/objc-act.c	27 Jun 2004 11:18:52 -0000
@@ -201,6 +201,8 @@
 static tree lookup_protocol (tree);
 static void check_protocol_recursively (tree, tree);
 static tree lookup_and_install_protocols (tree);
+static void mark_protocols_declared_by_root_class (tree, int);
+static tree instance_prototype_of_root_protocol (tree, tree, int);
 
 /* Type encoding.  */
 
@@ -295,6 +297,8 @@
 /* Reserved tag definitions.  */
 
 #define TYPE_ID			"id"
+#define TYPE_CLASS		"Class"
+
 #define TAG_OBJECT		"objc_object"
 #define TAG_CLASS		"objc_class"
 #define TAG_SUPER		"objc_super"
@@ -950,57 +954,58 @@
 	   IDENTIFIER_POINTER (type));
 }
 
-/* Implement static typing.  At this point, we know we have an interface.  */
-
-tree
-get_static_reference (tree interface, tree protocols)
-{
-  tree type = xref_tag (RECORD_TYPE, interface);
-
-  if (protocols)
-    {
-      tree t, m = TYPE_MAIN_VARIANT (type);
-
-      t = copy_node (type);
-
-      /* Add this type to the chain of variants of TYPE.  */
-      TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
-      TYPE_NEXT_VARIANT (m) = t;
-
-      /* Look up protocols and install in lang specific list.  Note
-	 that the protocol list can have a different lifetime than T!  */
-      SET_TYPE_PROTOCOL_LIST (t, lookup_and_install_protocols (protocols));
-
-      /* This forces a new pointer type to be created later
-	 (in build_pointer_type)...so that the new template
-	 we just created will actually be used...what a hack!  */
-      if (TYPE_POINTER_TO (t))
-	TYPE_POINTER_TO (t) = NULL_TREE;
-
-      type = t;
-    }
-
-  return type;
-}
+/* Construct a PROTOCOLS-qualified variant of INTERFACE, where INTERFACE may
+   either name an Objective-C class, or refer to the special 'id' or 'Class'
+   types.  If INTERFACE is not a valid ObjC type, report error.  */
 
-/* Return a declaration corresponding to a protocol list qualified 'id'. */
 tree
-get_protocol_reference (tree protocols)
+get_protocol_reference (tree interface, tree protocols, int is_class)
 {
-  tree type_decl = lookup_name (objc_id_id);
+  tree type_decl;
+  tree expected_type_ref;
   tree type;
 
-  if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
+  if (is_class) /* CLASSNAME <protocol> ...*/
     {
-      type = TREE_TYPE (type_decl);
-      if (TYPE_MAIN_VARIANT (type) != objc_id_type)
-	warning ("unexpected type for `id' (%s)",
-		 gen_declaration (type, errbuf));
+      type = xref_tag (RECORD_TYPE, interface);
     }
   else
     {
-      error ("undefined type `id', please import <objc/objc.h>");
-      return error_mark_node;
+      /* 'id <proto> ...' || '<proto> ...'*/
+      if (interface == objc_type_id_id || !interface)
+	{
+	  type_decl = lookup_name (objc_type_id_id);
+	  expected_type_ref = objc_id_type;
+	}
+      /* 'Class <proto> ...' */
+      else if (interface == objc_type_class_id)
+	{
+	  type_decl = lookup_name (objc_type_class_id);
+	  expected_type_ref = objc_class_type;
+	}
+      else
+	{
+	  error ("protocol qualifier is invalid for type `%s'",
+		 IDENTIFIER_POINTER(interface));
+	  return error_mark_node;
+	}
+
+      /* Test whether 'id'/'Class' are of the expected type.  */
+      if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
+	{
+	  type = TREE_TYPE (type_decl);
+
+	  if (TYPE_MAIN_VARIANT (type) != expected_type_ref)
+	    warning ("unexpected type for `%s' (%s)",
+		     (IS_ID(interface) ? TYPE_ID : TYPE_CLASS),
+		     gen_declaration (type, errbuf));
+	}
+      else
+	{
+	  error ("undefined type `%s', please import <objc/objc.h>",
+		 (IS_ID(interface) ? TYPE_ID : TYPE_CLASS));
+	  return error_mark_node;
+	}
     }
 
   /* This clause creates a new pointer type that is qualified with
@@ -1055,8 +1060,10 @@
     }
 }
 
-/* Look up PROTOCOLS, and return a list of those that are found.
-   If none are found, return NULL.  */
+/* Look up PROTOCOLS, a list of identifiers, and return a list 
+   of the protocol interface declarations that are found.  Invokes error
+   for each identifier for which the lookup failed.
+   If PROTOCOLS is empty, return NULL.  */
 
 static tree
 lookup_and_install_protocols (tree protocols)
@@ -1080,6 +1087,95 @@
   return return_value;
 }
 
+/* Iterates over the protocol interface list RPROTOS marking each as
+   PROTOCOL_DECLARED_BY_ROOT.  Registers the instance methods prototypes 
+   of each protocol and their inherited protocols recursively as 
+   potential class methods.  IGNORE should always be 0.  It is used
+   for recursive calls to insure that inherited protocols will not be
+   marked unduly.  */
+
+static void
+mark_protocols_declared_by_root_class (tree rprotos, int ignore)
+{
+  tree protocol_ch;
+  tree protocol;
+
+  for (protocol_ch = rprotos;
+       protocol_ch;
+       protocol_ch = TREE_CHAIN (protocol_ch))
+    {
+      protocol = TREE_CHECK(TREE_VALUE (protocol_ch),
+			    PROTOCOL_INTERFACE_TYPE);
+
+      /* Minor efficency check.  Expect all protocols which have
+	 been previously marked, to have had their methods registered.
+	 A protocol which itself is not declared by a root class yet
+	 is inherited by multiple root classes will have its instance
+	 methods processed redundantly, but it does not seem worth while
+	 to flag them just to avoid this.  */
+      if (!PROTOCOL_DECLARED_BY_ROOT (protocol))
+	{
+	  tree method_decl;
+
+	  for (method_decl = PROTOCOL_NST_METHODS (protocol);
+	       method_decl;
+	       method_decl = TREE_CHAIN (method_decl))
+	    {
+	      add_method_to_hash_list(cls_method_hash_list,  method_decl);
+	    }
+	}
+
+      if (!ignore)
+	{
+	  PROTOCOL_DECLARED_BY_ROOT (protocol) = 1;
+	}
+
+      mark_protocols_declared_by_root_class (PROTOCOL_LIST (protocol), 1);
+    }
+}
+
+/* Searches for SELECTOR in the instance methods 
+   of the protocol interface list RPROTOS.  Returns 
+   the prototype only if the corresponding protocol from RPROTOS
+   is declared by any root class.  IGNORE should always be 0.
+   It is used for the recursive prototype search of inherited protocols.  */
+
+static tree
+instance_prototype_of_root_protocol (tree rprotos, tree selector, int ignore)
+{
+  tree protocol_ch;
+  tree protocol;
+  tree prototype = NULL_TREE;
+
+  /* Loop over protocol list and search for protocols declared by root classes
+     that declare the method as an instance method.  */
+  for (protocol_ch = rprotos;
+       protocol_ch;
+       protocol_ch = TREE_CHAIN (protocol_ch))
+    {
+      protocol = TREE_CHECK(TREE_VALUE (protocol_ch),
+			    PROTOCOL_INTERFACE_TYPE);
+
+      if (ignore || PROTOCOL_DECLARED_BY_ROOT (protocol))
+	{
+	  /* Check the protocol itself.  */
+	  prototype = lookup_method (PROTOCOL_NST_METHODS (protocol),
+				     selector);
+	  if (prototype)
+	    return prototype;
+
+	  /* Search prototypes of inherited protocols independent of mark.  */
+	  prototype	
+	    = instance_prototype_of_root_protocol (PROTOCOL_LIST (protocol),
+						   selector, 1);
+	  if (prototype)
+	    return prototype;
+	}
+    }
+
+  return prototype;
+}
+
 /* Create and push a decl for a built-in external variable or field NAME.
    CODE says which.
    TYPE is its data type.  */
@@ -1146,7 +1242,9 @@
 
   objc_id_type = build_pointer_type (objc_object_reference);
 
-  objc_id_id = get_identifier (TYPE_ID);
+  objc_type_id_id = get_identifier (TYPE_ID);
+  objc_type_class_id = get_identifier (TYPE_CLASS);
+
   objc_class_id = get_identifier (TAG_CLASS);
 
   objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
@@ -5723,16 +5821,32 @@
 	  rtype = NULL_TREE;
 	}
       else
-	class_tree = TYPE_NAME (rtype) = get_identifier ("Class");
+	{
+	  rprotos = TYPE_PROTOCOL_LIST (rtype);
+	  class_tree = TYPE_NAME (rtype) = objc_type_class_id;
+
+	  if (rprotos)
+	    rtype = NULL_TREE;
+	}
 
       if (rprotos)
-	method_prototype
-	  = lookup_method_in_protocol_list (rprotos, sel_name,
-					    class_tree != NULL_TREE);
+	{
+	  method_prototype
+	    = lookup_method_in_protocol_list (rprotos, sel_name,
+					      class_tree != NULL_TREE);
+
+	  if (!method_prototype && class_tree != NULL_TREE)
+	    method_prototype
+	      = instance_prototype_of_root_protocol(rprotos,
+						    sel_name, 0);
+	}
+
       if (!method_prototype && !rprotos)
-	method_prototype
-	  = lookup_method_in_hash_lists (sel_name,
-					 class_tree != NULL_TREE);
+	{
+	  method_prototype
+	    = lookup_method_in_hash_lists (sel_name,
+					   class_tree != NULL_TREE);
+	}
     }
   else
     {
@@ -6840,8 +6954,14 @@
         add_class (class);
 
       if (protocol_list)
-	CLASS_PROTOCOL_LIST (class)
-	  = lookup_and_install_protocols (protocol_list);
+	{
+	  CLASS_PROTOCOL_LIST (class)
+	    = lookup_and_install_protocols (protocol_list);
+
+	  if (!CLASS_SUPER_NAME (class))
+	    mark_protocols_declared_by_root_class (CLASS_PROTOCOL_LIST (class),
+						   0);
+	}
     }
 
   else if (code == CATEGORY_INTERFACE_TYPE)
@@ -6862,8 +6982,14 @@
         add_category (class_category_is_assoc_with, class);
 
       if (protocol_list)
-	CLASS_PROTOCOL_LIST (class)
-	  = lookup_and_install_protocols (protocol_list);
+	{
+	  CLASS_PROTOCOL_LIST (class)
+	    = lookup_and_install_protocols (protocol_list);
+
+	  if (!CLASS_SUPER_NAME (class_category_is_assoc_with))
+	    mark_protocols_declared_by_root_class (CLASS_PROTOCOL_LIST (class),
+						   0);
+	}
     }
 
   else if (code == CATEGORY_IMPLEMENTATION_TYPE)
@@ -7107,8 +7233,26 @@
 }
 
 void
-finish_protocol (tree protocol ATTRIBUTE_UNUSED)
+finish_protocol (tree protocol)
 {
+  if (PROTOCOL_DECLARED_BY_ROOT (protocol))
+    {
+      tree method_decl;
+
+      /* Since we do not have a protocol list, 
+	 go ahead and register the method list directly.  */
+      for (method_decl = PROTOCOL_NST_METHODS (protocol);
+	   method_decl;
+	   method_decl = TREE_CHAIN (method_decl))
+	{
+	  add_method_to_hash_list(cls_method_hash_list,  method_decl);
+	}
+      
+      /* This protocol is marked.  Now insure that that all instance 
+	 prototypes of inherited protocols get registered as class 
+	 methods without marking them.  */
+      mark_protocols_declared_by_root_class (PROTOCOL_LIST (protocol), 1);
+    }
 }
 
 
Index: gcc/objc/objc-act.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.h,v
retrieving revision 1.25
diff -u -r1.25 objc-act.h
--- gcc/objc/objc-act.h	24 Jun 2004 23:12:30 -0000	1.25
+++ gcc/objc/objc-act.h	27 Jun 2004 11:18:52 -0000
@@ -56,8 +56,7 @@
 void objc_clear_super_receiver (void);
 tree get_class_ivars_from_name (tree);
 tree get_class_reference (tree);
-tree get_static_reference (tree, tree);
-tree get_protocol_reference (tree);
+tree get_protocol_reference (tree, tree, int);
 tree build_message_expr (tree);
 tree finish_message_expr (tree, tree, tree);
 tree build_selector_expr (tree);
@@ -85,6 +84,14 @@
 #define CLASS_BINFO_ELTS		6
 #define PROTOCOL_BINFO_ELTS		2
 
+/*
+  Objective-C usage for TREE_LANG_FLAG_?:
+
+  0: PROTOCOL_DECLARED_BY_ROOT - (valid for PROTOCOL_INTERFACE_TYPE)
+     Marks protocol declarations that are declared by root classes
+     so that instance methods are also checked for Class references.
+*/
+
 /* KEYWORD_DECL */
 #define KEYWORD_KEY_NAME(DECL) ((DECL)->decl.name)
 #define KEYWORD_ARG_NAME(DECL) ((DECL)->decl.arguments)
@@ -115,6 +122,7 @@
 #define PROTOCOL_CLS_METHODS(CLASS) ((CLASS)->type.maxval)
 #define PROTOCOL_FORWARD_DECL(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 1)
 #define PROTOCOL_DEFINED(CLASS) TREE_USED (CLASS)
+#define PROTOCOL_DECLARED_BY_ROOT(CLASS) TREE_LANG_FLAG_0 (CLASS)
 /* We need to distinguish TYPE_PROTOCOL_LISTs from TYPE_CONTEXTs, both of which
    are stored in the same accessor slot.  */
 #define TYPE_PROTOCOL_LIST(TYPE)				\
@@ -255,9 +263,10 @@
     OCTI_FUNCTION1_TEMPL,
     OCTI_FUNCTION2_TEMPL,
 
+    OCTI_TYPE_ID_ID,
+    OCTI_TYPE_CLS_ID,
     OCTI_OBJ_ID,
     OCTI_CLS_ID,
-    OCTI_ID_ID,
     OCTI_CNST_STR_ID,
     OCTI_CNST_STR_TYPE,
     OCTI_CNST_STR_GLOB_ID,
@@ -411,9 +420,10 @@
 #define function1_template	objc_global_trees[OCTI_FUNCTION1_TEMPL]
 #define function2_template	objc_global_trees[OCTI_FUNCTION2_TEMPL]
 
+#define objc_type_id_id		objc_global_trees[OCTI_TYPE_ID_ID]
+#define objc_type_class_id	objc_global_trees[OCTI_TYPE_CLS_ID]
 #define objc_object_id		objc_global_trees[OCTI_OBJ_ID]
 #define objc_class_id		objc_global_trees[OCTI_CLS_ID]
-#define objc_id_id		objc_global_trees[OCTI_ID_ID]
 #define constant_string_id	objc_global_trees[OCTI_CNST_STR_ID]
 #define constant_string_type	objc_global_trees[OCTI_CNST_STR_TYPE]
 #define constant_string_global_id		\

Attachment: objc.patch.gz
Description: application/gunzip

/* Check Class <protocol> types */
/* Author: David Ayers <d.ayers@inode.at> */
/* { dg-do compile } */

#include <objc/objc.h>
#include <objc/objc-api.h>

@protocol MyProto1
+(void)doItClass1;
-(void)doItInstance1;
@end

@protocol MyProto2
+(void)doItClass2;
-(void)doItInstance2;
@end

@interface MyClass1 <MyProto1>
{
  Class isa;
}
@end
@implementation MyClass1
+(void)doItClass1{}
-(void)doItInstance1{}
@end

@interface MyClass2 : MyClass1 <MyProto2>
@end
@implementation MyClass2
+(void)doItClass2{}
-(void)doItInstance2{}
@end

/*----------------------------------------*/

Class cls = 0;
Class <MyProto1> clsP1 = 0;
Class <MyProto2> clsP2 = 0;

void
testSimple(void)
{
  [cls doItClass1];
  [cls doItInstance1]; /* Do not warn as root Class declares this.  */
  [cls doItClass2];
  [cls doItInstance2]; /* { dg-warning "may not respond" } */

  [clsP1 doItClass1];
  [clsP1 doItInstance1]; /* Do not warn as root Class declares this.  */
  [clsP1 doItClass2];    /* { dg-warning "not implemented by protocol" } */
  [clsP1 doItInstance2]; /* { dg-warning "not implemented by protocol" } */

  [clsP2 doItClass1];    /* { dg-warning "not implemented by protocol" } */
  [clsP2 doItInstance1]; /* { dg-warning "not implemented by protocol" } */
  [clsP2 doItClass2];
  [clsP2 doItInstance2]; /* { dg-warning "not implemented by protocol" } */

  [MyClass1 doItClass1];
  [MyClass1 doItInstance1];
  [MyClass1 doItClass2];    /* { dg-warning "may not respond to" } */
  [MyClass1 doItInstance2]; /* { dg-warning "may not respond to" } */

  [MyClass2 doItClass1];
  [MyClass2 doItInstance1];
  [MyClass2 doItClass2];
  [MyClass2 doItInstance2]; /* { dg-warning "may not respond to" } */

}

/*----------------------------------------*/
/* Protocols declared by categories */

@protocol MyProto3
+(void)doItClass3;
-(void)doItInstance3;
@end
@protocol MyProto4
+(void)doItClass4;
-(void)doItInstance4;
@end

@interface MyClass1 (Category1) <MyProto3>
@end
@interface MyClass2 (Category2) <MyProto4>
@end

void
testCategory(void)
{
  [cls doItClass3];
  [cls doItInstance3];      /* Do not warn as root Class declares this.  */
  [cls doItClass4];
  [cls doItInstance4];      /* { dg-warning "may not respond" } */

  [MyClass1 doItClass3];
  [MyClass1 doItInstance3];
  [MyClass1 doItClass4];    /* { dg-warning "may not respond" } */
  [MyClass1 doItInstance4]; /* { dg-warning "may not respond" } */

  [MyClass2 doItClass3];
  [MyClass2 doItInstance3];
  [MyClass2 doItClass4];
  [MyClass2 doItInstance4]; /* { dg-warning "may not respond" } */

}

/*----------------------------------------*/
/* Inherited protocols declared by categories */

@protocol MyProto5 <MyProto1>
+(void)doItClass5;
-(void)doItInstance5;
@end

@protocol MyProto6 <MyProto2>
+(void)doItClass6;
-(void)doItInstance6;
@end

@interface MyClass1 (Category3) <MyProto5>
@end
@interface MyClass2 (Category4) <MyProto6>
@end

Class <MyProto5> clsP5 = 0;
Class <MyProto6> clsP6 = 0;

void
testCategoryInherited(void)
{
  [cls doItClass5];
  [cls doItInstance5]; /* Do not warn as root Class declares this.  */
  [cls doItClass6];
  [cls doItInstance6]; /* { dg-warning "may not respond" } */

  [clsP5 doItClass1];
  [clsP5 doItInstance1];
  [clsP5 doItClass2];    /* { dg-warning "not implemented by protocol" } */
  [clsP5 doItInstance2]; /* { dg-warning "not implemented by protocol" } */

  [clsP6 doItClass1];    /* { dg-warning "not implemented by protocol" } */
  [clsP6 doItInstance1]; /* { dg-warning "not implemented by protocol" } */
  [clsP6 doItClass2];
  [clsP6 doItInstance2]; /* { dg-warning "not implemented by protocol" } */

  [MyClass1 doItClass5];
  [MyClass1 doItInstance5]; /* Do not warn as root Class declares this.  */
  [MyClass1 doItClass6];    /* { dg-warning "may not respond" } */
  [MyClass1 doItInstance6]; /* { dg-warning "may not respond" } */

  [MyClass2 doItClass5];
  [MyClass2 doItInstance5]; /* Do not warn as root Class declares this.  */
  [MyClass2 doItClass6];
  [MyClass2 doItInstance6]; /* { dg-warning "may not respond" } */

}

/*----------------------------------------*/
/* Forward declared root protocols */

@protocol FwProto;

@interface MyClass1 (Forward) <FwProto>
@end

Class <FwProto> clsP7 = 0;

void
testForwardeDeclared1(void)
{
  [cls doItClass7];         /* { dg-warning "may not respond" } */
  [cls doItInstance7];      /* { dg-warning "may not respond" } */

  [clsP7 doItClass7];       /* { dg-warning "not implemented by protocol" } */
  [clsP7 doItInstance7];    /* { dg-warning "not implemented by protocol" } */

  [MyClass1 doItClass7];    /* { dg-warning "may not respond" } */
  [MyClass1 doItInstance7]; /* { dg-warning "may not respond" } */

  [MyClass2 doItClass7];    /* { dg-warning "may not respond" } */
  [MyClass2 doItInstance7]; /* { dg-warning "may not respond" } */

}

@protocol FwProto
+(void)doItClass7;
-(void)doItInstance7;
@end

void
testForwardeDeclared2(void)
{
  [cls doItClass7];
  [cls doItInstance7];   /* Do not warn as root Class declares this.  */

  [clsP7 doItClass7];    
  [clsP7 doItInstance7]; /* Do not warn as root Class declares this.  */

  [MyClass1 doItClass7];
  [MyClass1 doItInstance7];

  [MyClass2 doItClass7];
  [MyClass2 doItInstance7];
}

/*----------------------------------------*/
/* Inherited non root protocols */

@protocol MyProto8
+(void)doItClass8;
-(void)doItInstance8;
@end

@protocol MyProto9 <MyProto8>
+(void)doItClass9;
-(void)doItInstance9;
@end

@interface MyClass1 (InheritedNonRoot) <MyProto9>
@end

Class <MyProto8> clsP8 = 0;
Class <MyProto9> clsP9 = 0;

void
testInheritedNonRoot(void)
{
  [cls doItClass8];
  [cls doItInstance8]; /* Do not warn as root Class declares super.  */
  [cls doItClass9];
  [cls doItInstance9]; /* Do not warn as root Class declares this.  */

  [clsP8 doItClass8];
  [clsP8 doItInstance8]; /* { dg-warning "not implemented by protocol" } */
  [clsP8 doItClass9];    /* { dg-warning "not implemented by protocol" } */
  [clsP8 doItInstance9]; /* { dg-warning "not implemented by protocol" } */

  [clsP9 doItClass8];
  [clsP9 doItInstance8];
  [clsP9 doItClass9];
  [clsP9 doItInstance9];

  [MyClass1 doItClass8];
  [MyClass1 doItInstance8]; /* Do not warn as root Class declares this.  */
  [MyClass1 doItClass9];
  [MyClass1 doItInstance9];

  [MyClass2 doItClass8];
  [MyClass2 doItInstance8]; /* Do not warn as root Class declares this.  */
  [MyClass2 doItClass9];
  [MyClass2 doItInstance9];
  
}

int main ()
{
  testSimple();
  testCategory();
  testCategoryInherited();
  return(0);
}

/* { dg-warning "Messages without a matching" "" { target *-*-* } 47 } */
/* { dg-warning "will be assumed to return" "" { target *-*-* } 47 } */
/* { dg-warning "as arguments" "" { target *-*-* } 47 } */

Attachment: class-protocol-1.m.gz
Description: application/gunzip


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