[PR c++/84789] do not resolve typename into template-independent

Alexandre Oliva aoliva@redhat.com
Fri Mar 16 22:22:00 GMT 2018


resolve_typename_type may peek into template types that might still be
specialized.  In some cases, e.g. g++.dg/template/friend48.C or
g++.dg/template/decl2.C, that is exactly the right thing to do.  In
others, like the newly-added testcase g++.dg/template/pr84789.C, it
isn't, and if the qualifying scope happens to resolve to a non-template
type, we resolve to that and then fail the assert that checks we still
have a template-dependent scope.

It appears to me that, in cases in which the assert would fail, we are
missing the typename keyword, and we ought to report an error; if we
just return the incoming type unchanged, that's exactly what we get.
So, I'm turning such failed asserts into early returns, so that the
parser can recover and report an error.

Regstrapped on i686- and x86_64-linux-gnu.  Ok to install?


for  gcc/cp/ChangeLog

	PR c++/84789
	* pt.c (resolve_typename_type): Keep the type
	template-dependent.

for  gcc/testsuite/ChangeLog

	PR c++/84789
	* g++.dg/template/pr84789.C: New.
---
 gcc/cp/pt.c                             |   19 +++++++++++++++++--
 gcc/testsuite/g++.dg/template/pr84789.C |   13 +++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/pr84789.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 89024c10fe2b..067221fa78ea 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -25195,8 +25195,23 @@ resolve_typename_type (tree type, bool only_current_p)
     /* 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);
-  /* We shouldn't have built a TYPENAME_TYPE with a non-dependent scope.  */
-  gcc_checking_assert (uses_template_parms (scope));
+  /* We shouldn't have built a TYPENAME_TYPE with a non-dependent
+     scope.  However, it might be a dependent scope that's being
+     resolved to a non-dependent scope just because we're looking up
+     scopes we shouldn't, e.g.
+
+       template <typename> class B { typedef int I; };
+       template <typename T> class C : B<T> { B<T>::I i; };
+
+     We need 'typename' before C<T>::i's type, because we can't enter
+     the scope of B<T> for an unbound template parameter T to tell I
+     identifies a type (that's why we need typename), but the parser
+     attempts to do so, presumably so that it can produce better error
+     messages.  However, we'd skip necessary errors if we resolved a
+     template-dependent type to a template-independent one, so don't
+     do that.  */
+  if (!uses_template_parms (scope))
+    return type;
   /* 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))
diff --git a/gcc/testsuite/g++.dg/template/pr84789.C b/gcc/testsuite/g++.dg/template/pr84789.C
new file mode 100644
index 000000000000..bc1567f3fe77
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr84789.C
@@ -0,0 +1,13 @@
+// { dg-do compile }
+
+struct A
+{
+  typedef int I;
+};
+
+template<typename> struct B : A {};
+
+template<typename T> struct C : B<T>
+{
+  B<T>::A::I::I i; // { dg-error "typename" }
+};


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer



More information about the Gcc-patches mailing list