c-common.c (struct c_common_resword): Add __underlying_type.
authorPaolo Carlini <paolo.carlini@oracle.com>
Mon, 25 Apr 2011 22:27:19 +0000 (22:27 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Mon, 25 Apr 2011 22:27:19 +0000 (22:27 +0000)
/gcc
2011-04-25  Paolo Carlini  <paolo.carlini@oracle.com>

* c-family/c-common.c (struct c_common_resword): Add
__underlying_type.
* c-family/c-common.h (enum rid): Add RID_UNDERLYING_TYPE.

/cp
2011-04-25  Paolo Carlini  <paolo.carlini@oracle.com>

* cp-tree.def: Add a new UNDERLYING_TYPE tree code.
* cp-tree.h (enum cp_trait_kind): Add CPTK_UNDERLYING_TYPE, tidy.
(UNDERLYING_TYPE_TYPE): Add.
* cp-objcp-common.c (cp_common_init_ts): Mark UNDERLYING_TYPE
as TS_COMMON.
* parser.c (cp_lexer_next_token_is_decl_specifier_keyword,
cp_parser_simple_type_specifier): Handle UNDERLYING_TYPE.
(cp_parser_trait_expr): Deal with RID_UNDERLYING_TYPE; tidy.
* semantics.c (finish_underlying_type): New.
* typeck.c (structural_comptypes): Handle UNDERLYING_TYPE.
* error.c (dump_type, dump_type_prefix, dump_type_suffix): Likewise.
* cxx-pretty-print.c (p_cxx_type_id): Likewise.
* tree.c (cp_walk_subtrees): Likewise.
* pt.c (for_each_template_parm_r, tsubst, unify,
dependent_type_p_r): Likewise.
* mangle.c (write_type): Sorry for __underlying_type.
* doc/extend.texi: Document __underlying_type.

/testsuite
2011-04-25  Paolo Carlini  <paolo.carlini@oracle.com>

* g++.dg/ext/underlying_type1.C: New.
* g++.dg/ext/underlying_type2.C: Likewise.
* g++.dg/ext/underlying_type3.C: Likewise.
* g++.dg/ext/underlying_type4.C: Likewise.
* g++.dg/ext/underlying_type5.C: Likewise.
* g++.dg/ext/underlying_type6.C: Likewise.
* g++.dg/ext/underlying_type7.C: Likewise.
* g++.dg/ext/underlying_type8.C: Likewise.
* g++.dg/ext/underlying_type9.C: Likewise.
* g++.dg/ext/underlying_type10.C: Likewise.

From-SVN: r172943

26 files changed:
gcc/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/cp/ChangeLog
gcc/cp/cp-objcp-common.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/cxx-pretty-print.c
gcc/cp/error.c
gcc/cp/mangle.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/underlying_type1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/underlying_type10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/underlying_type2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/underlying_type3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/underlying_type4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/underlying_type5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/underlying_type6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/underlying_type7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/underlying_type8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/underlying_type9.C [new file with mode: 0644]

index 26b8cb9..334ee8f 100644 (file)
@@ -1,3 +1,9 @@
+2011-04-25  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       * c-family/c-common.c (struct c_common_resword): Add
+       __underlying_type.
+       * c-family/c-common.h (enum rid): Add RID_UNDERLYING_TYPE.
+
 2011-04-25  Segher Boessenkool  <segher@kernel.crashing.org>
 
        * config/rs6000/titan.md (automata_option "progress"): Remove.
index 752806e..63277ca 100644 (file)
@@ -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 da9dad5..09aa600 100644 (file)
@@ -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 d2dbe4e..303a4c9 100644 (file)
@@ -1,3 +1,23 @@
+2011-04-25  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       * cp-tree.def: Add a new UNDERLYING_TYPE tree code.
+       * cp-tree.h (enum cp_trait_kind): Add CPTK_UNDERLYING_TYPE, tidy.
+       (UNDERLYING_TYPE_TYPE): Add.
+       * cp-objcp-common.c (cp_common_init_ts): Mark UNDERLYING_TYPE
+       as TS_COMMON.
+       * parser.c (cp_lexer_next_token_is_decl_specifier_keyword,
+       cp_parser_simple_type_specifier): Handle UNDERLYING_TYPE.
+       (cp_parser_trait_expr): Deal with RID_UNDERLYING_TYPE; tidy.
+       * semantics.c (finish_underlying_type): New.
+       * typeck.c (structural_comptypes): Handle UNDERLYING_TYPE.
+       * error.c (dump_type, dump_type_prefix, dump_type_suffix): Likewise.
+       * cxx-pretty-print.c (p_cxx_type_id): Likewise.
+       * tree.c (cp_walk_subtrees): Likewise.
+       * pt.c (for_each_template_parm_r, tsubst, unify,
+       dependent_type_p_r): Likewise.
+       * mangle.c (write_type): Sorry for __underlying_type.
+       * doc/extend.texi: Document __underlying_type.
+
 2011-04-25  Jason Merrill  <jason@redhat.com>
 
        PR c++/48707
index 6421f6f..d15aed0 100644 (file)
@@ -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 42840a8..7bd35e0 100644 (file)
@@ -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_exceptional, 0)
    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 66ac4e8..1c7a4e6 100644 (file)
