From 26f2269fc4d1e4f97044db07b159f6d4eb4ab963 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli <dodji@redhat.com> Date: Fri, 16 Nov 2012 15:20:03 +0000 Subject: [PATCH] PR c++/54875 - Error with alias template that resolves to an enum Consider this short example: 1 template<typename T> 2 using AddConst = T const; 3 4 enum FwdEnum : int; 5 6 int main() { 7 AddConst<FwdEnum> *ptr = nullptr; 8 } At line 7, when we build the type for AddConst<FwdEnum> in lookup_template_class_1, the resulting type is the enum FwdEnum. This confuses lookup_template_class_1 near the if below, wrongly making it taking the branch and thus calling tsubst_enum while it shouldn't: if (TREE_CODE (t) == ENUMERAL_TYPE && !is_dependent_type) /* 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 sure to register the type first, and then create the constants. That way, doing tsubst_expr for the enumeration constants won't result in recursive calls here; we'll find the instantiation and exit above. */ tsubst_enum (template_type, t, arglist); Before the alias template feature, the only reason why TREE_CODE (t) == ENUMERAL_TYPE would be true is when lookup_template_class_1 is called for an enum that is a member of a class template. But that condition can be also true for an alias template instantiation. So I guess that condition should be changed to TREE_CODE (template_type) == ENUMERAL_TYPE, to specifically detect the member enum of a class template case. Note that for the alias template instantiation case above, template_type points to a TEMPLATE_TYPE_PARM which name is AddConst. This is what the patchlet below does. Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk. gcc/cp/ * pt.c (lookup_template_class_1): Look at the type of the potential member enum of class template to determine if we are actually substituting into a member enum of class template. gcc/testsuite/ * g++.dg/cpp0x/alias-decl-27.C: New test. From-SVN: r193562 --- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/pt.c | 2 +- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/cpp0x/alias-decl-27.C | 11 +++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-27.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6f9380935086..3b0918af5d8f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2012-11-16 Dodji Seketeli <dodji@redhat.com> + + PR c++/54875 + * pt.c (lookup_template_class_1): Look at the type of the + potential member enum of class template to determine if we are + actually substituting into a member enum of class template. + 2012-11-16 Jakub Jelinek <jakub@redhat.com> PR c++/55337 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3c9bb56c66ba..101b22d9bcff 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7487,7 +7487,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, = tree_cons (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (templ)); - if (TREE_CODE (t) == ENUMERAL_TYPE && !is_dependent_type) + if (TREE_CODE (template_type) == ENUMERAL_TYPE && !is_dependent_type) /* 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d163db26f1bd..314c2e4565af 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-11-16 Dodji Seketeli <dodji@redhat.com> + + PR c++/54875 + * g++.dg/cpp0x/alias-decl-27.C: New test. + 2012-11-16 Jakub Jelinek <jakub@redhat.com> PR c++/55337 diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-27.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-27.C new file mode 100644 index 000000000000..91208abf90eb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-27.C @@ -0,0 +1,11 @@ +// Origin: PR c++/54875 +// { dg-do compile { target c++11 } } + +template<typename T> +using AddConst = T const; + +enum FwdEnum : int; + +int main() { + AddConst<FwdEnum> *ptr = nullptr; +} -- GitLab