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