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