From 8a61db89b2da509e9cb72c5e6d6fe463c8d22fbf Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sun, 24 Jul 2016 19:40:05 -0400 Subject: [PATCH] PR c++/71515 - typename in partial specialization * pt.c (resolve_typename_type): Try to avoid calling currently_open_class. From-SVN: r238696 --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/pt.c | 25 ++++++++++------------ gcc/testsuite/g++.dg/template/typename22.C | 8 +++++++ 3 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/typename22.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6c5b5de2923..b5d816de90d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2016-07-24 Jason Merrill + + PR c++/71515 + * pt.c (resolve_typename_type): Try to avoid calling + currently_open_class. + 2016-07-23 Jason Merrill PR c++/66617 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 65fa9825862..a61f1c81a19 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -23678,29 +23678,26 @@ resolve_typename_type (tree type, bool only_current_p) } /* If we don't know what SCOPE refers to, then we cannot resolve the TYPENAME_TYPE. */ - if (TREE_CODE (scope) == TYPENAME_TYPE) - return type; - /* If the SCOPE is a template type parameter, we have no way of - resolving the name. */ - if (TREE_CODE (scope) == TEMPLATE_TYPE_PARM) - return type; - /* If the SCOPE is not the current instantiation, there's no reason - to look inside it. */ - if (only_current_p && !currently_open_class (scope)) + if (!CLASS_TYPE_P (scope)) return type; /* If this is a typedef, we don't want to look inside (c++/11987). */ if (typedef_variant_p (type)) return type; /* If SCOPE isn't the template itself, it will not have a valid TYPE_FIELDS list. */ - if (CLASS_TYPE_P (scope) - && same_type_p (scope, CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope))) + if (same_type_p (scope, CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope))) /* scope is either the template itself or a compatible instantiation like X, so look up the name in the original template. */ scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope); - else - /* scope is a partial instantiation, so we can't do the lookup or we - will lose the template arguments. */ + /* We shouldn't have built a TYPENAME_TYPE with a non-dependent scope. */ + gcc_checking_assert (uses_template_parms (scope)); + /* If scope has no fields, it can't be a current instantiation. Check this + before currently_open_class to avoid infinite recursion (71515). */ + if (!TYPE_FIELDS (scope)) + return type; + /* If the SCOPE is not the current instantiation, there's no reason + to look inside it. */ + if (only_current_p && !currently_open_class (scope)) return type; /* Enter the SCOPE so that name lookup will be resolved as if we were in the class definition. In particular, SCOPE will no diff --git a/gcc/testsuite/g++.dg/template/typename22.C b/gcc/testsuite/g++.dg/template/typename22.C new file mode 100644 index 00000000000..b5dc1b57189 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typename22.C @@ -0,0 +1,8 @@ +// PR c++/71515 + +template < typename, typename = int > struct A; + +template < typename T > struct A < T, typename A < T >::type > +{ + A < int > *a; +}; -- 2.30.2