This patch fixes an ICE-on-invalid (becase out-of-line constructors can't have
template arguments and also because function templates can't be partially
specialized) in C++2a: when we're parsing

  template<typename T> template<typename U> A<T>::A<U> ()

in the attached test we end up parsing "A<T>::A<U>" as a type name, and first we
try a class-name.  First we process "A<T>::" as the nested name specifier and 
then
we parse "A<U>".  In this test that results in a BASELINK.  Because in this 
context
we're supposed to treat it as a typename ([temp.res]/6), we call 
make_typename_type,
but that crashes.

Implicit 'typename' doesn't make sense for function types, so a safe fix would 
be
the following: avoid calling make_typename_type; the rest of the function will
make sure to emit an error and return the error_mark_node.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-01-28  Marek Polacek  <pola...@redhat.com>

        PR c++/88325 - ICE with invalid out-of-line template member definition.
        * parser.c (cp_parser_class_name): Don't call make_typename_type
        for overloads.

        * g++.dg/cpp2a/typename14.C: New test.

diff --git gcc/cp/parser.c gcc/cp/parser.c
index 16f2a32bc0b..1bfa0c88f5b 100644
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -23167,7 +23167,9 @@ cp_parser_class_name (cp_parser *parser,
   decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);
 
   /* If this is a typename, create a TYPENAME_TYPE.  */
-  if (typename_p && decl != error_mark_node)
+  if (typename_p
+      && decl != error_mark_node
+      && !is_overloaded_fn (decl))
     {
       decl = make_typename_type (scope, decl, typename_type,
                                 /*complain=*/tf_error);
diff --git gcc/testsuite/g++.dg/cpp2a/typename14.C 
gcc/testsuite/g++.dg/cpp2a/typename14.C
new file mode 100644
index 00000000000..4750db35cd8
--- /dev/null
+++ gcc/testsuite/g++.dg/cpp2a/typename14.C
@@ -0,0 +1,25 @@
+// PR c++/88325
+// { dg-do compile { target c++2a } }
+
+template<typename> struct A
+{
+  template<typename> A ();
+};
+
+template<typename T>
+template<typename U>
+A<T>::A<U> () // { dg-error "partial specialization" }
+{
+}
+
+template<typename> struct B
+{
+  template<typename> int foo (int);
+};
+
+template<typename T>
+template<typename U>
+B<T>::foo<int>(int) // { dg-error "partial specialization|declaration" }
+{
+  return 1;
+}

Reply via email to