__intN patch 3/5: main __int128 -> __intN conversion.
diff mbox

Message ID 201408260303.s7Q33nqm024601@greed.delorie.com
State New
Headers show

Commit Message

DJ Delorie Aug. 26, 2014, 3:03 a.m. UTC
> I'd like to see the updated version of the whole of patch 3 (tested
> to be actually independent of the other patches) for review, though
> I won't be reviewing the C++ parts.

Here it is.  Tested on x86_64.  I include the msp430-modes.def patch
for demonstration purposes although obviously msp430's __int20 won't
work without the other patches.

gcc/
	* machmode.h (int_n_data_t): New.
	(int_n_enabled_p): New.
	(int_n_data): New.
	* tree.c (int_n_enabled_p): New.
	(int_n_trees): New.
	(make_or_reuse_type): Check for all __intN types, not just
	__int128.
	(build_common_tree_nodes): Likewise.  Also fill in integer_typs[]
	entries.
	* tree.h (int128_integer_type_node): Remove.
	(int128_unsigned_type_node): Remove.
	(int_n_trees_t): New.
	(int_n_enabled_p): New.
	(int_n_trees): New.
	* toplev.c (standard_type_bitsize): New.
	(do_compile): Check which __intN types are enabled for the current
	run.
	* builtin-types.def (BT_INT128): Remove.
	(BT_UINT128): Remove.
	* machmode.def: Add macro to create __int128 for all targets.
	* stor-layout.c (mode_for_size): Support __intN types.
	(smallest_mode_for_size): Likewise.
	(initialize_sizetypes): Support __intN types.
	* genmodes.c (struct mode_data): Add int_n field.
	(blank_mode): Likewise.
	(INT_N): New.
	(make_int_n): New.
	(emit_insn_modes_h): Count __intN entries and define
	NUM_INT_N_ENTS.
	(emit_mode_int_n): New.
	(emit_insn_modes_c): Call it.
	* gimple.c (gimple_signed_or_unsigned_type): Check for all __intN
	types, not just __int128.
	* tree-core.h (integer_type_kind): Remove __int128-specific
	entries, reserve spots for __intN entries.

gcc/c-family/

	* c-pretty-print.c (pp_c_integer_constant): Check for all __intN
	types, not just __int128.
	* c-cppbuiltin.c (c_cpp_builtins): Add builtins for all __intN
	types, not just __int128.
	(type_suffix): Use type precision, not specific types.
	* c-common.c (c_common_reswords): Remove __int128 special case.
	(c_common_type_for_size): Check for all __intN types, not just
	__int128.
	(c_common_type_for_mode): Likewise.
	(c_common_signed_or_unsigned_type): Likewise.
	(c_build_bitfield_integer_type): Likewise.
	(c_common_nodes_and_builtins): Likewise.
	(keyword_begins_type_specifier): Likewise.
	* c-common.h (rid): Remove RID_INT128 and add RID_INT_N_* for all
	__intN variants.

gcc/c/

	* c-parser.c (c_parse_init): Add RID entries for each __intN.
	(c_token_starts_typename): Check all __intN, not just __int128.
	(c_token_starts_declspecs): Likewise.
	(c_parser_declspecs): Likewise.
	(c_parser_attribute_any_word): Likewise.
	(c_parser_objc_selector): Likewise.
	* c-tree.h (c_typespec_keyword): cts_int128 -> cts_int_n.
	(struct c_declspecs): Add int_n_idx field to record *which* __intN
	is specified.
	* c-decl.c (declspecs_add_type): Check for all __intN, not just
	__int128.
	(finish_declspecs): Likewise.

gcc/cp/
	* typeck.c (cp_common_type): Check for all __intN types, not just
	__int128.
	* decl.c (grokdeclarator): Likewise.
	* rtti.c (emit_support_tinfos): Check for all __intN types, not just
	__int128.
	* parser.c (cp_lexer_next_token_is_decl_specifier_keyword): Check
	for all __intN types, not just __int128.
	(cp_parser_simple_type_specifier): Likewise.
	* mangle.c (integer_type_codes): Remove int128-specific codes.
	* cp-tree.h (cp_decl_specifier_seq): Add int_n_idx to store which
	__intN was specified.
	* lex.c (init_reswords): Reserve all __intN keywords.

gcc/lto/
	* lto-lang.c (lto_build_c_type_nodes): Check intN types for
	size-type as well.
	(lto_init): Initialize all intN types, not just int128.

* libstdc++-v3/
	* src/c++11/limits.cc: Add support for __intN types.
	* include/std/type_traits: Likewise.
	* include/std/limits: Likewise.
	* include/c_std/cstdlib: Likewise.
	* include/bits/cpp_type_traits.h: Likewise.
	* include/c_global/cstdlib: Likewise.

gcc/config/msp430
	* config/msp430/msp430-modes.def (PSI): Add.

Comments

Joseph Myers Sept. 1, 2014, 9:47 p.m. UTC | #1
On Mon, 25 Aug 2014, DJ Delorie wrote:

> +  for (i = 0; i < NUM_INT_N_ENTS; i ++)
> +    if (int_n_enabled_p[i])
> +      {
> +	char buf[35+20+20];
> +
> +	/* These are used to configure the C++ library.  */
> +
> +	if (!flag_iso || int_n_data[i].bitsize == POINTER_SIZE)
> +	  {
> +	    sprintf (buf, "__GLIBCXX_TYPE_INT_N_%d=__int%d", i, int_n_data[i].bitsize);
> +	    cpp_define (parse_in, buf);
> +
> +	    sprintf (buf, "__GLIBCXX_BITSIZE_INT_N_%d=%d", i, int_n_data[i].bitsize);
> +	    cpp_define (parse_in, buf);
> +	  }
> +      }

I think this should at least initially be conditioned on c_dialect_cxx ().

> +	    case RID_INT_N_0:
> +	    case RID_INT_N_1:
> +	    case RID_INT_N_2:
> +	    case RID_INT_N_3:
> +	      specs->int_n_idx = i - RID_INT_N_0;
> +	      if (!in_system_header_at (input_location)
> +		  /* As a special exception, allow a type that's used
> +		     for __SIZE_TYPE__.  */
> +		  && int_n_data[specs->int_n_idx].bitsize != POINTER_SIZE)

Given the precedent for long long as __SIZE_TYPE__, I don't think we 
should have that special exception.

The non-C++/libstdc++ parts are OK with those changes.
Jonathan Wakely Sept. 23, 2014, 7:03 p.m. UTC | #2
On 25/08/14 23:03 -0400, DJ Delorie wrote:
>
>> I'd like to see the updated version of the whole of patch 3 (tested
>> to be actually independent of the other patches) for review, though
>> I won't be reviewing the C++ parts.
>
>Here it is.  Tested on x86_64.  I include the msp430-modes.def patch
>for demonstration purposes although obviously msp430's __int20 won't
>work without the other patches.

[snip]

>* libstdc++-v3/
>	* src/c++11/limits.cc: Add support for __intN types.
>	* include/std/type_traits: Likewise.
>	* include/std/limits: Likewise.
>	* include/c_std/cstdlib: Likewise.
>	* include/bits/cpp_type_traits.h: Likewise.
>	* include/c_global/cstdlib: Likewise.

These libstdc++ changes are OK for trunk.

Just one question about the include/std/limits changes below.

It seems that __glibcxx_signed_b isn't strictly necessary as it
doesn't use the B argument, so is it just there for consistency?

>Index: libstdc++-v3/include/std/limits
>===================================================================
>--- libstdc++-v3/include/std/limits	(revision 214383)
>+++ libstdc++-v3/include/std/limits	(working copy)
>@@ -122,27 +122,38 @@
> #ifndef __glibcxx_long_double_tinyness_before
> #  define __glibcxx_long_double_tinyness_before false
> #endif
>
> // You should not need to define any macros below this point.
>
>-#define __glibcxx_signed(T)	((T)(-1) < 0)
>+#define __glibcxx_signed_b(T,B)	((T)(-1) < 0)
>
>-#define __glibcxx_min(T) \
>-  (__glibcxx_signed (T) ? -__glibcxx_max (T) - 1 : (T)0)
>+#define __glibcxx_min_b(T,B)					\
>+  (__glibcxx_signed_b (T,B) ? -__glibcxx_max_b (T,B) - 1 : (T)0)
>
>-#define __glibcxx_max(T) \
>-  (__glibcxx_signed (T) ? \
>-   (((((T)1 << (__glibcxx_digits (T) - 1)) - 1) << 1) + 1) : ~(T)0)
>+#define __glibcxx_max_b(T,B)						\
>+  (__glibcxx_signed_b (T,B) ?						\
>+   (((((T)1 << (__glibcxx_digits_b (T,B) - 1)) - 1) << 1) + 1) : ~(T)0)
>
>-#define __glibcxx_digits(T) \
>-  (sizeof(T) * __CHAR_BIT__ - __glibcxx_signed (T))
>+#define __glibcxx_digits_b(T,B)				\
>+  (B - __glibcxx_signed_b (T,B))
>
> // The fraction 643/2136 approximates log10(2) to 7 significant digits.
>+#define __glibcxx_digits10_b(T,B)		\
>+  (__glibcxx_digits_b (T,B) * 643L / 2136)
>+
>+#define __glibcxx_signed(T) \
>+  __glibcxx_signed_b (T, sizeof(T) * __CHAR_BIT__)
DJ Delorie Sept. 29, 2014, 6:06 p.m. UTC | #3
> Just one question about the include/std/limits changes below.
> 
> It seems that __glibcxx_signed_b isn't strictly necessary as it
> doesn't use the B argument, so is it just there for consistency?

Yup.
Jonathan Wakely Sept. 29, 2014, 6:37 p.m. UTC | #4
On 29/09/14 14:06 -0400, DJ Delorie wrote:
>
>> Just one question about the include/std/limits changes below.
>>
>> It seems that __glibcxx_signed_b isn't strictly necessary as it
>> doesn't use the B argument, so is it just there for consistency?
>
>Yup.

OK, thanks for confirming.
DJ Delorie Sept. 30, 2014, 7:37 p.m. UTC | #5
Joseph S. Myers <joseph@codesourcery.com> wrote:
> The non-C++/libstdc++ parts are OK with those changes.

Jonathan Wakely <jwakely@redhat.com> wrote:
> >* libstdc++-v3/
> >	* src/c++11/limits.cc: Add support for __intN types.
> >	* include/std/type_traits: Likewise.
> >	* include/std/limits: Likewise.
> >	* include/c_std/cstdlib: Likewise.
> >	* include/bits/cpp_type_traits.h: Likewise.
> >	* include/c_global/cstdlib: Likewise.
> 
> These libstdc++ changes are OK for trunk.

Do I still need approval for gcc/cp/* or do these cover it?
Jonathan Wakely Sept. 30, 2014, 10:54 p.m. UTC | #6
On 30/09/14 15:37 -0400, DJ Delorie wrote:
>
>Joseph S. Myers <joseph@codesourcery.com> wrote:
>> The non-C++/libstdc++ parts are OK with those changes.
>
>Jonathan Wakely <jwakely@redhat.com> wrote:
>> >* libstdc++-v3/
>> >	* src/c++11/limits.cc: Add support for __intN types.
>> >	* include/std/type_traits: Likewise.
>> >	* include/std/limits: Likewise.
>> >	* include/c_std/cstdlib: Likewise.
>> >	* include/bits/cpp_type_traits.h: Likewise.
>> >	* include/c_global/cstdlib: Likewise.
>>
>> These libstdc++ changes are OK for trunk.
>
>Do I still need approval for gcc/cp/* or do these cover it?

I can't approve gcc/cp/* changes and as Joseph says non-C++ I think
you need to chase someone else (i.e. Jason :-) for that.
DJ Delorie Sept. 30, 2014, 11:14 p.m. UTC | #7
Joseph S. Myers <joseph@codesourcery.com> wrote:
> The non-C++/libstdc++ parts are OK with those changes.

Jonathan Wakely <jwakely@redhat.com> wrote:
> These libstdc++ changes are OK for trunk.

Jason/Nathan,

Could one of you two please review the remaining C++ parts (cp/*) ?

  https://gcc.gnu.org/ml/gcc-patches/2014-08/msg02360.html

Thanks!
Jason Merrill Oct. 2, 2014, 3:22 a.m. UTC | #8
On 09/30/2014 07:14 PM, DJ Delorie wrote:
> Could one of you two please review the remaining C++ parts (cp/*) ?
>
>    https://gcc.gnu.org/ml/gcc-patches/2014-08/msg02360.html

> +      for (i = 0; i < NUM_INT_N_ENTS; i ++)
>  	{
> +	  if (int_n_enabled_p [i]
> +	      && (same_type_p (TYPE_MAIN_VARIANT (t1),
> +			       int_n_trees[i].signed_type)
> +		  || same_type_p (TYPE_MAIN_VARIANT (t2),
> +				  int_n_trees[i].signed_type)))
> +	    {
> +	      tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
> +			? int_n_trees[i].unsigned_type
> +			: int_n_trees[i].signed_type);
> +	      return build_type_attribute_variant (t, attributes);
> +	    }
>  	}

It seems like the int128 code here was broken and this is continuing 
that brokenness.  Extended integer types have integer conversion rank 
corresponding to their bitsize, so int128 should have higher rank than 
long long, but here it was being checked after long long, and your code 
also follows the long long code.  Also, we should be checking for both 
signed and unsigned variants.

If you plan to allow __intN with sizes between those of int and long 
long, they need to have the appropriate intermediate conversion rank for 
their size.

Basically I think the integral conversion code in cp_common_type ought 
to be rewritten to work on integer_types rather than naming specific types.

> -  'n',  /* itk_int128 */
> -  'o',  /* itk_unsigned_int128  */
> +  /* __intN types are handled separately */

Where are they mangled now?  I also don't see any mangling tests.

Jason
DJ Delorie Oct. 2, 2014, 3:52 a.m. UTC | #9
> It seems like the int128 code here was broken and this is continuing 
> that brokenness.  Extended integer types have integer conversion rank 
> corresponding to their bitsize, so int128 should have higher rank than 
> long long, but here it was being checked after long long, and your code 
> also follows the long long code.  Also, we should be checking for both 
> signed and unsigned variants.

In this case, we know that the two types are the same bitsize.  We
also know that no __intN type has the same size as a standard type
(__int128 being an exception).  So in any case where other __intN
types match, they won't match any of the other tests in this area
anyway.  Aside from choosing unsigned vs sighed (which the code does),
there are no other conversions within those bitsizes.

