1 /* Support routines shared by all runtimes.
2    Copyright (C) 2011-2016 Free Software Foundation, Inc.
3    Contributed by Iain Sandoe (partially split from objc-act.c)
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11 
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "stringpool.h"
26 
27 #ifdef OBJCPLUS
28 #include "cp/cp-tree.h"
29 #else
30 #include "c/c-tree.h"
31 #include "c/c-lang.h"
32 #endif
33 #include "c-family/c-objc.h"
34 #include "objc-act.h"
35 
36 /* When building Objective-C++, we are not linking against the C front-end
37    and so need to replicate the C tree-construction functions in some way.  */
38 #ifdef OBJCPLUS
39 #define OBJCP_REMAP_FUNCTIONS
40 #include "objcp-decl.h"
41 #endif  /* OBJCPLUS */
42 
43 /* Hooks for string decls etc.  */
44 #include "objc-runtime-hooks.h"
45 
46 #include "objc-runtime-shared-support.h"
47 #include "objc-encoding.h"
48 
49 /* rt_trees identifiers - shared between NeXT implementations.  These allow
50    the FE to tag meta-data in a manner that survives LTO and can be used when
51    the  runtime requires that certain meta-data items appear in particular
52    named sections.  */
53 #include "objc-next-metadata-tags.h"
54 extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
55 
56 /* Rather than repeatedly looking up the identifiers, we save them here.  */
57 tree objc_rt_trees[OCTI_RT_META_MAX];
58 
59 /* For building an objc struct.  These might not be used when this file
60    is compiled as part of obj-c++.  */
61 
62 static bool objc_building_struct;
63 static struct c_struct_parse_info *objc_struct_info ATTRIBUTE_UNUSED;
64 
65 /* Start building a struct for objc.  */
66 
67 tree
objc_start_struct(tree name)68 objc_start_struct (tree name)
69 {
70   gcc_assert (!objc_building_struct);
71   objc_building_struct = true;
72   return start_struct (input_location, RECORD_TYPE, name, &objc_struct_info);
73 }
74 
75 /* Finish building a struct for objc.  */
76 
77 tree
objc_finish_struct(tree type,tree fieldlist)78 objc_finish_struct (tree type, tree fieldlist)
79 {
80   gcc_assert (objc_building_struct);
81   objc_building_struct = false;
82   return finish_struct (input_location, type, fieldlist, NULL_TREE,
83 			objc_struct_info);
84 }
85 
86 tree
build_sized_array_type(tree base_type,int size)87 build_sized_array_type (tree base_type, int size)
88 {
89   tree index_type = build_index_type (build_int_cst (NULL_TREE, size - 1));
90   return build_array_type (base_type, index_type);
91 }
92 
93 /* Create a declaration for field NAME of a given TYPE.  */
94 
95 static tree
create_field_decl(tree type,const char * name)96 create_field_decl (tree type, const char *name)
97 {
98   return build_decl (input_location,
99 		     FIELD_DECL, get_identifier (name), type);
100 }
101 
102 tree
add_field_decl(tree type,const char * name,tree ** chain)103 add_field_decl (tree type, const char *name, tree **chain)
104 {
105   tree field = create_field_decl (type, name);
106 
107   if (*chain != NULL)
108     **chain = field;
109   *chain = &DECL_CHAIN (field);
110 
111   return field;
112 }
113 
114 /* Create a global, static declaration for variable NAME of a given TYPE.  The
115    finish_var_decl() routine will need to be called on it afterwards.  */
116 
117 tree
start_var_decl(tree type,const char * name)118 start_var_decl (tree type, const char *name)
119 {
120   tree var = build_decl (input_location,
121 			 VAR_DECL, get_identifier (name), type);
122   TREE_STATIC (var) = 1;
123   DECL_INITIAL (var) = error_mark_node;  /* A real initializer is coming... */
124   DECL_IGNORED_P (var) = 1;
125   DECL_ARTIFICIAL (var) = 1;
126   DECL_CONTEXT (var) = NULL_TREE;
127 #ifdef OBJCPLUS
128   DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */
129 #endif
130   return var;
131 }
132 
133 /* Finish off the variable declaration created by start_var_decl().  */
134 
135 void
finish_var_decl(tree var,tree initializer)136 finish_var_decl (tree var, tree initializer)
137 {
138   finish_decl (var, input_location, initializer, NULL_TREE, NULL_TREE);
139 }
140 
141 /* Just a handy wrapper for add_objc_string.  */
142 
143 tree
build_selector(tree ident)144 build_selector (tree ident)
145 {
146   return convert (objc_selector_type, add_objc_string (ident, meth_var_names));
147 }
148 
149 /* --- templates --- */
150 
151 /* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
152    This needs to be done just once per compilation.  */
153 
154 /* struct _objc_super {
155      struct _objc_object *self;
156      struct _objc_class *super_class;
157 		[or Class cls; for the abi v2]
158    };  */
159 
160 void
build_super_template(void)161 build_super_template (void)
162 {
163   tree decls, *chain = NULL;
164 
165   objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
166 
167   /* struct _objc_object *self; */
168   decls = add_field_decl (objc_object_type, "self", &chain);
169 
170   /* struct _objc_class *super_class; */
171   add_field_decl (build_pointer_type (objc_class_template),
172 		  "super_class", &chain);
173 
174   objc_finish_struct (objc_super_template, decls);
175 }
176 
177 /* To accomplish method prototyping without generating all kinds of
178    inane warnings, the definition of the dispatch table entries were
179    changed from:
180 
181 	struct objc_method { SEL _cmd; ...; id (*_imp)(); };
182    to:
183 	struct objc_method { SEL _cmd; ...; void *_imp; };  */
184 
185 tree
build_method_template(void)186 build_method_template (void)
187 {
188   tree _SLT_record;
189   tree decls, *chain = NULL;
190 
191   _SLT_record = objc_start_struct (get_identifier (UTAG_METHOD));
192 
193   /* SEL _cmd; */
194   decls = add_field_decl (objc_selector_type, "_cmd", &chain);
195 
196   /* char *method_types; */
197   add_field_decl (string_type_node, "method_types", &chain);
198 
199   /* void *_imp; */
200   add_field_decl (build_pointer_type (void_type_node), "_imp", &chain);
201 
202   objc_finish_struct (_SLT_record, decls);
203 
204   return _SLT_record;
205 }
206 
207 tree
build_method_prototype_template(void)208 build_method_prototype_template (void)
209 {
210   tree proto_record;
211   tree decls, *chain = NULL;
212 
213   proto_record = objc_start_struct (get_identifier (UTAG_METHOD_PROTOTYPE));
214 
215   /* SEL _cmd; */
216   decls = add_field_decl (objc_selector_type, "_cmd", &chain);
217 
218   /* char *method_types; */
219   add_field_decl (string_type_node, "method_types", &chain);
220 
221   objc_finish_struct (proto_record, decls);
222 
223   return proto_record;
224 }
225 
226 /* struct {
227      struct _objc__method_prototype_list *method_next;
228      int method_count;
229      struct objc_method method_list[method_count];
230    };  */
231 
232 tree
build_method_list_template(tree list_type,int size)233 build_method_list_template (tree list_type, int size)
234 {
235   tree objc_ivar_list_record;
236   tree array_type, decls, *chain = NULL;
237 
238   objc_ivar_list_record = objc_start_struct (NULL_TREE);
239 
240   /* struct _objc__method_prototype_list *method_next; */
241   decls = add_field_decl (objc_method_proto_list_ptr, "method_next", &chain);
242 
243   /* int method_count; */
244   add_field_decl (integer_type_node, "method_count", &chain);
245 
246   /* struct objc_method method_list[]; */
247   array_type = build_sized_array_type (list_type, size);
248   add_field_decl (array_type, "method_list", &chain);
249 
250   objc_finish_struct (objc_ivar_list_record, decls);
251 
252   return objc_ivar_list_record;
253 }
254 
255 /* struct objc_method_prototype_list {
256      int count;
257      struct objc_method_prototype {
258 	SEL name;
259 	char *types;
260      } list[1];
261    };  */
262 
263 tree
build_method_prototype_list_template(tree list_type,int size)264 build_method_prototype_list_template (tree list_type, int size)
265 {
266   tree objc_ivar_list_record;
267   tree array_type, decls, *chain = NULL;
268 
269   /* Generate an unnamed struct definition.  */
270 
271   objc_ivar_list_record = objc_start_struct (NULL_TREE);
272 
273   /* int method_count; */
274   decls = add_field_decl (integer_type_node, "method_count", &chain);
275 
276   /* struct objc_method method_list[]; */
277   array_type = build_sized_array_type (list_type, size);
278   add_field_decl (array_type, "method_list", &chain);
279 
280   objc_finish_struct (objc_ivar_list_record, decls);
281 
282   return objc_ivar_list_record;
283 }
284 
285 /* --- names, decls entry --- */
286 
287 /* For each string section we have a chain which maps identifier nodes
288    to decls for the strings.  */
289 
290 static GTY(()) int meth_var_names_idx;
291 static GTY(()) int meth_var_types_idx;
292 static GTY(()) int property_name_attr_idx;
293 
294 tree
add_objc_string(tree ident,string_section section)295 add_objc_string (tree ident, string_section section)
296 {
297   tree *chain, decl, type;
298   char buf[BUFSIZE];
299 
300   switch (section)
301     {
302     case class_names:
303       chain = &class_names_chain;
304       snprintf (buf, BUFSIZE, "_OBJC_ClassName_%s", IDENTIFIER_POINTER (ident));
305       break;
306     case meth_var_names:
307       chain = &meth_var_names_chain;
308       snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
309       break;
310     case meth_var_types:
311       chain = &meth_var_types_chain;
312       snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
313       break;
314     case prop_names_attr:
315       chain = &prop_names_attr_chain;
316       snprintf (buf, BUFSIZE, "_OBJC_PropertyAttributeOrName_%d", property_name_attr_idx++);
317       break;
318     default:
319       gcc_unreachable ();
320     }
321 
322   while (*chain)
323     {
324       if (TREE_VALUE (*chain) == ident)
325 	return convert (string_type_node,
326 			build_unary_op (input_location,
327 					ADDR_EXPR, TREE_PURPOSE (*chain), 1));
328 
329       chain = &TREE_CHAIN (*chain);
330     }
331 
332   type = build_sized_array_type (char_type_node, IDENTIFIER_LENGTH (ident) + 1);
333   /* Get a runtime-specific string decl which will be finish_var()'ed in
334      generate_strings ().  */
335   decl = (*runtime.string_decl) (type, buf, section);
336   TREE_CONSTANT (decl) = 1;
337   *chain = tree_cons (decl, ident, NULL_TREE);
338 
339   return convert (string_type_node,
340 		  build_unary_op (input_location, ADDR_EXPR, decl, 1));
341 }
342 
343 /* --- shared metadata routines --- */
344 
345 tree
build_descriptor_table_initializer(tree type,tree entries)346 build_descriptor_table_initializer (tree type, tree entries)
347 {
348   vec<constructor_elt, va_gc> *inits = NULL;
349 
350   do
351     {
352       vec<constructor_elt, va_gc> *elts = NULL;
353 
354       CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
355 			      build_selector (METHOD_SEL_NAME (entries)));
356       CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
357 			      add_objc_string (METHOD_ENCODING (entries),
358 					       meth_var_types));
359 
360       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
361 			      objc_build_constructor (type, elts));
362 
363       entries = DECL_CHAIN (entries);
364     }
365   while (entries);
366 
367   return objc_build_constructor (build_array_type (type, 0), inits);
368 }
369 
370 tree
build_dispatch_table_initializer(tree type,tree entries)371 build_dispatch_table_initializer (tree type, tree entries)
372 {
373   vec<constructor_elt, va_gc> *inits = NULL;
374 
375   do
376     {
377       vec<constructor_elt, va_gc> *elems = NULL;
378       tree expr;
379 
380       CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
381 			      build_selector (METHOD_SEL_NAME (entries)));
382 
383       /* Generate the method encoding if we don't have one already.  */
384       if (! METHOD_ENCODING (entries))
385 	METHOD_ENCODING (entries) =
386 	  encode_method_prototype (entries);
387 
388       CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
389 			      add_objc_string (METHOD_ENCODING (entries),
390 					       meth_var_types));
391 
392       expr = convert (ptr_type_node,
393 		      build_unary_op (input_location, ADDR_EXPR,
394 				      METHOD_DEFINITION (entries), 1));
395       CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, expr);
396 
397       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
398 			      objc_build_constructor (type, elems));
399 
400       entries = DECL_CHAIN (entries);
401     }
402   while (entries);
403 
404   return objc_build_constructor (build_array_type (type, 0), inits);
405 }
406 
407 /* Used only by build_*_selector_translation_table (). */
408 void
diagnose_missing_method(tree meth,location_t here)409 diagnose_missing_method (tree meth, location_t here)
410 {
411   tree method_chain;
412   bool found = false;
413   for (method_chain = meth_var_names_chain;
414        method_chain;
415        method_chain = TREE_CHAIN (method_chain))
416     {
417       if (TREE_VALUE (method_chain) == meth)
418 	{
419 	  found = true;
420 	  break;
421 	}
422      }
423 
424   if (!found)
425     warning_at (here, 0, "creating selector for nonexistent method %qE",
426 			meth);
427 }
428 
429 
430 static tree
init_module_descriptor(tree type,long vers)431 init_module_descriptor (tree type, long vers)
432 {
433   tree expr, ltyp;
434   location_t loc;
435   vec<constructor_elt, va_gc> *v = NULL;
436 
437   /* No really useful place to point to.  */
438   loc = UNKNOWN_LOCATION;
439 
440   /* version = { 1, ... } */
441 
442   expr = build_int_cst (long_integer_type_node, vers);
443   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
444 
445   /* size = { ..., sizeof (struct _objc_module), ... } */
446 
447   expr = convert (long_integer_type_node,
448 		  size_in_bytes (objc_module_template));
449   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
450 
451   /* Don't provide any file name for security reasons. */
452   /* name = { ..., "", ... } */
453 
454   expr = add_objc_string (get_identifier (""), class_names);
455   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
456 
457   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
458 
459   ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
460 				       get_identifier (UTAG_SYMTAB)));
461   if (UOBJC_SYMBOLS_decl)
462     expr = convert (ltyp, build_unary_op (loc,
463 			   ADDR_EXPR, UOBJC_SYMBOLS_decl, 0));
464   else
465     expr = convert (ltyp, null_pointer_node);
466   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
467 
468   return objc_build_constructor (type, v);
469 }
470 
471 /* Write out the data structures to describe Objective C classes defined.
472 
473    struct _objc_module { ... } _OBJC_MODULE = { ... };   */
474 
475 void
build_module_descriptor(long vers,tree attr)476 build_module_descriptor (long vers, tree attr)
477 {
478   tree decls, *chain = NULL;
479 
480 #ifdef OBJCPLUS
481   push_lang_context (lang_name_c); /* extern "C" */
482 #endif
483 
484   objc_module_template = objc_start_struct (get_identifier (UTAG_MODULE));
485 
486   /* long version; */
487   decls = add_field_decl (long_integer_type_node, "version", &chain);
488 
489   /* long size; */
490   add_field_decl (long_integer_type_node, "size", &chain);
491 
492   /* char *name; */
493   add_field_decl (string_type_node, "name", &chain);
494 
495   /* struct _objc_symtab *symtab; */
496   add_field_decl (build_pointer_type (xref_tag (RECORD_TYPE,
497 						get_identifier (UTAG_SYMTAB))),
498 		  "symtab", &chain);
499 
500   objc_finish_struct (objc_module_template, decls);
501 
502   /* Create an instance of "_objc_module".  */
503   UOBJC_MODULES_decl = start_var_decl (objc_module_template,
504 				       /* FIXME - why the conditional
505 					  if the symbol is the
506 					  same.  */
507 				       flag_next_runtime ? "_OBJC_Module" :  "_OBJC_Module");
508 
509   /* This is the root of the metadata for defined classes and categories, it
510      is referenced by the runtime and, therefore, needed.  */
511   DECL_PRESERVE_P (UOBJC_MODULES_decl) = 1;
512 
513   /* Squash `defined but not used' warning.  */
514   TREE_USED (UOBJC_MODULES_decl) = 1;
515 
516   /* Allow the runtime to mark meta-data such that it can be assigned to target
517      specific sections by the back-end.  */
518   if (attr)
519     DECL_ATTRIBUTES (UOBJC_MODULES_decl) = attr;
520 
521   finish_var_decl (UOBJC_MODULES_decl,
522 		   init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl),
523 					   vers));
524 
525 #ifdef OBJCPLUS
526   pop_lang_context ();
527 #endif
528 }
529 
530 tree
build_ivar_list_initializer(tree type,tree field_decl)531 build_ivar_list_initializer (tree type, tree field_decl)
532 {
533   vec<constructor_elt, va_gc> *inits = NULL;
534 
535   do
536     {
537       vec<constructor_elt, va_gc> *ivar = NULL;
538       tree id;
539 
540       /* Set name.  */
541       if (DECL_NAME (field_decl))
542 	CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
543 				add_objc_string (DECL_NAME (field_decl),
544 						 meth_var_names));
545       else
546 	/* Unnamed bit-field ivar (yuck).  */
547 	CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, build_int_cst (NULL_TREE, 0));
548 
549       /* Set type.  */
550       id = add_objc_string (encode_field_decl (field_decl),
551                             meth_var_types);
552       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
553 
554       /* Set offset.  */
555       CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, byte_position (field_decl));
556       CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
557 			      objc_build_constructor (type, ivar));
558       do
559 	field_decl = DECL_CHAIN (field_decl);
560       while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
561     }
562   while (field_decl);
563 
564   return objc_build_constructor (build_array_type (type, 0), inits);
565 }
566 
567 /* struct {
568      int ivar_count;
569      struct objc_ivar ivar_list[ivar_count];
570    };  */
571 
572 tree
build_ivar_list_template(tree list_type,int size)573 build_ivar_list_template (tree list_type, int size)
574 {
575   tree objc_ivar_list_record;
576   tree array_type, decls, *chain = NULL;
577 
578   objc_ivar_list_record = objc_start_struct (NULL_TREE);
579 
580   /* int ivar_count; */
581   decls = add_field_decl (integer_type_node, "ivar_count", &chain);
582 
583   /* struct objc_ivar ivar_list[]; */
584   array_type = build_sized_array_type (list_type, size);
585   add_field_decl (array_type, "ivar_list", &chain);
586 
587   objc_finish_struct (objc_ivar_list_record, decls);
588 
589   return objc_ivar_list_record;
590 }
591 
592 /* struct _objc_ivar {
593      char *ivar_name;
594      char *ivar_type;
595      int ivar_offset;
596    };  */
597 
598 tree
build_ivar_template(void)599 build_ivar_template (void)
600 {
601   tree objc_ivar_id, objc_ivar_record;
602   tree decls, *chain = NULL;
603 
604   objc_ivar_id = get_identifier (UTAG_IVAR);
605   objc_ivar_record = objc_start_struct (objc_ivar_id);
606 
607   /* char *ivar_name; */
608   decls = add_field_decl (string_type_node, "ivar_name", &chain);
609 
610   /* char *ivar_type; */
611   add_field_decl (string_type_node, "ivar_type", &chain);
612 
613   /* int ivar_offset; */
614   add_field_decl (integer_type_node, "ivar_offset", &chain);
615 
616   objc_finish_struct (objc_ivar_record, decls);
617 
618   return objc_ivar_record;
619 }
620 
621 /* Used by NeXT ABI=0..2 */
622 void
build_next_selector_translation_table(void)623 build_next_selector_translation_table (void)
624 {
625   tree chain;
626   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
627     {
628       tree expr;
629       tree decl = TREE_PURPOSE (chain);
630       if (warn_selector)
631 	{
632 	  location_t loc;
633 	  if (decl)
634 	    loc = DECL_SOURCE_LOCATION (decl);
635 	  else
636 	    loc = UNKNOWN_LOCATION;
637 	  diagnose_missing_method (TREE_VALUE (chain), loc);
638 	}
639 
640       expr = build_selector (TREE_VALUE (chain));
641 
642       if (decl)
643 	{
644 	  /* Entries of this form are used for references to methods.
645 	  The runtime re-writes these on start-up, but the compiler can't see
646 	  that and optimizes it away unless we force it.  */
647 	  DECL_PRESERVE_P (decl) = 1;
648 	  finish_var_decl (decl, expr);
649 	}
650     }
651 }
652 
653 void
generate_protocol_references(tree plist)654 generate_protocol_references (tree plist)
655 {
656   tree lproto;
657 
658   /* Forward declare protocols referenced.  */
659   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
660     {
661       tree proto = TREE_VALUE (lproto);
662 
663       if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
664 	  && PROTOCOL_NAME (proto))
665 	{
666           if (! PROTOCOL_FORWARD_DECL (proto))
667             PROTOCOL_FORWARD_DECL (proto) = (*runtime.protocol_decl) (proto);
668 
669           if (PROTOCOL_LIST (proto))
670             generate_protocol_references (PROTOCOL_LIST (proto));
671         }
672     }
673 }
674 
675 /* --- new routines --- */
676 
677 /* Output all strings.  */
678 
679 /* FIXME: don't use global vars for all this... */
680 
681 /* This emits all the meta-data string tables (and finalizes each var
682    as it goes).  */
683 void
generate_strings(void)684 generate_strings (void)
685 {
686   tree chain, string_expr;
687   tree string, decl; /* , type;*/
688 
689   for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
690     {
691       string = TREE_VALUE (chain);
692       decl = TREE_PURPOSE (chain);
693       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
694 				     IDENTIFIER_POINTER (string));
695       finish_var_decl (decl, string_expr);
696     }
697 
698   for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
699     {
700       string = TREE_VALUE (chain);
701       decl = TREE_PURPOSE (chain);
702       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
703 				     IDENTIFIER_POINTER (string));
704       finish_var_decl (decl, string_expr);
705     }
706 
707   for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
708     {
709       string = TREE_VALUE (chain);
710       decl = TREE_PURPOSE (chain);
711       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
712 				     IDENTIFIER_POINTER (string));
713       finish_var_decl (decl, string_expr);
714     }
715 
716   for (chain = prop_names_attr_chain; chain; chain = TREE_CHAIN (chain))
717     {
718       string = TREE_VALUE (chain);
719       decl = TREE_PURPOSE (chain);
720       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
721 				     IDENTIFIER_POINTER (string));
722       finish_var_decl (decl, string_expr);
723     }
724 }
725 
726 #include "gt-objc-objc-runtime-shared-support.h"
727