re PR c++/60573 ([c++1y] ICE with defining generic function of nested class in class scope)

Fix PR c++/60573

	PR c++/60573
	* name-lookup.h (cp_binding_level): New transient field defining_class_p
	to indicate whether a scope is in the process of defining a class.
	* semantics.c (begin_class_definition): Set defining_class_p.
	* name-lookup.c (leave_scope): Reset defining_class_p.
	* parser.c (synthesize_implicit_template_parm): Use cp_binding_level::
	defining_class_p rather than TYPE_BEING_DEFINED as the predicate for
	unwinding to class-defining scope to handle the erroneous definition of
	a generic function of an arbitrarily nested class within an enclosing
	class.

	PR c++/60573
	* g++.dg/cpp1y/pr60573.C: New testcase.

From-SVN: r208921
This commit is contained in:
Adam Butcher 2014-03-28 20:41:45 +00:00
parent eee32b5ea3
commit 5294e4c32d
7 changed files with 81 additions and 11 deletions

View File

@ -1,6 +1,20 @@
2014-03-28 Adam Butcher <adam@jessamine.co.uk>
PR c++/60573
* name-lookup.h (cp_binding_level): New transient field defining_class_p
to indicate whether a scope is in the process of defining a class.
* semantics.c (begin_class_definition): Set defining_class_p.
* name-lookup.c (leave_scope): Reset defining_class_p.
* parser.c (synthesize_implicit_template_parm): Use cp_binding_level::
defining_class_p rather than TYPE_BEING_DEFINED as the predicate for
unwinding to class-defining scope to handle the erroneous definition of
a generic function of an arbitrarily nested class within an enclosing
class.
2014-03-26 Fabien Chêne <fabien@gcc.gnu.org>
PR c++/52369
* cp/method.c (walk_field_subobs): improve the diagnostic
PR c++/52369
* cp/method.c (walk_field_subobs): improve the diagnostic
locations for both REFERENCE_TYPEs and non-static const members.
* cp/init.c (diagnose_uninitialized_cst_or_ref_member): use %q#D
instead of %qD to be consistent with the c++11 diagnostic.

View File

@ -1630,10 +1630,14 @@ leave_scope (void)
free_binding_level = scope;
}
/* Find the innermost enclosing class scope, and reset
CLASS_BINDING_LEVEL appropriately. */
if (scope->kind == sk_class)
{
/* Reset DEFINING_CLASS_P to allow for reuse of a
class-defining scope in a non-defining context. */
scope->defining_class_p = 0;
/* Find the innermost enclosing class scope, and reset
CLASS_BINDING_LEVEL appropriately. */
class_binding_level = NULL;
for (scope = current_binding_level; scope; scope = scope->level_chain)
if (scope->kind == sk_class)

View File

@ -255,7 +255,14 @@ struct GTY(()) cp_binding_level {
unsigned more_cleanups_ok : 1;
unsigned have_cleanups : 1;
/* 24 bits left to fill a 32-bit word. */
/* Transient state set if this scope is of sk_class kind
and is in the process of defining 'this_entity'. Reset
on leaving the class definition to allow for the scope
to be subsequently re-used as a non-defining scope for
'this_entity'. */
unsigned defining_class_p : 1;
/* 23 bits left to fill a 32-bit word. */
};
/* The binding level currently in effect. */

View File

@ -31999,7 +31999,7 @@ synthesize_implicit_template_parm (cp_parser *parser)
{
/* If not defining a class, then any class scope is a scope level in
an out-of-line member definition. In this case simply wind back
beyond the first such scope to inject the template argument list.
beyond the first such scope to inject the template parameter list.
Otherwise wind back to the class being defined. The latter can
occur in class member friend declarations such as:
@ -32010,12 +32010,23 @@ synthesize_implicit_template_parm (cp_parser *parser)
friend void A::foo (auto);
};
The template argument list synthesized for the friend declaration
must be injected in the scope of 'B', just beyond the scope of 'A'
introduced by 'A::'. */
The template parameter list synthesized for the friend declaration
must be injected in the scope of 'B'. This can also occur in
erroneous cases such as:
while (scope->kind == sk_class
&& !TYPE_BEING_DEFINED (scope->this_entity))
struct A {
struct B {
void foo (auto);
};
void B::foo (auto) {}
};
Here the attempted definition of 'B::foo' within 'A' is ill-formed
but, nevertheless, the template parameter list synthesized for the
declarator should be injected into the scope of 'A' as if the
ill-formed template was specified explicitly. */
while (scope->kind == sk_class && !scope->defining_class_p)
{
parent_scope = scope;
scope = scope->level_chain;

View File

@ -2777,6 +2777,7 @@ begin_class_definition (tree t)
maybe_process_partial_specialization (t);
pushclass (t);
TYPE_BEING_DEFINED (t) = 1;
class_binding_level->defining_class_p = 1;
if (flag_pack_struct)
{

View File

@ -1,3 +1,8 @@
2014-03-28 Adam Butcher <adam@jessamine.co.uk>
PR c++/60573
* g++.dg/cpp1y/pr60573.C: New testcase.
2014-03-28 Jakub Jelinek <jakub@redhat.com>
PR target/60693

View File

@ -0,0 +1,28 @@
// PR c++/60573
// { dg-do compile { target c++1y } }
// { dg-options "" }
struct A
{
struct B
{
void foo(auto);
};
void B::foo(auto) {} // { dg-error "cannot define" }
struct X
{
struct Y
{
struct Z
{
void foo(auto);
};
};
void Y::Z::foo(auto) {} // { dg-error "cannot define" }
};
void X::Y::Z::foo(auto) {} // { dg-error "cannot define" }
};