So if you think the __int128 case should be elsewhere in that logic
(and it seems to me that "long long" *should* be preferred over
__int128 if they're ths same bitsize) I can move it, but I don't think
there's any need to worry about other __intN types here.

> If you plan to allow __intN with sizes between those of int and long 
> long, they need to have the appropriate intermediate conversion rank for 
> their size.

But... we don't know the bit sizes at the gcc source level, we only
know them by iterating the array.  We'd have to iterate the array at
evey step to see if it's between bitsize N and M, or add the standard
types to some array, or add the __intN variants to integer_types[] and
re-sort i_t[].  However, doing that introduces the __intN types to
*everything* that uses integer_types[].  I was hesitant to add
nonstandard types to the standard promotion rules.

> Basically I think the integral conversion code in cp_common_type ought 
> to be rewritten to work on integer_types rather than naming specific types.

That would be the "re-sort it" option.

> > -  'n',  /* itk_int128 */
> > -  'o',  /* itk_unsigned_int128  */
> > +  /* __intN types are handled separately */
> 
> Where are they mangled now?  I also don't see any mangling tests.

They mangle as Inn like I20 or I128 (that might be the wrong letter,
but the syntax is like that).  It surprised me that there was a case
for "other unknown types", but there's a case for it :-)

The NULs are there just to ensure the array access works, and to tell
the code that there isn't a special case for those types.
Jason Merrill Oct. 2, 2014, 2:22 p.m. UTC | #10
On 10/01/2014 11:52 PM, DJ Delorie wrote:
>> It seems like the int128 code here was broken and this is continuing
>> that brokenness.  Extended integer types have integer conversion rank
>> corresponding to their bitsize, so int128 should have higher rank than
>> long long, but here it was being checked after long long, and your code
>> also follows the long long code.  Also, we should be checking for both
>> signed and unsigned variants.
>
> In this case, we know that the two types are the same bitsize.

True, when __int128 is the same size as long long it has lower rank. 
But it isn't always the same size; specifically, in the x32 ABI long 
long is 64 bits.  So we definitely need to deal with extended integer 
types larger than long long.

>> If you plan to allow __intN with sizes between those of int and long
>> long, they need to have the appropriate intermediate conversion rank for
>> their size.
>
> But... we don't know the bit sizes at the gcc source level, we only
> know them by iterating the array.  We'd have to iterate the array at
> evey step to see if it's between bitsize N and M, or add the standard
> types to some array, or add the __intN variants to integer_types[] and
> re-sort i_t[].

Right.

> However, doing that introduces the __intN types to
> *everything* that uses integer_types[].  I was hesitant to add
> nonstandard types to the standard promotion rules.

The C++ standard says that extended integer types participate in the 
usual arithmetic conversions.  If I add a 32-bit int and an __int48, the 
usual arithmetic conversions should convert the int to __int48.

I don't mind if you deal with this by asserting that extended integer 
types never fall between int and long long rather than actually trying 
to support it.

Extended integer types larger than long long also participate in 
enumeral promotion if needed, but I think your changes to 
c_common_type_for_size handle that.

>> Basically I think the integral conversion code in cp_common_type ought
>> to be rewritten to work on integer_types rather than naming specific types.
>
> That would be the "re-sort it" option.
>
>>> -  'n',  /* itk_int128 */
>>> -  'o',  /* itk_unsigned_int128  */
>>> +  /* __intN types are handled separately */
>>
>> Where are they mangled now?  I also don't see any mangling tests.
>
> They mangle as Inn like I20 or I128 (that might be the wrong letter,
> but the syntax is like that).  It surprised me that there was a case
> for "other unknown types", but there's a case for it :-)

Ah, I see that 'n' and 'o' for __int128 are handled further down in 
write_builtin_type. And we do have mangling tests for that 
(g++.dg/abi/mangle43.C).

We still need mangling tests for __int20, though.

Jason
Jason Merrill Oct. 2, 2014, 2:48 p.m. UTC | #11
On 10/02/2014 10:22 AM, Jason Merrill wrote:
> Extended integer types larger than long long also participate in
> enumeral promotion if needed, but I think your changes to
> c_common_type_for_size handle that.

...and it seems we currently don't support enums with underlying type 
larger than long long, though that would be nice to fix and adding 
extended integer types to integer_types[] would fix it.

Jason
DJ Delorie Oct. 2, 2014, 4:41 p.m. UTC | #12
> The C++ standard says that extended integer types participate in the 
> usual arithmetic conversions.  If I add a 32-bit int and an __int48, the 
> usual arithmetic conversions should convert the int to __int48.

Except the code you're referring to isn't part of that conversion.  It
only handles types that are the same size, not different sizes, and as
I said the __intN types are never the same size as standard types
(except __int128) so there are no conversions to worry about - in the
code you're referring to.

In the common parts of the MI the __intN types are handled separately,
in each case where i_t[] is referenced.

> We still need mangling tests for __int20, though.

The test would only pass for msp430x (and fail for msp430, which is
the same target back-end).  Do I need to redo the big patch, or would
a separate one suffice?
Jason Merrill Oct. 2, 2014, 5:44 p.m. UTC | #13
On 10/02/2014 12:41 PM, DJ Delorie wrote:
>> The C++ standard says that extended integer types participate in the
>> usual arithmetic conversions.  If I add a 32-bit int and an __int48, the
>> usual arithmetic conversions should convert the int to __int48.
>
> Except the code you're referring to isn't part of that conversion.  It
> only handles types that are the same size, not different sizes

Ah, good point.  In which case I don't see what this code is trying to 
accomplish relative to falling through to the "prefer the unsigned one" 
code below.  Shall we just remove it?

> The test would only pass for msp430x (and fail for msp430, which is
> the same target back-end).  Do I need to redo the big patch, or would
> a separate one suffice?

Separate is fine.

Jason
DJ Delorie Oct. 2, 2014, 6 p.m. UTC | #14
> Ah, good point.  In which case I don't see what this code is trying to 
> accomplish relative to falling through to the "prefer the unsigned one" 
> code below.  Shall we just remove it?

I don't know for sure.  There was __int128 code there, I replaced it
with the "same" code, so as to avoid any functional differences on
mainstream targets.

I imagine the code is there for when __int128 is the same size as some
other types besides long long.
DJ Delorie Oct. 2, 2014, 7:14 p.m. UTC | #15
> > The test would only pass for msp430x (and fail for msp430, which is
> > the same target back-end).  Do I need to redo the big patch, or would
> > a separate one suffice?
> 
> Separate is fine.

Turns out it's mangled like this:

__int20 foo (__int20 a, unsigned __int20 b);

_Z3foou5int20u6uint20
Jason Merrill Oct. 3, 2014, 2:06 p.m. UTC | #16
On 10/02/2014 02:00 PM, DJ Delorie wrote:
>> Ah, good point.  In which case I don't see what this code is trying to
>> accomplish relative to falling through to the "prefer the unsigned one"
>> code below.  Shall we just remove it?
>
> I don't know for sure.  There was __int128 code there, I replaced it
> with the "same" code, so as to avoid any functional differences on
> mainstream targets.
>
> I imagine the code is there for when __int128 is the same size as some
> other types besides long long.

But if __int128 happened to be the same size as long the code was wrong. 
  Well, I suppose it could be there to prefer __int128 to 
intTI_type_node.  I guess let's move the intN handling below the code 
for (u)long and add support for unsigned extended integers like there is 
for both long and long long.

Jason
DJ Delorie Oct. 3, 2014, 8:11 p.m. UTC | #17
Note that there is a separate __int128_t type that isn't part of the
"standard" extension.  Maybe it's there for that type?

Otherwise, I don't see what moving the test would accomplish.  If
"long" is never 128 bits, it doesn't matter if the int128 test is
before or after it, and the other intN are never the same size as
standard types, and we already have code to prefer unsigned for intN
types.
Jason Merrill Oct. 4, 2014, 6:10 p.m. UTC | #18
On 10/03/2014 04:11 PM, DJ Delorie wrote:
> Note that there is a separate __int128_t type that isn't part of the
> "standard" extension.  Maybe it's there for that type?
>
> Otherwise, I don't see what moving the test would accomplish.  If
> "long" is never 128 bits, it doesn't matter if the int128 test is
> before or after it, and the other intN are never the same size as
> standard types,

I don't see how you can assert that these will never happen.  Why not 
make the code more correct, while we're touching it?

> and we already have code to prefer unsigned for intN types.

What I don't see is the intN parallel to this:

>       if (same_type_p (TYPE_MAIN_VARIANT (t1), long_long_unsigned_type_node)
>           || same_type_p (TYPE_MAIN_VARIANT (t2), long_long_unsigned_type_node))
>         return build_type_attribute_variant (long_long_unsigned_type_node,
>                                              attributes);

Your patch only compares t1/t2 to int_n_trees[i].signed_type.

Jason
DJ Delorie Oct. 4, 2014, 6:36 p.m. UTC | #19
> > Otherwise, I don't see what moving the test would accomplish.  If
> > "long" is never 128 bits, it doesn't matter if the int128 test is
> > before or after it, and the other intN are never the same size as
> > standard types,
> 
> I don't see how you can assert that these will never happen.

It's checked specifically in toplev.c - if the backend *does* request
a type that matches a standard size, they won't get it:
 
+static bool
+standard_type_bitsize (int bitsize)
+{
+  /* As a special exception, we always want __int128 enabled if possible.  */
+  if (bitsize == 128)
+    return false;
+  if (bitsize == CHAR_TYPE_SIZE
+      || bitsize == SHORT_TYPE_SIZE
+      || bitsize == INT_TYPE_SIZE
+      || bitsize == LONG_TYPE_SIZE
+      || (bitsize == LONG_LONG_TYPE_SIZE && LONG_LONG_TYPE_SIZE < GET_MODE_BITSIZE (TImode)))
+    return true;
+  return false;
+}

+      /* This must happen after the backend has a chance to process
+	 command line options, but before the parsers are
+	 initialized.  */
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
+	if (targetm.scalar_mode_supported_p (int_n_data[i].m)
+	    && ! standard_type_bitsize (int_n_data[i].bitsize)
+	    && int_n_data[i].bitsize <= HOST_BITS_PER_WIDE_INT * 2)
+	  int_n_enabled_p[i] = true;
+	else
+	  int_n_enabled_p[i] = false;
+
Markus Trippelsdorf Oct. 14, 2014, 8:17 p.m. UTC | #20
On 2014.08.25 at 23:03 -0400, DJ Delorie wrote:
> 
> > I'd like to see the updated version of the whole of patch 3 (tested
> > to be actually independent of the other patches) for review, though
> > I won't be reviewing the C++ parts.
> 
> Here it is.  Tested on x86_64.  I include the msp430-modes.def patch
> for demonstration purposes although obviously msp430's __int20 won't
> work without the other patches.

This patch breaks ppc64:

../../gcc/gcc/config/rs6000/rs6000-c.c: In function ‘cpp_hashnode* rs6000_macro_to_expand(cpp_reader*, const cpp_token*)’:
../../gcc/gcc/config/rs6000/rs6000-c.c:237:24: error: ‘RID_INT128’ was not declared in this scope
make[3]: *** [rs6000-c.o] Error 1
DJ Delorie Oct. 14, 2014, 9:10 p.m. UTC | #21
> ../../gcc/gcc/config/rs6000/rs6000-c.c:237:24: error: ‘RID_INT128’ was not declared in this scope

Two options:

1. If you know the RS6000 will never have any __intN other than
   __int128, just use RID_INT_N_0, although this is a hack it will
   work as long as there *is* an __int128 for RS6000.

2. Alternately, you need to check all entries in the __int<N> array
   for proper size, which is more correct but more complex.

Would you like me to work on the second option, or would you prefer to
tackle this yourself?
Markus Trippelsdorf Oct. 15, 2014, 8:14 a.m. UTC | #22
On 2014.10.14 at 17:10 -0400, DJ Delorie wrote:
> 
> > ../../gcc/gcc/config/rs6000/rs6000-c.c:237:24: error: ‘RID_INT128’ was not declared in this scope
> 
> Two options:
> 
> 1. If you know the RS6000 will never have any __intN other than
>    __int128, just use RID_INT_N_0, although this is a hack it will
>    work as long as there *is* an __int128 for RS6000.
> 
> 2. Alternately, you need to check all entries in the __int<N> array
>    for proper size, which is more correct but more complex.
> 
> Would you like me to work on the second option, or would you prefer to
> tackle this yourself?

If you could implement the second option, it would be appreciated.

(I just noticed the build failure on the POWER7 compile farm machine,
that I use for testing sometimes.)

Thanks.
Andreas Schwab Oct. 16, 2014, 11:02 a.m. UTC | #23
FAIL: g++.dg/init/enum1.C  -std=gnu++11  (test for errors, line 12)
FAIL: g++.dg/init/enum1.C  -std=gnu++1y  (test for errors, line 12)
FAIL: g++.dg/init/enum1.C  -std=gnu++98  (test for errors, line 12)

That used to complain about "enum1.C:12:1: error: no integral type can
represent all of the enumerator values for 'test'"

Andreas.
DJ Delorie Oct. 16, 2014, 10:39 p.m. UTC | #24
> FAIL: g++.dg/init/enum1.C  -std=gnu++11  (test for errors, line 12)
> FAIL: g++.dg/init/enum1.C  -std=gnu++1y  (test for errors, line 12)
> FAIL: g++.dg/init/enum1.C  -std=gnu++98  (test for errors, line 12)
> 
> That used to complain about "enum1.C:12:1: error: no integral type can
> represent all of the enumerator values for 'test'"

On what host?  It works OK on x86-64.

PASS: g++.dg/init/enum1.C  -std=gnu++98  (test for errors, line 12)
PASS: g++.dg/init/enum1.C  -std=gnu++98 (test for excess errors)
PASS: g++.dg/init/enum1.C  -std=gnu++11  (test for errors, line 12)
PASS: g++.dg/init/enum1.C  -std=gnu++11 (test for excess errors)
PASS: g++.dg/init/enum1.C  -std=gnu++1y  (test for errors, line 12)
PASS: g++.dg/init/enum1.C  -std=gnu++1y (test for excess errors)
Andreas Schwab Oct. 20, 2014, 8:09 a.m. UTC | #25
DJ Delorie <dj@redhat.com> writes:

>> FAIL: g++.dg/init/enum1.C  -std=gnu++11  (test for errors, line 12)
>> FAIL: g++.dg/init/enum1.C  -std=gnu++1y  (test for errors, line 12)
>> FAIL: g++.dg/init/enum1.C  -std=gnu++98  (test for errors, line 12)
>> 
>> That used to complain about "enum1.C:12:1: error: no integral type can
>> represent all of the enumerator values for 'test'"
>
> On what host?  It works OK on x86-64.

Have you considered doing proper testing?

http://gcc.gnu.org/ml/gcc-testresults/2014-10/msg02106.html

Andreas.

Patch
diff mbox

Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	(revision 214383)
+++ gcc/machmode.h	(working copy)
@@ -342,7 +342,19 @@  extern void init_adjust_machine_modes (v
 			 GET_MODE_PRECISION (MODE2))
 
 #define HWI_COMPUTABLE_MODE_P(MODE) \
   (SCALAR_INT_MODE_P (MODE) \
    && GET_MODE_PRECISION (MODE) <= HOST_BITS_PER_WIDE_INT)
 
+typedef struct {
+  /* These parts are initailized by genmodes output */
+  unsigned int bitsize;
+  enum machine_mode m;
+  /* RID_* is RID_INTN_BASE + index into this array */
+} int_n_data_t;
+
+/* This is also in tree.h.  genmodes.c guarantees the're sorted from
+   smallest bitsize to largest bitsize. */
+extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+extern const int_n_data_t int_n_data[NUM_INT_N_ENTS];
+
 #endif /* not HAVE_MACHINE_MODES */
