diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7954df7805bea70a8b2d7733627e05ec15640369..68dd7e9f8b41400676436cfc446e3ce26eeb5a9b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+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
diff --git a/gcc/doc/objc.texi b/gcc/doc/objc.texi
index 1beb748cfc23133255f8c5e9b9cc1e9fc37c9c9c..bf328797c72678121e987bf04a3d38ef32735f44 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 8e70e208bcda04abfca256d7ff3070788cba481e..b1fb7bc2a5f863196bcdd10cfc0a83262438da78 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,51 @@
+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.
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 5d76596479c148c9dbdcd81f0d5d9585f6003cb7..101f9fce0c932347b753ab67e0efa7520a823b2b 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 24f0c17c4bdfc75f95281bb7014712430b93a79d..150dac4e4b88d0c7dc1807d33862453f5804f12e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,63 @@
+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
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 0000000000000000000000000000000000000000..47673f20cb20cfe37fb152ca2a35cc01483d8500
--- /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 c5f5ea969ab35518361ecb3755075d92dc60a69e..5f5ba20139efef1618e1970d90adaa4f01444ef6 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 4959ea394a318c4cff1e70a1ad747a5de7fae117..18db3f3dd8c6e6470d9a5d3476c63847fcfed5a8 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 0000000000000000000000000000000000000000..56fa701c86f2148fae34c6f1c94b566d20e81492
--- /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 50e9919f941b5480dbc7d86c6fb25cc63976b429..09cb6af19c2b7ed9848c79208ed58d4b6a8c6304 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 63a92e19cd04fc82ae18a917b1d5f7af1b4f30d3..432245337abd44bf4277152732ab95e74d3798d7 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 0000000000000000000000000000000000000000..c3d922659aa8d4aaf904adeed2d6aa3db0030f48
--- /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 263b02ad0f3c805ad2b03a1784e309ed966e43fa..291a41e96a0a783f1055ab8a502aa5c21c360bdb 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 0000000000000000000000000000000000000000..2a064d8816c4e9f4edddeb8b403d6ab4ca6dd453
--- /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 0000000000000000000000000000000000000000..60db23675ebf974a186c30e7c56ecfd5581d4423
--- /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 7c6c62d241b1f503d90061a515f0856d29992dab..ac650aa25a784e874fcb02f1ae84f60bca5176d0 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 0000000000000000000000000000000000000000..8e4f2bed1740bcdbc1b43f376ba395be05f087fc
--- /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 2f8d517a3a3ecd27e158ca033cb76f176e9f7b56..499f0831dd25cbe955759aa2977acdcf0503122d 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 0000000000000000000000000000000000000000..9486658853c9f0613fe2cbf3ec8776fd22710571
--- /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 f9d9925798af44c618d740c055c857b0fdf7e5b4..029b0a31ad8184236cedfc7891a4ce45ad893761 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,13 @@
+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.
diff --git a/libobjc/encoding.c b/libobjc/encoding.c
index 35c95521b80523993a9e94045e2671d67abdb701..d417b87396eff13bba01cd40f957c2e03a89debc 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 0deae5f7fc2d7228f82bb78f8ac27b195cef0d95..177ef726a00e2a20c6758c2b484268284b814188 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 9903739248cdafed4addccf5dca6ee6c2200fb54..be433cb9a0515aac0b5541c92de89ff0b4e0fa7c 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"