@@ -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_arg_iterator *iter)
 /* 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
 
@@ -5321,6 +5326,7 @@ extern tree finish_id_expression          (tree, tree, tree,
                                                 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);
index d8bf912..bd0381b 100644 (file)
@@ -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 <gdr@integrable-solutions.net>
 
 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 ec9b9fe..fce7403 100644 (file)
@@ -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 b33f317..3dbc3b7 100644 (file)
@@ -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 7d3121c..bb97700 100644 (file)
@@ -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 <mark@codesourcery.com>.
 
    This file is part of GCC.
@@ -654,6 +654,7 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
     case RID_TYPEOF:
       /* C++0x extensions.  */
     case RID_DECLTYPE:
+    case RID_UNDERLYING_TYPE:
       return true;
 
     default:
@@ -7129,7 +7130,10 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   return expr;
 }
 
-/* Parse a trait expression.  */
+/* Parse a trait expression.
+
+   Returns a representation of the expression, the underlying 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 keyword)
     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 keyword)
     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 keyword)
 
   /* 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 70fcbba..654289a 100644 (file)
@@ -7255,6 +7255,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
       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, tree in_decl)
                                             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 arg, int strict)
 
     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 7763ae0..62272aa 100644 (file)
@@ -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 23daa6c..fd5c55e 100644 (file)
@@ -2831,6 +2831,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
     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 dcdc790..afe0dbc 100644 (file)
@@ -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 cd361e7..f464fa4 100644 (file)
@@ -1,3 +1,16 @@
+2011-04-25  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       * g++.dg/ext/underlying_type1.C: New.
+       * g++.dg/ext/underlying_type2.C: Likewise.
+       * g++.dg/ext/underlying_type3.C: Likewise.
+       * g++.dg/ext/underlying_type4.C: Likewise.
+       * g++.dg/ext/underlying_type5.C: Likewise.
+       * g++.dg/ext/underlying_type6.C: Likewise.
+       * g++.dg/ext/underlying_type7.C: Likewise.
+       * g++.dg/ext/underlying_type8.C: Likewise.
+       * g++.dg/ext/underlying_type9.C: Likewise.
+       * g++.dg/ext/underlying_type10.C: Likewise.
+
 2011-04-25  Jason Merrill  <jason@redhat.com>
 
        * g++.dg/cpp0x/regress/template-const2.C: New.
diff --git a/gcc/testsuite/g++.dg/ext/underlying_type1.C b/gcc/testsuite/g++.dg/ext/underlying_type1.C
new file mode 100644 (file)
index 0000000..a8f68d3
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-do compile }
+
+struct B { };
+union U { };
+
+template<typename T>
+  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<int>::type i5;
+underlying_type<A>::type   i6; // { dg-error "not declared|template|expected" }
+underlying_type<B>::type   i7;
+underlying_type<U>::type   i8;
diff --git a/gcc/testsuite/g++.dg/ext/underlying_type10.C b/gcc/testsuite/g++.dg/ext/underlying_type10.C
new file mode 100644 (file)
index 0000000..cb57407
--- /dev/null
@@ -0,0 +1,32 @@
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+#include <cassert>
+
+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<typename T>
+  struct underlying_type
+  { typedef __underlying_type(T) type; };
+
+template<typename T>
+  void
+  test(T t, typename underlying_type<T>::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__);
+}
diff --git a/gcc/testsuite/g++.dg/ext/underlying_type2.C b/gcc/testsuite/g++.dg/ext/underlying_type2.C
new file mode 100644 (file)
index 0000000..0e45198
--- /dev/null
@@ -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__;
diff --git a/gcc/testsuite/g++.dg/ext/underlying_type3.C b/gcc/testsuite/g++.dg/ext/underlying_type3.C
new file mode 100644 (file)
index 0000000..b78cc7d
--- /dev/null
@@ -0,0 +1,33 @@
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+template<typename T1, typename T2>
+  struct is_same
+  { static const bool value = false; };
+
+template<typename T>
+  struct is_same<T, T>
+  { 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");
diff --git a/gcc/testsuite/g++.dg/ext/underlying_type4.C b/gcc/testsuite/g++.dg/ext/underlying_type4.C
new file mode 100644 (file)
index 0000000..b80ed57
--- /dev/null
@@ -0,0 +1,25 @@
+// { dg-do compile }
+
+#include <tr1/type_traits>
+
+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<typename T>
+  struct underlying_type
+  { typedef __underlying_type(T) type; };
+
+int test1[is_same<underlying_type<E1>::type, UTE1>::value ? 1 : -1];
+int test2[is_same<underlying_type<E2>::type, UTE2>::value ? 1 : -1];
+int test3[is_same<underlying_type<E3>::type, UTE3>::value ? 1 : -1];
+
+int test4[is_integral<underlying_type<E1>::type>::value ? 1 : -1];
+int test5[is_integral<underlying_type<E2>::type>::value ? 1 : -1];
+int test6[is_integral<underlying_type<E3>::type>::value ? 1 : -1];
diff --git a/gcc/testsuite/g++.dg/ext/underlying_type5.C b/gcc/testsuite/g++.dg/ext/underlying_type5.C
new file mode 100644 (file)
index 0000000..a9c1992
--- /dev/null
@@ -0,0 +1,43 @@
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+template<typename T1, typename T2>
+  struct is_same
+  { static const bool value = false; };
+
+template<typename T>
+  struct is_same<T, T>
+  { 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<typename T>
+  struct underlying_type
+  { typedef __underlying_type(T) type; };
+
+static_assert(is_same<underlying_type<E1>::type, UTE1>::value, "Error");
+static_assert(is_same<underlying_type<E2>::type, UTE2>::value, "Error");
+static_assert(is_same<underlying_type<E3>::type, UTE3>::value, "Error");
+static_assert(is_same<underlying_type<E4>::type, UTE4>::value, "Error");
+static_assert(is_same<underlying_type<E5>::type, UTE5>::value, "Error");
+static_assert(is_same<underlying_type<E6>::type, UTE6>::value, "Error");
+
+static_assert(is_same<underlying_type<E1>::type, unsigned>::value, "Error");
+static_assert(is_same<underlying_type<E2>::type, char>::value, "Error");
+static_assert(is_same<underlying_type<E3>::type, int>::value, "Error");
+static_assert(is_same<underlying_type<E4>::type, 
+                     unsigned char>::value, "Error");
+static_assert(is_same<underlying_type<E5>::type, int>::value, "Error");
+static_assert(is_same<underlying_type<E6>::type, long>::value, "Error");
diff --git a/gcc/testsuite/g++.dg/ext/underlying_type6.C b/gcc/testsuite/g++.dg/ext/underlying_type6.C
new file mode 100644 (file)
index 0000000..50f5288
--- /dev/null
@@ -0,0 +1,31 @@
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+template<typename T1, typename T2>
+  struct is_same
+  { static const bool value = false; };
+
+template<typename T>
+  struct is_same<T, T>
+  { 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<typename T, typename U,
+        typename V = __underlying_type(T)>
+  struct test
+  {
+    static_assert(is_same<U, V>::value, "Error");
+  };
+
+template class test<E1, unsigned>;
+template class test<E2, char>;
+template class test<E3, int>;
+template class test<E4, unsigned char>;
+template class test<E5, int>;
+template class test<E6, long>;
diff --git a/gcc/testsuite/g++.dg/ext/underlying_type7.C b/gcc/testsuite/g++.dg/ext/underlying_type7.C
new file mode 100644 (file)
index 0000000..872fe52
--- /dev/null
@@ -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<typename T>
+  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__);
+}
diff --git a/gcc/testsuite/g++.dg/ext/underlying_type8.C b/gcc/testsuite/g++.dg/ext/underlying_type8.C
new file mode 100644 (file)
index 0000000..0bbed2b
--- /dev/null
@@ -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<typename T1, typename T2>
+  struct is_same
+  { static const bool value = false; };
+
+template<typename T>
+  struct is_same<T, T>
+  { static const bool value = true; };
+
+template<typename>
+  struct underlying_type;
+
+template<typename T, typename U>
+  void
+  test(T, U, typename underlying_type<T>::type);
+
+template<typename T>
+  struct underlying_type
+  { typedef __underlying_type(T) type; };
+
+template<typename T, typename U>
+  void
+  test(T, U, typename underlying_type<T>::type)
+  {
+    static_assert(is_same<typename underlying_type<T>::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__);
+}
diff --git a/gcc/testsuite/g++.dg/ext/underlying_type9.C b/gcc/testsuite/g++.dg/ext/underlying_type9.C
new file mode 100644 (file)
index 0000000..9ffd244
--- /dev/null
@@ -0,0 +1,30 @@
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+template<typename T1, typename T2>
+  struct is_same
+  { static const bool value = false; };
+
+template<typename T>
+  struct is_same<T, T>
+  { 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<typename T, typename U>
+  struct test
+  {
+    static_assert(is_same<T, U>::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;