aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-07-24 19:40:05 -0400
committerJason Merrill <jason@gcc.gnu.org>2016-07-24 19:40:05 -0400
commit8a61db89b2da509e9cb72c5e6d6fe463c8d22fbf (patch)
tree717147bc17259f9655b02c65bb56fddb9ccf43d1 /gcc
parent635c1074bec1f91d4c210b1b66cf910220fa13a5 (diff)
downloadgcc-8a61db89b2da509e9cb72c5e6d6fe463c8d22fbf.zip
gcc-8a61db89b2da509e9cb72c5e6d6fe463c8d22fbf.tar.gz
gcc-8a61db89b2da509e9cb72c5e6d6fe463c8d22fbf.tar.bz2
PR c++/71515 - typename in partial specialization
* pt.c (resolve_typename_type): Try to avoid calling currently_open_class. From-SVN: r238696
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c25
-rw-r--r--gcc/testsuite/g++.dg/template/typename22.C8
3 files changed, 25 insertions, 14 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6c5b5de..b5d816d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2016-07-24 Jason Merrill <jason@redhat.com>
+
+ PR c++/71515
+ * pt.c (resolve_typename_type): Try to avoid calling
+ currently_open_class.
+
2016-07-23 Jason Merrill <jason@redhat.com>
PR c++/66617
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 65fa982..a61f1c8 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<T>, 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 0000000..b5dc1b5
--- /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;
+};