summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/doc/objc.texi182
-rw-r--r--gcc/objc/ChangeLog48
-rw-r--r--gcc/objc/objc-act.c447
-rw-r--r--gcc/testsuite/ChangeLog60
-rw-r--r--gcc/testsuite/obj-c++.dg/encode-1-next.mm26
-rw-r--r--gcc/testsuite/obj-c++.dg/encode-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/encode-5.mm16
-rw-r--r--gcc/testsuite/obj-c++.dg/threedotthree-abi-1.mm71
-rw-r--r--gcc/testsuite/objc.dg/encode-1.m1
-rw-r--r--gcc/testsuite/objc.dg/encode-3.m18
-rw-r--r--gcc/testsuite/objc.dg/encode-6-next.m23
-rw-r--r--gcc/testsuite/objc.dg/encode-6.m1
-rw-r--r--gcc/testsuite/objc.dg/encode-7-next-64bit.m266
-rw-r--r--gcc/testsuite/objc.dg/encode-7-next.m267
-rw-r--r--gcc/testsuite/objc.dg/proto-qual-1.m10
-rw-r--r--gcc/testsuite/objc.dg/threedotthree-abi-1.m68
-rw-r--r--gcc/testsuite/objc.dg/type-size-2.m15
-rw-r--r--gcc/testsuite/objc.dg/type-size-3.m18
-rw-r--r--libobjc/ChangeLog10
-rw-r--r--libobjc/encoding.c79
-rw-r--r--libobjc/objc/encoding.h2
-rw-r--r--libobjc/objc/objc-api.h12
23 files changed, 1537 insertions, 121 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7954df7805b..68dd7e9f8b4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,22 @@
2010-09-27 Nicola Pero <nicola.pero@meta-innovation.com>
+ * doc/objc.texi (Type encoding): Added the new 'long double' (D)
+ code. Added byref, which was missing in the list of codes.
+ Explain that enumeration values are encoded as the integer type
+ that the compiler uses to store them. Explain and make examples
+ of how 'const' interacts with pointers, and the complication of
+ the encoding of 'const char *'.
+ (Legacy type encoding): New subsection, explaining that GCC emits
+ incorrect type encodings for the NeXT runtime for compatibility
+ reasons.
+ (@@encode): New subsection, explaining @encode and particularly
+ that protocol qualifiers are not recognized inside an @encode()
+ expression.
+ (Method signatures): New subsection, explaining how method
+ signatures are encoded.
+
+2010-09-27 Nicola Pero <nicola.pero@meta-innovation.com>
+
Merge from 'apple/trunk' branch on FSF servers. Removed small
change in build_conditional_expr that had been added when fixing
PR objc/27377 and which did the same check in a less complete way.
diff --git a/gcc/doc/objc.texi b/gcc/doc/objc.texi
index 1beb748cfc2..bf328797c72 100644
--- a/gcc/doc/objc.texi
+++ b/gcc/doc/objc.texi
@@ -170,9 +170,13 @@ above apply to classes defined in bundle.
@node Type encoding
@section Type encoding
-The Objective-C compiler generates type encodings for all the
-types. These type encodings are used at runtime to find out information
-about selectors and methods and about objects and classes.
+This is an advanced section. Type encodings are used extensively by
+the compiler and by the runtime, but you generally do not need to know
+about them to use Objective-C.
+
+The Objective-C compiler generates type encodings for all the types.
+These type encodings are used at runtime to find out information about
+selectors and methods and about objects and classes.
The types are encoded in the following way:
@@ -205,6 +209,8 @@ The types are encoded in the following way:
@tab @code{f}
@item @code{double}
@tab @code{d}
+@item @code{long double}
+@tab @code{D}
@item @code{void}
@tab @code{v}
@item @code{id}
@@ -215,6 +221,9 @@ The types are encoded in the following way:
@tab @code{:}
@item @code{char*}
@tab @code{*}
+@item @code{enum}
+@tab an @code{enum} is encoded exactly as the integer type that the compiler uses for it, which depends on the enumeration
+values. Often the compiler users @code{unsigned int}, which is then encoded as @code{I}.
@item unknown type
@tab @code{?}
@item Complex types
@@ -225,15 +234,16 @@ The types are encoded in the following way:
@c @sp 1
-The encoding of bit-fields has changed to allow bit-fields to be properly
-handled by the runtime functions that compute sizes and alignments of
-types that contain bit-fields. The previous encoding contained only the
-size of the bit-field. Using only this information it is not possible to
-reliably compute the size occupied by the bit-field. This is very
-important in the presence of the Boehm's garbage collector because the
-objects are allocated using the typed memory facility available in this
-collector. The typed memory allocation requires information about where
-the pointers are located inside the object.
+The encoding of bit-fields has changed to allow bit-fields to be
+properly handled by the runtime functions that compute sizes and
+alignments of types that contain bit-fields. The previous encoding
+contained only the size of the bit-field. Using only this information
+it is not possible to reliably compute the size occupied by the
+bit-field. This is very important in the presence of the Boehm's
+garbage collector because the objects are allocated using the typed
+memory facility available in this collector. The typed memory
+allocation requires information about where the pointers are located
+inside the object.
The position in the bit-field is the position, counting in bits, of the
bit closest to the beginning of the structure.
@@ -251,6 +261,8 @@ The non-atomic types are encoded as follows:
@tab @samp{@{} followed by the name of the structure (or @samp{?} if the structure is unnamed), the @samp{=} sign, the type of the members and by @samp{@}}
@item unions
@tab @samp{(} followed by the name of the structure (or @samp{?} if the union is unnamed), the @samp{=} sign, the type of the members followed by @samp{)}
+@item vectors
+@tab @samp{![} followed by the vector_size (the number of bytes composing the vector) followed by a comma, followed by the alignment (in bytes) of the vector, followed by the type of the elements followed by @samp{]}
@end multitable
Here are some types and their encodings, as they are generated by the
@@ -277,6 +289,11 @@ struct @{
@}
@end smallexample
@tab @code{@{?=i[3f]b128i3b131i2c@}}
+@item
+@smallexample
+int a __attribute__ ((vector_size (16)));
+@end smallexample
+@tab @code{![16,16i]} (alignment would depend on the machine)
@end multitable
@sp 1
@@ -300,6 +317,8 @@ Objective-C type specifiers:
@tab @code{o}
@item @code{bycopy}
@tab @code{O}
+@item @code{byref}
+@tab @code{R}
@item @code{oneway}
@tab @code{V}
@end multitable
@@ -310,6 +329,145 @@ The type specifiers are encoded just before the type. Unlike types
however, the type specifiers are only encoded when they appear in method
argument types.
+Note how @code{const} interacts with pointers:
+
+@sp 1
+
+@multitable @columnfractions .25 .75
+@item Objective-C type
+@tab Compiler encoding
+@item
+@smallexample
+const int
+@end smallexample
+@tab @code{ri}
+@item
+@smallexample
+const int*
+@end smallexample
+@tab @code{^ri}
+@item
+@smallexample
+int *const
+@end smallexample
+@tab @code{r^i}
+@end multitable
+
+@sp 1
+
+@code{const int*} is a pointer to a @code{const int}, and so is
+encoded as @code{^ri}. @code{int* const}, instead, is a @code{const}
+pointer to an @code{int}, and so is encoded as @code{r^i}.
+
+Finally, there is a complication when encoding @code{const char *}
+versus @code{char * const}. Because @code{char *} is encoded as
+@code{*} and not as @code{^c}, there is no way to express the fact
+that @code{r} applies to the pointer or to the pointee.
+
+Hence, it is assumed as a convention that @code{r*} means @code{const
+char *} (since it is what is most often meant), and there is no way to
+encode @code{char *const}. @code{char *const} would simply be encoded
+as @code{*}, and the @code{const} is lost.
+
+@menu
+* Legacy type encoding::
+* @@encode::
+* Method signatures::
+@end menu
+
+@node Legacy type encoding
+@subsection Legacy type encoding
+
+Unfortunately, historically GCC used to have a number of bugs in its
+encoding code. The NeXT runtime expects GCC to emit type encodings in
+this historical format (compatible with GCC-3.3), so when using the
+NeXT runtime, GCC will introduce on purpose a number of incorrect
+encodings:
+
+@itemize @bullet
+
+@item
+the read-only qualifier of the pointee gets emitted before the '^'.
+The read-only qualifier of the pointer itself gets ignored, unless it
+is a typedef. Also, the 'r' is only emitted for the outermost type.
+
+@item
+32-bit longs are encoded as 'l' or 'L', but not always. For typedefs,
+the compiler uses 'i' or 'I' instead if encoding a struct field or a
+pointer.
+
+@item
+@code{enum}s are always encoded as 'i' (int) even if they are actually
+unsigned or long.
+
+@end itemize
+
+In addition to that, the NeXT runtime uses a different encoding for
+bitfields. It encodes them as @code{b} followed by the size, without
+a bit offset or the underlying field type.
+
+@node @@encode
+@subsection @@encode
+
+GNU Objective-C supports the @code{@@encode} syntax that allows you to
+create a type encoding from a C/Objective-C type. For example,
+@code{@@encode(int)} is compiled by the compiler into @code{"i"}.
+
+@code{@@encode} does not support type qualifiers other than
+@code{const}. For example, @code{@@encode(const char*)} is valid and
+is compiled into @code{"r*"}, while @code{@@encode(bycopy char *)} is
+invalid and will cause a compilation error.
+
+@node Method signatures
+@subsection Method signatures
+
+This section documents the encoding of method types, which is rarely
+needed to use Objective-C. You should skip it at a first reading; the
+runtime provides functions that will work on methods and can walk
+through the list of parameters and interpret them for you. These
+functions are part of the public ``API'' and are the preferred way to
+interact with method signatures from user code.
+
+But if you need to debug a problem with method signatures and need to
+know how they are implemented (ie, the ``ABI''), read on.
+
+Methods have their ``signature'' encoded and made available to the
+runtime. The ``signature'' encodes all the information required to
+dynamically build invocations of the method at runtime: return type
+and arguments.
+
+The ``signature'' is a null-terminated string, composed of the following:
+
+@itemize @bullet
+
+@item
+The return type, including type qualifiers. For example, a method
+returning @code{int} would have @code{i} here.
+
+@item
+The total size (in bytes) required to pass all the parameters. This
+includes the two hidden parameters (the object @code{self} and the
+method selector @code{_cmd}).
+
+@item
+Each argument, with the type encoding, followed by the offset (in
+bytes) of the argument in the list of parameters.
+
+@end itemize
+
+For example, a method with no arguments and returning @code{int} would
+have the signature @code{i8@@0:4} if the size of a pointer is 4. The
+signature is interpreted as follows: the @code{i} is the return type
+(an @code{int}), the @code{8} is the total size of the parameters in
+bytes (two pointers each of size 4), the @code{@@0} is the first
+parameter (an object at byte offset @code{0}) and @code{:4} is the
+second parameter (a @code{SEL} at byte offset @code{4}).
+
+You can easily find more examples by running the ``strings'' program
+on an Objective-C object file compiled by GCC. You'll see a lot of
+strings that look very much like @code{i8@@0:4}. They are signatures
+of Objective-C methods.
+
@node Garbage Collection
@section Garbage Collection
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 8e70e208bcd..b1fb7bc2a5f 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,5 +1,53 @@
2010-09-27 Nicola Pero <nicola.pero@meta-innovation.com>
+ PR objc/45763
+ PR objc/25450
+ PR objc/25464
+ * objc-act.c: Improved comments for encoding functions.
+ (encode_aggregate_within): For the GNU runtime, rewritten some
+ obsfuscated code to clarify the various cases.
+ (encode_aggregate): Function removed.
+ (encode_array): Generate an error if asked to encode an incomplete
+ array as part of generating instance variables. Else, when
+ encoding an incomplete array inside a structure, encode it as an
+ array of zero size.
+ (encode_pointer): For the GNU runtime, fixed encoding 'BOOL *' as
+ '^c' instead of '*'.
+ (encode_gnu_bitfield): Encode enumerated types exactly in the same
+ type as integer types instead of using a hardcoded 'i'. If asked
+ to encode a non-integer type as a bitfield, do not abort
+ compilation immediately; instead generate an error, then skip the
+ type.
+ (encode_type): Use a 'switch' instead of a sequence of 'if's.
+ Added a 'default' clause that gets executed if the type can not be
+ matched, and that encodes it as '?' (unknown) and produces a
+ warning. For the GNU runtime, encode enumerated types exactly in
+ the same way as integer types instead of using a hardcoded 'i'.
+ Encode long double as 'D'. Encode 128-bit integers as 'T' or 't'.
+ Encode C++ reference types as pointers. Call encode_vector to
+ encode vectors.
+ (encode_vector): New function.
+
+2010-09-27 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ Merge from 'apple/trunk' branch on FSF servers. I modified the
+ changes to be used only when compiling for the NeXT runtime.
+
+ 2005-10-10 Fariborz Jahanian <fjahanian@apple.com>
+
+ Radar 4301047
+
+ * objc-act.c (encode_type): Remove the hack.
+
+ 2005-07-20 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 4136935
+ * objc-act.c (pointee_is_readonly): New function.
+ (encode_pointer, encode_aggregate_within, encode_type):
+ Attempt to emulate GCC 3.3 when generating type encodings.
+
+2010-09-27 Nicola Pero <nicola.pero@meta-innovation.com>
+
Merge from 'apple/trunk' branch on FSF servers.
2005-12-15 Fariborz Jahanian <fjahanian@apple.com>
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 5d76596479c..101f9fce0c9 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -4434,6 +4434,11 @@ objc_encoded_type_size (tree type)
return sz;
}
+/* Encode a method prototype.
+
+ The format is described in gcc/doc/objc.texi, section 'Method
+ signatures'.
+ */
static tree
encode_method_prototype (tree method_decl)
{
@@ -6796,6 +6801,8 @@ objc_build_selector_expr (location_t loc, tree selnamelist)
return build_selector_reference (loc, selname);
}
+/* This is used to implement @encode(). See gcc/doc/objc.texi,
+ section '@encode'. */
tree
objc_build_encode_expr (tree type)
{
@@ -7931,7 +7938,34 @@ start_protocol (enum tree_code code, tree name, tree list)
/* "Encode" a data type into a string, which grows in util_obstack.
- ??? What is the FORMAT? Someone please document this! */
+
+ The format is described in gcc/doc/objc.texi, section 'Type
+ encoding'.
+
+ Most of the encode_xxx functions have a 'type' argument, which is
+ the type to encode, and an integer 'curtype' argument, which is the
+ index in the encoding string of the beginning of the encoding of
+ the current type, and allows you to find what characters have
+ already been written for the current type (they are the ones in the
+ current encoding string starting from 'curtype').
+
+ For example, if we are encoding a method which returns 'int' and
+ takes a 'char **' argument, then when we get to the point of
+ encoding the 'char **' argument, the encoded string already
+ contains 'i12@0:4' (assuming a pointer size of 4 bytes). So,
+ 'curtype' will be set to 7 when starting to encode 'char **'.
+ During the whole of the encoding of 'char **', 'curtype' will be
+ fixed at 7, so the routine encoding the second pointer can find out
+ that it's actually encoding a pointer to a pointer by looking
+ backwards at what has already been encoded for the current type,
+ and seeing there is a "^" (meaning a pointer) in there.
+*/
+
+
+/* Encode type qualifiers encodes one of the "PQ" Objective-C
+ keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
+ 'const', instead, is encoded directly as part of the type.
+ */
static void
encode_type_qualifiers (tree declspecs)
@@ -7940,6 +7974,7 @@ encode_type_qualifiers (tree declspecs)
for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
{
+ /* FIXME: Shouldn't we use token->keyword here ? */
if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
obstack_1grow (&util_obstack, 'n');
else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
@@ -7955,6 +7990,18 @@ encode_type_qualifiers (tree declspecs)
}
}
+/* Determine if a pointee is marked read-only. Only used by the NeXT
+ runtime to be compatible with gcc-3.3. */
+
+static bool
+pointee_is_readonly (tree pointee)
+{
+ while (POINTER_TYPE_P (pointee))
+ pointee = TREE_TYPE (pointee);
+
+ return TYPE_READONLY (pointee);
+}
+
/* Encode a pointer type. */
static void
@@ -7962,6 +8009,22 @@ encode_pointer (tree type, int curtype, int format)
{
tree pointer_to = TREE_TYPE (type);
+ if (flag_next_runtime)
+ {
+ /* This code is used to be compatible with gcc-3.3. */
+ /* For historical/compatibility reasons, the read-only qualifier
+ of the pointee gets emitted _before_ the '^'. The read-only
+ qualifier of the pointer itself gets ignored, _unless_ we are
+ looking at a typedef! Also, do not emit the 'r' for anything
+ but the outermost type! */
+ if (!generating_instance_variables
+ && (obstack_object_size (&util_obstack) - curtype <= 1)
+ && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ ? TYPE_READONLY (type)
+ : pointee_is_readonly (pointer_to)))
+ obstack_1grow (&util_obstack, 'r');
+ }
+
if (TREE_CODE (pointer_to) == RECORD_TYPE)
{
if (OBJC_TYPE_NAME (pointer_to)
@@ -8010,21 +8073,28 @@ encode_pointer (tree type, int curtype, int format)
? OBJC_TYPE_NAME (pointer_to)
: DECL_NAME (OBJC_TYPE_NAME (pointer_to));
- if (!flag_next_runtime || strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
+ /* (BOOL *) are an exception and are encoded as ^c, while all
+ other pointers to char are encoded as *. */
+ if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
{
- /* It appears that "r*" means "const char *" rather than
- "char *const". */
- if (TYPE_READONLY (pointer_to))
- obstack_1grow (&util_obstack, 'r');
+ if (!flag_next_runtime)
+ {
+ /* The NeXT runtime adds the 'r' before getting here. */
+
+ /* It appears that "r*" means "const char *" rather than
+ "char *const". "char *const" is encoded as "*",
+ which is identical to "char *", so the "const" is
+ unfortunately lost. */
+ if (TYPE_READONLY (pointer_to))
+ obstack_1grow (&util_obstack, 'r');
+ }
obstack_1grow (&util_obstack, '*');
return;
}
}
- /* We have a type that does not get special treatment. */
-
- /* NeXT extension */
+ /* We have a normal pointer type that does not get special treatment. */
obstack_1grow (&util_obstack, '^');
encode_type (pointer_to, curtype, format);
}
@@ -8036,14 +8106,51 @@ encode_array (tree type, int curtype, int format)
tree array_of = TREE_TYPE (type);
char buffer[40];
- /* An incomplete array is treated like a pointer. */
if (an_int_cst == NULL)
{
- encode_pointer (type, curtype, format);
- return;
- }
+ /* We are trying to encode an incomplete array. An incomplete
+ array is forbidden as part of an instance variable. */
+ if (generating_instance_variables)
+ {
+ /* TODO: Detect this error earlier. */
+ error ("instance variable has unknown size");
+ return;
+ }
+
+ /* So the only case in which an incomplete array could occur is
+ if we are encoding the arguments or return value of a method.
+ In that case, an incomplete array argument or return value
+ (eg, -(void)display: (char[])string) is treated like a
+ pointer because that is how the compiler does the function
+ call. A special, more complicated case, is when the
+ incomplete array is the last member of a struct (eg, if we
+ are encoding "struct { unsigned long int a;double b[];}"),
+ which is again part of a method argument/return value. In
+ that case, we really need to communicate to the runtime that
+ there is an incomplete array (not a pointer!) there. So, we
+ detect that special case and encode it as a zero-length
+ array.
+
+ Try to detect that we are part of a struct. We do this by
+ searching for '=' in the type encoding for the current type.
+ NB: This hack assumes that you can't use '=' as part of a C
+ identifier.
+ */
+ char *enc = obstack_base (&util_obstack) + curtype;
+ if (memchr (enc, '=',
+ obstack_object_size (&util_obstack) - curtype) == NULL)
+ {
+ /* We are not inside a struct. Encode the array as a
+ pointer. */
+ encode_pointer (type, curtype, format);
+ return;
+ }
- if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
+ /* Else, we are in a struct, and we encode it as a zero-length
+ array. */
+ sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
+ }
+ else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
else
sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
@@ -8055,6 +8162,37 @@ encode_array (tree type, int curtype, int format)
obstack_1grow (&util_obstack, ']');
return;
}
+
+/* Encode a vector. The vector type is a GCC extension to C. */
+static void
+encode_vector (tree type, int curtype, int format)
+{
+ tree vector_of = TREE_TYPE (type);
+ char buffer[40];
+
+ /* Vectors are like simple fixed-size arrays. */
+
+ /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
+ alignment of the vector, and <code> is the base type. Eg, int
+ __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
+ assuming that the alignment is 32 bytes. We include size and
+ alignment in bytes so that the runtime does not have to have any
+ knowledge of the actual types.
+ */
+ sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
+ /* We want to compute the equivalent of sizeof (<vector>).
+ Code inspired by c_sizeof_or_alignof_type. */
+ ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
+ / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
+ /* We want to compute the equivalent of __alignof__
+ (<vector>). Code inspired by
+ c_sizeof_or_alignof_type. */
+ TYPE_ALIGN_UNIT (type));
+ obstack_grow (&util_obstack, buffer, strlen (buffer));
+ encode_type (vector_of, curtype, format);
+ obstack_1grow (&util_obstack, ']');
+ return;
+}
static void
encode_aggregate_fields (tree type, int pointed_to, int curtype, int format)
@@ -8105,12 +8243,64 @@ encode_aggregate_within (tree type, int curtype, int format, int left,
/* NB: aggregates that are pointed to have slightly different encoding
rules in that you never encode the names of instance variables. */
int ob_size = obstack_object_size (&util_obstack);
- char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
- char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
- int pointed_to = (c0 == '^' || (c1 == '^' && c0 == 'r'));
- int inline_contents
- = ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
- && (!pointed_to || ob_size - curtype == (c1 == 'r' ? 2 : 1)));
+ bool inline_contents = false;
+ bool pointed_to = false;
+
+ if (flag_next_runtime)
+ {
+ pointed_to = (ob_size > 0
+ ? *(obstack_next_free (&util_obstack) - 1) == '^'
+ : 0);
+ inline_contents = ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
+ && (!pointed_to
+ || ob_size - curtype == 1
+ || (ob_size - curtype == 2
+ && *(obstack_next_free (&util_obstack) - 2) == 'r')));
+ }
+ else
+ {
+ /* c0 and c1 are the last two characters in the encoding of the
+ current type; if the last two characters were '^' or '^r',
+ then we are encoding an aggregate that is "pointed to". The
+ comment above applies: in that case we should avoid encoding
+ the names of instance variables.
+ */
+ char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
+ char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
+
+ if (c0 == '^' || (c1 == '^' && c0 == 'r'))
+ pointed_to = true;
+
+ if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
+ {
+ if (!pointed_to)
+ inline_contents = true;
+ else
+ {
+ /* FIXME: It's hard to understand what the following
+ code is meant to be doing. It seems that it will
+ inline contents even if we are encoding a pointed
+ structure and the last characters were 'r^' or just
+ '^'.
+
+ So it seems that in the end the only case where we
+ don't inline contents is '^r', which is a pointer to
+ a 'const' structure! If that is the case, the whole
+ blob of code could be rewritten in a simpler way.
+ */
+ if (c1 == 'r')
+ {
+ if (ob_size - curtype == 2)
+ inline_contents = true;
+ }
+ else
+ {
+ if (ob_size - curtype == 1)
+ inline_contents = true;
+ }
+ }
+ }
+ }
/* Traverse struct aliases; it is important to get the
original struct and its tag name (if any). */
@@ -8150,33 +8340,6 @@ encode_aggregate_within (tree type, int curtype, int format, int left,
obstack_1grow (&util_obstack, right);
}
-static void
-encode_aggregate (tree type, int curtype, int format)
-{
- enum tree_code code = TREE_CODE (type);
-
- switch (code)
- {
- case RECORD_TYPE:
- {
- encode_aggregate_within (type, curtype, format, '{', '}');
- break;
- }
- case UNION_TYPE:
- {
- encode_aggregate_within (type, curtype, format, '(', ')');
- break;
- }
-
- case ENUMERAL_TYPE:
- obstack_1grow (&util_obstack, 'i');
- break;
-
- default:
- break;
- }
-}
-
/* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
field type. */
@@ -8188,74 +8351,159 @@ encode_next_bitfield (int width)
obstack_grow (&util_obstack, buffer, strlen (buffer));
}
-/* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */
+
+/* Encodes 'type', ignoring type qualifiers (which you should encode
+ beforehand if needed) with the exception of 'const', which is
+ encoded by encode_type. See above for the explanation of
+ 'curtype'. 'format' can be OBJC_ENCODE_INLINE_DEFS or
+ OBJC_ENCODE_DONT_INLINE_DEFS.
+*/
static void
encode_type (tree type, int curtype, int format)
{
enum tree_code code = TREE_CODE (type);
char c;
+ /* Ignore type qualifiers other than 'const' when encoding a
+ type. */
+
if (type == error_mark_node)
return;
if (TYPE_READONLY (type))
obstack_1grow (&util_obstack, 'r');
- if (code == INTEGER_TYPE)
+ switch (code)
{
- switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+ case ENUMERAL_TYPE:
+ if (flag_next_runtime)
{
- case 8: c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
- case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
- case 32:
- if (type == long_unsigned_type_node
- || type == long_integer_type_node)
- c = TYPE_UNSIGNED (type) ? 'L' : 'l';
- else
- c = TYPE_UNSIGNED (type) ? 'I' : 'i';
+ /* Kludge for backwards-compatibility with gcc-3.3: enums
+ are always encoded as 'i' no matter what type they
+ actually are (!). */
+ c = 'i';
break;
- case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
- default: abort ();
}
- obstack_1grow (&util_obstack, c);
- }
-
- else if (code == REAL_TYPE)
- {
- /* Floating point types. */
- switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
- {
- case 32: c = 'f'; break;
- case 64:
- case 96:
- case 128: c = 'd'; break;
- default: abort ();
- }
- obstack_1grow (&util_obstack, c);
- }
+ /* Else, they are encoded exactly like the integer type that is
+ used by the compiler to store them. */
+ case INTEGER_TYPE:
+ {
+ switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+ {
+ case 8: c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
+ case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
+ case 32:
+ if (flag_next_runtime)
+ {
+ tree int_type;
+ /* Another legacy kludge for compatiblity with
+ gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
+ but not always. For typedefs, we need to use 'i'
+ or 'I' instead if encoding a struct field, or a
+ pointer! */
+ int_type = ((!generating_instance_variables
+ && (obstack_object_size (&util_obstack)
+ == (unsigned) curtype))
+ ? TYPE_MAIN_VARIANT (type)
+ : type);
+
+ if (int_type == long_unsigned_type_node
+ || int_type == long_integer_type_node)
+ c = TYPE_UNSIGNED (type) ? 'L' : 'l';
+ else
+ c = TYPE_UNSIGNED (type) ? 'I' : 'i';
+ }
+ else
+ {
+ if (type == long_unsigned_type_node
+ || type == long_integer_type_node)
+ c = TYPE_UNSIGNED (type) ? 'L' : 'l';
+ else
+ c = TYPE_UNSIGNED (type) ? 'I' : 'i';
+ }
+ break;
+ case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
+ case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
+ default: abort ();
+ }
+ obstack_1grow (&util_obstack, c);
+ break;
+ }
+ case REAL_TYPE:
+ {
+ /* Floating point types. */
+ switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+ {
+ case 32: c = 'f'; break;
+ case 64: c = 'd'; break;
+ case 96:
+ case 128: c = 'D'; break;
+ default: abort ();
+ }
+ obstack_1grow (&util_obstack, c);
+ break;
+ }
+ case VOID_TYPE:
+ obstack_1grow (&util_obstack, 'v');
+ break;
- else if (code == VOID_TYPE)
- obstack_1grow (&util_obstack, 'v');
+ case BOOLEAN_TYPE:
+ obstack_1grow (&util_obstack, 'B');
+ break;
- else if (code == BOOLEAN_TYPE)
- obstack_1grow (&util_obstack, 'B');
+ case ARRAY_TYPE:
+ encode_array (type, curtype, format);
+ break;
- else if (code == ARRAY_TYPE)
- encode_array (type, curtype, format);
+ case POINTER_TYPE:
+#ifdef OBJCPLUS
+ case REFERENCE_TYPE:
+#endif
+ encode_pointer (type, curtype, format);
+ break;
- else if (code == POINTER_TYPE)
- encode_pointer (type, curtype, format);
+ case RECORD_TYPE:
+ encode_aggregate_within (type, curtype, format, '{', '}');
+ break;
- else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
- encode_aggregate (type, curtype, format);
+ case UNION_TYPE:
+ encode_aggregate_within (type, curtype, format, '(', ')');
+ break;
- else if (code == FUNCTION_TYPE) /* '?' */
- obstack_1grow (&util_obstack, '?');
+ case FUNCTION_TYPE: /* '?' means an unknown type. */
+ obstack_1grow (&util_obstack, '?');
+ break;
- else if (code == COMPLEX_TYPE)
- {
+ case COMPLEX_TYPE:
+ /* A complex is encoded as 'j' followed by the inner type (eg,
+ "_Complex int" is encoded as 'ji'). */
obstack_1grow (&util_obstack, 'j');
encode_type (TREE_TYPE (type), curtype, format);
+ break;
+
+ case VECTOR_TYPE:
+ encode_vector (type, curtype, format);
+ break;
+
+ default:
+ warning (0, "unknown type %s found during Objective-C encoding",
+ gen_type_name (type));
+ obstack_1grow (&util_obstack, '?');
+ break;
+ }
+
+ if (flag_next_runtime)
+ {
+ /* Super-kludge. Some ObjC qualifier and type combinations need
+ to be rearranged for compatibility with gcc-3.3. */
+ if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
+ {
+ char *enc = obstack_base (&util_obstack) + curtype;
+
+ /* Rewrite "in const" from "nr" to "rn". */
+ if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
+ strncpy (enc - 1, "rn", 2);
+ }
}
}
@@ -8266,12 +8514,14 @@ encode_gnu_bitfield (int position, tree type, int size)
char buffer[40];
char charType = '?';
- if (code == INTEGER_TYPE)
+ /* This code is only executed for the GNU runtime, so we can ignore
+ the NeXT runtime kludge of always encoding enums as 'i' no matter
+ what integers they actually are. */
+ if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
{
if (integer_zerop (TYPE_MIN_VALUE (type)))
+ /* Unsigned integer types. */
{
- /* Unsigned integer types. */
-
if (TYPE_MODE (type) == QImode)
charType = 'C';
else if (TYPE_MODE (type) == HImode)
@@ -8286,7 +8536,6 @@ encode_gnu_bitfield (int position, tree type, int size)
else if (TYPE_MODE (type) == DImode)
charType = 'Q';
}
-
else
/* Signed integer types. */
{
@@ -8306,10 +8555,12 @@ encode_gnu_bitfield (int position, tree type, int size)
charType = 'q';
}
}
- else if (code == ENUMERAL_TYPE)
- charType = 'i';
else
- abort ();
+ {
+ /* Do not do any encoding, produce an error and keep going. */
+ error ("trying to encode non-integer type as a bitfield");
+ return;
+ }
sprintf (buffer, "b%d%c%d", position, charType, size);
obstack_grow (&util_obstack, buffer, strlen (buffer));
@@ -8335,7 +8586,7 @@ encode_field_decl (tree field_decl, int curtype, int format)
encode_next_bitfield (size);
else
encode_gnu_bitfield (int_bit_position (field_decl),
- DECL_BIT_FIELD_TYPE (field_decl), size);
+ DECL_BIT_FIELD_TYPE (field_decl), size);
}
else
encode_type (TREE_TYPE (field_decl), curtype, format);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 24f0c17c4bd..150dac4e4b8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,65 @@
2010-09-27 Nicola Pero <nicola.pero@meta-innovation.com>
+ PR objc/25464
+ * objc.dg/type-size-3.m: New test.
+
+2010-09-27 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ PR objc/45763
+ * objc.dg/encode-1.m: Execute the test with the GNU runtime as
+ well.
+
+2010-09-27 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ PR objc/25450
+ * objc.dg/encode-3.m: Updated for fix of encoding of enums.
+ * objc.dg/type-size-2.m: Same change.
+ * obj-c++.dg/encode-5.mm: Same change.
+
+2010-09-27 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ Merge from 'apple/trunk' branch on FSF servers. The original
+ Changelogs are below.
+
+ * objc.dg/encode-6.m: Execute the test only with the GNU runtime.
+ * objc.dg/encode-6-next.m: New file (from encode-6.m in the
+ branch).
+ * objc.dg/encode-7-next.m: New file (from encode-7.m in the
+ branch).
+ * objc.dg/encode-7-next-64bit.m: New file (from encode-7-64bit.m
+ in the branch).
+ * objc.dg/proto-qual-1.m: Test the 3.3 ABI on NeXT (from
+ proto-qual-1.m in the branch) and the normal ABI on GNU.
+ * objc.dg/threedotthree-abi-1.m: New file (from the branch). Run
+ the test only with the NeXT runtime.
+ * obj-c++/encode-1.mm: Execute the test only with the GNU runtime.
+ * obj-c++/encode-1-next.mm: New file (from encode-1.mm in the
+ branch).
+ * obj-c++.dg/threedotthree-abi-1.mm: New file (from the branch).
+ Run the test only with the NeXT runtime.
+
+ 2006-03-30 Fariborz Jahanian <fjahanian@apple.com>
+
+ Radar 4492973
+ * objc.dg/encode-7-64bit.m: New.
+ * objc.dg/encode-7.m: Skip if -m64.
+
+ 2005-10-19 Fariborz Jahanian <fjahanian@apple.com>
+
+ Radar 4301047
+ * objc.dg/proto-qual-1.m: Fix test to match 3.3 ABI
+ * obj-c++.dg/threedotthree-abi-1.mm: New
+ * objc.dg/threedotthree-abi-1.m: New
+
+ 2005-07-20 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 4136935
+ * obj-c++.dg/encode-1.mm: Tweak encodings to match fix.
+ * objc.dg/encode-6.m: Likewise.
+ * objc.dg/encode-7.m: New test case.
+
+2010-09-27 Nicola Pero <nicola.pero@meta-innovation.com>
+
Merge from 'apple/trunk' branch on FSF servers. Renamed
const-str-12.m to constr-str-12b.m to avoid conflicts.
diff --git a/gcc/testsuite/obj-c++.dg/encode-1-next.mm b/gcc/testsuite/obj-c++.dg/encode-1-next.mm
new file mode 100644
index 00000000000..47673f20cb2
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/encode-1-next.mm
@@ -0,0 +1,26 @@
+/* This file tests that things are encoded using the gcc-3.3 ABI which is only
+ used by the NeXT runtime. */
+/* Test for graceful encoding of const-qualified fields and parameters. */
+/* Author: Ziemowit Laski <zlaski@apple.com> */
+
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+
+struct Cxx {
+ const struct Cxx *next;
+};
+
+@interface ObjC {
+ const struct Cxx *obj;
+}
+- (ObjC *)initWithCxx: (struct Cxx *const)c and: (const struct Cxx *)d;
+@end
+
+@implementation ObjC
+- (ObjC *)initWithCxx: (struct Cxx *const)c and: (const struct Cxx *)d {
+ obj = d;
+ return self;
+}
+@end
+
+/* { dg-final { scan-assembler "@\[0-9\]+@0:\[0-9\]+\\^{Cxx=\\^{Cxx}}\[0-9\]+r\\^{Cxx=\\^{Cxx}}" } } */
diff --git a/gcc/testsuite/obj-c++.dg/encode-1.mm b/gcc/testsuite/obj-c++.dg/encode-1.mm
index c5f5ea969ab..5f5ba20139e 100644
--- a/gcc/testsuite/obj-c++.dg/encode-1.mm
+++ b/gcc/testsuite/obj-c++.dg/encode-1.mm
@@ -2,6 +2,7 @@
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
struct Cxx {
const struct Cxx *next;
diff --git a/gcc/testsuite/obj-c++.dg/encode-5.mm b/gcc/testsuite/obj-c++.dg/encode-5.mm
index 4959ea394a3..18db3f3dd8c 100644
--- a/gcc/testsuite/obj-c++.dg/encode-5.mm
+++ b/gcc/testsuite/obj-c++.dg/encode-5.mm
@@ -70,7 +70,21 @@ int main(void) {
CHECK_IF(offs3 == offs2 + sizeof(XXRect) && offs4 == offs3 + sizeof(int));
CHECK_IF(totsize == offs4 + sizeof(int));
meth = [proto descriptionForClassMethod: @selector(getEnum:enum:bool:)];
- scan_initial("^i%u@%u:%u^{?=ff(__XXAngle=II)}%ui%uc%u");
+ /* Here we have the complication that 'enum Enum' could be encoded
+ as 'i' on __NEXT_RUNTIME_, and (most likely) as 'I' on the GNU
+ runtime. So we get the @encode(enum Enum), then put it into the
+ string in place of the traditional 'i'.
+ */
+ /* scan_initial("^i%u@%u:%u^{?=ff(__XXAngle=II)}%ui%uc%u"); */
+ {
+ char pattern[1024];
+
+ sprintf (pattern, "^%s%%u@%%u:%%u^{?=ff(__XXAngle=II)}%%u%s%%uc%%u",
+ @encode(enum Enum), @encode(enum Enum));
+ scan_initial(pattern);
+ }
+
+
CHECK_IF(offs3 == offs2 + sizeof(XXPoint *) && offs4 == offs3 + sizeof(enum Enum));
CHECK_IF(totsize == offs4 + sizeof(int)); /* 'ObjCBool' is really 'char' */
meth = [proto descriptionForClassMethod: @selector(getBool:)];
diff --git a/gcc/testsuite/obj-c++.dg/threedotthree-abi-1.mm b/gcc/testsuite/obj-c++.dg/threedotthree-abi-1.mm
new file mode 100644
index 00000000000..56fa701c86f
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/threedotthree-abi-1.mm
@@ -0,0 +1,71 @@
+/* This file tests that things are encoded using the gcc-3.3 ABI which is only
+ used by the NeXT runtime. */
+/* { dg-do run { target *-*-darwin* } } */
+/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+#include <stdio.h>
+#include <string.h>
+#include "../objc-obj-c++-shared/Protocol1.h"
+#ifndef __NEXT_RUNTIME__
+#include <objc/objc-api.h>
+#endif
+
+extern "C" void abort();
+
+
+@protocol CommonProtocol
+
+-(oneway void)methodCall_On:(in bycopy id)someValue_On;
+-(oneway void)methodCall_nO:(bycopy in id)someValue_nO;
+
+-(oneway void)methodCall_Oo:(out bycopy id)someValue_Oo;
+-(oneway void)methodCall_oO:(bycopy out id)someValue_oO;
+
+-(oneway void)methodCall_rn:(in const id)someValue_rn;
+
+-(oneway void)methodCall_oOn:(in bycopy out id)someValue_oOn;
+
+@end
+
+@interface ObjCClass <CommonProtocol>
+{
+
+}
+
+@end
+
+@implementation ObjCClass
+-(oneway void)methodCall_On:(in bycopy id)someValue_On { }
+-(oneway void)methodCall_nO:(bycopy in id)someValue_nO { }
+
+-(oneway void)methodCall_Oo:(out bycopy id)someValue_Oo { }
+-(oneway void)methodCall_oO:(bycopy out id)someValue_oO { }
+
+-(oneway void)methodCall_rn:(in const id)someValue_rn { }
+-(oneway void)methodCall_oOn:(in bycopy out id)someValue_oOn { }
+@end
+
+Protocol *proto = @protocol(CommonProtocol);
+struct objc_method_description *meth;
+
+int main()
+{
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_On:)];
+ if (strcmp (meth->types, "Vv12@0:4On@8"))
+ abort();
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_nO:)];
+ if (strcmp (meth->types, "Vv12@0:4nO@8"))
+ abort();
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_Oo:)];
+ if (strcmp (meth->types, "Vv12@0:4Oo@8"))
+ abort();
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_oO:)];
+ if (strcmp (meth->types, "Vv12@0:4oO@8"))
+ abort();
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_rn:)];
+ if (strcmp (meth->types, "Vv12@0:4rn@8"))
+ abort();
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_oOn:)];
+ if (strcmp (meth->types, "Vv12@0:4oOn@8"))
+ abort();
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/encode-1.m b/gcc/testsuite/objc.dg/encode-1.m
index 50e9919f941..09cb6af19c2 100644
--- a/gcc/testsuite/objc.dg/encode-1.m
+++ b/gcc/testsuite/objc.dg/encode-1.m
@@ -4,7 +4,6 @@
where we have 'typedef char BOOL'. */
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */
-/* { dg-options "-fnext-runtime" } */
#include <string.h>
#include <stdlib.h>
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc.dg/encode-3.m b/gcc/testsuite/objc.dg/encode-3.m
index 63a92e19cd0..432245337ab 100644
--- a/gcc/testsuite/objc.dg/encode-3.m
+++ b/gcc/testsuite/objc.dg/encode-3.m
@@ -44,7 +44,7 @@ unsigned totsize, offs0, offs1, offs2, offs3, offs4, offs5, offs6, offs7;
static void scan_initial(const char *pattern) {
totsize = offs0 = offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = offs7 = (unsigned)-1;
sscanf(meth->types, pattern, &totsize, &offs0, &offs1, &offs2, &offs3,
- &offs4, &offs5, &offs6, &offs7);
+ &offs4, &offs5, &offs6, &offs7);
CHECK_IF(!offs0 && offs1 == sizeof(id) && offs2 == offs1 + sizeof(SEL) && totsize >= offs2);
}
@@ -65,7 +65,21 @@ int main(void) {
CHECK_IF(offs3 == offs2 + sizeof(XXRect) && offs4 == offs3 + sizeof(int));
CHECK_IF(totsize == offs4 + sizeof(int));
meth = [proto descriptionForClassMethod: @selector(getEnum:enum:bool:)];
- scan_initial("^i%u@%u:%u^{?=ff(__XXAngle=II)}%ui%uc%u");
+
+ /* Here we have the complication that 'enum Enum' could be encoded
+ as 'i' on __NEXT_RUNTIME_, and (most likely) as 'I' on the GNU
+ runtime. So we get the @encode(enum Enum), then put it into the
+ string in place of the traditional 'i'.
+ */
+ /* scan_initial("^i%u@%u:%u^{?=ff(__XXAngle=II)}%ui%uc%u"); */
+ {
+ char pattern[1024];
+
+ sprintf (pattern, "^%s%%u@%%u:%%u^{?=ff(__XXAngle=II)}%%u%s%%uc%%u",
+ @encode(enum Enum), @encode(enum Enum));
+ scan_initial(pattern);
+ }
+
CHECK_IF(offs3 == offs2 + sizeof(XXPoint *) && offs4 == offs3 + sizeof(enum Enum));
CHECK_IF(totsize == offs4 + sizeof(int)); /* 'ObjCBool' is really 'char' */
meth = [proto descriptionForClassMethod: @selector(getBool:)];
diff --git a/gcc/testsuite/objc.dg/encode-6-next.m b/gcc/testsuite/objc.dg/encode-6-next.m
new file mode 100644
index 00000000000..c3d922659aa
--- /dev/null
+++ b/gcc/testsuite/objc.dg/encode-6-next.m
@@ -0,0 +1,23 @@
+/* Test for graceful encoding of const-qualified fields and parameters. */
+/* Author: Ziemowit Laski <zlaski@apple.com> */
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+
+struct Cxx {
+ const struct Cxx *next;
+};
+
+@interface ObjC {
+ const struct Cxx *obj;
+}
+- (ObjC *)initWithCxx: (struct Cxx *const)c and: (const struct Cxx *)d;
+@end
+
+@implementation ObjC
+- (ObjC *)initWithCxx: (struct Cxx *const)c and: (const struct Cxx *)d {
+ obj = d;
+ return self;
+}
+@end
+
+/* { dg-final { scan-assembler "@\[0-9\]+@0:\[0-9\]+\\^{Cxx=\\^{Cxx}}\[0-9\]+r\\^{Cxx=\\^{Cxx}}" } } */
diff --git a/gcc/testsuite/objc.dg/encode-6.m b/gcc/testsuite/objc.dg/encode-6.m
index 263b02ad0f3..291a41e96a0 100644
--- a/gcc/testsuite/objc.dg/encode-6.m
+++ b/gcc/testsuite/objc.dg/encode-6.m
@@ -1,6 +1,7 @@
/* Test for graceful encoding of const-qualified fields and parameters. */
/* Author: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
struct Cxx {
const struct Cxx *next;
diff --git a/gcc/testsuite/objc.dg/encode-7-next-64bit.m b/gcc/testsuite/objc.dg/encode-7-next-64bit.m
new file mode 100644
index 00000000000..2a064d8816c
--- /dev/null
+++ b/gcc/testsuite/objc.dg/encode-7-next-64bit.m
@@ -0,0 +1,266 @@
+/* Additional testing for the NeXT runtime. Encoding in -m64 mode */
+
+/* { dg-do run { target *-*-darwin* } } */
+/* { dg-options "-m64" } */
+/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+
+#include <objc/Object.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#define CHECK_IF(E) if (!(E)) abort ()
+
+@class NSDictionary, NSFont, NSError, _NSATSTypesetterGuts, NSString, NSMenu, NSArray;
+
+typedef unsigned char UInt8;
+typedef const signed long OSStatus;
+typedef unsigned long CFIndex;
+typedef unsigned int UInt32;
+typedef UInt32 FourCharCode;
+typedef FourCharCode OSType;
+
+struct FSRef {
+ UInt8 hidden[80];
+};
+typedef struct FSRef FSRef;
+
+typedef struct _NSPoint {
+ float x;
+ float y;
+} NSPoint;
+
+typedef struct _NSSize {
+ float width;
+ float height;
+} NSSize;
+
+typedef struct _NSRect {
+ NSPoint origin;
+ NSSize size;
+} NSRect;
+
+typedef struct _NSRange {
+ unsigned int location;
+ unsigned int length;
+} NSRange;
+
+typedef const char *NXAtom;
+
+typedef struct {
+ NSDictionary *_attributes;
+ NSFont *_font;
+ CFIndex _characterLength;
+ CFIndex _nominalGlyphLocation;
+ const CFIndex *p;
+ float _defaultLineHeight;
+ float _defaultBaselineOffset;
+ float _horizExpansion;
+ float _baselineDelta;
+ NSRect _attachmentBBox;
+ long ll, *llp;
+ unsigned long ull, *ullp;
+ id a;
+ const id a1;
+ const struct objc_object *a2;
+ SEL b;
+ const SEL b1;
+ const struct objc_selector *b2;
+ const char *str1;
+ char *str2;
+ char *const str3;
+ const char *const str4;
+ struct {
+ unsigned int _isAttachmentRun:1;
+ unsigned int _hasPositionalStake:1;
+ unsigned int _isDefaultFace:1;
+ unsigned int _hasCombiningMarks:1;
+ unsigned int _isScreenFont:1;
+ unsigned int _reserved:27;
+ } _rFlags;
+} NSATSGlyphStorageRun;
+
+typedef struct __CFSet *CFMutableSetRef;
+typedef const struct __CTLine * CTLineRef;
+typedef const struct __NSAppleEventManagerSuspension* NSAppleEventManagerSuspensionID;
+
+struct ComponentInstanceRecord {
+ long data[1];
+};
+typedef struct ComponentInstanceRecord ComponentInstanceRecord;
+typedef ComponentInstanceRecord *ComponentInstance;
+
+typedef NSString *(*NSErrorUserInfoFormatterFunc)(id objToBeDisplayed, NSError *err, char modifier);
+typedef struct {
+ NSErrorUserInfoFormatterFunc formatterFunc;
+ NSString *userInfoKey;
+ unsigned int parameterMask;
+} NSErrorUserInfoFormatter;
+
+typedef Object MyObj;
+typedef Object *MyPtr;
+
+@interface Foo: Object {
+ NSATSGlyphStorageRun r;
+}
+- (NSError *)_errorWithOSStatus:(OSStatus)inOSStatus ref1:(const FSRef *)inRef1 ref2:(const struct FSRef *)inRef2
+ reading:(BOOL)inReadingNotWriting;
+- (const NSATSGlyphStorageRun *)_attributeRunForCharacterAtIndex:(const CFIndex)charIndex;
+- (const _NSATSTypesetterGuts *)_getATSTypesetterGuts:(const struct objc_selector *)sel;
+- (void)resumeWithSuspensionID:(NSAppleEventManagerSuspensionID)suspensionID and:(const CFIndex *)status;
+- (const id)anotherMeth:(const SEL)sel and:(const Foo *)foo and:(const struct objc_object *)obj;
+- (id)str1:(const char *)str1 str2:(char *)str2 str3:(char *const)str3 str4:(const char *const)str4;
+- (oneway void)foo1:(Foo *)foo1 foo2:(const Foo *)foo2 foo3:(Foo *const)foo3 foo4:(const Foo *const)foo4;
+- (in const char *)sel1:(const SEL)sel1 id1:(const id)id1;
+- (inout id)obj1:(const MyPtr)obj1 obj2:(Object *const)obj2 obj3:(MyObj *const)obj3;
++ (ComponentInstance)_defaultScriptingComponent;
+- (NSString *)_formatCocoaErrorString:(NSString *)formatString parameters:(const char *)parameters
+ applicableFormatters:(NSErrorUserInfoFormatter **)formatters count:(int)numFormatters;
+- (NSErrorUserInfoFormatter *)formatter_func:(id)obj run:(const NSATSGlyphStorageRun **)run;
+- (BOOL)_forgetWord:(bycopy in NSString *)word inDictionary:(bycopy in NSString *)language;
+- (void)_registerServicesMenu:(NSMenu *)servicesMenu withSendTypes:(const NXAtom *)sendTypes
+ andReturnTypes:(const NXAtom *)returnTypes addToList:(BOOL)addToList;
++ (CFMutableSetRef *)_proxySharePointer;
+- (NSRange)_checkGrammarInString:(in NSString *)stringToCheck language:(bycopy in NSString *)language details:(bycopy out NSArray **)details;
+- (bool)_resolvePositionalStakeGlyphsForLineFragment:(CTLineRef)line lineFragmentRect:(NSRect)lineFragmentRect
+ minPosition:(float)minPosition maxPosition:(float)maxPosition maxLineFragmentWidth:(float)maxLineFragmentWidth
+ breakHint:(CFIndex *)charIndex;
++ (BOOL)findVoiceByIdentifier:(NSString *)identifier returningCreator:(OSType *)returnedCreator returningID:(OSType *)returnedID;
+@end
+
+NSRange globalRange;
+
+@implementation Foo
+- (NSError *)_errorWithOSStatus:(OSStatus)inOSStatus ref1:(const FSRef *)inRef1 ref2:(const struct FSRef *)inRef2
+ reading:(BOOL)inReadingNotWriting {
+ return (NSError *)self;
+}
+- (const NSATSGlyphStorageRun *)_attributeRunForCharacterAtIndex:(CFIndex)charIndex {
+ return (const NSATSGlyphStorageRun *)self;
+}
+- (const _NSATSTypesetterGuts *)_getATSTypesetterGuts:(const struct objc_selector *)sel {
+ return (const _NSATSTypesetterGuts *)self;
+}
+- (void)resumeWithSuspensionID:(NSAppleEventManagerSuspensionID)suspensionID and:(const CFIndex *)status {
+}
+- (const id)anotherMeth:(const SEL)sel and:(const Foo *)foo and:(const struct objc_object *)obj {
+ return (const id)self;
+}
+- (id)str1:(const char *)str1 str2:(char *)str2 str3:(char *const)str3 str4:(const char *const)str4 {
+ return self;
+}
+- (oneway void)foo1:(Foo *)foo1 foo2:(const Foo *)foo2 foo3:(Foo *const)foo3 foo4:(const Foo *const)foo4 {
+}
+- (in const char *)sel1:(const SEL)sel1 id1:(const id)id1 {
+ return "Hello";
+}
+- (inout id)obj1:(const MyPtr)obj1 obj2:(Object *const)obj2 obj3:(MyObj *const)obj3 {
+ return self;
+}
++ (ComponentInstance)_defaultScriptingComponent {
+ return (ComponentInstance)0;
+}
+- (NSString *)_formatCocoaErrorString:(NSString *)formatString parameters:(const char *)parameters
+ applicableFormatters:(NSErrorUserInfoFormatter **)formatters count:(int)numFormatters {
+ return (NSString *)self;
+}
+- (NSErrorUserInfoFormatter *)formatter_func:(id)obj run:(const NSATSGlyphStorageRun **)run {
+ return (NSErrorUserInfoFormatter *)0;
+}
+- (BOOL)_forgetWord:(bycopy in NSString *)word inDictionary:(bycopy in NSString *)language {
+ return YES;
+}
+- (void)_registerServicesMenu:(NSMenu *)servicesMenu withSendTypes:(const NXAtom *)sendTypes
+ andReturnTypes:(const NXAtom *)returnTypes addToList:(BOOL)addToList {
+}
++ (CFMutableSetRef *)_proxySharePointer {
+ return (CFMutableSetRef *)0;
+}
+- (NSRange)_checkGrammarInString:(in NSString *)stringToCheck language:(bycopy in NSString *)language details:(bycopy out NSArray **)details {
+ return globalRange;
+}
+- (bool)_resolvePositionalStakeGlyphsForLineFragment:(CTLineRef)line lineFragmentRect:(NSRect)lineFragmentRect
+ minPosition:(float)minPosition maxPosition:(float)maxPosition maxLineFragmentWidth:(float)maxLineFragmentWidth
+ breakHint:(CFIndex *)charIndex {
+ return false;
+}
++ (BOOL)findVoiceByIdentifier:(NSString *)identifier returningCreator:(OSType *)returnedCreator returningID:(OSType *)returnedID {
+ return NO;
+}
+@end
+
+int main(void) {
+ Class fooClass = objc_getClass ("Foo");
+ Method meth;
+ struct objc_ivar_list *ivars;
+ struct objc_ivar *ivar;
+
+ meth = class_getInstanceMethod (fooClass, @selector(_errorWithOSStatus:ref1:ref2:reading:));
+ CHECK_IF (!strcmp (meth->method_types, "@44@0:8q16r^{FSRef=[80C]}24r^{FSRef=[80C]}32c40"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_attributeRunForCharacterAtIndex:));
+ CHECK_IF (!strcmp (meth->method_types, "r^{?=@@QQ^Qffff{_NSRect={_NSPoint=ff}{_NSSize=ff}}q^qQ^Q@@@:::****{?=b1b1b1b1b1b27}}24@0:8Q16"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_getATSTypesetterGuts:));
+ CHECK_IF (!strcmp (meth->method_types, "r@24@0:8r:16"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(resumeWithSuspensionID:and:));
+ CHECK_IF (!strcmp (meth->method_types, "v32@0:8^{__NSAppleEventManagerSuspension=}16r^Q24"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(anotherMeth:and:and:));
+ CHECK_IF (!strcmp (meth->method_types, "r@40@0:8r:16r@24r@32"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(str1:str2:str3:str4:));
+ CHECK_IF (!strcmp (meth->method_types, "@48@0:8r*16*24*32r*40"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(foo1:foo2:foo3:foo4:));
+ CHECK_IF (!strcmp (meth->method_types, "Vv48@0:8@16r@24@32r@40"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(sel1:id1:));
+ CHECK_IF (!strcmp (meth->method_types, "rn*32@0:8r:16r@24"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(obj1:obj2:obj3:));
+ CHECK_IF (!strcmp (meth->method_types, "N@40@0:8r@16@24^{Object=#}32"));
+
+ meth = class_getClassMethod (fooClass, @selector(_defaultScriptingComponent));
+ CHECK_IF (!strcmp (meth->method_types, "^{ComponentInstanceRecord=[1q]}16@0:8"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_formatCocoaErrorString:parameters:applicableFormatters:count:));
+ CHECK_IF (!strcmp (meth->method_types, "@44@0:8@16r*24^^{?}32i40"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(formatter_func:run:));
+ CHECK_IF (!strcmp (meth->method_types, "^{?=^?@I}32@0:8@16r^^{?}24"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_forgetWord:inDictionary:));
+ CHECK_IF (!strcmp (meth->method_types, "c32@0:8nO@16nO@24"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_registerServicesMenu:withSendTypes:andReturnTypes:addToList:));
+ CHECK_IF (!strcmp (meth->method_types, "v44@0:8@16r^*24r^*32c40"));
+
+ meth = class_getClassMethod (fooClass, @selector(_proxySharePointer));
+ CHECK_IF (!strcmp (meth->method_types, "^^{__CFSet}16@0:8"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_checkGrammarInString:language:details:));
+ CHECK_IF (!strcmp (meth->method_types, "{_NSRange=II}40@0:8n@16nO@24oO^@32"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_resolvePositionalStakeGlyphsForLineFragment:lineFragmentRect:minPosition:maxPosition:maxLineFragmentWidth:breakHint:));
+ CHECK_IF (!strcmp (meth->method_types, "B60@0:8^{__CTLine=}16{_NSRect={_NSPoint=ff}{_NSSize=ff}}24f40f44f48^Q52"));
+
+ meth = class_getClassMethod (fooClass, @selector(findVoiceByIdentifier:returningCreator:returningID:));
+ CHECK_IF (!strcmp (meth->method_types, "c40@0:8@16^I24^I32"));
+
+ ivars = fooClass->ivars;
+ CHECK_IF (ivars->ivar_count == 1);
+
+ ivar = ivars->ivar_list;
+ CHECK_IF (!strcmp (ivar->ivar_name, "r"));
+ CHECK_IF (!strcmp (ivar->ivar_type,
+ "{?=\"_attributes\"@\"NSDictionary\"\"_font\"@\"NSFont\"\"_characterLength\""
+ "Q\"_nominalGlyphLocation\"Q\"p\"^Q\"_defaultLineHeight\"f\"_defaultBaselineOffset\""
+ "f\"_horizExpansion\"f\"_baselineDelta\"f\"_attachmentBBox\"{_NSRect=\"origin\""
+ "{_NSPoint=\"x\"f\"y\"f}\"size\"{_NSSize=\"width\"f\"height\"f}}\"ll\"q\"llp\"^q\"ull\""
+ "Q\"ullp\"^Q\"a\"@\"a1\"@\"a2\"@\"b\":\"b1\":\"b2\":\"str1\"*\"str2\"*\"str3\"*\"str4\""
+ "*\"_rFlags\"{?=\"_isAttachmentRun\"b1\"_hasPositionalStake\"b1\"_isDefaultFace\""
+ "b1\"_hasCombiningMarks\"b1\"_isScreenFont\"b1\"_reserved\"b27}}"));
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/encode-7-next.m b/gcc/testsuite/objc.dg/encode-7-next.m
new file mode 100644
index 00000000000..60db23675eb
--- /dev/null
+++ b/gcc/testsuite/objc.dg/encode-7-next.m
@@ -0,0 +1,267 @@
+/* Additional testing for the NeXT runtime. */
+/* Author: Ziemowit Laski <zlaski@apple.com> */
+
+/* { dg-do run { target *-*-darwin* } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "-m64" } { "" } } */
+/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+
+#include "../objc-obj-c++-shared/Object1.h"
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#define CHECK_IF(E) if (!(E)) abort ()
+
+@class NSDictionary, NSFont, NSError, _NSATSTypesetterGuts, NSString, NSMenu, NSArray;
+
+typedef unsigned char UInt8;
+typedef const signed long OSStatus;
+typedef unsigned long CFIndex;
+typedef unsigned int UInt32;
+typedef UInt32 FourCharCode;
+typedef FourCharCode OSType;
+
+struct FSRef {
+ UInt8 hidden[80];
+};
+typedef struct FSRef FSRef;
+
+typedef struct _NSPoint {
+ float x;
+ float y;
+} NSPoint;
+
+typedef struct _NSSize {
+ float width;
+ float height;
+} NSSize;
+
+typedef struct _NSRect {
+ NSPoint origin;
+ NSSize size;
+} NSRect;
+
+typedef struct _NSRange {
+ unsigned int location;
+ unsigned int length;
+} NSRange;
+
+typedef const char *NXAtom;
+
+typedef struct {
+ NSDictionary *_attributes;
+ NSFont *_font;
+ CFIndex _characterLength;
+ CFIndex _nominalGlyphLocation;
+ const CFIndex *p;
+ float _defaultLineHeight;
+ float _defaultBaselineOffset;
+ float _horizExpansion;
+ float _baselineDelta;
+ NSRect _attachmentBBox;
+ long ll, *llp;
+ unsigned long ull, *ullp;
+ id a;
+ const id a1;
+ const struct objc_object *a2;
+ SEL b;
+ const SEL b1;
+ const struct objc_selector *b2;
+ const char *str1;
+ char *str2;
+ char *const str3;
+ const char *const str4;
+ struct {
+ unsigned int _isAttachmentRun:1;
+ unsigned int _hasPositionalStake:1;
+ unsigned int _isDefaultFace:1;
+ unsigned int _hasCombiningMarks:1;
+ unsigned int _isScreenFont:1;
+ unsigned int _reserved:27;
+ } _rFlags;
+} NSATSGlyphStorageRun;
+
+typedef struct __CFSet *CFMutableSetRef;
+typedef const struct __CTLine * CTLineRef;
+typedef const struct __NSAppleEventManagerSuspension* NSAppleEventManagerSuspensionID;
+
+struct ComponentInstanceRecord {
+ long data[1];
+};
+typedef struct ComponentInstanceRecord ComponentInstanceRecord;
+typedef ComponentInstanceRecord *ComponentInstance;
+
+typedef NSString *(*NSErrorUserInfoFormatterFunc)(id objToBeDisplayed, NSError *err, char modifier);
+typedef struct {
+ NSErrorUserInfoFormatterFunc formatterFunc;
+ NSString *userInfoKey;
+ unsigned int parameterMask;
+} NSErrorUserInfoFormatter;
+
+typedef Object MyObj;
+typedef Object *MyPtr;
+
+@interface Foo: Object {
+ NSATSGlyphStorageRun r;
+}
+- (NSError *)_errorWithOSStatus:(OSStatus)inOSStatus ref1:(const FSRef *)inRef1 ref2:(const struct FSRef *)inRef2
+ reading:(BOOL)inReadingNotWriting;
+- (const NSATSGlyphStorageRun *)_attributeRunForCharacterAtIndex:(const CFIndex)charIndex;
+- (const _NSATSTypesetterGuts *)_getATSTypesetterGuts:(const struct objc_selector *)sel;
+- (void)resumeWithSuspensionID:(NSAppleEventManagerSuspensionID)suspensionID and:(const CFIndex *)status;
+- (const id)anotherMeth:(const SEL)sel and:(const Foo *)foo and:(const struct objc_object *)obj;
+- (id)str1:(const char *)str1 str2:(char *)str2 str3:(char *const)str3 str4:(const char *const)str4;
+- (oneway void)foo1:(Foo *)foo1 foo2:(const Foo *)foo2 foo3:(Foo *const)foo3 foo4:(const Foo *const)foo4;
+- (in const char *)sel1:(const SEL)sel1 id1:(const id)id1;
+- (inout id)obj1:(const MyPtr)obj1 obj2:(Object *const)obj2 obj3:(MyObj *const)obj3;
++ (ComponentInstance)_defaultScriptingComponent;
+- (NSString *)_formatCocoaErrorString:(NSString *)formatString parameters:(const char *)parameters
+ applicableFormatters:(NSErrorUserInfoFormatter **)formatters count:(int)numFormatters;
+- (NSErrorUserInfoFormatter *)formatter_func:(id)obj run:(const NSATSGlyphStorageRun **)run;
+- (BOOL)_forgetWord:(bycopy in NSString *)word inDictionary:(bycopy in NSString *)language;
+- (void)_registerServicesMenu:(NSMenu *)servicesMenu withSendTypes:(const NXAtom *)sendTypes
+ andReturnTypes:(const NXAtom *)returnTypes addToList:(BOOL)addToList;
++ (CFMutableSetRef *)_proxySharePointer;
+- (NSRange)_checkGrammarInString:(in NSString *)stringToCheck language:(bycopy in NSString *)language details:(bycopy out NSArray **)details;
+- (bool)_resolvePositionalStakeGlyphsForLineFragment:(CTLineRef)line lineFragmentRect:(NSRect)lineFragmentRect
+ minPosition:(float)minPosition maxPosition:(float)maxPosition maxLineFragmentWidth:(float)maxLineFragmentWidth
+ breakHint:(CFIndex *)charIndex;
++ (BOOL)findVoiceByIdentifier:(NSString *)identifier returningCreator:(OSType *)returnedCreator returningID:(OSType *)returnedID;
+@end
+
+NSRange globalRange;
+
+@implementation Foo
+- (NSError *)_errorWithOSStatus:(OSStatus)inOSStatus ref1:(const FSRef *)inRef1 ref2:(const struct FSRef *)inRef2
+ reading:(BOOL)inReadingNotWriting {
+ return (NSError *)self;
+}
+- (const NSATSGlyphStorageRun *)_attributeRunForCharacterAtIndex:(CFIndex)charIndex {
+ return (const NSATSGlyphStorageRun *)self;
+}
+- (const _NSATSTypesetterGuts *)_getATSTypesetterGuts:(const struct objc_selector *)sel {
+ return (const _NSATSTypesetterGuts *)self;
+}
+- (void)resumeWithSuspensionID:(NSAppleEventManagerSuspensionID)suspensionID and:(const CFIndex *)status {
+}
+- (const id)anotherMeth:(const SEL)sel and:(const Foo *)foo and:(const struct objc_object *)obj {
+ return (const id)self;
+}
+- (id)str1:(const char *)str1 str2:(char *)str2 str3:(char *const)str3 str4:(const char *const)str4 {
+ return self;
+}
+- (oneway void)foo1:(Foo *)foo1 foo2:(const Foo *)foo2 foo3:(Foo *const)foo3 foo4:(const Foo *const)foo4 {
+}
+- (in const char *)sel1:(const SEL)sel1 id1:(const id)id1 {
+ return "Hello";
+}
+- (inout id)obj1:(const MyPtr)obj1 obj2:(Object *const)obj2 obj3:(MyObj *const)obj3 {
+ return self;
+}
++ (ComponentInstance)_defaultScriptingComponent {
+ return (ComponentInstance)0;
+}
+- (NSString *)_formatCocoaErrorString:(NSString *)formatString parameters:(const char *)parameters
+ applicableFormatters:(NSErrorUserInfoFormatter **)formatters count:(int)numFormatters {
+ return (NSString *)self;
+}
+- (NSErrorUserInfoFormatter *)formatter_func:(id)obj run:(const NSATSGlyphStorageRun **)run {
+ return (NSErrorUserInfoFormatter *)0;
+}
+- (BOOL)_forgetWord:(bycopy in NSString *)word inDictionary:(bycopy in NSString *)language {
+ return YES;
+}
+- (void)_registerServicesMenu:(NSMenu *)servicesMenu withSendTypes:(const NXAtom *)sendTypes
+ andReturnTypes:(const NXAtom *)returnTypes addToList:(BOOL)addToList {
+}
++ (CFMutableSetRef *)_proxySharePointer {
+ return (CFMutableSetRef *)0;
+}
+- (NSRange)_checkGrammarInString:(in NSString *)stringToCheck language:(bycopy in NSString *)language details:(bycopy out NSArray **)details {
+ return globalRange;
+}
+- (bool)_resolvePositionalStakeGlyphsForLineFragment:(CTLineRef)line lineFragmentRect:(NSRect)lineFragmentRect
+ minPosition:(float)minPosition maxPosition:(float)maxPosition maxLineFragmentWidth:(float)maxLineFragmentWidth
+ breakHint:(CFIndex *)charIndex {
+ return false;
+}
++ (BOOL)findVoiceByIdentifier:(NSString *)identifier returningCreator:(OSType *)returnedCreator returningID:(OSType *)returnedID {
+ return NO;
+}
+@end
+
+int main(void) {
+ Class fooClass = objc_getClass ("Foo");
+ Method meth;
+ struct objc_ivar_list *ivars;
+ struct objc_ivar *ivar;
+
+ meth = class_getInstanceMethod (fooClass, @selector(_errorWithOSStatus:ref1:ref2:reading:));
+ CHECK_IF (!strcmp (meth->method_types, "@24@0:4l8r^{FSRef=[80C]}12r^{FSRef=[80C]}16c20"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_attributeRunForCharacterAtIndex:));
+ CHECK_IF (!strcmp (meth->method_types, "r^{?=@@II^Iffff{_NSRect={_NSPoint=ff}{_NSSize=ff}}l^lL^L@@@:::****{?=b1b1b1b1b1b27}}12@0:4L8"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_getATSTypesetterGuts:));
+ CHECK_IF (!strcmp (meth->method_types, "r@12@0:4r:8"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(resumeWithSuspensionID:and:));
+ CHECK_IF (!strcmp (meth->method_types, "v16@0:4^{__NSAppleEventManagerSuspension=}8r^I12"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(anotherMeth:and:and:));
+ CHECK_IF (!strcmp (meth->method_types, "r@20@0:4r:8r@12r@16"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(str1:str2:str3:str4:));
+ CHECK_IF (!strcmp (meth->method_types, "@24@0:4r*8*12*16r*20"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(foo1:foo2:foo3:foo4:));
+ CHECK_IF (!strcmp (meth->method_types, "Vv24@0:4@8r@12@16r@20"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(sel1:id1:));
+ CHECK_IF (!strcmp (meth->method_types, "rn*16@0:4r:8r@12"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(obj1:obj2:obj3:));
+ CHECK_IF (!strcmp (meth->method_types, "N@20@0:4r@8@12^{Object=#}16"));
+
+ meth = class_getClassMethod (fooClass, @selector(_defaultScriptingComponent));
+ CHECK_IF (!strcmp (meth->method_types, "^{ComponentInstanceRecord=[1l]}8@0:4"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_formatCocoaErrorString:parameters:applicableFormatters:count:));
+ CHECK_IF (!strcmp (meth->method_types, "@24@0:4@8r*12^^{?}16i20"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(formatter_func:run:));
+ CHECK_IF (!strcmp (meth->method_types, "^{?=^?@I}16@0:4@8r^^{?}12"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_forgetWord:inDictionary:));
+ CHECK_IF (!strcmp (meth->method_types, "c16@0:4nO@8nO@12"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_registerServicesMenu:withSendTypes:andReturnTypes:addToList:));
+ CHECK_IF (!strcmp (meth->method_types, "v24@0:4@8r^*12r^*16c20"));
+
+ meth = class_getClassMethod (fooClass, @selector(_proxySharePointer));
+ CHECK_IF (!strcmp (meth->method_types, "^^{__CFSet}8@0:4"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_checkGrammarInString:language:details:));
+ CHECK_IF (!strcmp (meth->method_types, "{_NSRange=II}20@0:4n@8nO@12oO^@16"));
+
+ meth = class_getInstanceMethod (fooClass, @selector(_resolvePositionalStakeGlyphsForLineFragment:lineFragmentRect:minPosition:maxPosition:maxLineFragmentWidth:breakHint:));
+ CHECK_IF (!strcmp (meth->method_types, "B44@0:4^{__CTLine=}8{_NSRect={_NSPoint=ff}{_NSSize=ff}}12f28f32f36^I40"));
+
+ meth = class_getClassMethod (fooClass, @selector(findVoiceByIdentifier:returningCreator:returningID:));
+ CHECK_IF (!strcmp (meth->method_types, "c20@0:4@8^I12^I16"));
+
+ ivars = fooClass->ivars;
+ CHECK_IF (ivars->ivar_count == 1);
+
+ ivar = ivars->ivar_list;
+ CHECK_IF (!strcmp (ivar->ivar_name, "r"));
+ CHECK_IF (!strcmp (ivar->ivar_type,
+ "{?=\"_attributes\"@\"NSDictionary\"\"_font\"@\"NSFont\"\"_characterLength\""
+ "I\"_nominalGlyphLocation\"I\"p\"^I\"_defaultLineHeight\"f\"_defaultBaselineOffset\""
+ "f\"_horizExpansion\"f\"_baselineDelta\"f\"_attachmentBBox\"{_NSRect=\"origin\""
+ "{_NSPoint=\"x\"f\"y\"f}\"size\"{_NSSize=\"width\"f\"height\"f}}\"ll\"l\"llp\"^l\"ull\""
+ "L\"ullp\"^L\"a\"@\"a1\"@\"a2\"@\"b\":\"b1\":\"b2\":\"str1\"*\"str2\"*\"str3\"*\"str4\""
+ "*\"_rFlags\"{?=\"_isAttachmentRun\"b1\"_hasPositionalStake\"b1\"_isDefaultFace\""
+ "b1\"_hasCombiningMarks\"b1\"_isScreenFont\"b1\"_reserved\"b27}}"));
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/proto-qual-1.m b/gcc/testsuite/objc.dg/proto-qual-1.m
index 7c6c62d241b..ac650aa25a7 100644
--- a/gcc/testsuite/objc.dg/proto-qual-1.m
+++ b/gcc/testsuite/objc.dg/proto-qual-1.m
@@ -44,10 +44,20 @@ static void scan_initial(const char *pattern) {
int main(void) {
meth = [proto descriptionForInstanceMethod: @selector(address:with:)];
+#ifndef __NEXT_RUNTIME__
scan_initial("O@%u@%u:%uRN@%uo^^S%u");
+#else
+ /* The NEXT runtime tries to be compatible with gcc-3.3 */
+ scan_initial("O@%u@%u:%uNR@%uo^^S%u");
+#endif
CHECK_IF(offs3 == offs2 + aligned_sizeof(id) && totsize == offs3 + aligned_sizeof(unsigned));
meth = [proto descriptionForClassMethod: @selector(retainArgument:with:)];
+#ifndef __NEXT_RUNTIME__
scan_initial("Vv%u@%u:%uoO@%un^*%u");
+#else
+ /* The NEXT runtime tries to be compatible with gcc-3.3 */
+ scan_initial("Vv%u@%u:%uOo@%un^*%u");
+#endif
CHECK_IF(offs3 == offs2 + aligned_sizeof(id) && totsize == offs3 + aligned_sizeof(char **));
return 0;
}
diff --git a/gcc/testsuite/objc.dg/threedotthree-abi-1.m b/gcc/testsuite/objc.dg/threedotthree-abi-1.m
new file mode 100644
index 00000000000..8e4f2bed174
--- /dev/null
+++ b/gcc/testsuite/objc.dg/threedotthree-abi-1.m
@@ -0,0 +1,68 @@
+/* This file tests that things are encoded using the gcc-3.3 ABI which is only
+ used by the NeXT runtime. */
+/* { dg-do run { target *-*-darwin* } } */
+/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+#include <stdio.h>
+#include <string.h>
+#include "../objc-obj-c++-shared/Protocol1.h"
+
+extern void abort();
+
+
+@protocol CommonProtocol
+
+-(oneway void)methodCall_On:(in bycopy id)someValue_On;
+-(oneway void)methodCall_nO:(bycopy in id)someValue_nO;
+
+-(oneway void)methodCall_Oo:(out bycopy id)someValue_Oo;
+-(oneway void)methodCall_oO:(bycopy out id)someValue_oO;
+
+-(oneway void)methodCall_rn:(in const id)someValue_rn;
+
+-(oneway void)methodCall_oOn:(in bycopy out id)someValue_oOn;
+
+@end
+
+@interface ObjCClass <CommonProtocol>
+{
+
+}
+
+@end
+
+@implementation ObjCClass
+-(oneway void)methodCall_On:(in bycopy id)someValue_On { }
+-(oneway void)methodCall_nO:(bycopy in id)someValue_nO { }
+
+-(oneway void)methodCall_Oo:(out bycopy id)someValue_Oo { }
+-(oneway void)methodCall_oO:(bycopy out id)someValue_oO { }
+
+-(oneway void)methodCall_rn:(in const id)someValue_rn { }
+-(oneway void)methodCall_oOn:(in bycopy out id)someValue_oOn { }
+@end
+
+Protocol *proto = @protocol(CommonProtocol);
+struct objc_method_description *meth;
+
+int main()
+{
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_On:)];
+ if (strcmp (meth->types, "Vv12@0:4On@8"))
+ abort();
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_nO:)];
+ if (strcmp (meth->types, "Vv12@0:4nO@8"))
+ abort();
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_Oo:)];
+ if (strcmp (meth->types, "Vv12@0:4Oo@8"))
+ abort();
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_oO:)];
+ if (strcmp (meth->types, "Vv12@0:4oO@8"))
+ abort();
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_rn:)];
+ if (strcmp (meth->types, "Vv12@0:4rn@8"))
+ abort();
+ meth = [proto descriptionForInstanceMethod: @selector(methodCall_oOn:)];
+ if (strcmp (meth->types, "Vv12@0:4oOn@8"))
+ abort();
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/type-size-2.m b/gcc/testsuite/objc.dg/type-size-2.m
index 2f8d517a3a3..499f0831dd2 100644
--- a/gcc/testsuite/objc.dg/type-size-2.m
+++ b/gcc/testsuite/objc.dg/type-size-2.m
@@ -48,7 +48,20 @@ int main(void) {
cls = objc_get_class("ArrayTest");
meth = class_get_instance_method(cls, @selector(str:with:and:));
- scan_initial("r*%u@%u:%u*%u*%u[4i]%u");
+
+ /* Here we have the complication that 'enum Enum' could be encoded
+ as 'i' on __NEXT_RUNTIME_, and (most likely) as 'I' on the GNU
+ runtime. So we get the @encode(enum Enum), then put it into the
+ string in place of the traditional 'i'.
+ */
+ /* scan_initial("r*%u@%u:%u*%u*%u[4i]%u"); */
+ {
+ char pattern[1024];
+
+ sprintf (pattern, "r*%%u@%%u:%%u*%%u*%%u[4%s]%%u", @encode(enum Enum));
+ scan_initial(pattern);
+ }
+
CHECK_IF(offs3 == offs2 + sizeof(signed char *) && offs4 == offs3 + sizeof(unsigned char *));
CHECK_IF(totsize == offs4 + sizeof(enum Enum *));
meth = class_get_instance_method(cls, @selector(meth1:with:with:));
diff --git a/gcc/testsuite/objc.dg/type-size-3.m b/gcc/testsuite/objc.dg/type-size-3.m
new file mode 100644
index 00000000000..9486658853c
--- /dev/null
+++ b/gcc/testsuite/objc.dg/type-size-3.m
@@ -0,0 +1,18 @@
+/* Reject ivars with an unknown size. */
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com> */
+/* { dg-do compile } */
+
+typedef struct
+{
+ unsigned long int a;
+ double b[];
+} test_type;
+
+@interface Test
+{
+ test_type c;
+}
+@end
+
+@implementation Test
+@end /* { dg-error "instance variable has unknown size" } */
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index f9d9925798a..029b0a31ad8 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,5 +1,15 @@
2010-09-26 Nicola Pero <nicola.pero@meta-innovation.com>
+ * encoding.c (objc_sizeof_type): Added support for vector type and
+ for double long types.
+ (objc_alignof_type): Same change.
+ (objc_skip_typespec): Same change.
+ * objc/encoding.h (_C_GCINVISIBLE): Use '|' for _C_GCINVISIBLE
+ instead of '!' since '!' is already used for _C_VECTOR.
+ * objc/objc-api.h (_C_LNG_DBL): Added.
+
+2010-09-26 Nicola Pero <nicola.pero@meta-innovation.com>
+
* libobjc_entry.c: File removed.
2010-09-26 Kai Tietz <kai.tietz@onevision.com>
diff --git a/libobjc/encoding.c b/libobjc/encoding.c
index 35c95521b80..d417b87396e 100644
--- a/libobjc/encoding.c
+++ b/libobjc/encoding.c
@@ -148,6 +148,8 @@ objc_sizeof_type (const char *type)
/* Skip the variable name if any */
if (*type == '"')
{
+ /* FIXME: How do we know we won't read beyond the end of the
+ string. Here and in the rest of the file! */
for (type++; *type++ != '"';)
/* do nothing */;
}
@@ -217,6 +219,10 @@ objc_sizeof_type (const char *type)
return sizeof (double);
break;
+ case _C_LNG_DBL:
+ return sizeof (long double);
+ break;
+
case _C_VOID:
return sizeof (void);
break;
@@ -236,6 +242,19 @@ objc_sizeof_type (const char *type)
}
break;
+ case _C_VECTOR:
+ {
+ /* Skip the '!'. */
+ type++;
+ /* Skip the '['. */
+ type++;
+
+ /* The size in bytes is the following number. */
+ int size = atoi (type);
+ return size;
+ }
+ break;
+
case _C_BFLD:
{
/* The new encoding of bitfields is: b 'position' 'type' 'size' */
@@ -318,6 +337,10 @@ objc_sizeof_type (const char *type)
case _C_DBL:
return sizeof (_Complex double);
break;
+
+ case _C_LNG_DBL:
+ return sizeof (_Complex long double);
+ break;
default:
{
@@ -418,6 +441,10 @@ objc_alignof_type (const char *type)
return __alignof__ (double);
break;
+ case _C_LNG_DBL:
+ return __alignof__ (long double);
+ break;
+
case _C_PTR:
case _C_ATOM:
case _C_CHARPTR:
@@ -429,6 +456,23 @@ objc_alignof_type (const char *type)
/* do nothing */;
return objc_alignof_type (type);
+ case _C_VECTOR:
+ {
+ /* Skip the '!'. */
+ type++;
+ /* Skip the '['. */
+ type++;
+
+ /* Skip the size. */
+ while (isdigit ((unsigned char)*type))
+ type++;
+
+ /* Skip the ','. */
+ type++;
+
+ /* The alignment in bytes is the following number. */
+ return atoi (type);
+ }
case _C_STRUCT_B:
case _C_UNION_B:
{
@@ -496,6 +540,10 @@ objc_alignof_type (const char *type)
case _C_DBL:
return __alignof__ (_Complex double);
break;
+
+ case _C_LNG_DBL:
+ return __alignof__ (_Complex long double);
+ break;
default:
{
@@ -631,6 +679,7 @@ objc_skip_typespec (const char *type)
case _C_ULNG_LNG:
case _C_FLT:
case _C_DBL:
+ case _C_LNG_DBL:
case _C_VOID:
case _C_UNDEF:
return ++type;
@@ -642,7 +691,6 @@ objc_skip_typespec (const char *type)
case _C_ARY_B:
/* skip digits, typespec and closing ']' */
-
while (isdigit ((unsigned char)*++type))
;
type = objc_skip_typespec (type);
@@ -654,6 +702,30 @@ objc_skip_typespec (const char *type)
return 0;
}
+ case _C_VECTOR:
+ /* Skip '!' */
+ type++;
+ /* Skip '[' */
+ type++;
+ /* Skip digits (size) */
+ while (isdigit ((unsigned char)*type))
+ type++;
+ /* Skip ',' */
+ type++;
+ /* Skip digits (alignment) */
+ while (isdigit ((unsigned char)*type))
+ type++;
+ /* Skip typespec. */
+ type = objc_skip_typespec (type);
+ /* Skip closing ']'. */
+ if (*type == _C_ARY_E)
+ return ++type;
+ else
+ {
+ _objc_abort ("bad vector type %s\n", type);
+ return 0;
+ }
+
case _C_BFLD:
/* The new encoding of bitfields is: b 'position' 'type' 'size' */
while (isdigit ((unsigned char)*++type))
@@ -700,6 +772,8 @@ objc_skip_typespec (const char *type)
/*
Skip an offset as part of a method encoding. This is prepended by a
'+' if the argument is passed in registers.
+
+ FIXME: The compiler never generates '+'.
*/
const char *
objc_skip_offset (const char *type)
@@ -883,7 +957,7 @@ objc_get_type_qualifiers (const char *type)
the presence of bitfields inside the structure. */
void
objc_layout_structure (const char *type,
- struct objc_struct_layout *layout)
+ struct objc_struct_layout *layout)
{
const char *ntype;
@@ -979,6 +1053,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
bfld_field_size = atoi (objc_skip_typespec (bfld_type));
}
+ /* The following won't work for vectors. */
#ifdef BIGGEST_FIELD_ALIGNMENT
desired_align = MIN (desired_align, BIGGEST_FIELD_ALIGNMENT);
#endif
diff --git a/libobjc/objc/encoding.h b/libobjc/objc/encoding.h
index 0deae5f7fc2..177ef726a00 100644
--- a/libobjc/objc/encoding.h
+++ b/libobjc/objc/encoding.h
@@ -42,7 +42,7 @@ extern "C" {
#define _C_BYCOPY 'O'
#define _C_BYREF 'R'
#define _C_ONEWAY 'V'
-#define _C_GCINVISIBLE '!'
+#define _C_GCINVISIBLE '|'
#define _F_CONST 0x01
#define _F_IN 0x01
diff --git a/libobjc/objc/objc-api.h b/libobjc/objc/objc-api.h
index 9903739248c..be433cb9a05 100644
--- a/libobjc/objc/objc-api.h
+++ b/libobjc/objc/objc-api.h
@@ -68,13 +68,13 @@ struct objc_method_description
#define _C_ULNG_LNG 'Q'
#define _C_FLT 'f'
#define _C_DBL 'd'
+#define _C_LNG_DBL 'D'
#define _C_BFLD 'b'
-#define _C_BOOL 'B'
+#define _C_BOOL 'B'
#define _C_VOID 'v'
#define _C_UNDEF '?'
#define _C_PTR '^'
#define _C_CHARPTR '*'
-#define _C_ATOM '%'
#define _C_ARY_B '['
#define _C_ARY_E ']'
#define _C_UNION_B '('
@@ -82,7 +82,13 @@ struct objc_method_description
#define _C_STRUCT_B '{'
#define _C_STRUCT_E '}'
#define _C_VECTOR '!'
-#define _C_COMPLEX 'j'
+#define _C_COMPLEX 'j'
+
+/* The following one is never generated by the compiler. You can
+ treat it as equivalent to "*".
+*/
+#define _C_ATOM '%'
+
#include "deprecated/objc_error.h"