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; +}