Index: doc/extend.texi =================================================================== --- doc/extend.texi (revision 172932) +++ doc/extend.texi (working copy) @@ -14422,6 +14422,10 @@ type, (possibly cv-qualified) @code{void}, or an a If @code{type} is a cv union type ([basic.compound]) the trait is true, else it is false. +@item __underlying_type (type) +The underlying type of @code{type}. Requires: @code{type} shall be +an enumeration type ([dcl.enum]). + @end table @node Java Exceptions Index: c-family/c-common.c =================================================================== --- c-family/c-common.c (revision 172932) +++ c-family/c-common.c (working copy) @@ -450,6 +450,7 @@ const struct c_common_resword c_common_reswords[] { "__is_trivial", RID_IS_TRIVIAL, D_CXXONLY }, { "__is_union", RID_IS_UNION, D_CXXONLY }, { "__is_literal_type", RID_IS_LITERAL_TYPE, D_CXXONLY }, + { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY }, { "__imag", RID_IMAGPART, 0 }, { "__imag__", RID_IMAGPART, 0 }, { "__inline", RID_INLINE, 0 }, Index: c-family/c-common.h =================================================================== --- c-family/c-common.h (revision 172932) +++ c-family/c-common.h (working copy) @@ -138,6 +138,7 @@ enum rid RID_IS_POD, RID_IS_POLYMORPHIC, RID_IS_STD_LAYOUT, RID_IS_TRIVIAL, RID_IS_UNION, RID_IS_LITERAL_TYPE, + RID_UNDERLYING_TYPE, /* C++0x */ RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT, Index: testsuite/g++.dg/ext/underlying_type5.C =================================================================== --- testsuite/g++.dg/ext/underlying_type5.C (revision 0) +++ testsuite/g++.dg/ext/underlying_type5.C (revision 0) @@ -0,0 +1,43 @@ +// { dg-do compile } +// { dg-options "-std=c++0x" } + +template + struct is_same + { static const bool value = false; }; + +template + struct is_same + { static const bool value = true; }; + +enum E1 : unsigned { }; +enum E2 : char { }; +enum class E3 { }; +enum class E4 : unsigned char { c = 1 }; +enum class E5 : int { a = -1, b = 1 }; +enum class E6 : long { c = __LONG_MAX__ }; + +typedef __underlying_type(E1) UTE1; +typedef __underlying_type(E2) UTE2; +typedef __underlying_type(E3) UTE3; +typedef __underlying_type(E4) UTE4; +typedef __underlying_type(E5) UTE5; +typedef __underlying_type(E6) UTE6; + +template + struct underlying_type + { typedef __underlying_type(T) type; }; + +static_assert(is_same::type, UTE1>::value, "Error"); +static_assert(is_same::type, UTE2>::value, "Error"); +static_assert(is_same::type, UTE3>::value, "Error"); +static_assert(is_same::type, UTE4>::value, "Error"); +static_assert(is_same::type, UTE5>::value, "Error"); +static_assert(is_same::type, UTE6>::value, "Error"); + +static_assert(is_same::type, unsigned>::value, "Error"); +static_assert(is_same::type, char>::value, "Error"); +static_assert(is_same::type, int>::value, "Error"); +static_assert(is_same::type, + unsigned char>::value, "Error"); +static_assert(is_same::type, int>::value, "Error"); +static_assert(is_same::type, long>::value, "Error"); Index: testsuite/g++.dg/ext/underlying_type6.C =================================================================== --- testsuite/g++.dg/ext/underlying_type6.C (revision 0) +++ testsuite/g++.dg/ext/underlying_type6.C (revision 0) @@ -0,0 +1,31 @@ +// { dg-do compile } +// { dg-options "-std=c++0x" } + +template + struct is_same + { static const bool value = false; }; + +template + struct is_same + { static const bool value = true; }; + +enum E1 : unsigned { }; +enum E2 : char { }; +enum class E3 { }; +enum class E4 : unsigned char { c = 1 }; +enum class E5 : int { a = -1, b = 1 }; +enum class E6 : long { c = __LONG_MAX__ }; + +template + struct test + { + static_assert(is_same::value, "Error"); + }; + +template class test; +template class test; +template class test; +template class test; +template class test; +template class test; Index: testsuite/g++.dg/ext/underlying_type7.C =================================================================== --- testsuite/g++.dg/ext/underlying_type7.C (revision 0) +++ testsuite/g++.dg/ext/underlying_type7.C (revision 0) @@ -0,0 +1,24 @@ +// { dg-do compile } +// { dg-options "-std=c++0x" } + +enum E1 : unsigned { E1_en = 1 }; +enum E2 : char { E2_en = 1 }; +enum class E3 { a = -1 }; +enum class E4 : unsigned char { c = 1 }; +enum class E5 : int { a = -1, b = 1 }; +enum class E6 : long { c = __LONG_MAX__ }; + +template + void + test(T, __underlying_type(T)) // { dg-message "sorry, unimplemented: mangling" } + { } + +int main() +{ + test(E1::E1_en, 1); + test(E2::E2_en, 1); + test(E3::a, -1); + test(E4::c, 1); + test(E5::a, -1); + test(E6::c, __LONG_MAX__); +} Index: testsuite/g++.dg/ext/underlying_type8.C =================================================================== --- testsuite/g++.dg/ext/underlying_type8.C (revision 0) +++ testsuite/g++.dg/ext/underlying_type8.C (revision 0) @@ -0,0 +1,46 @@ +// { dg-do compile } +// { dg-options "-std=c++0x" } + +enum E1 : unsigned { E1_en = 1 }; +enum E2 : char { E2_en = 1 }; +enum class E3 { a = -1 }; +enum class E4 : unsigned char { c = 1 }; +enum class E5 : int { a = -1, b = 1 }; +enum class E6 : long { c = __LONG_MAX__ }; + +template + struct is_same + { static const bool value = false; }; + +template + struct is_same + { static const bool value = true; }; + +template + struct underlying_type; + +template + void + test(T, U, typename underlying_type::type); + +template + struct underlying_type + { typedef __underlying_type(T) type; }; + +template + void + test(T, U, typename underlying_type::type) + { + static_assert(is_same::type, U>::value, + "Error"); + } + +int main() +{ + test(E1::E1_en, unsigned(), 1); + test(E2::E2_en, char(), 1); + test(E3::a, int(), -1); + test(E4::c, (unsigned char)(1), 1); + test(E5::a, int(), -1); + test(E6::c, long(), __LONG_MAX__); +} Index: testsuite/g++.dg/ext/underlying_type1.C =================================================================== --- testsuite/g++.dg/ext/underlying_type1.C (revision 0) +++ testsuite/g++.dg/ext/underlying_type1.C (revision 0) @@ -0,0 +1,18 @@ +// { dg-do compile } + +struct B { }; +union U { }; + +template + struct underlying_type + { typedef __underlying_type(T) type; }; // { dg-error "not an enumeration" } + +__underlying_type(int) i1; // { dg-error "not an enumeration|invalid" } +__underlying_type(A) i2; // { dg-error "expected" } +__underlying_type(B) i3; // { dg-error "not an enumeration|invalid" } +__underlying_type(U) i4; // { dg-error "not an enumeration|invalid" } + +underlying_type::type i5; +underlying_type::type i6; // { dg-error "not declared|template|expected" } +underlying_type::type i7; +underlying_type::type i8; Index: testsuite/g++.dg/ext/underlying_type9.C =================================================================== --- testsuite/g++.dg/ext/underlying_type9.C (revision 0) +++ testsuite/g++.dg/ext/underlying_type9.C (revision 0) @@ -0,0 +1,30 @@ +// { dg-do compile } +// { dg-options "-std=c++0x" } + +template + struct is_same + { static const bool value = false; }; + +template + struct is_same + { static const bool value = true; }; + +enum E1 : unsigned { }; +enum E2 : char { }; +enum class E3 { }; +enum class E4 : unsigned char { c = 1 }; +enum class E5 : int { a = -1, b = 1 }; +enum class E6 : long { c = __LONG_MAX__ }; + +template + struct test + { + static_assert(is_same::value, "Error"); + }; + +test<__underlying_type(E1), unsigned> t1; +test<__underlying_type(E2), char> t2; +test<__underlying_type(E3), int> t3; +test<__underlying_type(E4), unsigned char> t4; +test<__underlying_type(E5), int> t5; +test<__underlying_type(E6), long> t6; Index: testsuite/g++.dg/ext/underlying_type2.C =================================================================== --- testsuite/g++.dg/ext/underlying_type2.C (revision 0) +++ testsuite/g++.dg/ext/underlying_type2.C (revision 0) @@ -0,0 +1,9 @@ +// { dg-do compile } + +enum E1 { }; +enum E2 { a = -1, b = 1 }; +enum E3 { c = __LONG_MAX__ }; + +__underlying_type(E1) e1 = 0; +__underlying_type(E2) e2 = b; +__underlying_type(E3) e3 = __LONG_MAX__; Index: testsuite/g++.dg/ext/underlying_type3.C =================================================================== --- testsuite/g++.dg/ext/underlying_type3.C (revision 0) +++ testsuite/g++.dg/ext/underlying_type3.C (revision 0) @@ -0,0 +1,33 @@ +// { dg-do compile } +// { dg-options "-std=c++0x" } + +template + struct is_same + { static const bool value = false; }; + +template + struct is_same + { static const bool value = true; }; + +enum E1 : unsigned { }; +enum E2 : char { }; +enum class E3 { }; +enum class E4 : unsigned char { c = 1 }; +enum class E5 : int { a = -1, b = 1 }; +enum class E6 : long { c = __LONG_MAX__ }; + +__underlying_type(E1) i1 = __INT_MAX__ * 2U + 1; +__underlying_type(E2) i2 = (char(-1) < 0 + ? __SCHAR_MAX__ + : __SCHAR_MAX__ * 2U + 1); +__underlying_type(E3) i3 = __INT_MAX__; +__underlying_type(E4) i4 = __SCHAR_MAX__ * 2U + 1; +__underlying_type(E5) i5 = int(E5::b); +__underlying_type(E6) i6 = __LONG_MAX__; + +static_assert(is_same<__underlying_type(E1), unsigned>::value, "Error"); +static_assert(is_same<__underlying_type(E2), char>::value, "Error"); +static_assert(is_same<__underlying_type(E3), int>::value, "Error"); +static_assert(is_same<__underlying_type(E4), unsigned char>::value, "Error"); +static_assert(is_same<__underlying_type(E5), int>::value, "Error"); +static_assert(is_same<__underlying_type(E6), long>::value, "Error"); Index: testsuite/g++.dg/ext/underlying_type10.C =================================================================== --- testsuite/g++.dg/ext/underlying_type10.C (revision 0) +++ testsuite/g++.dg/ext/underlying_type10.C (revision 0) @@ -0,0 +1,32 @@ +// { dg-do run } +// { dg-options "-std=c++0x" } + +#include + +enum E1 : unsigned { E1_en = 1 }; +enum E2 : char { E2_en = 1 }; +enum class E3 { a = -1 }; +enum class E4 : unsigned char { c = 1 }; +enum class E5 : int { a = -1, b = 1 }; +enum class E6 : long { c = __LONG_MAX__ }; + +template + struct underlying_type + { typedef __underlying_type(T) type; }; + +template + void + test(T t, typename underlying_type::type v) + { + assert( t == T(v) ); + } + +int main() +{ + test(E1::E1_en, 1); + test(E2::E2_en, 1); + test(E3::a, -1); + test(E4::c, 1); + test(E5::a, -1); + test(E6::c, __LONG_MAX__); +} Index: testsuite/g++.dg/ext/underlying_type4.C =================================================================== --- testsuite/g++.dg/ext/underlying_type4.C (revision 0) +++ testsuite/g++.dg/ext/underlying_type4.C (revision 0) @@ -0,0 +1,25 @@ +// { dg-do compile } + +#include + +using namespace std::tr1; + +enum E1 { }; +enum E2 { a = -1, b = 1 }; +enum E3 { c = __LONG_MAX__ }; + +typedef __underlying_type(E1) UTE1; +typedef __underlying_type(E2) UTE2; +typedef __underlying_type(E3) UTE3; + +template + struct underlying_type + { typedef __underlying_type(T) type; }; + +int test1[is_same::type, UTE1>::value ? 1 : -1]; +int test2[is_same::type, UTE2>::value ? 1 : -1]; +int test3[is_same::type, UTE3>::value ? 1 : -1]; + +int test4[is_integral::type>::value ? 1 : -1]; +int test5[is_integral::type>::value ? 1 : -1]; +int test6[is_integral::type>::value ? 1 : -1]; Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 172932) +++ cp/typeck.c (working copy) @@ -1331,6 +1331,10 @@ structural_comptypes (tree t1, tree t2, int strict return false; break; + case UNDERLYING_TYPE: + return same_type_p (UNDERLYING_TYPE_TYPE (t1), + UNDERLYING_TYPE_TYPE (t2)); + default: return false; } Index: cp/error.c =================================================================== --- cp/error.c (revision 172932) +++ cp/error.c (working copy) @@ -1,7 +1,8 @@ /* Call-backs for C++ error reporting. This code is non-reentrant. Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, - 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify @@ -483,6 +484,14 @@ dump_type (tree t, int flags) pp_cxx_right_paren (cxx_pp); break; + case UNDERLYING_TYPE: + pp_cxx_ws_string (cxx_pp, "__underlying_type"); + pp_cxx_whitespace (cxx_pp); + pp_cxx_left_paren (cxx_pp); + dump_expr (UNDERLYING_TYPE_TYPE (t), flags & ~TFF_EXPR_IN_PARENS); + pp_cxx_right_paren (cxx_pp); + break; + case TYPE_PACK_EXPANSION: dump_type (PACK_EXPANSION_PATTERN (t), flags); pp_cxx_ws_string (cxx_pp, "..."); @@ -731,6 +740,7 @@ dump_type_prefix (tree t, int flags) case COMPLEX_TYPE: case VECTOR_TYPE: case TYPEOF_TYPE: + case UNDERLYING_TYPE: case DECLTYPE_TYPE: case TYPE_PACK_EXPANSION: case FIXED_POINT_TYPE: @@ -834,6 +844,7 @@ dump_type_suffix (tree t, int flags) case COMPLEX_TYPE: case VECTOR_TYPE: case TYPEOF_TYPE: + case UNDERLYING_TYPE: case DECLTYPE_TYPE: case TYPE_PACK_EXPANSION: case FIXED_POINT_TYPE: Index: cp/tree.c =================================================================== --- cp/tree.c (revision 172932) +++ cp/tree.c (working copy) @@ -2831,6 +2831,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, case TEMPLATE_TYPE_PARM: case TYPENAME_TYPE: case TYPEOF_TYPE: + case UNDERLYING_TYPE: /* None of these have subtrees other than those already walked above. */ *walk_subtrees_p = 0; Index: cp/cxx-pretty-print.c =================================================================== --- cp/cxx-pretty-print.c (revision 172932) +++ cp/cxx-pretty-print.c (working copy) @@ -1,6 +1,6 @@ /* Implementation of subroutines for the GNU C++ pretty-printer. Copyright (C) 2003, 2004, 2005, 2007, 2008, - 2009, 2010 Free Software Foundation, Inc. + 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis This file is part of GCC. @@ -1694,6 +1694,7 @@ pp_cxx_type_id (cxx_pretty_printer *pp, tree t) case TEMPLATE_PARM_INDEX: case TEMPLATE_DECL: case TYPEOF_TYPE: + case UNDERLYING_TYPE: case DECLTYPE_TYPE: case TEMPLATE_ID_EXPR: pp_cxx_type_specifier_seq (pp, t); Index: cp/pt.c =================================================================== --- cp/pt.c (revision 172932) +++ cp/pt.c (working copy) @@ -7255,6 +7255,7 @@ for_each_template_parm_r (tree *tp, int *walk_subt break; case TYPEOF_TYPE: + case UNDERLYING_TYPE: if (pfd->include_nondeduced_p && for_each_template_parm (TYPE_FIELDS (t), fn, data, pfd->visited, @@ -11032,6 +11033,13 @@ tsubst (tree t, tree args, tsubst_flags_t complain complain); } + case UNDERLYING_TYPE: + { + tree type = tsubst (UNDERLYING_TYPE_TYPE (t), args, + complain, in_decl); + return finish_underlying_type (type); + } + case TYPE_ARGUMENT_PACK: case NONTYPE_ARGUMENT_PACK: { @@ -15692,8 +15700,9 @@ unify (tree tparms, tree targs, tree parm, tree ar case TYPEOF_TYPE: case DECLTYPE_TYPE: - /* Cannot deduce anything from TYPEOF_TYPE or DECLTYPE_TYPE - nodes. */ + case UNDERLYING_TYPE: + /* Cannot deduce anything from TYPEOF_TYPE, DECLTYPE_TYPE, + or UNDERLYING_TYPE nodes. */ return 0; case ERROR_MARK: @@ -17952,11 +17961,12 @@ dependent_type_p_r (tree type) (INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type))))) return true; - /* All TYPEOF_TYPEs and DECLTYPE_TYPEs are dependent; if the - argument of the `typeof' expression is not type-dependent, then - it should already been have resolved. */ + /* All TYPEOF_TYPEs, DECLTYPE_TYPEs, and UNDERLYING_TYPEs are + dependent; if the argument of the `typeof' expression is not + type-dependent, then it should already been have resolved. */ if (TREE_CODE (type) == TYPEOF_TYPE - || TREE_CODE (type) == DECLTYPE_TYPE) + || TREE_CODE (type) == DECLTYPE_TYPE + || TREE_CODE (type) == UNDERLYING_TYPE) return true; /* A template argument pack is dependent if any of its packed Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 172932) +++ cp/semantics.c (working copy) @@ -3366,6 +3366,44 @@ finish_typeof (tree expr) return type; } +/* Implement the __underlying_type keyword: Return the underlying + type of TYPE, suitable for use as a type-specifier. */ + +tree +finish_underlying_type (tree type) +{ + tree underlying_type; + + if (processing_template_decl) + { + underlying_type = cxx_make_type (UNDERLYING_TYPE); + UNDERLYING_TYPE_TYPE (underlying_type) = type; + SET_TYPE_STRUCTURAL_EQUALITY (underlying_type); + + return underlying_type; + } + + complete_type (type); + + if (TREE_CODE (type) != ENUMERAL_TYPE) + { + error ("%qE is not an enumeration type", type); + return error_mark_node; + } + + underlying_type = ENUM_UNDERLYING_TYPE (type); + + /* Fixup necessary in this case because ENUM_UNDERLYING_TYPE + includes TYPE_MIN_VALUE and TYPE_MAX_VALUE information. + See finish_enum_value_list for details. */ + if (!ENUM_FIXED_UNDERLYING_TYPE_P (type)) + underlying_type + = c_common_type_for_mode (TYPE_MODE (underlying_type), + TYPE_UNSIGNED (underlying_type)); + + return underlying_type; +} + /* Perform C++-specific checks for __builtin_offsetof before calling fold_offsetof. */ Index: cp/parser.c =================================================================== --- cp/parser.c (revision 172932) +++ cp/parser.c (working copy) @@ -1,6 +1,6 @@ /* C++ Parser. Copyright (C) 2000, 2001, 2002, 2003, 2004, - 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Mark Mitchell . This file is part of GCC. @@ -654,6 +654,7 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_ case RID_TYPEOF: /* C++0x extensions. */ case RID_DECLTYPE: + case RID_UNDERLYING_TYPE: return true; default: @@ -7129,8 +7130,11 @@ cp_parser_builtin_offsetof (cp_parser *parser) return expr; } -/* Parse a trait expression. */ +/* Parse a trait expression. + Returns a representation of the expression, the underyling type + of the type at issue when KEYWORD is RID_UNDERLYING_TYPE. */ + static tree cp_parser_trait_expr (cp_parser* parser, enum rid keyword) { @@ -7185,6 +7189,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid case RID_IS_ENUM: kind = CPTK_IS_ENUM; break; + case RID_IS_LITERAL_TYPE: + kind = CPTK_IS_LITERAL_TYPE; + break; case RID_IS_POD: kind = CPTK_IS_POD; break; @@ -7200,8 +7207,8 @@ cp_parser_trait_expr (cp_parser* parser, enum rid case RID_IS_UNION: kind = CPTK_IS_UNION; break; - case RID_IS_LITERAL_TYPE: - kind = CPTK_IS_LITERAL_TYPE; + case RID_UNDERLYING_TYPE: + kind = CPTK_UNDERLYING_TYPE; break; default: gcc_unreachable (); @@ -7247,7 +7254,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid /* Complete the trait expression, which may mean either processing the trait expr now or saving it for template instantiation. */ - return finish_trait_expr (kind, type1, type2); + return kind != CPTK_UNDERLYING_TYPE + ? finish_trait_expr (kind, type1, type2) + : finish_underlying_type (type1); } /* Lambdas that appear in variable initializer or default argument scope @@ -12505,6 +12514,7 @@ cp_parser_type_specifier (cp_parser* parser, decltype ( expression ) char16_t char32_t + __underlying_type ( type-id ) GNU Extension: @@ -12621,6 +12631,16 @@ cp_parser_simple_type_specifier (cp_parser* parser return type; + case RID_UNDERLYING_TYPE: + type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE); + + if (decl_specs) + cp_parser_set_decl_spec_type (decl_specs, type, + token->location, + /*user_defined_p=*/true); + + return type; + default: break; } Index: cp/cp-tree.def =================================================================== --- cp/cp-tree.def (revision 172932) +++ cp/cp-tree.def (working copy) @@ -2,7 +2,7 @@ additional tree codes used in the GNU C++ compiler (see tree.def for the standard codes). Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998, 2003, 2004, 2005, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2010 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2010, 2011 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) @@ -450,6 +450,10 @@ DEFTREECODE (LAMBDA_EXPR, "lambda_expr", tcc_excep DECLTYPE_FOR_LAMBDA_RETURN is set if we want lambda return deduction. */ DEFTREECODE (DECLTYPE_TYPE, "decltype_type", tcc_type, 0) +/* A type designated by `__underlying_type (type)'. + UNDERLYING_TYPE_TYPE is the type in question. */ +DEFTREECODE (UNDERLYING_TYPE, "underlying_type", tcc_type, 0) + /* Used to represent the template information stored by template specializations. The accessors are: Index: cp/cp-objcp-common.c =================================================================== --- cp/cp-objcp-common.c (revision 172932) +++ cp/cp-objcp-common.c (working copy) @@ -238,6 +238,7 @@ cp_common_init_ts (void) MARK_TS_COMMON (TEMPLATE_INFO); MARK_TS_COMMON (TYPENAME_TYPE); MARK_TS_COMMON (TYPEOF_TYPE); + MARK_TS_COMMON (UNDERLYING_TYPE); MARK_TS_COMMON (BASELINK); MARK_TS_COMMON (TYPE_PACK_EXPANSION); MARK_TS_COMMON (EXPR_PACK_EXPANSION); Index: cp/mangle.c =================================================================== --- cp/mangle.c (revision 172932) +++ cp/mangle.c (working copy) @@ -1991,6 +1991,10 @@ write_type (tree type) sorry ("mangling typeof, use decltype instead"); break; + case UNDERLYING_TYPE: + sorry ("mangling __underlying_type"); + break; + case LANG_TYPE: /* fall through. */ Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 172932) +++ cp/cp-tree.h (working copy) @@ -556,12 +556,13 @@ typedef enum cp_trait_kind CPTK_IS_CONVERTIBLE_TO, CPTK_IS_EMPTY, CPTK_IS_ENUM, + CPTK_IS_LITERAL_TYPE, CPTK_IS_POD, CPTK_IS_POLYMORPHIC, CPTK_IS_STD_LAYOUT, CPTK_IS_TRIVIAL, - CPTK_IS_LITERAL_TYPE, - CPTK_IS_UNION + CPTK_IS_UNION, + CPTK_UNDERLYING_TYPE } cp_trait_kind; /* The types that we are processing. */ @@ -3360,6 +3361,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_a /* The expression in question for a TYPEOF_TYPE. */ #define TYPEOF_TYPE_EXPR(NODE) (TYPEOF_TYPE_CHECK (NODE))->type.values +/* The type in question for an UNDERLYING_TYPE. */ +#define UNDERLYING_TYPE_TYPE(NODE) \ + (UNDERLYING_TYPE_CHECK (NODE))->type.values + /* The expression in question for a DECLTYPE_TYPE. */ #define DECLTYPE_TYPE_EXPR(NODE) (DECLTYPE_TYPE_CHECK (NODE))->type.values @@ -5320,6 +5325,7 @@ extern tree finish_id_expression (tree, tree, tre const char **, location_t); extern tree finish_typeof (tree); +extern tree finish_underlying_type (tree); extern tree finish_offsetof (tree); extern void finish_decl_cleanup (tree, tree); extern void finish_eh_cleanup (tree);