mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 19:01:17 +08:00
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:
parent
eee32b5ea3
commit
5294e4c32d
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
28
gcc/testsuite/g++.dg/cpp1y/pr60573.C
Normal file
28
gcc/testsuite/g++.dg/cpp1y/pr60573.C
Normal 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" }
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user