re PR c++/57734 (Returning template alias to enum class fails with "invalid declarator")
authorPaolo Carlini <paolo.carlini@oracle.com>
Tue, 12 Nov 2013 09:21:45 +0000 (09:21 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Tue, 12 Nov 2013 09:21:45 +0000 (09:21 +0000)
/cp
2013-11-12  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/57734
* pt.c (lookup_template_class_1): Handle alias template declarations
of enumeration types.

/testsuite
2013-11-12  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/57734
* g++.dg/cpp0x/alias-decl-enum-1.C: New.

From-SVN: r204697

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/alias-decl-enum-1.C [new file with mode: 0644]

index 4934577..fc70bbd 100644 (file)
@@ -1,3 +1,9 @@
+2013-11-12  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/57734
+       * pt.c (lookup_template_class_1): Handle alias template declarations
+       of enumeration types.
+
 2013-11-10  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * cvt.c (cp_convert_to_pointer): Call build_ptrmemfunc before
index 8c1553f..d066c26 100644 (file)
@@ -7458,30 +7458,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
        context = global_namespace;
 
       /* Create the type.  */
-      if (TREE_CODE (template_type) == ENUMERAL_TYPE)
-       {
-         if (!is_dependent_type)
-           {
-             set_current_access_from_decl (TYPE_NAME (template_type));
-             t = start_enum (TYPE_IDENTIFIER (template_type), NULL_TREE,
-                             tsubst (ENUM_UNDERLYING_TYPE (template_type),
-                                     arglist, complain, in_decl),
-                             SCOPED_ENUM_P (template_type), NULL);
-           }
-         else
-            {
-              /* We don't want to call start_enum for this type, since
-                 the values for the enumeration constants may involve
-                 template parameters.  And, no one should be interested
-                 in the enumeration constants for such a type.  */
-              t = cxx_make_type (ENUMERAL_TYPE);
-              SET_SCOPED_ENUM_P (t, SCOPED_ENUM_P (template_type));
-            }
-          SET_OPAQUE_ENUM_P (t, OPAQUE_ENUM_P (template_type));
-         ENUM_FIXED_UNDERLYING_TYPE_P (t)
-           = ENUM_FIXED_UNDERLYING_TYPE_P (template_type);
-       }
-      else if (DECL_ALIAS_TEMPLATE_P (gen_tmpl))
+      if (DECL_ALIAS_TEMPLATE_P (gen_tmpl))
        {
          /* The user referred to a specialization of an alias
            template represented by GEN_TMPL.
@@ -7505,6 +7482,29 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
          if (t == error_mark_node)
            return t;
        }
+      else if (TREE_CODE (template_type) == ENUMERAL_TYPE)
+       {
+         if (!is_dependent_type)
+           {
+             set_current_access_from_decl (TYPE_NAME (template_type));
+             t = start_enum (TYPE_IDENTIFIER (template_type), NULL_TREE,
+                             tsubst (ENUM_UNDERLYING_TYPE (template_type),
+                                     arglist, complain, in_decl),
+                             SCOPED_ENUM_P (template_type), NULL);
+           }
+         else
+            {
+              /* We don't want to call start_enum for this type, since
+                 the values for the enumeration constants may involve
+                 template parameters.  And, no one should be interested
+                 in the enumeration constants for such a type.  */
+              t = cxx_make_type (ENUMERAL_TYPE);
+              SET_SCOPED_ENUM_P (t, SCOPED_ENUM_P (template_type));
+            }
+          SET_OPAQUE_ENUM_P (t, OPAQUE_ENUM_P (template_type));
+         ENUM_FIXED_UNDERLYING_TYPE_P (t)
+           = ENUM_FIXED_UNDERLYING_TYPE_P (template_type);
+       }
       else if (CLASS_TYPE_P (template_type))
        {
          t = make_class_type (TREE_CODE (template_type));
@@ -7661,7 +7661,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
        = tree_cons (arglist, t,
                     DECL_TEMPLATE_INSTANTIATIONS (templ));
 
-      if (TREE_CODE (template_type) == ENUMERAL_TYPE && !is_dependent_type)
+      if (TREE_CODE (template_type) == ENUMERAL_TYPE && !is_dependent_type
+         && !DECL_ALIAS_TEMPLATE_P (gen_tmpl))
        /* Now that the type has been registered on the instantiations
           list, we set up the enumerators.  Because the enumeration
           constants may involve the enumeration type itself, we make
index 849597c..07106bc 100644 (file)
@@ -1,3 +1,8 @@
+2013-11-12  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/57734
+       * g++.dg/cpp0x/alias-decl-enum-1.C: New.
+
 2013-11-11  Martin Liska       <marxin.liska@gmail.com>
 
        * gcc.dg/time-profiler-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-enum-1.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-enum-1.C
new file mode 100644 (file)
index 0000000..260a193
--- /dev/null
@@ -0,0 +1,47 @@
+// PR c++/57734
+// { dg-do compile { target c++11 } }
+
+template<typename T, typename U>
+struct same_type { static const bool value = false; };
+
+template<typename T>
+struct same_type<T, T> { static const bool value = true; };
+
+enum e { zero };
+enum class eclass { one };
+
+template<typename T>
+using enum_alias = e;
+
+template<typename T>
+using eclass_alias = eclass;
+
+typedef enum_alias<void> etest0;
+typedef enum_alias<void> etest0;
+typedef enum_alias<int>  etest0;
+typedef enum_alias<int>  etest1;
+
+static_assert (same_type<etest0, etest1>::value, "");
+
+typedef eclass_alias<void> ectest0;
+typedef eclass_alias<void> ectest0;
+typedef eclass_alias<int>  ectest0;
+typedef eclass_alias<int>  ectest1;
+
+static_assert (same_type<ectest0, ectest1>::value, "");
+
+template<typename T>
+enum_alias<T> efoo(T f) { return enum_alias<T>::zero; }
+
+template<typename T>
+constexpr enum_alias<T> cefoo(T f) { return enum_alias<T>::zero; }
+
+static_assert ( cefoo(1) == e::zero, "");
+
+template<typename T>
+eclass_alias<T> ecfoo(T f) { return eclass_alias<T>::one; }
+
+template<typename T>
+constexpr eclass_alias<T> cecfoo(T f) { return eclass_alias<T>::one; }
+
+static_assert ( cecfoo(1) == eclass::one, "");