Index: gcc/c-family/c-pretty-print.c
===================================================================
--- gcc/c-family/c-pretty-print.c	(revision 214383)
+++ gcc/c-family/c-pretty-print.c	(working copy)
@@ -917,12 +917,14 @@  pp_c_void_constant (c_pretty_printer *pp
 
 /* Pretty-print an INTEGER literal.  */
 
 static void
 pp_c_integer_constant (c_pretty_printer *pp, tree i)
 {
+  int idx;
+
   /* We are going to compare the type of I to other types using
      pointer comparison so we need to use its canonical type.  */
   tree type =
     TYPE_CANONICAL (TREE_TYPE (i))
     ? TYPE_CANONICAL (TREE_TYPE (i))
     : TREE_TYPE (i);
@@ -947,15 +949,23 @@  pp_c_integer_constant (c_pretty_printer 
     pp_character (pp, 'u');
   if (type == long_integer_type_node || type == long_unsigned_type_node)
     pp_character (pp, 'l');
   else if (type == long_long_integer_type_node
 	   || type == long_long_unsigned_type_node)
     pp_string (pp, "ll");
-  else if (type == int128_integer_type_node
-           || type == int128_unsigned_type_node)
-    pp_string (pp, "I128");
+  else for (idx = 0; idx < NUM_INT_N_ENTS; idx ++)
+    if (int_n_enabled_p[idx])
+      {
+	char buf[2+20];
+	if (type == int_n_trees[idx].signed_type
+	    || type == int_n_trees[idx].unsigned_type)
+	  {
+	    sprintf (buf, "I%d", int_n_data[idx].bitsize);
+	    pp_string (pp, buf);
+	  }
+      }
 }
 
 /* Print out a CHARACTER literal.  */
 
 static void
 pp_c_character_constant (c_pretty_printer *pp, tree c)
Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c	(revision 214383)
+++ gcc/c-family/c-cppbuiltin.c	(working copy)
@@ -775,12 +775,14 @@  cpp_iec_559_complex_value (void)
 }
 
 /* Hook that registers front end and target-specific built-ins.  */
 void
 c_cpp_builtins (cpp_reader *pfile)
 {
+  int i;
+
   /* -undef turns off target-specific built-ins.  */
   if (flag_undef)
     return;
 
   define_language_independent_builtin_macros (pfile);
 
@@ -845,12 +847,29 @@  c_cpp_builtins (cpp_reader *pfile)
   builtin_define_type_minmax ("__WCHAR_MIN__", "__WCHAR_MAX__",
 			      underlying_wchar_type_node);
   builtin_define_type_minmax ("__WINT_MIN__", "__WINT_MAX__", wint_type_node);
   builtin_define_type_max ("__PTRDIFF_MAX__", ptrdiff_type_node);
   builtin_define_type_max ("__SIZE_MAX__", size_type_node);
 
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i])
+      {
+	char buf[35+20+20];
+
+	/* These are used to configure the C++ library.  */
+
+	if (!flag_iso || int_n_data[i].bitsize == POINTER_SIZE)
+	  {
+	    sprintf (buf, "__GLIBCXX_TYPE_INT_N_%d=__int%d", i, int_n_data[i].bitsize);
+	    cpp_define (parse_in, buf);
+
+	    sprintf (buf, "__GLIBCXX_BITSIZE_INT_N_%d=%d", i, int_n_data[i].bitsize);
+	    cpp_define (parse_in, buf);
+	  }
+      }
+
   /* stdint.h and the testsuite need to know these.  */
   builtin_define_stdint_macros ();
 
   /* Provide information for library headers to determine whether to
      define macros such as __STDC_IEC_559__ and
      __STDC_IEC_559_COMPLEX__.  */
@@ -993,15 +1012,20 @@  c_cpp_builtins (cpp_reader *pfile)
   else if (flag_stack_protect == 1)
     cpp_define (pfile, "__SSP__=1");
 
   if (flag_openmp)
     cpp_define (pfile, "_OPENMP=201307");
 
