1 /* Support routines shared by all runtimes.
2    Copyright (C) 2011-2018 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, "_OBJC_Module");
504 
505   /* This is the root of the metadata for defined classes and categories, it
506      is referenced by the runtime and, therefore, needed.  */
507   DECL_PRESERVE_P (UOBJC_MODULES_decl) = 1;
508 
509   /* Squash `defined but not used' warning.  */
510   TREE_USED (UOBJC_MODULES_decl) = 1;
511 
512   /* Allow the runtime to mark meta-data such that it can be assigned to target
513      specific sections by the back-end.  */
514   if (attr)
515     DECL_ATTRIBUTES (UOBJC_MODULES_decl) = attr;
516 
517   finish_var_decl (UOBJC_MODULES_decl,
518 		   init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl),
519 					   vers));
520 
521 #ifdef OBJCPLUS
522   pop_lang_context ();
523 #endif
524 }
525 
526 tree
build_ivar_list_initializer(tree type,tree field_decl)527 build_ivar_list_initializer (tree type, tree field_decl)
528 {
529   vec<constructor_elt, va_gc> *inits = NULL;
530 
531   for (; field_decl; field_decl = DECL_CHAIN (field_decl))
532     if (TREE_CODE (field_decl) == FIELD_DECL)
533       {
534 	vec<constructor_elt, va_gc> *ivar = NULL;
535 	tree id;
536 
537 	/* Set name.  */
538 	if (DECL_NAME (field_decl))
539 	  CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
540 				  add_objc_string (DECL_NAME (field_decl),
541 						   meth_var_names));
542 	else
543 	  /* Unnamed bit-field ivar (yuck).  */
544 	  CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
545 				  build_int_cst (NULL_TREE, 0));
546 
547 	/* Set type.  */
548 	id = add_objc_string (encode_field_decl (field_decl),
549 			      meth_var_types);
550 	CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
551 
552 	/* Set offset.  */
553 	CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, byte_position (field_decl));
554 	CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
555 				objc_build_constructor (type, ivar));
556     }
557 
558   return objc_build_constructor (build_array_type (type, 0), inits);
559 }
560 
561 /* struct {
562      int ivar_count;
563      struct objc_ivar ivar_list[ivar_count];
564    };  */
565 
566 tree
build_ivar_list_template(tree list_type,int size)567 build_ivar_list_template (tree list_type, int size)
568 {
569   tree objc_ivar_list_record;
570   tree array_type, decls, *chain = NULL;
571 
572   objc_ivar_list_record = objc_start_struct (NULL_TREE);
573 
574   /* int ivar_count; */
575   decls = add_field_decl (integer_type_node, "ivar_count", &chain);
576 
577   /* struct objc_ivar ivar_list[]; */
578   array_type = build_sized_array_type (list_type, size);
579   add_field_decl (array_type, "ivar_list", &chain);
580 
581   objc_finish_struct (objc_ivar_list_record, decls);
582 
583   return objc_ivar_list_record;
584 }
585 
586 /* struct _objc_ivar {
587      char *ivar_name;
588      char *ivar_type;
589      int ivar_offset;
590    };  */
591 
592 tree
build_ivar_template(void)593 build_ivar_template (void)
594 {
595   tree objc_ivar_id, objc_ivar_record;
596   tree decls, *chain = NULL;
597 
598   objc_ivar_id = get_identifier (UTAG_IVAR);
599   objc_ivar_record = objc_start_struct (objc_ivar_id);
600 
601   /* char *ivar_name; */
602   decls = add_field_decl (string_type_node, "ivar_name", &chain);
603 
604   /* char *ivar_type; */
605   add_field_decl (string_type_node, "ivar_type", &chain);
606 
607   /* int ivar_offset; */
608   add_field_decl (integer_type_node, "ivar_offset", &chain);
609 
610   objc_finish_struct (objc_ivar_record, decls);
611 
612   return objc_ivar_record;
613 }
614 
615 /* Used by NeXT ABI=0..2 */
616 void
build_next_selector_translation_table(void)617 build_next_selector_translation_table (void)
618 {
619   tree chain;
620   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
621     {
622       tree expr;
623       tree decl = TREE_PURPOSE (chain);
624       if (warn_selector)
625 	{
626 	  location_t loc;
627 	  if (decl)
628 	    loc = DECL_SOURCE_LOCATION (decl);
629 	  else
630 	    loc = UNKNOWN_LOCATION;
631 	  diagnose_missing_method (TREE_VALUE (chain), loc);
632 	}
633 
634       expr = build_selector (TREE_VALUE (chain));
635 
636       if (decl)
637 	{
638 	  /* Entries of this form are used for references to methods.
639 	  The runtime re-writes these on start-up, but the compiler can't see
640 	  that and optimizes it away unless we force it.  */
641 	  DECL_PRESERVE_P (decl) = 1;
642 	  finish_var_decl (decl, expr);
643 	}
644     }
645 }
646 
647 void
generate_protocol_references(tree plist)648 generate_protocol_references (tree plist)
649 {
650   tree lproto;
651 
652   /* Forward declare protocols referenced.  */
653   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
654     {
655       tree proto = TREE_VALUE (lproto);
656 
657       if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
658 	  && PROTOCOL_NAME (proto))
659 	{
660           if (! PROTOCOL_FORWARD_DECL (proto))
661             PROTOCOL_FORWARD_DECL (proto) = (*runtime.protocol_decl) (proto);
662 
663           if (PROTOCOL_LIST (proto))
664             generate_protocol_references (PROTOCOL_LIST (proto));
665         }
666     }
667 }
668 
669 /* --- new routines --- */
670 
671 /* Output all strings.  */
672 
673 /* FIXME: don't use global vars for all this... */
674 
675 /* This emits all the meta-data string tables (and finalizes each var
676    as it goes).  */
677 void
generate_strings(void)678 generate_strings (void)
679 {
680   tree chain, string_expr;
681   tree string, decl; /* , type;*/
682 
683   for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
684     {
685       string = TREE_VALUE (chain);
686       decl = TREE_PURPOSE (chain);
687       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
688 				     IDENTIFIER_POINTER (string));
689       finish_var_decl (decl, string_expr);
690     }
691 
692   for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
693     {
694       string = TREE_VALUE (chain);
695       decl = TREE_PURPOSE (chain);
696       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
697 				     IDENTIFIER_POINTER (string));
698       finish_var_decl (decl, string_expr);
699     }
700 
701   for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
702     {
703       string = TREE_VALUE (chain);
704       decl = TREE_PURPOSE (chain);
705       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
706 				     IDENTIFIER_POINTER (string));
707       finish_var_decl (decl, string_expr);
708     }
709 
710   for (chain = prop_names_attr_chain; chain; chain = TREE_CHAIN (chain))
711     {
712       string = TREE_VALUE (chain);
713       decl = TREE_PURPOSE (chain);
714       string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
715 				     IDENTIFIER_POINTER (string));
716       finish_var_decl (decl, string_expr);
717     }
718 }
719 
720 #include "gt-objc-objc-runtime-shared-support.h"
721