1 /* Routines dealing with ObjC encoding of types
2 Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
3 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
34 #include "c-family/c-common.h"
35 #include "c-family/c-objc.h"
37 #include "objc-encoding.h"
40 /* For my_build_string(). */
41 #include "objc-runtime-shared-support.h"
43 /* For BITS_PER_UNIT. */
46 /* When building Objective-C++, we are not linking against the C front-end
47 and so need to replicate the C tree-construction functions in some way. */
49 #define OBJCP_REMAP_FUNCTIONS
50 #include "objcp-decl.h"
53 /* Set up for use of obstacks. */
56 /* This obstack is used to accumulate the encoding of a data type.
57 TODO: Make this static. */
58 struct obstack util_obstack;
60 /* This points to the beginning of obstack contents, so we can free
61 the whole contents. TODO: Make this static. */
64 int generating_instance_variables = 0;
66 static void encode_type_qualifiers (tree);
67 static void encode_type (tree, int, int);
70 objc_method_parm_type (tree type)
72 type = TREE_VALUE (TREE_TYPE (type));
73 if (TREE_CODE (type) == TYPE_DECL)
74 type = TREE_TYPE (type);
79 objc_encoded_type_size (tree type)
81 int sz = int_size_in_bytes (type);
83 /* Make all integer and enum types at least as large
85 if (sz > 0 && INTEGRAL_TYPE_P (type))
86 sz = MAX (sz, int_size_in_bytes (integer_type_node));
87 /* Treat arrays as pointers, since that's how they're
89 else if (TREE_CODE (type) == ARRAY_TYPE)
90 sz = int_size_in_bytes (ptr_type_node);
94 /* Encode a method prototype. */
96 encode_method_prototype (tree method_decl)
103 /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */
104 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl)));
106 /* Encode return type. */
107 encode_type (objc_method_parm_type (method_decl),
108 obstack_object_size (&util_obstack),
109 OBJC_ENCODE_INLINE_DEFS);
112 /* The first two arguments (self and _cmd) are pointers; account for
114 i = int_size_in_bytes (ptr_type_node);
116 for (parms = METHOD_SEL_ARGS (method_decl); parms;
117 parms = DECL_CHAIN (parms))
119 tree type = objc_method_parm_type (parms);
120 int sz = objc_encoded_type_size (type);
122 /* If a type size is not known, bail out. */
125 error_at (DECL_SOURCE_LOCATION (method_decl),
126 "type %qT does not have a known size",
128 /* Pretend that the encoding succeeded; the compilation will
129 fail nevertheless. */
130 goto finish_encoding;
135 sprintf (buf, "%d@0:%d", parm_offset, i);
136 obstack_grow (&util_obstack, buf, strlen (buf));
138 /* Argument types. */
140 for (parms = METHOD_SEL_ARGS (method_decl); parms;
141 parms = DECL_CHAIN (parms))
143 tree type = objc_method_parm_type (parms);
145 /* Process argument qualifiers for user supplied arguments. */
146 encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (parms)));
149 encode_type (type, obstack_object_size (&util_obstack),
150 OBJC_ENCODE_INLINE_DEFS);
152 /* Compute offset. */
153 sprintf (buf, "%d", parm_offset);
154 parm_offset += objc_encoded_type_size (type);
156 obstack_grow (&util_obstack, buf, strlen (buf));
160 obstack_1grow (&util_obstack, '\0');
161 result = get_identifier (XOBFINISH (&util_obstack, char *));
162 obstack_free (&util_obstack, util_firstobj);
166 /* This is used to implement @encode(). */
168 objc_build_encode_expr (tree type)
173 encode_type (type, obstack_object_size (&util_obstack),
174 OBJC_ENCODE_INLINE_DEFS);
175 obstack_1grow (&util_obstack, 0); /* null terminate string */
176 string = XOBFINISH (&util_obstack, const char *);
178 /* Synthesize a string that represents the encoded struct/union. */
179 result = my_build_string (strlen (string) + 1, string);
180 obstack_free (&util_obstack, util_firstobj);
184 /* "Encode" a data type into a string, which grows in util_obstack.
186 The format is described in gcc/doc/objc.texi, section 'Type
189 Most of the encode_xxx functions have a 'type' argument, which is
190 the type to encode, and an integer 'curtype' argument, which is the
191 index in the encoding string of the beginning of the encoding of
192 the current type, and allows you to find what characters have
193 already been written for the current type (they are the ones in the
194 current encoding string starting from 'curtype').
196 For example, if we are encoding a method which returns 'int' and
197 takes a 'char **' argument, then when we get to the point of
198 encoding the 'char **' argument, the encoded string already
199 contains 'i12@0:4' (assuming a pointer size of 4 bytes). So,
200 'curtype' will be set to 7 when starting to encode 'char **'.
201 During the whole of the encoding of 'char **', 'curtype' will be
202 fixed at 7, so the routine encoding the second pointer can find out
203 that it's actually encoding a pointer to a pointer by looking
204 backwards at what has already been encoded for the current type,
205 and seeing there is a "^" (meaning a pointer) in there. */
208 /* Encode type qualifiers encodes one of the "PQ" Objective-C
209 keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
210 'const', instead, is encoded directly as part of the type. */
212 encode_type_qualifiers (tree declspecs)
216 for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
218 /* FIXME: Shouldn't we use token->keyword here ? */
219 if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
220 obstack_1grow (&util_obstack, 'n');
221 else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
222 obstack_1grow (&util_obstack, 'N');
223 else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
224 obstack_1grow (&util_obstack, 'o');
225 else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
226 obstack_1grow (&util_obstack, 'O');
227 else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
228 obstack_1grow (&util_obstack, 'R');
229 else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
230 obstack_1grow (&util_obstack, 'V');
236 /* Determine if a pointee is marked read-only. Only used by the NeXT
237 runtime to be compatible with gcc-3.3. */
239 pointee_is_readonly (tree pointee)
241 while (POINTER_TYPE_P (pointee))
242 pointee = TREE_TYPE (pointee);
244 return TYPE_READONLY (pointee);
247 /* Encode a pointer type. */
249 encode_pointer (tree type, int curtype, int format)
251 tree pointer_to = TREE_TYPE (type);
253 if (flag_next_runtime)
255 /* This code is used to be compatible with gcc-3.3. */
256 /* For historical/compatibility reasons, the read-only qualifier
257 of the pointee gets emitted _before_ the '^'. The read-only
258 qualifier of the pointer itself gets ignored, _unless_ we are
259 looking at a typedef! Also, do not emit the 'r' for anything
260 but the outermost type! */
261 if (!generating_instance_variables
262 && (obstack_object_size (&util_obstack) - curtype <= 1)
263 && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
264 ? TYPE_READONLY (type)
265 : pointee_is_readonly (pointer_to)))
266 obstack_1grow (&util_obstack, 'r');
269 if (TREE_CODE (pointer_to) == RECORD_TYPE)
271 if (OBJC_TYPE_NAME (pointer_to)
272 && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
274 const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
276 if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
278 obstack_1grow (&util_obstack, '@');
281 else if (TYPE_HAS_OBJC_INFO (pointer_to)
282 && TYPE_OBJC_INTERFACE (pointer_to))
284 if (generating_instance_variables)
286 obstack_1grow (&util_obstack, '@');
287 obstack_1grow (&util_obstack, '"');
288 obstack_grow (&util_obstack, name, strlen (name));
289 obstack_1grow (&util_obstack, '"');
294 obstack_1grow (&util_obstack, '@');
298 else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
300 obstack_1grow (&util_obstack, '#');
303 else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
305 obstack_1grow (&util_obstack, ':');
310 else if (TREE_CODE (pointer_to) == INTEGER_TYPE
311 && TYPE_MODE (pointer_to) == QImode)
313 tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
314 ? OBJC_TYPE_NAME (pointer_to)
315 : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
317 /* (BOOL *) are an exception and are encoded as ^c, while all
318 other pointers to char are encoded as *. */
319 if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
321 if (!flag_next_runtime)
323 /* The NeXT runtime adds the 'r' before getting here. */
325 /* It appears that "r*" means "const char *" rather than
326 "char *const". "char *const" is encoded as "*",
327 which is identical to "char *", so the "const" is
328 unfortunately lost. */
329 if (TYPE_READONLY (pointer_to))
330 obstack_1grow (&util_obstack, 'r');
333 obstack_1grow (&util_obstack, '*');
338 /* We have a normal pointer type that does not get special treatment. */
339 obstack_1grow (&util_obstack, '^');
340 encode_type (pointer_to, curtype, format);
344 encode_array (tree type, int curtype, int format)
346 tree an_int_cst = TYPE_SIZE (type);
347 tree array_of = TREE_TYPE (type);
350 if (an_int_cst == NULL)
352 /* We are trying to encode an incomplete array. An incomplete
353 array is forbidden as part of an instance variable; but it
354 may occur if the instance variable is a pointer to such an
357 /* So the only case in which an incomplete array could occur
358 (without being pointed to) is if we are encoding the
359 arguments or return value of a method. In that case, an
360 incomplete array argument or return value (eg,
361 -(void)display: (char[])string) is treated like a pointer
362 because that is how the compiler does the function call. A
363 special, more complicated case, is when the incomplete array
364 is the last member of a struct (eg, if we are encoding
365 "struct { unsigned long int a;double b[];}"), which is again
366 part of a method argument/return value. In that case, we
367 really need to communicate to the runtime that there is an
368 incomplete array (not a pointer!) there. So, we detect that
369 special case and encode it as a zero-length array.
371 Try to detect that we are part of a struct. We do this by
372 searching for '=' in the type encoding for the current type.
373 NB: This hack assumes that you can't use '=' as part of a C
377 char *enc = obstack_base (&util_obstack) + curtype;
378 if (memchr (enc, '=',
379 obstack_object_size (&util_obstack) - curtype) == NULL)
381 /* We are not inside a struct. Encode the array as a
383 encode_pointer (type, curtype, format);
388 /* Else, we are in a struct, and we encode it as a zero-length
390 sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
392 else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
393 sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
395 sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
396 TREE_INT_CST_LOW (an_int_cst)
397 / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
399 obstack_grow (&util_obstack, buffer, strlen (buffer));
400 encode_type (array_of, curtype, format);
401 obstack_1grow (&util_obstack, ']');
405 /* Encode a vector. The vector type is a GCC extension to C. */
407 encode_vector (tree type, int curtype, int format)
409 tree vector_of = TREE_TYPE (type);
412 /* Vectors are like simple fixed-size arrays. */
414 /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
415 alignment of the vector, and <code> is the base type. Eg, int
416 __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
417 assuming that the alignment is 32 bytes. We include size and
418 alignment in bytes so that the runtime does not have to have any
419 knowledge of the actual types.
421 sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
422 /* We want to compute the equivalent of sizeof (<vector>).
423 Code inspired by c_sizeof_or_alignof_type. */
424 ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
425 / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
426 /* We want to compute the equivalent of __alignof__
427 (<vector>). Code inspired by
428 c_sizeof_or_alignof_type. */
429 TYPE_ALIGN_UNIT (type));
430 obstack_grow (&util_obstack, buffer, strlen (buffer));
431 encode_type (vector_of, curtype, format);
432 obstack_1grow (&util_obstack, ']');
437 encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
439 tree field = TYPE_FIELDS (type);
441 for (; field; field = DECL_CHAIN (field))
444 /* C++ static members, and things that are not field at all,
445 should not appear in the encoding. */
446 if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
450 /* Recursively encode fields of embedded base classes. */
451 if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
452 && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
454 encode_aggregate_fields (TREE_TYPE (field),
455 pointed_to, curtype, format);
459 if (generating_instance_variables && !pointed_to)
461 tree fname = DECL_NAME (field);
463 obstack_1grow (&util_obstack, '"');
465 if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
466 obstack_grow (&util_obstack,
467 IDENTIFIER_POINTER (fname),
468 strlen (IDENTIFIER_POINTER (fname)));
470 obstack_1grow (&util_obstack, '"');
473 encode_field_decl (field, curtype, format);
478 encode_aggregate_within (tree type, int curtype, int format, int left,
482 /* NB: aggregates that are pointed to have slightly different encoding
483 rules in that you never encode the names of instance variables. */
484 int ob_size = obstack_object_size (&util_obstack);
485 bool inline_contents = false;
486 bool pointed_to = false;
488 if (flag_next_runtime)
490 if (ob_size > 0 && *(obstack_next_free (&util_obstack) - 1) == '^')
493 if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
494 && (!pointed_to || ob_size - curtype == 1
495 || (ob_size - curtype == 2
496 && *(obstack_next_free (&util_obstack) - 2) == 'r')))
497 inline_contents = true;
501 /* c0 and c1 are the last two characters in the encoding of the
502 current type; if the last two characters were '^' or '^r',
503 then we are encoding an aggregate that is "pointed to". The
504 comment above applies: in that case we should avoid encoding
505 the names of instance variables.
507 char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
508 char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
510 if (c0 == '^' || (c1 == '^' && c0 == 'r'))
513 if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
516 inline_contents = true;
519 /* Note that the check (ob_size - curtype < 2) prevents
520 infinite recursion when encoding a structure which is
521 a linked list (eg, struct node { struct node *next;
522 }). Each time we follow a pointer, we add one
523 character to ob_size, and curtype is fixed, so after
524 at most two pointers we stop inlining contents and
527 The other case where we don't inline is "^r", which
528 is a pointer to a constant struct.
530 if ((ob_size - curtype <= 2) && !(c0 == 'r'))
531 inline_contents = true;
536 /* Traverse struct aliases; it is important to get the
537 original struct and its tag name (if any). */
538 type = TYPE_MAIN_VARIANT (type);
539 name = OBJC_TYPE_NAME (type);
540 /* Open parenth/bracket. */
541 obstack_1grow (&util_obstack, left);
543 /* Encode the struct/union tag name, or '?' if a tag was
544 not provided. Typedef aliases do not qualify. */
546 /* For compatibility with the NeXT runtime, ObjC++ encodes template
547 args as a composite struct tag name. */
548 if (name && TREE_CODE (name) == IDENTIFIER_NODE
549 /* Did this struct have a tag? */
550 && !TYPE_WAS_ANONYMOUS (type))
551 obstack_grow (&util_obstack,
552 decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
553 strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
555 if (name && TREE_CODE (name) == IDENTIFIER_NODE)
556 obstack_grow (&util_obstack,
557 IDENTIFIER_POINTER (name),
558 strlen (IDENTIFIER_POINTER (name)));
561 obstack_1grow (&util_obstack, '?');
563 /* Encode the types (and possibly names) of the inner fields,
567 obstack_1grow (&util_obstack, '=');
568 encode_aggregate_fields (type, pointed_to, curtype, format);
570 /* Close parenth/bracket. */
571 obstack_1grow (&util_obstack, right);
574 /* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
577 encode_next_bitfield (int width)
580 sprintf (buffer, "b%d", width);
581 obstack_grow (&util_obstack, buffer, strlen (buffer));
584 /* Encodes 'type', ignoring type qualifiers (which you should encode
585 beforehand if needed) with the exception of 'const', which is
586 encoded by encode_type. See above for the explanation of
587 'curtype'. 'format' can be OBJC_ENCODE_INLINE_DEFS or
588 OBJC_ENCODE_DONT_INLINE_DEFS. */
590 encode_type (tree type, int curtype, int format)
592 enum tree_code code = TREE_CODE (type);
594 /* Ignore type qualifiers other than 'const' when encoding a
597 if (type == error_mark_node)
600 if (!flag_next_runtime)
602 if (TYPE_READONLY (type))
603 obstack_1grow (&util_obstack, 'r');
609 if (flag_next_runtime)
611 /* Kludge for backwards-compatibility with gcc-3.3: enums
612 are always encoded as 'i' no matter what type they
614 obstack_1grow (&util_obstack, 'i');
617 /* Else, they are encoded exactly like the integer type that is
618 used by the compiler to store them. */
622 switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
624 case 8: c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
625 case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
628 tree int_type = type;
629 if (flag_next_runtime)
631 /* Another legacy kludge for compatiblity with
632 gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
633 but not always. For typedefs, we need to use 'i'
634 or 'I' instead if encoding a struct field, or a
636 int_type = ((!generating_instance_variables
637 && (obstack_object_size (&util_obstack)
638 == (unsigned) curtype))
639 ? TYPE_MAIN_VARIANT (type)
642 if (int_type == long_unsigned_type_node
643 || int_type == long_integer_type_node)
644 c = TYPE_UNSIGNED (type) ? 'L' : 'l';
646 c = TYPE_UNSIGNED (type) ? 'I' : 'i';
649 case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
650 case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
651 default: gcc_unreachable ();
653 obstack_1grow (&util_obstack, c);
659 /* Floating point types. */
660 switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
662 case 32: c = 'f'; break;
663 case 64: c = 'd'; break;
665 case 128: c = 'D'; break;
666 default: gcc_unreachable ();
668 obstack_1grow (&util_obstack, c);
672 obstack_1grow (&util_obstack, 'v');
676 obstack_1grow (&util_obstack, 'B');
680 encode_array (type, curtype, format);
687 encode_pointer (type, curtype, format);
691 encode_aggregate_within (type, curtype, format, '{', '}');
695 encode_aggregate_within (type, curtype, format, '(', ')');
698 case FUNCTION_TYPE: /* '?' means an unknown type. */
699 obstack_1grow (&util_obstack, '?');
703 /* A complex is encoded as 'j' followed by the inner type (eg,
704 "_Complex int" is encoded as 'ji'). */
705 obstack_1grow (&util_obstack, 'j');
706 encode_type (TREE_TYPE (type), curtype, format);
710 encode_vector (type, curtype, format);
714 warning (0, "unknown type %<%T%> found during Objective-C encoding",
716 obstack_1grow (&util_obstack, '?');
720 if (flag_next_runtime)
722 /* Super-kludge. Some ObjC qualifier and type combinations need
723 to be rearranged for compatibility with gcc-3.3. */
724 if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
726 char *enc = obstack_base (&util_obstack) + curtype;
728 /* Rewrite "in const" from "nr" to "rn". */
729 if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
730 strncpy (enc - 1, "rn", 2);
736 encode_gnu_bitfield (int position, tree type, int size)
738 enum tree_code code = TREE_CODE (type);
742 /* This code is only executed for the GNU runtime, so we can ignore
743 the NeXT runtime kludge of always encoding enums as 'i' no matter
744 what integers they actually are. */
745 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
747 if (integer_zerop (TYPE_MIN_VALUE (type)))
748 /* Unsigned integer types. */
750 switch (TYPE_MODE (type))
753 charType = 'C'; break;
755 charType = 'S'; break;
758 if (type == long_unsigned_type_node)
765 charType = 'Q'; break;
771 /* Signed integer types. */
773 switch (TYPE_MODE (type))
776 charType = 'c'; break;
778 charType = 's'; break;
781 if (type == long_integer_type_node)
788 charType = 'q'; break;
796 /* Do not do any encoding, produce an error and keep going. */
797 error ("trying to encode non-integer type as a bitfield");
801 sprintf (buffer, "b%d%c%d", position, charType, size);
802 obstack_grow (&util_obstack, buffer, strlen (buffer));
806 encode_field_decl (tree field_decl, int curtype, int format)
809 /* C++ static members, and things that are not fields at all,
810 should not appear in the encoding. */
811 if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
815 /* Generate the bitfield typing information, if needed. Note the difference
816 between GNU and NeXT runtimes. */
817 if (DECL_BIT_FIELD_TYPE (field_decl))
819 int size = tree_low_cst (DECL_SIZE (field_decl), 1);
821 if (flag_next_runtime)
822 encode_next_bitfield (size);
824 encode_gnu_bitfield (int_bit_position (field_decl),
825 DECL_BIT_FIELD_TYPE (field_decl), size);
828 encode_type (TREE_TYPE (field_decl), curtype, format);
831 /* This routine encodes the attribute of the input PROPERTY according
832 to following formula:
834 Property attributes are stored as a comma-delimited C string.
835 Simple attributes such as readonly are encoded as single
836 character. The parametrized attributes, getter=name and
837 setter=name, are encoded as a single character followed by an
838 identifier. Property types are also encoded as a parametrized
839 attribute. The characters used to encode these attributes are
840 defined by the following enumeration:
842 enum PropertyAttributes {
843 kPropertyReadOnly = 'R',
844 kPropertyBycopy = 'C',
845 kPropertyByref = '&',
846 kPropertyDynamic = 'D',
847 kPropertyGetter = 'G',
848 kPropertySetter = 'S',
849 kPropertyInstanceVariable = 'V',
852 kPropertyStrong = 'P',
853 kPropertyNonAtomic = 'N'
856 objc_v2_encode_prop_attr (tree property)
859 tree type = TREE_TYPE (property);
861 obstack_1grow (&util_obstack, 'T');
862 encode_type (type, obstack_object_size (&util_obstack),
863 OBJC_ENCODE_INLINE_DEFS);
865 if (PROPERTY_READONLY (property))
866 obstack_grow (&util_obstack, ",R", 2);
868 switch (PROPERTY_ASSIGN_SEMANTICS (property))
870 case OBJC_PROPERTY_COPY:
871 obstack_grow (&util_obstack, ",C", 2);
873 case OBJC_PROPERTY_RETAIN:
874 obstack_grow (&util_obstack, ",&", 2);
876 case OBJC_PROPERTY_ASSIGN:
881 if (PROPERTY_DYNAMIC (property))
882 obstack_grow (&util_obstack, ",D", 2);
884 if (PROPERTY_NONATOMIC (property))
885 obstack_grow (&util_obstack, ",N", 2);
887 /* Here we want to encode the getter name, but only if it's not the
889 if (PROPERTY_GETTER_NAME (property) != PROPERTY_NAME (property))
891 obstack_grow (&util_obstack, ",G", 2);
892 string = IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property));
893 obstack_grow (&util_obstack, string, strlen (string));
896 if (!PROPERTY_READONLY (property))
898 /* Here we want to encode the setter name, but only if it's not
900 tree standard_setter = get_identifier (objc_build_property_setter_name (PROPERTY_NAME (property)));
901 if (PROPERTY_SETTER_NAME (property) != standard_setter)
903 obstack_grow (&util_obstack, ",S", 2);
904 string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property));
905 obstack_grow (&util_obstack, string, strlen (string));
909 /* TODO: Encode strong ('P'), weak ('W') for garbage collection. */
911 if (!PROPERTY_DYNAMIC (property))
913 obstack_grow (&util_obstack, ",V", 2);
914 if (PROPERTY_IVAR_NAME (property))
915 string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property));
917 string = IDENTIFIER_POINTER (PROPERTY_NAME (property));
918 obstack_grow (&util_obstack, string, strlen (string));
921 /* NULL-terminate string. */
922 obstack_1grow (&util_obstack, 0);
923 string = XOBFINISH (&util_obstack, char *);
924 obstack_free (&util_obstack, util_firstobj);
925 return get_identifier (string);