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