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 4934577ea2a7615ff335ffa631bcc062fb1b91ad..fc70bbdc8cb99cb8777d0aade93344d0e298f56f 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 8c1553feca20c7715c868fe45e2e2e723907d0a6..d066c26dd88208ceb83e00554d4054172b78bdd4 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 849597c0d0cbdd57b1ad54dcb606ec0daf54a8f9..07106bc31a7ba3a376409d323ed36382b86af0d6 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, "");