c++: ICE with bogus late return type [PR99803]

Here we ICE when compiling this code in C++20, because we're trying to
slam a 'typename' after the ->.  The cp_parser_template_id call just
before the spot I'm changing parsed A::template A<int> as a BASELINK
that contains a constructor, but make_typename_type crashes on that.

This patch makes make_typename_type more robust instead of checking
for is_overloaded_fn prior calling it.

gcc/cp/ChangeLog:

	PR c++/99803
	* decl.c (make_typename_type): Give an error and return when
	name is is_overloaded_fn.
	* parser.c (cp_parser_class_name): Don't check is_overloaded_fn
	before calling make_typename_type.

gcc/testsuite/ChangeLog:

	PR c++/99803
	* g++.dg/cpp2a/typename14.C: Don't expect particular error
	messages.
	* g++.dg/cpp2a/typename19.C: New test.
This commit is contained in:
Marek Polacek 2021-04-14 17:57:15 -04:00
parent eb8c931e0d
commit 70f2bff43a
4 changed files with 15 additions and 6 deletions

View File

@ -4055,6 +4055,12 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
error ("%qD used without template arguments", name);
return error_mark_node;
}
else if (is_overloaded_fn (name))
{
if (complain & tf_error)
error ("%qD is a function, not a type", name);
return error_mark_node;
}
gcc_assert (identifier_p (name));
gcc_assert (TYPE_P (context));
@ -4066,7 +4072,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
error ("%q#T is not a class", context);
return error_mark_node;
}
/* When the CONTEXT is a dependent type, NAME could refer to a
dependent base class of CONTEXT. But look inside it anyway
if CONTEXT is a currently open scope, in case it refers to a

View File

@ -24730,9 +24730,7 @@ 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
&& !is_overloaded_fn (decl))
if (typename_p && decl != error_mark_node)
{
decl = make_typename_type (scope, decl, typename_type,
/*complain=*/tf_error);

View File

@ -8,7 +8,7 @@ template<typename> struct A
template<typename T>
template<typename U>
A<T>::A<U> () // { dg-error "partial specialization" }
A<T>::A<U> () // { dg-error "" }
{
}
@ -19,7 +19,7 @@ template<typename> struct B
template<typename T>
template<typename U>
B<T>::foo<int>(int) // { dg-error "partial specialization|declaration" }
B<T>::foo<int>(int) // { dg-error "" }
{
return 1;
}

View File

@ -0,0 +1,5 @@
// PR c++/99803
// { dg-do compile { target c++20 } }
struct A { template<typename T> A(T); };
auto A(unsigned) -> A::template A<int>; // { dg-error "not a type" }