-  if (int128_integer_type_node != NULL_TREE)
-    builtin_define_type_sizeof ("__SIZEOF_INT128__",
-			        int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i])
+      {
+	char buf[15+20];
+	sprintf(buf, "__SIZEOF_INT%d__", int_n_data[i].bitsize);
+	builtin_define_type_sizeof (buf,
+				    int_n_trees[i].signed_type);
+      }
   builtin_define_type_sizeof ("__SIZEOF_WCHAR_T__", wchar_type_node);
   builtin_define_type_sizeof ("__SIZEOF_WINT_T__", wint_type_node);
   builtin_define_type_sizeof ("__SIZEOF_PTRDIFF_T__",
 			      unsigned_ptrdiff_type_node);
 
   /* A straightforward target hook doesn't work, because of problems
@@ -1227,18 +1251,21 @@  builtin_define_with_hex_fp_value (const 
 static const char *
 type_suffix (tree type)
 {
   static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
   int unsigned_suffix;
   int is_long;
+  int tp = TYPE_PRECISION (type);
 
   if (type == long_long_integer_type_node
-      || type == long_long_unsigned_type_node)
+      || type == long_long_unsigned_type_node
+      || tp > TYPE_PRECISION (long_integer_type_node))
     is_long = 2;
   else if (type == long_integer_type_node
-	   || type == long_unsigned_type_node)
+	   || type == long_unsigned_type_node
+	   || tp > TYPE_PRECISION (integer_type_node))
     is_long = 1;
   else if (type == integer_type_node
 	   || type == unsigned_type_node
 	   || type == short_integer_type_node
 	   || type == short_unsigned_type_node
 	   || type == signed_char_type_node
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 214383)
+++ gcc/c-family/c-common.c	(working copy)
@@ -58,18 +58,16 @@  cpp_reader *parse_in;		/* Declared in c-
 
    INTEGER_TYPE and REAL_TYPE nodes for the standard data types.
 
 	tree short_integer_type_node;
 	tree long_integer_type_node;
 	tree long_long_integer_type_node;
-	tree int128_integer_type_node;
 
 	tree short_unsigned_type_node;
 	tree long_unsigned_type_node;
 	tree long_long_unsigned_type_node;
-	tree int128_unsigned_type_node;
 
 	tree truthvalue_type_node;
 	tree truthvalue_false_node;
 	tree truthvalue_true_node;
 
 	tree ptrdiff_type_node;
@@ -462,13 +460,12 @@  const struct c_common_resword c_common_r
   { "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, D_CXXONLY },
   { "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, D_CXXONLY },
   { "__imag",		RID_IMAGPART,	0 },
   { "__imag__",		RID_IMAGPART,	0 },
   { "__inline",		RID_INLINE,	0 },
   { "__inline__",	RID_INLINE,	0 },
-  { "__int128",		RID_INT128,	0 },
   { "__is_abstract",	RID_IS_ABSTRACT, D_CXXONLY },
   { "__is_base_of",	RID_IS_BASE_OF, D_CXXONLY },
   { "__is_class",	RID_IS_CLASS,	D_CXXONLY },
   { "__is_convertible_to", RID_IS_CONVERTIBLE_TO, D_CXXONLY },
   { "__is_empty",	RID_IS_EMPTY,	D_CXXONLY },
   { "__is_enum",	RID_IS_ENUM,	D_CXXONLY },
@@ -3435,12 +3432,14 @@  check_case_bounds (location_t loc, tree 
 /* Return an integer type with BITS bits of precision,
    that is unsigned if UNSIGNEDP is nonzero, otherwise signed.  */
 
 tree
 c_common_type_for_size (unsigned int bits, int unsignedp)
 {
+  int i;
+
   if (bits == TYPE_PRECISION (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
   if (bits == TYPE_PRECISION (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
 
@@ -3451,16 +3450,17 @@  c_common_type_for_size (unsigned int bit
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
 
   if (bits == TYPE_PRECISION (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
 
-  if (int128_integer_type_node
-      && bits == TYPE_PRECISION (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& bits == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (bits == TYPE_PRECISION (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
 
   if (bits <= TYPE_PRECISION (intQI_type_node))
@@ -3518,12 +3518,13 @@  tree registered_builtin_types;
    then UNSIGNEDP selects between saturating and nonsaturating types.  */
 
 tree
 c_common_type_for_mode (enum machine_mode mode, int unsignedp)
 {
   tree t;
+  int i;
 
   if (mode == TYPE_MODE (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
   if (mode == TYPE_MODE (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -3534,15 +3535,17 @@  c_common_type_for_mode (enum machine_mod
   if (mode == TYPE_MODE (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
 
   if (mode == TYPE_MODE (long_long_integer_type_node))
     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
 
-  if (int128_integer_type_node
-      && mode == TYPE_MODE (int128_integer_type_node))
-    return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& mode == int_n_data[i].m)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (mode == TYPE_MODE (widest_integer_literal_type_node))
     return unsignedp ? widest_unsigned_literal_type_node
 		     : widest_integer_literal_type_node;
 
   if (mode == QImode)
@@ -3734,12 +3737,13 @@  c_common_signed_type (tree type)
    signed according to UNSIGNEDP.  */
 
 tree
 c_common_signed_or_unsigned_type (int unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   /* This block of code emulates the behavior of the old
      c_common_unsigned_type. In particular, it returns
      long_unsigned_type_node if passed a long, even when a int would
      have the same size. This is necessary for warnings to work
      correctly in archs where sizeof(int) == sizeof(long) */
@@ -3752,16 +3756,20 @@  c_common_signed_or_unsigned_type (int un
   if (type1 == short_integer_type_node || type1 == short_unsigned_type_node)
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (type1 == long_integer_type_node || type1 == long_unsigned_type_node)
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (type1 == long_long_integer_type_node || type1 == long_long_unsigned_type_node)
     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
-  if (int128_integer_type_node
-      && (type1 == int128_integer_type_node
-	  || type1 == int128_unsigned_type_node))
-    return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& (type1 == int_n_trees[i].unsigned_type
+	    || type1 == int_n_trees[i].signed_type))
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
+
   if (type1 == widest_integer_literal_type_node || type1 == widest_unsigned_literal_type_node)
     return unsignedp ? widest_unsigned_literal_type_node : widest_integer_literal_type_node;
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
@@ -3870,15 +3878,20 @@  c_common_signed_or_unsigned_type (int un
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (TYPE_OK (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (TYPE_OK (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& TYPE_MODE (type) == int_n_data[i].m
+	&& TYPE_PRECISION (type) == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
+
   if (TYPE_OK (widest_integer_literal_type_node))
     return (unsignedp ? widest_unsigned_literal_type_node
 	    : widest_integer_literal_type_node);
 
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
@@ -3899,12 +3912,14 @@  c_common_signed_or_unsigned_type (int un
 
 /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
 
 tree
 c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
 {
+  int i;
+
   /* Extended integer types of the same width as a standard type have
      lesser rank, so those of the same width as int promote to int or
      unsigned int and are valid for printf formats expecting int or
      unsigned int.  To avoid such special cases, avoid creating
      extended integer types for bit-fields if a standard integer type
      is available.  */
@@ -3916,16 +3931,17 @@  c_build_bitfield_integer_type (unsigned 
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (width == TYPE_PRECISION (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (width == TYPE_PRECISION (long_long_integer_type_node))
     return (unsignedp ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node
-      && width == TYPE_PRECISION (int128_integer_type_node))
-    return (unsignedp ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& width == int_n_data[i].bitsize)
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
   return build_nonstandard_integer_type (width, unsignedp);
 }
 
 /* The C version of the register_builtin_type langhook.  */
 
 void
@@ -5316,12 +5332,13 @@  c_common_nodes_and_builtins (void)
   int char16_type_size;
   int char32_type_size;
   int wchar_type_size;
   tree array_domain_type;
   tree va_list_ref_type_node;
   tree va_list_arg_type_node;
+  int i;
 
   build_common_tree_nodes (flag_signed_char, flag_short_double);
 
   /* Define `int' and `char' first so that dbx will output them first.  */
   record_builtin_type (RID_INT, NULL, integer_type_node);
   record_builtin_type (RID_CHAR, "char", char_type_node);
@@ -5332,19 +5349,25 @@  c_common_nodes_and_builtins (void)
   if (c_dialect_cxx ())
     record_builtin_type (RID_SIGNED, NULL, integer_type_node);
   record_builtin_type (RID_LONG, "long int", long_integer_type_node);
   record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node);
   record_builtin_type (RID_MAX, "long unsigned int",
 		       long_unsigned_type_node);
-  if (int128_integer_type_node != NULL_TREE)
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
     {
-      record_builtin_type (RID_INT128, "__int128",
-			   int128_integer_type_node);
-      record_builtin_type (RID_MAX, "__int128 unsigned",
-			   int128_unsigned_type_node);
+      char name[25];
+
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), xstrdup (name),
+			   int_n_trees[i].signed_type);
+      sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+      record_builtin_type (RID_MAX, xstrdup (name),
+			   int_n_trees[i].unsigned_type);
     }
+
   if (c_dialect_cxx ())
     record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node);
   record_builtin_type (RID_MAX, "long long int",
 		       long_long_integer_type_node);
   record_builtin_type (RID_MAX, "long long unsigned int",
 		       long_long_unsigned_type_node);
@@ -5374,12 +5397,14 @@  c_common_nodes_and_builtins (void)
 					 TYPE_DECL, NULL_TREE,
 					 intSI_type_node));
   lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					 TYPE_DECL, NULL_TREE,
 					 intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
+  /* Note that this is different than the __int128 type that's part of
+     the generic __intN support.  */
   if (targetm.scalar_mode_supported_p (TImode))
     lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
 					   TYPE_DECL,
 					   get_identifier ("__int128_t"),
 					   intTI_type_node));
 #endif
@@ -11726,13 +11751,12 @@  keyword_begins_type_specifier (enum rid 
     case RID_AUTO_TYPE:
     case RID_INT:
     case RID_CHAR:
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
-    case RID_INT128:
     case RID_UNSIGNED:
     case RID_LONG:
     case RID_SHORT:
     case RID_SIGNED:
     case RID_DFLOAT32:
     case RID_DFLOAT64:
@@ -11749,12 +11773,16 @@  keyword_begins_type_specifier (enum rid 
     case RID_STRUCT:
     case RID_CLASS:
     case RID_UNION:
     case RID_ENUM:
       return true;
     default:
+      if (keyword >= RID_FIRST_INT_N
+	  && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	  && int_n_enabled_p[keyword-RID_FIRST_INT_N])
+	return true;
       return false;
     }
 }
 
 /* Return true if KEYWORD names a type qualifier.  */
 
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 214383)
+++ gcc/c-family/c-common.h	(working copy)
@@ -88,13 +88,12 @@  enum rid
   /* C (reserved and imaginary types not implemented, so any use is a
      syntax error) */
   RID_IMAGINARY,
 
   /* C */
   RID_INT,     RID_CHAR,   RID_FLOAT,    RID_DOUBLE, RID_VOID,
-  RID_INT128,
   RID_ENUM,    RID_STRUCT, RID_UNION,    RID_IF,     RID_ELSE,
   RID_WHILE,   RID_DO,     RID_FOR,      RID_SWITCH, RID_CASE,
   RID_DEFAULT, RID_BREAK,  RID_CONTINUE, RID_RETURN, RID_GOTO,
   RID_SIZEOF,
 
   /* C extensions */
@@ -185,12 +184,29 @@  enum rid
   RID_ADDR_SPACE_14,
   RID_ADDR_SPACE_15,
 
   RID_FIRST_ADDR_SPACE = RID_ADDR_SPACE_0,
   RID_LAST_ADDR_SPACE = RID_ADDR_SPACE_15,
 
+  /* __intN keywords.  The _N_M here doesn't correspond to the intN
+     in the keyword; use the bitsize in int_n_t_data_t[M] for that.
+     For example, if int_n_t_data_t[0].bitsize is 13, then RID_INT_N_0
+     is for __int13.  */
+
+  /* Note that the range to use is RID_FIRST_INT_N through
+     RID_FIRST_INT_N + NUM_INT_N_ENTS - 1 and c-parser.c has a list of
+     all RID_INT_N_* in a case statement.  */
+
+  RID_INT_N_0,
+  RID_INT_N_1,
+  RID_INT_N_2,
+  RID_INT_N_3,
+
+  RID_FIRST_INT_N = RID_INT_N_0,
+  RID_LAST_INT_N = RID_INT_N_3,
+
   RID_MAX,
 
   RID_FIRST_MODIFIER = RID_STATIC,
   RID_LAST_MODIFIER = RID_ONEWAY,
 
   RID_FIRST_CXX0X = RID_CONSTEXPR,
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 214383)
+++ gcc/c/c-parser.c	(working copy)
@@ -110,12 +110,22 @@  c_parse_init (void)
 
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       C_IS_RESERVED_WORD (id) = 1;
       ridpointers [(int) c_common_reswords[i].rid] = id;
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    {
+      /* We always create the symbols but they aren't always supported.  */
+      char name[50];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      id = get_identifier (xstrdup (name));
+      C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+      C_IS_RESERVED_WORD (id) = 1;
+    }
 }
 
 /* The C lexer intermediates between the lexer in cpplib and c-lex.c
    and the C parser.  Unlike the C++ lexer, the parser structure
    stores the lexer information instead of using a separate structure.
    Identifiers are separated into ordinary identifiers, type names,
@@ -485,13 +495,12 @@  c_token_starts_typename (c_token *token)
 	}
     case CPP_KEYWORD:
       switch (token->keyword)
 	{
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -513,12 +522,16 @@  c_token_starts_typename (c_token *token)
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	      && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -643,13 +656,12 @@  c_token_starts_declspecs (c_token *token
 	case RID_INLINE:
 	case RID_NORETURN:
 	case RID_AUTO:
 	case RID_THREAD:
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -672,12 +684,16 @@  c_token_starts_declspecs (c_token *token
 	case RID_SAT:
 	case RID_ALIGNAS:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
 	  return true;
 	default:
+	  if (token->keyword >= RID_FIRST_INT_N
+	      && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	      && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	    return true;
 	  return false;
 	}
     case CPP_LESS:
       if (c_dialect_objc ())
 	return true;
       return false;
@@ -2156,13 +2172,13 @@  c_parser_static_assert_declaration_no_se
    storage-class-specifier:
      __thread
 
    type-specifier:
      typeof-specifier
      __auto_type
-     __int128
+     __intN
      _Decimal32
      _Decimal64
      _Decimal128
      _Fract
      _Accum
      _Sat
@@ -2310,13 +2326,12 @@  c_parser_declspecs (c_parser *parser, st
 	case RID_AUTO_TYPE:
 	  if (!auto_type_ok)
 	    goto out;
 	  /* Fall through.  */
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_SHORT:
 	case RID_SIGNED:
 	case RID_COMPLEX:
 	case RID_INT:
 	case RID_CHAR:
 	case RID_FLOAT:
@@ -2326,12 +2341,16 @@  c_parser_declspecs (c_parser *parser, st
 	case RID_DFLOAT64:
 	case RID_DFLOAT128:
 	case RID_BOOL:
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  if (!typespec_ok)
 	    goto out;
 	  attrs_ok = true;
 	  seen_type = true;
 	  if (c_dialect_objc ())
 	    parser->objc_need_raw_identifier = true;
@@ -3736,13 +3755,12 @@  c_parser_attribute_any_word (c_parser *p
       bool ok;
       switch (c_parser_peek_token (parser)->keyword)
 	{
 	case RID_STATIC:
 	case RID_UNSIGNED:
 	case RID_LONG:
-	case RID_INT128:
 	case RID_CONST:
 	case RID_EXTERN:
 	case RID_REGISTER:
 	case RID_TYPEDEF:
 	case RID_SHORT:
 	case RID_INLINE:
@@ -3766,12 +3784,16 @@  c_parser_attribute_any_word (c_parser *p
 	case RID_ACCUM:
 	case RID_SAT:
 	case RID_TRANSACTION_ATOMIC:
 	case RID_TRANSACTION_CANCEL:
 	case RID_ATOMIC:
 	case RID_AUTO_TYPE:
+	case RID_INT_N_0:
+	case RID_INT_N_1:
+	case RID_INT_N_2:
+	case RID_INT_N_3:
 	  ok = true;
 	  break;
 	default:
 	  ok = false;
 	  break;
 	}
@@ -8980,13 +9002,12 @@  c_parser_objc_selector (c_parser *parser
     case RID_ASM:
     case RID_SIZEOF:
     case RID_TYPEOF:
     case RID_ALIGNOF:
     case RID_UNSIGNED:
     case RID_LONG:
-    case RID_INT128:
     case RID_CONST:
     case RID_SHORT:
     case RID_VOLATILE:
     case RID_SIGNED:
     case RID_RESTRICT:
     case RID_COMPLEX:
@@ -9001,12 +9022,16 @@  c_parser_objc_selector (c_parser *parser
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
     case RID_BOOL:
     case RID_ATOMIC:
     case RID_AUTO_TYPE:
+    case RID_INT_N_0:
+    case RID_INT_N_1:
+    case RID_INT_N_2:
+    case RID_INT_N_3:
       c_parser_consume_token (parser);
       return value;
     default:
       return NULL_TREE;
     }
 }
Index: gcc/c/c-tree.h
===================================================================
--- gcc/c/c-tree.h	(revision 214383)
+++ gcc/c/c-tree.h	(working copy)
@@ -199,13 +199,13 @@  enum c_typespec_keyword {
   cts_none,
   cts_void,
   cts_bool,
   cts_char,
   cts_int,
   cts_float,
-  cts_int128,
+  cts_int_n,
   cts_double,
   cts_dfloat32,
   cts_dfloat64,
   cts_dfloat128,
   cts_fract,
   cts_accum,
@@ -266,12 +266,14 @@  struct c_declspecs {
      separately.  */
   tree attrs;
   /* The base-2 log of the greatest alignment required by an _Alignas
      specifier, in bytes, or -1 if no such specifiers with nonzero
      alignment.  */
   int align_log;
+  /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
+  int int_n_idx;
   /* The storage class specifier, or csc_none if none.  */
   enum c_storage_class storage_class;
   /* Any type specifier keyword used such as "int", not reflecting
      modifiers such as "short", or cts_none if none.  */
   ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8;
   /* The kind of type specifier if one has been seen, ctsk_none
Index: gcc/c/c-decl.c
===================================================================
--- gcc/c/c-decl.c	(revision 214383)
+++ gcc/c/c-decl.c	(working copy)
@@ -9174,16 +9174,17 @@  declspecs_add_type (location_t loc, stru
 			  ("both %<long%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
 		error_at (loc,
 			  ("both %<long%> and %<void%> in "
 			   "declaration specifiers"));
-	      else if (specs->typespec_word == cts_int128)
+	      else if (specs->typespec_word == cts_int_n)
 		  error_at (loc,
-			    ("both %<long%> and %<__int128%> in "
-			     "declaration specifiers"));
+			    ("both %<long%> and %<__int%d%> in "
+			     "declaration specifiers"),
+			    int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->typespec_word == cts_bool)
 		error_at (loc,
 			  ("both %<long%> and %<_Bool%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
 		error_at (loc,
@@ -9222,16 +9223,17 @@  declspecs_add_type (location_t loc, stru
 			  ("both %<short%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
 		error_at (loc,
 			  ("both %<short%> and %<void%> in "
 			   "declaration specifiers"));
-	      else if (specs->typespec_word == cts_int128)
+	      else if (specs->typespec_word == cts_int_n)
 		error_at (loc,
-			  ("both %<short%> and %<__int128%> in "
-			   "declaration specifiers"));
+			  ("both %<short%> and %<__int%d%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->typespec_word == cts_bool)
 		error_at (loc,
 			  ("both %<short%> and %<_Bool%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_char)
 		error_at (loc,
@@ -9399,17 +9401,18 @@  declspecs_add_type (location_t loc, stru
 		}
 	      break;
 	    case RID_SAT:
 	      dupe = specs->saturating_p;
 	      pedwarn (loc, OPT_Wpedantic,
 		       "ISO C does not support saturating types");
-	      if (specs->typespec_word == cts_int128)
+	      if (specs->typespec_word == cts_int_n)
 	        {
 		  error_at (loc,
-			    ("both %<_Sat%> and %<__int128%> in "
-			     "declaration specifiers"));
+			    ("both %<_Sat%> and %<__int%d%> in "
+			     "declaration specifiers"),
+			    int_n_data[specs->int_n_idx].bitsize);
 	        }
 	      else if (specs->typespec_word == cts_auto_type)
 		error_at (loc,
 			  ("both %<_Sat%> and %<__auto_type%> in "
 			   "declaration specifiers"));
 	      else if (specs->typespec_word == cts_void)
@@ -9467,13 +9470,13 @@  declspecs_add_type (location_t loc, stru
 
 	  return specs;
 	}
       else
 	{
 	  /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
-	     "__int128", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+	     "__intN", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
 	     "__auto_type".  */
 	  if (specs->typespec_word != cts_none)
 	    {
 	      error_at (loc,
 			"two or more data types in declaration specifiers");
 	      return specs;
@@ -9508,37 +9511,47 @@  declspecs_add_type (location_t loc, stru
 	      else
 		{
 		  specs->typespec_word = cts_auto_type;
 		  specs->locations[cdw_typespec] = loc;
 		}
 	      return specs;
-	    case RID_INT128:
-	      if (int128_integer_type_node == NULL_TREE)
-		{
-		  error_at (loc, "%<__int128%> is not supported for this target");
-		  return specs;
-		}
-	      if (!in_system_header_at (input_location))
+	    case RID_INT_N_0:
+	    case RID_INT_N_1:
+	    case RID_INT_N_2:
+	    case RID_INT_N_3:
+	      specs->int_n_idx = i - RID_INT_N_0;
+	      if (!in_system_header_at (input_location)
+		  /* As a special exception, allow a type that's used
+		     for __SIZE_TYPE__.  */
+		  && int_n_data[specs->int_n_idx].bitsize != POINTER_SIZE)
 		pedwarn (loc, OPT_Wpedantic,
-			 "ISO C does not support %<__int128%> type");
+			 "ISO C does not support %<__int%d%> types",
+			 int_n_data[specs->int_n_idx].bitsize);
 
 	      if (specs->long_p)
 		error_at (loc,
-			  ("both %<__int128%> and %<long%> in "
-			   "declaration specifiers"));
+			  ("both %<__int%d%> and %<long%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->saturating_p)
 		error_at (loc,
-			  ("both %<_Sat%> and %<__int128%> in "
-			   "declaration specifiers"));
+			  ("both %<_Sat%> and %<__int%d%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else if (specs->short_p)
 		error_at (loc,
-			  ("both %<__int128%> and %<short%> in "
-			   "declaration specifiers"));
+			  ("both %<__int%d%> and %<short%> in "
+			   "declaration specifiers"),
+			  int_n_data[specs->int_n_idx].bitsize);
+	      else if (! int_n_enabled_p [specs->int_n_idx])
+		error_at (loc,
+			  "%<__int%d%> is not supported on this target",
+			  int_n_data[specs->int_n_idx].bitsize);
 	      else
 		{
-		  specs->typespec_word = cts_int128;
+		  specs->typespec_word = cts_int_n;
 		  specs->locations[cdw_typespec] = loc;
 		}
 	      return specs;
 	    case RID_VOID:
 	      if (specs->long_p)
 		error_at (loc,
@@ -10100,18 +10113,18 @@  finish_declspecs (struct c_declspecs *sp
 	{
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
       break;
-    case cts_int128:
+    case cts_int_n:
       gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
       gcc_assert (!(specs->signed_p && specs->unsigned_p));
       specs->type = (specs->unsigned_p
-		     ? int128_unsigned_type_node
-		     : int128_integer_type_node);
+		     ? int_n_trees[specs->int_n_idx].unsigned_type
+		     : int_n_trees[specs->int_n_idx].signed_type);
       if (specs->complex_p)
 	{
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support complex integer types");
 	  specs->type = build_complex_type (specs->type);
 	}
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 214383)
+++ gcc/tree.c	(working copy)
@@ -233,12 +233,15 @@  static int type_hash_marked_p (const voi
 static void type_hash_list (const_tree, inchash::hash &);
 static void attribute_hash_list (const_tree, inchash::hash &);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
 
+bool int_n_enabled_p[NUM_INT_N_ENTS];
+struct int_n_trees_t int_n_trees [NUM_INT_N_ENTS];
+
 unsigned char tree_contains_struct[MAX_TREE_CODES][64];
 
 /* Number of operands for each OpenMP clause.  */
 unsigned const char omp_clause_num_ops[] =
 {
   0, /* OMP_CLAUSE_ERROR  */
@@ -9416,26 +9419,31 @@  make_vector_type (tree innertype, int nu
   return t;
 }
 
 static tree
 make_or_reuse_type (unsigned size, int unsignedp)
 {
+  int i;
+
   if (size == INT_TYPE_SIZE)
     return unsignedp ? unsigned_type_node : integer_type_node;
   if (size == CHAR_TYPE_SIZE)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
   if (size == SHORT_TYPE_SIZE)
     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
   if (size == LONG_TYPE_SIZE)
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (size == LONG_LONG_TYPE_SIZE)
     return (unsignedp ? long_long_unsigned_type_node
             : long_long_integer_type_node);
-  if (size == 128 && int128_integer_type_node)
-    return (unsignedp ? int128_unsigned_type_node
-            : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (size == int_n_data[i].bitsize
+	&& int_n_enabled_p[i])
+      return (unsignedp ? int_n_trees[i].unsigned_type
+	      : int_n_trees[i].signed_type);
 
   if (unsignedp)
     return make_unsigned_type (size);
   else
     return make_signed_type (size);
 }
@@ -9545,12 +9553,14 @@  build_atomic_base (tree type, unsigned i
    SHORT_DOUBLE specifies whether double should be of the same precision
    as float.  */
 
 void
 build_common_tree_nodes (bool signed_char, bool short_double)
 {
+  int i;
+
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
   initialize_sizetypes ();
 
   /* Define both `signed char' and `unsigned char'.  */
@@ -9572,23 +9582,26 @@  build_common_tree_nodes (bool signed_cha
   integer_type_node = make_signed_type (INT_TYPE_SIZE);
   unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
   long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
   long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
   long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
   long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
-#if HOST_BITS_PER_WIDE_INT >= 64
-    /* TODO: This isn't correct, but as logic depends at the moment on
-       host's instead of target's wide-integer.
-       If there is a target not supporting TImode, but has an 128-bit
-       integer-scalar register, this target check needs to be adjusted. */
-    if (targetm.scalar_mode_supported_p (TImode))
-      {
-        int128_integer_type_node = make_signed_type (128);
-        int128_unsigned_type_node = make_unsigned_type (128);
-      }
-#endif
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    {
+      int_n_trees[i].signed_type = make_signed_type (int_n_data[i].bitsize);
+      int_n_trees[i].unsigned_type = make_unsigned_type (int_n_data[i].bitsize);
+      TYPE_SIZE (int_n_trees[i].signed_type) = bitsize_int (int_n_data[i].bitsize);
+      TYPE_SIZE (int_n_trees[i].unsigned_type) = bitsize_int (int_n_data[i].bitsize);
+
+      if (int_n_data[i].bitsize > LONG_LONG_TYPE_SIZE)
+	{
+	  integer_types[itk_intN_0 + i * 2] = int_n_trees[i].signed_type;
+	  integer_types[itk_unsigned_intN_0 + i * 2] = int_n_trees[i].unsigned_type;
+	}
+    }
 
   /* Define a boolean type.  This type only represents boolean values but
      may be larger than char depending on the value of BOOL_TYPE_SIZE.  */
   boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
   TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
   TYPE_PRECISION (boolean_type_node) = 1;
@@ -9601,13 +9614,30 @@  build_common_tree_nodes (bool signed_cha
     size_type_node = long_unsigned_type_node;
   else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0)
     size_type_node = long_long_unsigned_type_node;
   else if (strcmp (SIZE_TYPE, "short unsigned int") == 0)
     size_type_node = short_unsigned_type_node;
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      size_type_node = NULL_TREE;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZE_TYPE) == 0)
+	      {
+		size_type_node = int_n_trees[i].unsigned_type;
+	      }
+	  }
+      if (size_type_node == NULL_TREE)
+	gcc_unreachable ();
+    }
 
   /* Fill in the rest of the sized types.  Reuse existing type nodes
      when possible.  */
   intQI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (QImode), 0);
   intHI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (HImode), 0);
   intSI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (SImode), 0);
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 214383)
+++ gcc/tree.h	(working copy)
@@ -3419,14 +3419,12 @@  tree_operand_check_code (const_tree __t,
 #define integer_type_node		integer_types[itk_int]
 #define unsigned_type_node		integer_types[itk_unsigned_int]
 #define long_integer_type_node		integer_types[itk_long]
 #define long_unsigned_type_node		integer_types[itk_unsigned_long]
 #define long_long_integer_type_node	integer_types[itk_long_long]
 #define long_long_unsigned_type_node	integer_types[itk_unsigned_long_long]
-#define int128_integer_type_node	integer_types[itk_int128]
-#define int128_unsigned_type_node	integer_types[itk_unsigned_int128]
 
 /* True if NODE is an erroneous expression.  */
 
 #define error_operand_p(NODE)					\
   ((NODE) == error_mark_node					\
    || ((NODE) && TREE_TYPE ((NODE)) == error_mark_node))
@@ -4785,7 +4783,18 @@  extern tree get_inner_reference (tree, H
 				 bool);
 
 /* Return a tree representing the lower bound of the array mentioned in
    EXP, an ARRAY_REF or an ARRAY_RANGE_REF.  */
 extern tree array_ref_low_bound (tree);
 
+
+struct GTY(()) int_n_trees_t {
+  /* These parts are initialized at runtime */
+  tree signed_type;
+  tree unsigned_type;
+};
+
+/* This is also in machmode.h */
+extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+extern GTY(()) struct int_n_trees_t int_n_trees[NUM_INT_N_ENTS];
+
 #endif  /* GCC_TREE_H  */
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 214383)
+++ gcc/toplev.c	(working copy)
@@ -1894,12 +1894,27 @@  finalize (bool no_backend)
     dump_profile_report ();
 
   /* Language-specific end of compilation actions.  */
   lang_hooks.finish ();
 }
 
+static bool
+standard_type_bitsize (int bitsize)
+{
+  /* As a special exception, we always want __int128 enabled if possible.  */
+  if (bitsize == 128)
+    return false;
+  if (bitsize == CHAR_TYPE_SIZE
+      || bitsize == SHORT_TYPE_SIZE
+      || bitsize == INT_TYPE_SIZE
+      || bitsize == LONG_TYPE_SIZE
+      || bitsize == LONG_LONG_TYPE_SIZE)
+    return true;
+  return false;
+}
+
 /* Initialize the compiler, and compile the input file.  */
 static void
 do_compile (void)
 {
   /* Initialize timing first.  The C front ends read the main file in
      the post_options hook, and C++ does file timings.  */
@@ -1909,20 +1924,32 @@  do_compile (void)
 
   process_options ();
 
   /* Don't do any more if an error has already occurred.  */
   if (!seen_error ())
     {
+      int i;
+
       timevar_start (TV_PHASE_SETUP);
 
       /* This must be run always, because it is needed to compute the FP
 	 predefined macros, such as __LDBL_MAX__, for targets using non
 	 default FP formats.  */
       init_adjust_machine_modes ();
       init_derived_machine_modes ();
 
+      /* This must happen after the backend has a chance to process
+	 command line options, but before the parsers are
+	 initialized.  */
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
+	if (targetm.scalar_mode_supported_p (int_n_data[i].m)
+	    && ! standard_type_bitsize (int_n_data[i].bitsize))
+	  int_n_enabled_p[i] = true;
+	else
+	  int_n_enabled_p[i] = false;
+
       /* Set up the back-end if requested.  */
       if (!no_backend)
 	backend_init ();
 
       /* Language-dependent initialization.  Returns true on success.  */
       if (lang_dependent_init (main_input_filename))
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 214383)
+++ gcc/cp/typeck.c	(working copy)
@@ -267,12 +267,13 @@  original_type (tree t)
 static tree
 cp_common_type (tree t1, tree t2)
 {
   enum tree_code code1 = TREE_CODE (t1);
   enum tree_code code2 = TREE_CODE (t2);
   tree attributes;
+  int i;
 
 
   /* In what follows, we slightly generalize the rules given in [expr] so
      as to deal with `long long' and `complex'.  First, merge the
      attributes.  */
   attributes = (*targetm.merge_type_attributes) (t1, t2);
@@ -361,22 +362,25 @@  cp_common_type (tree t1, tree t2)
 	{
 	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
 		    ? long_long_unsigned_type_node
 		    : long_long_integer_type_node);
 	  return build_type_attribute_variant (t, attributes);
 	}
-      if (int128_integer_type_node != NULL_TREE
-	  && (same_type_p (TYPE_MAIN_VARIANT (t1),
-			   int128_integer_type_node)
-	      || same_type_p (TYPE_MAIN_VARIANT (t2),
-			      int128_integer_type_node)))
+      for (i = 0; i < NUM_INT_N_ENTS; i ++)
 	{
-	  tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
-		    ? int128_unsigned_type_node
-		    : int128_integer_type_node);
-	  return build_type_attribute_variant (t, attributes);
+	  if (int_n_enabled_p [i]
+	      && (same_type_p (TYPE_MAIN_VARIANT (t1),
+			       int_n_trees[i].signed_type)
+		  || same_type_p (TYPE_MAIN_VARIANT (t2),
+				  int_n_trees[i].signed_type)))
+	    {
+	      tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+			? int_n_trees[i].unsigned_type
+			: int_n_trees[i].signed_type);
+	      return build_type_attribute_variant (t, attributes);
+	    }
 	}
 
       /* Go through the same procedure, but for longs.  */
       if (same_type_p (TYPE_MAIN_VARIANT (t1), long_unsigned_type_node)
 	  || same_type_p (TYPE_MAIN_VARIANT (t2), long_unsigned_type_node))
 	return build_type_attribute_variant (long_unsigned_type_node,
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 214383)
+++ gcc/cp/decl.c	(working copy)
@@ -8771,13 +8771,13 @@  grokdeclarator (const cp_declarator *dec
 		enum decl_context decl_context,
 		int initialized,
 		tree* attrlist)
 {
   tree type = NULL_TREE;
   int longlong = 0;
-  int explicit_int128 = 0;
+  int explicit_intN = 0;
   int virtualp, explicitp, friendp, inlinep, staticp;
   int explicit_int = 0;
   int explicit_char = 0;
   int defaulted_int = 0;
 
   tree typedef_decl = NULL_TREE;
@@ -8844,13 +8844,13 @@  grokdeclarator (const cp_declarator *dec
 
   signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
   unsigned_p = decl_spec_seq_has_spec_p (declspecs, ds_unsigned);
   short_p = decl_spec_seq_has_spec_p (declspecs, ds_short);
   long_p = decl_spec_seq_has_spec_p (declspecs, ds_long);
   longlong = decl_spec_seq_has_spec_p (declspecs, ds_long_long);
-  explicit_int128 = declspecs->explicit_int128_p;
+  explicit_intN = declspecs->explicit_intN_p;
   thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
 
   if (decl_context == FUNCDEF)
     funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
     funcdef_flag = true, decl_context = FIELD;
@@ -9190,22 +9190,24 @@  grokdeclarator (const cp_declarator *dec
 
       type = integer_type_node;
     }
 
   ctype = NULL_TREE;
 
-  if (explicit_int128)
+  if (explicit_intN)
     {
-      if (int128_integer_type_node == NULL_TREE)
-	{
-	  error ("%<__int128%> is not supported by this target");
-	  explicit_int128 = false;
-	}
+      if (! int_n_enabled_p[declspecs->int_n_idx])
+       {
+         error ("%<__int%d%> is not supported by this target",
+		int_n_data[declspecs->int_n_idx].bitsize);
+         explicit_intN = false;
+       }
       else if (pedantic && ! in_system_header_at (input_location))
-	pedwarn (input_location, OPT_Wpedantic,
-		 "ISO C++ does not support %<__int128%> for %qs", name);
+       pedwarn (input_location, OPT_Wpedantic,
+                "ISO C++ does not support %<__int%d%> for %qs",
+		int_n_data[declspecs->int_n_idx].bitsize,  name);
     }
 
   /* Now process the modifiers that were specified
      and check for invalid combinations.  */
 
   /* Long double is a special combination.  */
@@ -9231,13 +9233,13 @@  grokdeclarator (const cp_declarator *dec
       else if (long_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<long%> invalid for %qs", name);
       else if (short_p && TREE_CODE (type) == REAL_TYPE)
 	error ("%<short%> invalid for %qs", name);
       else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE)
 	error ("%<long%> or %<short%> invalid for %qs", name);
-      else if ((long_p || short_p || explicit_char || explicit_int) && explicit_int128)
+      else if ((long_p || short_p || explicit_char || explicit_int) && explicit_intN)
 	error ("%<long%>, %<int%>, %<short%>, or %<char%> invalid for %qs", name);
       else if ((long_p || short_p) && explicit_char)
 	error ("%<long%> or %<short%> specified with char for %qs", name);
       else if (long_p && short_p)
 	error ("%<long%> and %<short%> specified together for %qs", name);
       else if (type == char16_type_node || type == char32_type_node)
@@ -9247,13 +9249,13 @@  grokdeclarator (const cp_declarator *dec
 	  else if (short_p || long_p)
 	    error ("%<short%> or %<long%> invalid for %qs", name);
 	}
       else
 	{
 	  ok = 1;
-	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_int128 && pedantic)
+	  if (!explicit_int && !defaulted_int && !explicit_char && !explicit_intN && pedantic)
 	    {
 	      pedwarn (input_location, OPT_Wpedantic, 
 		       "long, short, signed or unsigned used invalidly for %qs",
 		       name);
 	      if (flag_pedantic_errors)
 		ok = 0;
@@ -9289,14 +9291,14 @@  grokdeclarator (const cp_declarator *dec
 	     `signed int' cannot be so controlled.  */
 	  && !(typedef_decl
 	       && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
 	  && TREE_CODE (type) == INTEGER_TYPE
 	  && !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
     {
-      if (explicit_int128)
-	type = int128_unsigned_type_node;
+      if (explicit_intN)
+	type = int_n_trees[declspecs->int_n_idx].unsigned_type;
       else if (longlong)
 	type = long_long_unsigned_type_node;
       else if (long_p)
 	type = long_unsigned_type_node;
       else if (short_p)
 	type = short_unsigned_type_node;
@@ -9306,14 +9308,14 @@  grokdeclarator (const cp_declarator *dec
 	type = unsigned_type_for (type);
       else
 	type = unsigned_type_node;
     }
   else if (signed_p && type == char_type_node)
     type = signed_char_type_node;
-  else if (explicit_int128)
-    type = int128_integer_type_node;
+  else if (explicit_intN)
+    type = int_n_trees[declspecs->int_n_idx].signed_type;
   else if (longlong)
     type = long_long_integer_type_node;
   else if (long_p)
     type = long_integer_type_node;
   else if (short_p)
     type = short_integer_type_node;
@@ -9323,13 +9325,13 @@  grokdeclarator (const cp_declarator *dec
       if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
 	error ("complex invalid for %qs", name);
       /* If we just have "complex", it is equivalent to
 	 "complex double", but if any modifiers at all are specified it is
 	 the complex form of TYPE.  E.g, "complex short" is
 	 "complex short int".  */
-      else if (defaulted_int && ! longlong && ! explicit_int128
+      else if (defaulted_int && ! longlong && ! explicit_intN
 	       && ! (long_p || short_p || signed_p || unsigned_p))
 	type = complex_double_type_node;
       else if (type == integer_type_node)
 	type = complex_integer_type_node;
       else if (type == float_type_node)
 	type = complex_float_type_node;
Index: gcc/cp/rtti.c
===================================================================
--- gcc/cp/rtti.c	(revision 214383)
+++ gcc/cp/rtti.c	(working copy)
@@ -1516,13 +1516,12 @@  emit_support_tinfos (void)
     &wchar_type_node, &char16_type_node, &char32_type_node,
     &char_type_node, &signed_char_type_node, &unsigned_char_type_node,
     &short_integer_type_node, &short_unsigned_type_node,
     &integer_type_node, &unsigned_type_node,
     &long_integer_type_node, &long_unsigned_type_node,
     &long_long_integer_type_node, &long_long_unsigned_type_node,
-    &int128_integer_type_node, &int128_unsigned_type_node,
     &float_type_node, &double_type_node, &long_double_type_node,
     &dfloat32_type_node, &dfloat64_type_node, &dfloat128_type_node,
     &nullptr_type_node,
     0
   };
   int ix;
@@ -1538,12 +1537,18 @@  emit_support_tinfos (void)
   dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
   if (!dtor || DECL_EXTERNAL (dtor))
     return;
   doing_runtime = 1;
   for (ix = 0; fundamentals[ix]; ix++)
     emit_support_tinfo_1 (*fundamentals[ix]);
+  for (ix = 0; ix < NUM_INT_N_ENTS; ix ++)
+    if (int_n_enabled_p[ix])
+      {
+	emit_support_tinfo_1 (int_n_trees[ix].signed_type);
+	emit_support_tinfo_1 (int_n_trees[ix].unsigned_type);
+      }
 }
 
 /* Finish a type info decl. DECL_PTR is a pointer to an unemitted
    tinfo decl.  Determine whether it needs emitting, and if so
    generate the initializer.  */
 
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 214383)
+++ gcc/cp/parser.c	(working copy)
@@ -942,13 +942,12 @@  cp_lexer_next_token_is_decl_specifier_ke
     case RID_CHAR32:
     case RID_WCHAR:
     case RID_BOOL:
     case RID_SHORT:
     case RID_INT:
     case RID_LONG:
-    case RID_INT128:
     case RID_SIGNED:
     case RID_UNSIGNED:
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
       /* GNU extensions.  */ 
@@ -957,12 +956,16 @@  cp_lexer_next_token_is_decl_specifier_ke
       /* C++0x extensions.  */
     case RID_DECLTYPE:
     case RID_UNDERLYING_TYPE:
       return true;
 
     default:
+      if (token->keyword >= RID_FIRST_INT_N
+	  && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+	  && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
+	return true;
       return false;
     }
 }
 
 /* Returns TRUE iff the token T begins a decltype type.  */
 
@@ -14636,12 +14639,13 @@  static tree
 cp_parser_simple_type_specifier (cp_parser* parser,
 				 cp_decl_specifier_seq *decl_specs,
 				 cp_parser_flags flags)
 {
   tree type = NULL_TREE;
   cp_token *token;
+  int idx;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   /* If we're looking at a keyword, things are easy.  */
   switch (token->keyword)
@@ -14669,18 +14673,25 @@  cp_parser_simple_type_specifier (cp_pars
       break;
     case RID_INT:
       if (decl_specs)
 	decl_specs->explicit_int_p = true;
       type = integer_type_node;
       break;
-    case RID_INT128:
-      if (!int128_integer_type_node)
+    case RID_INT_N_0:
+    case RID_INT_N_1:
+    case RID_INT_N_2:
+    case RID_INT_N_3:
+      idx = token->keyword - RID_INT_N_0;
+      if (! int_n_enabled_p [idx])
 	break;
       if (decl_specs)
-        decl_specs->explicit_int128_p = true;
-      type = int128_integer_type_node;
+	{
+	  decl_specs->explicit_intN_p = true;
+	  decl_specs->int_n_idx = idx;
+	}
+      type = int_n_trees [idx].signed_type;
       break;
     case RID_LONG:
       if (decl_specs)
 	set_and_check_decl_spec_loc (decl_specs, ds_long, token);
       type = long_integer_type_node;
       break;
Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(revision 214383)
+++ gcc/cp/mangle.c	(working copy)
@@ -150,14 +150,14 @@  integer_type_codes[itk_none] =
   'i',  /* itk_int */
   'j',  /* itk_unsigned_int */
   'l',  /* itk_long */
   'm',  /* itk_unsigned_long */
   'x',  /* itk_long_long */
   'y',  /* itk_unsigned_long_long */
-  'n',  /* itk_int128 */
-  'o',  /* itk_unsigned_int128  */
+  /* __intN types are handled separately */
+  '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
 };
 
 static int decl_is_template_id (const tree, tree* const);
 
 /* Functions for handling substitutions.  */
 
@@ -2212,12 +2212,13 @@  write_builtin_type (tree type)
 	  size_t itk;
 	  /* Assume TYPE is one of the shared integer type nodes.  Find
 	     it in the array of these nodes.  */
 	iagain:
 	  for (itk = 0; itk < itk_none; ++itk)
 	    if (integer_types[itk] != NULL_TREE
+		&& integer_type_codes[itk] != '\0'
 		&& type == integer_types[itk])
 	      {
 		/* Print the corresponding single-letter code.  */
 		write_char (integer_type_codes[itk]);
 		break;
 	      }
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 214383)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -4875,12 +4875,14 @@  typedef struct cp_decl_specifier_seq {
   /* If non-NULL, a built-in type that the user attempted to redefine
      to some other type.  */
   tree redefined_builtin_type;
   /* The storage class specified -- or sc_none if no storage class was
      explicitly specified.  */
   cp_storage_class storage_class;
+  /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
+  int int_n_idx;
   /* True iff TYPE_SPEC defines a class or enum.  */
   BOOL_BITFIELD type_definition_p : 1;
   /* True iff multiple types were (erroneously) specified for this
      decl-specifier-seq.  */
   BOOL_BITFIELD multiple_types_p : 1;
   /* True iff multiple storage classes were (erroneously) specified
@@ -4890,14 +4892,14 @@  typedef struct cp_decl_specifier_seq {
   /* True iff at least one decl-specifier was found.  */
   BOOL_BITFIELD any_specifiers_p : 1;
   /* True iff at least one type-specifier was found.  */
   BOOL_BITFIELD any_type_specifiers_p : 1;
   /* True iff "int" was explicitly provided.  */
   BOOL_BITFIELD explicit_int_p : 1;
-  /* True iff "__int128" was explicitly provided.  */
-  BOOL_BITFIELD explicit_int128_p : 1;
+  /* True iff "__intN" was explicitly provided.  */
+  BOOL_BITFIELD explicit_intN_p : 1;
   /* True iff "char" was explicitly provided.  */
   BOOL_BITFIELD explicit_char_p : 1;
   /* True iff ds_thread is set for __thread, not thread_local.  */
   BOOL_BITFIELD gnu_thread_keyword_p : 1;
 } cp_decl_specifier_seq;
 
Index: gcc/cp/lex.c
===================================================================
--- gcc/cp/lex.c	(revision 214383)
+++ gcc/cp/lex.c	(working copy)
@@ -190,12 +190,21 @@  init_reswords (void)
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       ridpointers [(int) c_common_reswords[i].rid] = id;
       if (! (c_common_reswords[i].disable & mask))
 	C_IS_RESERVED_WORD (id) = 1;
     }
+
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    {
+      char name[50];
+      sprintf (name, "__int%d", int_n_data[i].bitsize);
+      id = get_identifier (name);
+      C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+      C_IS_RESERVED_WORD (id) = 1;
+    }
 }
 
 static void
 init_cp_pragma (void)
 {
   c_register_pragma (0, "vtable", handle_pragma_vtable);
Index: gcc/builtin-types.def
===================================================================
--- gcc/builtin-types.def	(revision 214383)
+++ gcc/builtin-types.def	(working copy)
@@ -62,14 +62,12 @@  DEF_PRIMITIVE_TYPE (BT_BOOL, boolean_typ
 DEF_PRIMITIVE_TYPE (BT_INT, integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT, unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONG, long_integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_ULONG, long_unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONGLONG, long_long_integer_type_node)
 DEF_PRIMITIVE_TYPE (BT_ULONGLONG, long_long_unsigned_type_node)
-DEF_PRIMITIVE_TYPE (BT_INT128, int128_integer_type_node)
-DEF_PRIMITIVE_TYPE (BT_UINT128, int128_unsigned_type_node)
 DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT16, uint16_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT32, uint32_type_node)
 DEF_PRIMITIVE_TYPE (BT_UINT64, uint64_type_node)
 DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
Index: gcc/machmode.def
===================================================================
--- gcc/machmode.def	(revision 214383)
+++ gcc/machmode.def	(working copy)
@@ -189,12 +189,19 @@  INT_MODE (HI, 2);
 INT_MODE (SI, 4);
 INT_MODE (DI, 8);
 INT_MODE (TI, 16);
 
 /* No partial integer modes are defined by default.  */
 
+/* The target normally defines any target-specific __intN types and
+   their modes, but __int128 for TImode is fairly common so define it
+   here.  The type will not be created unless the target supports
+   TImode.  */
+
+INT_N (TI, 128);
+
 /* Basic floating point modes.  SF and DF are the only modes provided
    by default.  The names QF, HF, XF, and TF are reserved for targets
    that need 1-word, 2-word, 80-bit, or 128-bit float types respectively.
 
    These are the IEEE mappings.  They can be overridden with
    RESET_FLOAT_FORMAT or at runtime (in TARGET_OPTION_OVERRIDE).  */
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	(revision 214383)
+++ gcc/stor-layout.c	(working copy)
@@ -310,22 +310,29 @@  finalize_size_functions (void)
    than MAX_FIXED_MODE_SIZE will not be used.  */
 
 enum machine_mode
 mode_for_size (unsigned int size, enum mode_class mclass, int limit)
 {
   enum machine_mode mode;
+  int i;
 
   if (limit && size > MAX_FIXED_MODE_SIZE)
     return BLKmode;
 
   /* Get the first mode which has this size, in the specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) == size)
       return mode;
 
+  if (mclass == MODE_INT || mclass == MODE_PARTIAL_INT)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize == size
+	  && int_n_enabled_p[i])
+	return int_n_data[i].m;
+
   return BLKmode;
 }
 
 /* Similar, except passed a tree node.  */
 
 enum machine_mode
@@ -346,22 +353,33 @@  mode_for_size_tree (const_tree size, enu
 /* Similar, but never return BLKmode; return the narrowest mode that
    contains at least the requested number of value bits.  */
 
 enum machine_mode
 smallest_mode_for_size (unsigned int size, enum mode_class mclass)
 {
-  enum machine_mode mode;
+  enum machine_mode mode = VOIDmode;
+  int i;
 
   /* Get the first mode which has at least this size, in the
      specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if (GET_MODE_PRECISION (mode) >= size)
-      return mode;
+      break;
 
-  gcc_unreachable ();
+  if (mclass == MODE_INT || mclass == MODE_PARTIAL_INT)
+    for (i = 0; i < NUM_INT_N_ENTS; i ++)
+      if (int_n_data[i].bitsize >= size
+	  && int_n_data[i].bitsize < GET_MODE_PRECISION (mode)
+	  && int_n_enabled_p[i])
+	mode = int_n_data[i].m;
+
+  if (mode == VOIDmode)
+    gcc_unreachable ();
+
+  return mode;
 }
 
 /* Find an integer mode of the exact same size, or BLKmode on failure.  */
 
 enum machine_mode
 int_mode_for_mode (enum machine_mode mode)
@@ -2542,13 +2560,30 @@  initialize_sizetypes (void)
     precision = LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "long long unsigned int") == 0)
     precision = LONG_LONG_TYPE_SIZE;
   else if (strcmp (SIZETYPE, "short unsigned int") == 0)
     precision = SHORT_TYPE_SIZE;
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      precision = -1;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZETYPE) == 0)
+	      {
+		precision = int_n_data[i].bitsize;
+	      }
+	  }
+      if (precision == -1)
+	gcc_unreachable ();
+    }
 
   bprecision
     = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
   bprecision
     = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
   if (bprecision > HOST_BITS_PER_DOUBLE_INT)
Index: gcc/genmodes.c
===================================================================
--- gcc/genmodes.c	(revision 214383)
+++ gcc/genmodes.c	(working copy)
@@ -71,23 +71,24 @@  struct mode_data
   unsigned int line;		/* for error reporting */
   unsigned int counter;		/* Rank ordering of modes */
   unsigned int ibit;		/* the number of integral bits */
   unsigned int fbit;		/* the number of fractional bits */
   bool need_bytesize_adj;	/* true if this mode need dynamic size
 				   adjustment */
+  unsigned int int_n;		/* If nonzero, then __int<INT_N> will be defined */
 };
 
 static struct mode_data *modes[MAX_MODE_CLASS];
 static unsigned int n_modes[MAX_MODE_CLASS];
 static struct mode_data *void_mode;
 
 static const struct mode_data blank_mode = {
   0, "<unknown>", MAX_MODE_CLASS,
   -1U, -1U, -1U, -1U,
   0, 0, 0, 0, 0,
-  "<unknown>", 0, 0, 0, 0, false
+  "<unknown>", 0, 0, 0, 0, false, 0
 };
 
 static htab_t modes_by_name;
 
 /* Data structure for recording target-specified runtime adjustments
    to a particular mode.  We support varying the byte size, the
@@ -629,12 +630,40 @@  reset_float_format (const char *name, co
       error ("%s:%d: mode \"%s\" is not a FLOAT class", file, line, name);
       return;
     }
   m->format = format;
 }
 
+/* __intN support.  */
+#define INT_N(M,PREC)				\
+  make_int_n (#M, PREC, __FILE__, __LINE__)
+static void ATTRIBUTE_UNUSED
+make_int_n (const char *m, int bitsize,
+            const char *file, unsigned int line)
+{
+  struct mode_data *component = find_mode (m);
+  if (!component)
+    {
+      error ("%s:%d: no mode \"%s\"", file, line, m);
+      return;
+    }
+  if (component->cl != MODE_INT
+      && component->cl != MODE_PARTIAL_INT)
+    {
+      error ("%s:%d: mode \"%s\" is not class INT or PARTIAL_INT", file, line, m);
+      return;
+    }
+  if (component->int_n != 0)
+    {
+      error ("%s:%d: mode \"%s\" already has an intN", file, line, m);
+      return;
+    }
+
+  component->int_n = bitsize;
+}
+
 /* Partial integer modes are specified by relation to a full integer
    mode.  */
 #define PARTIAL_INT_MODE(M,PREC,NAME)				\
   make_partial_integer_mode (#M, #NAME, PREC, __FILE__, __LINE__)
 static void ATTRIBUTE_UNUSED
 make_partial_integer_mode (const char *base, const char *name,
@@ -1007,12 +1036,13 @@  mode_inner_inline (enum machine_mode mod
 
 static void
 emit_insn_modes_h (void)
 {
   int c;
   struct mode_data *m, *first, *last;
+  int n_int_n_ents = 0;
 
   printf ("/* Generated automatically from machmode.def%s%s\n",
 	   HAVE_EXTRA_MODES ? " and " : "",
 	   EXTRA_MODES_FILE);
 
   puts ("\
@@ -1067,12 +1097,19 @@  enum machine_mode\n{");
 #if 0 /* disabled for backward compatibility, temporary */
   printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
 #endif
   printf ("#define CONST_MODE_IBIT%s\n", adj_ibit ? "" : " const");
   printf ("#define CONST_MODE_FBIT%s\n", adj_fbit ? "" : " const");
   emit_max_int ();
+
+  for_all_modes (c, m)
+    if (m->int_n)
+      n_int_n_ents ++;
+
+  printf ("#define NUM_INT_N_ENTS %d\n", n_int_n_ents);
+
   puts ("\n#if GCC_VERSION >= 4001\n");
   emit_mode_size_inline ();
   emit_mode_nunits_inline ();
   emit_mode_inner_inline ();
   puts ("#endif /* GCC_VERSION >= 4001 */");
 
@@ -1516,12 +1553,59 @@  emit_mode_fbit (void)
   for_all_modes (c, m)
     tagged_printf ("%u", m->fbit, m->name);
 
   print_closer ();
 }
 
+/* Emit __intN for all modes.  */
+
+static void
+emit_mode_int_n (void)
+{
+  int c;
+  struct mode_data *m;
+  struct mode_data **mode_sort;
+  int n_modes = 0;
+  int i, j;
+
+  print_decl ("int_n_data_t", "int_n_data", "");
+
+  n_modes = 0;
+  for_all_modes (c, m)
+    if (m->int_n)
+      n_modes ++;
+  mode_sort = XALLOCAVEC (struct mode_data *, n_modes);
+
+  n_modes = 0;
+  for_all_modes (c, m)
+    if (m->int_n)
+      mode_sort[n_modes++] = m;
+
+  /* Yes, this is a bubblesort, but there are at most four (and
+     usually only 1-2) entries to sort.  */
+  for (i = 0; i<n_modes - 1; i++)
+    for (j = i + 1; j < n_modes; j++)
+      if (mode_sort[i]->int_n > mode_sort[j]->int_n)
+	{
+	  m = mode_sort[i];
+	  mode_sort[i] = mode_sort[j];
+	  mode_sort[j] = m;
+	}
+
+  for (i = 0; i < n_modes; i ++)
+    {
+      m = mode_sort[i];
+      printf(" {\n");
+      tagged_printf ("%u", m->int_n, m->name);
+      printf ("%smode,", m->name);
+      printf(" },\n");
+    }
+
+  print_closer ();
+}
+
 
 static void
 emit_insn_modes_c (void)
 {
   emit_insn_modes_c_header ();
   emit_mode_name ();
@@ -1535,12 +1619,13 @@  emit_insn_modes_c (void)
   emit_mode_base_align ();
   emit_class_narrowest_mode ();
   emit_real_format_for_mode ();
   emit_mode_adjustments ();
   emit_mode_ibit ();
   emit_mode_fbit ();
+  emit_mode_int_n ();
 }
 
 static void
 emit_min_insn_modes_c (void)
 {
   emit_min_insn_modes_c_header ();
Index: gcc/lto/lto-lang.c
===================================================================
--- gcc/lto/lto-lang.c	(revision 214383)
+++ gcc/lto/lto-lang.c	(working copy)
@@ -1147,23 +1147,44 @@  lto_build_c_type_nodes (void)
     {
       intmax_type_node = long_long_integer_type_node;
       uintmax_type_node = long_long_unsigned_type_node;
       signed_size_type_node = long_long_integer_type_node;
     }
   else
-    gcc_unreachable ();
+    {
+      int i;
+
+      signed_size_type_node = NULL_TREE;
+      for (i = 0; i < NUM_INT_N_ENTS; i++)
+	if (int_n_enabled_p[i])
+	  {
+	    char name[50];
+	    sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+
+	    if (strcmp (name, SIZE_TYPE) == 0)
+	      {
+		intmax_type_node = int_n_trees[i].signed_type;
+		uintmax_type_node = int_n_trees[i].unsigned_type;
+		signed_size_type_node = int_n_trees[i].signed_type;
+	      }
+	  }
+      if (signed_size_type_node == NULL_TREE)
+	gcc_unreachable ();
+    }
 
   wint_type_node = unsigned_type_node;
   pid_type_node = integer_type_node;
 }
 
 /* Perform LTO-specific initialization.  */
 
 static bool
 lto_init (void)
 {
+  int i;
+
   /* We need to generate LTO if running in WPA mode.  */
   flag_generate_lto = (flag_wpa != NULL);
 
   /* Create the basic integer types.  */
   build_common_tree_nodes (flag_signed_char, flag_short_double);
 
@@ -1229,14 +1250,19 @@  lto_init (void)
   NAME_TYPE (long_double_type_node, "long double");
   NAME_TYPE (void_type_node, "void");
   NAME_TYPE (boolean_type_node, "bool");
   NAME_TYPE (complex_float_type_node, "complex float");
   NAME_TYPE (complex_double_type_node, "complex double");
   NAME_TYPE (complex_long_double_type_node, "complex long double");
-  if (int128_integer_type_node)
-    NAME_TYPE (int128_integer_type_node, "__int128");
+  for (i = 0; i < NUM_INT_N_ENTS; i++)
+    if (int_n_enabled_p[i])
+      {
+	char name[50];
+	sprintf (name, "__int%d", int_n_data[i].bitsize);
+	NAME_TYPE (int_n_trees[i].signed_type, name);
+      }
 #undef NAME_TYPE
 
   /* Initialize LTO-specific data structures.  */
   in_lto_p = true;
 
   return true;
Index: gcc/gimple.c
===================================================================
--- gcc/gimple.c	(revision 214383)
+++ gcc/gimple.c	(working copy)
@@ -2110,12 +2110,13 @@  gimple_compare_field_offset (tree f1, tr
    signed according to UNSIGNEDP.  */
 
 static tree
 gimple_signed_or_unsigned_type (bool unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   type1 = TYPE_MAIN_VARIANT (type);
   if (type1 == signed_char_type_node
       || type1 == char_type_node
       || type1 == unsigned_char_type_node)
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -2127,16 +2128,21 @@  gimple_signed_or_unsigned_type (bool uns
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (type1 == long_long_integer_type_node
       || type1 == long_long_unsigned_type_node)
     return unsignedp
            ? long_long_unsigned_type_node
 	   : long_long_integer_type_node;
-  if (int128_integer_type_node && (type1 == int128_integer_type_node || type1 == int128_unsigned_type_node))
-    return unsignedp
-           ? int128_unsigned_type_node
-	   : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& (type1 == int_n_trees[i].unsigned_type
+	    || type1 == int_n_trees[i].signed_type))
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
+
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (type1 == intDI_type_node || type1 == unsigned_intDI_type_node)
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
@@ -2243,16 +2249,20 @@  gimple_signed_or_unsigned_type (bool uns
   if (TYPE_OK (long_integer_type_node))
     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
   if (TYPE_OK (long_long_integer_type_node))
     return (unsignedp
 	    ? long_long_unsigned_type_node
 	    : long_long_integer_type_node);
-  if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
-    return (unsignedp
-	    ? int128_unsigned_type_node
-	    : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+	&& TYPE_MODE (type) == int_n_data[i].m
+	&& TYPE_PRECISION (type) == int_n_data[i].bitsize)
+	return unsignedp
+	  ? int_n_trees[i].unsigned_type
+	  : int_n_trees[i].signed_type;
 
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
 #endif
   if (TYPE_OK (intDI_type_node))
Index: gcc/tree-core.h
===================================================================
--- gcc/tree-core.h	(revision 214383)
+++ gcc/tree-core.h	(working copy)
@@ -562,14 +562,22 @@  enum integer_type_kind {
   itk_int,
   itk_unsigned_int,
   itk_long,
   itk_unsigned_long,
   itk_long_long,
   itk_unsigned_long_long,
-  itk_int128,
-  itk_unsigned_int128,
+
+  itk_intN_0,
+  itk_unsigned_intN_0,
+  itk_intN_1,
+  itk_unsigned_intN_1,
+  itk_intN_2,
+  itk_unsigned_intN_2,
+  itk_intN_3,
+  itk_unsigned_intN_3,
+
   itk_none
 };
 
 /* A pointer-to-function member type looks like:
 
      struct {


Index: gcc/config/msp430/msp430-modes.def
===================================================================
--- gcc/config/msp430/msp430-modes.def	(revision 214383)
+++ gcc/config/msp430/msp430-modes.def	(working copy)
@@ -1,3 +1,4 @@ 
 /* 20-bit address */
 PARTIAL_INT_MODE (SI, 20, PSI);
 
+INT_N (PSI, 20);


Index: libstdc++-v3/src/c++11/limits.cc
===================================================================
--- libstdc++-v3/src/c++11/limits.cc	(revision 214383)
+++ libstdc++-v3/src/c++11/limits.cc	(working copy)
@@ -385,60 +385,72 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   const bool numeric_limits<unsigned long long>::is_bounded;
   const bool numeric_limits<unsigned long long>::is_modulo;
   const bool numeric_limits<unsigned long long>::traps;
   const bool numeric_limits<unsigned long long>::tinyness_before;
   const float_round_style numeric_limits<unsigned long long>::round_style;
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  const bool numeric_limits<__int128>::is_specialized;
-  const int  numeric_limits<__int128>::digits;
-  const int  numeric_limits<__int128>::digits10;
-  const int  numeric_limits<__int128>::max_digits10;
-  const bool numeric_limits<__int128>::is_signed;
-  const bool numeric_limits<__int128>::is_integer;
-  const bool numeric_limits<__int128>::is_exact;
-  const int  numeric_limits<__int128>::radix;
-  const int  numeric_limits<__int128>::min_exponent;
-  const int  numeric_limits<__int128>::min_exponent10;
-  const int  numeric_limits<__int128>::max_exponent;
-  const int  numeric_limits<__int128>::max_exponent10;
-  const bool numeric_limits<__int128>::has_infinity;
-  const bool numeric_limits<__int128>::has_quiet_NaN;
-  const bool numeric_limits<__int128>::has_signaling_NaN;
-  const float_denorm_style numeric_limits<__int128>::has_denorm;
-  const bool numeric_limits<__int128>::has_denorm_loss;
-  const bool numeric_limits<__int128>::is_iec559;
-  const bool numeric_limits<__int128>::is_bounded;
-  const bool numeric_limits<__int128>::is_modulo;
-  const bool numeric_limits<__int128>::traps;
-  const bool numeric_limits<__int128>::tinyness_before;
-  const float_round_style numeric_limits<__int128>::round_style;
-
-  const bool numeric_limits<unsigned __int128>::is_specialized;
-  const int  numeric_limits<unsigned __int128>::digits;
-  const int  numeric_limits<unsigned __int128>::digits10;
-  const int  numeric_limits<unsigned __int128>::max_digits10;
-  const bool numeric_limits<unsigned __int128>::is_signed;
-  const bool numeric_limits<unsigned __int128>::is_integer;
-  const bool numeric_limits<unsigned __int128>::is_exact;
-  const int  numeric_limits<unsigned __int128>::radix;
-  const int  numeric_limits<unsigned __int128>::min_exponent;
-  const int  numeric_limits<unsigned __int128>::min_exponent10;
-  const int  numeric_limits<unsigned __int128>::max_exponent;
-  const int  numeric_limits<unsigned __int128>::max_exponent10;
-  const bool numeric_limits<unsigned __int128>::has_infinity;
-  const bool numeric_limits<unsigned __int128>::has_quiet_NaN;
-  const bool numeric_limits<unsigned __int128>::has_signaling_NaN;
-  const float_denorm_style numeric_limits<unsigned __int128>::has_denorm;
-  const bool numeric_limits<unsigned __int128>::has_denorm_loss;
-  const bool numeric_limits<unsigned __int128>::is_iec559;
-  const bool numeric_limits<unsigned __int128>::is_bounded;
-  const bool numeric_limits<unsigned __int128>::is_modulo;
-  const bool numeric_limits<unsigned __int128>::traps;
-  const bool numeric_limits<unsigned __int128>::tinyness_before;
-  const float_round_style numeric_limits<unsigned __int128>::round_style;
+#define INT_N(__INT_N_TYPE)							\
+  const bool numeric_limits<__INT_N_TYPE>::is_specialized;			\
+  const int  numeric_limits<__INT_N_TYPE>::digits;				\
+  const int  numeric_limits<__INT_N_TYPE>::digits10;				\
+  const int  numeric_limits<__INT_N_TYPE>::max_digits10;			\
+  const bool numeric_limits<__INT_N_TYPE>::is_signed;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_integer;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_exact;				\
+  const int  numeric_limits<__INT_N_TYPE>::radix;				\
+  const int  numeric_limits<__INT_N_TYPE>::min_exponent;			\
+  const int  numeric_limits<__INT_N_TYPE>::min_exponent10;			\
+  const int  numeric_limits<__INT_N_TYPE>::max_exponent;			\
+  const int  numeric_limits<__INT_N_TYPE>::max_exponent10;			\
+  const bool numeric_limits<__INT_N_TYPE>::has_infinity;			\
+  const bool numeric_limits<__INT_N_TYPE>::has_quiet_NaN;			\
+  const bool numeric_limits<__INT_N_TYPE>::has_signaling_NaN;			\
+  const float_denorm_style numeric_limits<__INT_N_TYPE>::has_denorm;		\
+  const bool numeric_limits<__INT_N_TYPE>::has_denorm_loss;			\
+  const bool numeric_limits<__INT_N_TYPE>::is_iec559;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_bounded;				\
+  const bool numeric_limits<__INT_N_TYPE>::is_modulo;				\
+  const bool numeric_limits<__INT_N_TYPE>::traps;				\
+  const bool numeric_limits<__INT_N_TYPE>::tinyness_before;			\
+  const float_round_style numeric_limits<__INT_N_TYPE>::round_style;		\
+  									\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_specialized;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::digits;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::digits10;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::max_digits10;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_signed;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_integer;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_exact;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::radix;			\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::min_exponent;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::min_exponent10;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::max_exponent;		\
+  const int  numeric_limits<unsigned __INT_N_TYPE>::max_exponent10;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_infinity;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_quiet_NaN;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_signaling_NaN;		\
+  const float_denorm_style numeric_limits<unsigned __INT_N_TYPE>::has_denorm;	\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::has_denorm_loss;		\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_iec559;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_bounded;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::is_modulo;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::traps;			\
+  const bool numeric_limits<unsigned __INT_N_TYPE>::tinyness_before;		\
+  const float_round_style numeric_limits<unsigned __INT_N_TYPE>::round_style;
+
+#ifdef __GLIBCXX_TYPE_INT_N_0
+  INT_N (__GLIBCXX_TYPE_INT_N_0)
+#endif
+#ifdef __GLIBCXX_TYPE_INT_N_1
+  INT_N (__GLIBCXX_TYPE_INT_N_1)
+#endif
+#ifdef __GLIBCXX_TYPE_INT_N_2
+  INT_N (__GLIBCXX_TYPE_INT_N_2)
+#endif
+#ifdef __GLIBCXX_TYPE_INT_N_3
+  INT_N (__GLIBCXX_TYPE_INT_N_3)
 #endif
 
   // float
   const bool numeric_limits<float>::is_specialized;
   const int  numeric_limits<float>::digits;
   const int  numeric_limits<float>::digits10;
Index: libstdc++-v3/include/std/type_traits
===================================================================
--- libstdc++-v3/include/std/type_traits	(revision 214383)
+++ libstdc++-v3/include/std/type_traits	(working copy)
@@ -236,19 +236,48 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public true_type { };
 
   template<>
     struct __is_integral_helper<unsigned long long>
     : public true_type { };
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+  // Conditionalizing on __STRICT_ANSI__ here will break any port that
+  // uses one of these types for size_t.
+#if defined(__GLIBCXX_TYPE_INT_N_0)
   template<>
-    struct __is_integral_helper<__int128>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0>
     : public true_type { };
 
   template<>
-    struct __is_integral_helper<unsigned __int128>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_0>
+    : public true_type { };
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_1)
+  template<>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_1>
+    : public true_type { };
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_2)
+  template<>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_2>
+    : public true_type { };
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_3)
+  template<>
+    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3>
+    : public true_type { };
+
+  template<>
+    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_3>
     : public true_type { };
 #endif
 
   /// is_integral
   template<typename _Tp>
     struct is_integral
@@ -1598,16 +1627,31 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if defined(_GLIBCXX_USE_WCHAR_T) && !defined(__WCHAR_UNSIGNED__)
   template<>
     struct __make_unsigned<wchar_t> : __make_unsigned<__WCHAR_TYPE__>
     { };
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+#if defined(__GLIBCXX_TYPE_INT_N_0)
+  template<>
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_0 __type; };
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_1)
+  template<>
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_1>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_1 __type; };
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_2)
   template<>
-    struct __make_unsigned<__int128>
-    { typedef unsigned __int128 __type; };
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_2>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_2 __type; };
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_3)
+  template<>
+    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_3>
+    { typedef unsigned __GLIBCXX_TYPE_INT_N_3 __type; };
 #endif
 
   // Select between integral and enum: not possible to be both.
   template<typename _Tp, 
 	   bool _IsInt = is_integral<_Tp>::value,
 	   bool _IsEnum = is_enum<_Tp>::value>
@@ -1695,16 +1739,31 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { };
   template<>
     struct __make_signed<char32_t> : __make_signed<uint_least32_t>
     { };
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
+#if defined(__GLIBCXX_TYPE_INT_N_0)
+  template<>
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_0>
+    { typedef __GLIBCXX_TYPE_INT_N_0 __type; };
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_1)
+  template<>
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_1>
+    { typedef __GLIBCXX_TYPE_INT_N_1 __type; };
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_2)
+  template<>
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_2>
+    { typedef __GLIBCXX_TYPE_INT_N_2 __type; };
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_3)
   template<>
-    struct __make_signed<unsigned __int128>
-    { typedef __int128 __type; };
+    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_3>
+    { typedef __GLIBCXX_TYPE_INT_N_3 __type; };
 #endif
 
   // Select between integral and enum: not possible to be both.
   template<typename _Tp, 
 	   bool _IsInt = is_integral<_Tp>::value,
 	   bool _IsEnum = is_enum<_Tp>::value>
Index: libstdc++-v3/include/std/limits
===================================================================
--- libstdc++-v3/include/std/limits	(revision 214383)
+++ libstdc++-v3/include/std/limits	(working copy)
@@ -122,27 +122,38 @@ 
 #ifndef __glibcxx_long_double_tinyness_before
 #  define __glibcxx_long_double_tinyness_before false
 #endif
 
 // You should not need to define any macros below this point.
 
-#define __glibcxx_signed(T)	((T)(-1) < 0)
+#define __glibcxx_signed_b(T,B)	((T)(-1) < 0)
 
-#define __glibcxx_min(T) \
-  (__glibcxx_signed (T) ? -__glibcxx_max (T) - 1 : (T)0)
+#define __glibcxx_min_b(T,B)					\
+  (__glibcxx_signed_b (T,B) ? -__glibcxx_max_b (T,B) - 1 : (T)0)
 
-#define __glibcxx_max(T) \
-  (__glibcxx_signed (T) ? \
-   (((((T)1 << (__glibcxx_digits (T) - 1)) - 1) << 1) + 1) : ~(T)0)
+#define __glibcxx_max_b(T,B)						\
+  (__glibcxx_signed_b (T,B) ?						\
+   (((((T)1 << (__glibcxx_digits_b (T,B) - 1)) - 1) << 1) + 1) : ~(T)0)
 
-#define __glibcxx_digits(T) \
-  (sizeof(T) * __CHAR_BIT__ - __glibcxx_signed (T))
+#define __glibcxx_digits_b(T,B)				\
+  (B - __glibcxx_signed_b (T,B))
 
 // The fraction 643/2136 approximates log10(2) to 7 significant digits.
+#define __glibcxx_digits10_b(T,B)		\
+  (__glibcxx_digits_b (T,B) * 643L / 2136)
+
+#define __glibcxx_signed(T) \
+  __glibcxx_signed_b (T, sizeof(T) * __CHAR_BIT__)
+#define __glibcxx_min(T) \
+  __glibcxx_min_b (T, sizeof(T) * __CHAR_BIT__)
+#define __glibcxx_max(T) \
+  __glibcxx_max_b (T, sizeof(T) * __CHAR_BIT__)
+#define __glibcxx_digits(T) \
+  __glibcxx_digits_b (T, sizeof(T) * __CHAR_BIT__)
 #define __glibcxx_digits10(T) \
-  (__glibcxx_digits (T) * 643L / 2136)
+  __glibcxx_digits10_b (T, sizeof(T) * __CHAR_BIT__)
 
 #define __glibcxx_max_digits10(T) \
   (2 + (T) * 643L / 2136)
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -1396,159 +1407,187 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps;
       static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
       static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 
        = round_toward_zero;
     };
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  /// numeric_limits<__int128> specialization.
-  template<>
-    struct numeric_limits<__int128>
-    {
-      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
+#if !defined(__STRICT_ANSI__)
 
-      static _GLIBCXX_CONSTEXPR __int128
-      min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (__int128); }
+#define __INT_N(TYPE, BITSIZE, EXT, UEXT)			\
+  template<> 									\
+    struct numeric_limits<TYPE> 						\
+    { 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+	min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min_b (TYPE, BITSIZE); } \
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max_b (TYPE, BITSIZE);; } 	\	
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int digits 					\
+       = BITSIZE - 1; 								\
+      static _GLIBCXX_USE_CONSTEXPR int digits10 				\
+       = (BITSIZE - 1) * 643L / 2136; 						\
+      										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR int radix = 2; 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } 			\
+ 										\
+      EXT									\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm 		\
+       = denorm_absent; 							\
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      infinity() _GLIBCXX_USE_NOEXCEPT 						\
+      { return static_cast<TYPE>(0); } 						\
+ 										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<TYPE>(0); } 						\
+       										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<TYPE>(0); } 						\
+       										\
+      static _GLIBCXX_CONSTEXPR TYPE 						\
+      denorm_min() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<TYPE>(0); } 						\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool traps 					\
+       = __glibcxx_integral_traps; 						\
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 		\
+       = round_toward_zero; 							\
+    }; 										\
+ 										\
+  template<> 									\
+    struct numeric_limits<unsigned TYPE> 					\
+    { 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      min() _GLIBCXX_USE_NOEXCEPT { return 0; } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      max() _GLIBCXX_USE_NOEXCEPT { return  __glibcxx_max_b (TYPE, BITSIZE); }  \
+ 										\
+      UEXT									\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int digits 					\
+       = BITSIZE; 								\
+      static _GLIBCXX_USE_CONSTEXPR int digits10 				\
+       = BITSIZE * 643L / 2136; 						\
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR int radix = 2; 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; 			\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm 		\
+       = denorm_absent; 							\
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; 		\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      infinity() _GLIBCXX_USE_NOEXCEPT 						\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_CONSTEXPR unsigned TYPE 					\
+      denorm_min() _GLIBCXX_USE_NOEXCEPT 					\
+      { return static_cast<unsigned TYPE>(0); } 				\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; 			\
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; 			\
+ 										\
+      static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; 	\
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 		\
+       = round_toward_zero; 							\
+    };
+
+#if __cplusplus >= 201103L
+
+#define __INT_N_201103(TYPE)							\
+      static constexpr TYPE 							\
+      lowest() noexcept { return min(); }					\
+      static constexpr int max_digits10 = 0;
 
-      static _GLIBCXX_CONSTEXPR __int128
-      max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (__int128); }
+#define __INT_N_U201103(TYPE)							\
+      static constexpr unsigned TYPE 						\
+      lowest() noexcept { return min(); }					\
+      static constexpr int max_digits10 = 0;
 
-#if __cplusplus >= 201103L
-      static constexpr __int128
-      lowest() noexcept { return min(); }
+#else
+#define __INT_N_201103(TYPE)
+#define __INT_N_U201103(TYPE)
 #endif
 
-      static _GLIBCXX_USE_CONSTEXPR int digits
-       = __glibcxx_digits (__int128);
-      static _GLIBCXX_USE_CONSTEXPR int digits10
-       = __glibcxx_digits10 (__int128);
-#if __cplusplus >= 201103L
-      static constexpr int max_digits10 = 0;
+#ifdef __GLIBCXX_TYPE_INT_N_0
+  __INT_N(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_0), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_0))
 #endif
-      static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
-      static _GLIBCXX_USE_CONSTEXPR int radix = 2;
-
-      static _GLIBCXX_CONSTEXPR __int128
-      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_CONSTEXPR __int128
-      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0;
-
-      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm
-       = denorm_absent;
-      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;
-
-      static _GLIBCXX_CONSTEXPR __int128
-      infinity() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR __int128
-      quiet_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-      
-      static _GLIBCXX_CONSTEXPR __int128
-      signaling_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-      
-      static _GLIBCXX_CONSTEXPR __int128
-      denorm_min() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<__int128>(0); }
-
-      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false;
-      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false;
-
-      static _GLIBCXX_USE_CONSTEXPR bool traps
-       = __glibcxx_integral_traps;
-      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
-      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style
-       = round_toward_zero;
-    };
-
-  /// numeric_limits<unsigned __int128> specialization.
-  template<>
-    struct numeric_limits<unsigned __int128>
-    {
-      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      min() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (unsigned __int128); }
-
-#if __cplusplus >= 201103L
-      static constexpr unsigned __int128
-      lowest() noexcept { return min(); }
+#ifdef __GLIBCXX_TYPE_INT_N_1
+  __INT_N (__GLIBCXX_TYPE_INT_N_1, __GLIBCXX_BITSIZE_INT_N_1,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_1), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_1))
 #endif
-
-      static _GLIBCXX_USE_CONSTEXPR int digits
-       = __glibcxx_digits (unsigned __int128);
-      static _GLIBCXX_USE_CONSTEXPR int digits10
-       = __glibcxx_digits10 (unsigned __int128);
-#if __cplusplus >= 201103L
-      static constexpr int max_digits10 = 0;
+#ifdef __GLIBCXX_TYPE_INT_N_2
+  __INT_N (__GLIBCXX_TYPE_INT_N_2, __GLIBCXX_BITSIZE_INT_N_2,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_2), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_2))
+#endif
+#ifdef __GLIBCXX_TYPE_INT_N_3
+  __INT_N (__GLIBCXX_TYPE_INT_N_3, __GLIBCXX_BITSIZE_INT_N_3,
+	  __INT_N_201103 (__GLIBCXX_TYPE_INT_N_3), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_3))
 #endif
-      static _GLIBCXX_USE_CONSTEXPR bool is_signed = false;
-      static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
-      static _GLIBCXX_USE_CONSTEXPR int radix = 2;
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      round_error() _GLIBCXX_USE_NOEXCEPT { return 0; }
-
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0;
-      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0;
-
-      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false;
-      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm
-       = denorm_absent;
-      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      infinity() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      quiet_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      signaling_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
-
-      static _GLIBCXX_CONSTEXPR unsigned __int128
-      denorm_min() _GLIBCXX_USE_NOEXCEPT
-      { return static_cast<unsigned __int128>(0); }
 
-      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false;
-      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
-      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true;
+#undef __INT_N
+#undef __INT_N_201103
+#undef __INT_N_U201103
 
-      static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps;
-      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
-      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style
-       = round_toward_zero;
-    };
 #endif
 
   /// numeric_limits<float> specialization.
   template<>
     struct numeric_limits<float>
     {
Index: libstdc++-v3/include/c_std/cstdlib
===================================================================
--- libstdc++-v3/include/c_std/cstdlib	(revision 214383)
+++ libstdc++-v3/include/c_std/cstdlib	(working copy)
@@ -166,15 +166,27 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #ifdef _GLIBCXX_USE_LONG_LONG
   inline long long
   abs(long long __x) { return __builtin_llabs (__x); }
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  inline __int128
-  abs(__int128 __x) { return __x >= 0 ? __x : -__x; }
+#if defined(__GLIBCXX_TYPE_INT_N_0)
+  inline __GLIBCXX_TYPE_INT_N_0
+  abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_1)
+  inline __GLIBCXX_TYPE_INT_N_1
+  abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_2)
+  inline __GLIBCXX_TYPE_INT_N_2
+  abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_3)
+  inline __GLIBCXX_TYPE_INT_N_3
+  abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
 #endif
 
   inline ldiv_t
   div(long __i, long __j) { return ldiv(__i, __j); }
 
 _GLIBCXX_END_NAMESPACE_VERSION
Index: libstdc++-v3/include/bits/cpp_type_traits.h
===================================================================
--- libstdc++-v3/include/bits/cpp_type_traits.h	(revision 214383)
+++ libstdc++-v3/include/bits/cpp_type_traits.h	(working copy)
@@ -138,13 +138,14 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       enum { __value = 0 };
       typedef __false_type __type;
     };
 
   // Thirteen specializations (yes there are eleven standard integer
   // types; <em>long long</em> and <em>unsigned long long</em> are
-  // supported as extensions)
+  // supported as extensions).  Up to four target-specific __int<N>
+  // types are supported as well.
   template<>
     struct __is_integer<bool>
     {
       enum { __value = 1 };
       typedef __true_type __type;
     };
@@ -248,12 +249,41 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_integer<unsigned long long>
     {
       enum { __value = 1 };
       typedef __true_type __type;
     };
 
+#define __INT_N(TYPE) 			\
+  template<>				\
+    struct __is_integer<TYPE>		\
+    {					\
+      enum { __value = 1 };		\
+      typedef __true_type __type;	\
+    };					\
+  template<>				\
+    struct __is_integer<unsigned TYPE>	\
+    {					\
+      enum { __value = 1 };		\
+      typedef __true_type __type;	\
+    };
+
+#ifdef __GLIBCXX_TYPE_INT_N_0
+__INT_N(__GLIBCXX_TYPE_INT_N_0)
+#endif
+#ifdef __GLIBCXX_TYPE_INT_N_1
+__INT_N(__GLIBCXX_TYPE_INT_N_1)
+#endif
+#ifdef __GLIBCXX_TYPE_INT_N_2
+__INT_N(__GLIBCXX_TYPE_INT_N_2)
+#endif
+#ifdef __GLIBCXX_TYPE_INT_N_3
+__INT_N(__GLIBCXX_TYPE_INT_N_3)
+#endif
+
+#undef __INT_N
+
   //
   // Floating point types
   //
   template<typename _Tp>
     struct __is_floating
     {
Index: libstdc++-v3/include/c_global/cstdlib
===================================================================
--- libstdc++-v3/include/c_global/cstdlib	(revision 214383)
+++ libstdc++-v3/include/c_global/cstdlib	(working copy)
@@ -171,17 +171,30 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #ifdef _GLIBCXX_USE_LONG_LONG
   inline long long
   abs(long long __x) { return __builtin_llabs (__x); }
 #endif
 
-#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
-  inline __int128
-  abs(__int128 __x) { return __x >= 0 ? __x : -__x; }
+#if defined(__GLIBCXX_TYPE_INT_N_0)
+  inline __GLIBCXX_TYPE_INT_N_0
+  abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_1)
+  inline __GLIBCXX_TYPE_INT_N_1
+  abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_2)
+  inline __GLIBCXX_TYPE_INT_N_2
+  abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_3)
+  inline __GLIBCXX_TYPE_INT_N_3
+  abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
 #endif
 
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
 #if _GLIBCXX_USE_C99
 
 #undef _Exit