Commit 5294e4c3 by Adam Butcher

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
parent eee32b5e
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.
......
......@@ -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)
......
......@@ -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. */
......
......@@ -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;
......
......@@ -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)
{
......
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
......
// 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" }
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment