@@ -255,7 +255,11 @@ struct GTY(()) cp_binding_level {
unsigned more_cleanups_ok : 1;
unsigned have_cleanups : 1;
- /* 24 bits left to fill a 32-bit word. */
+ /* Set if this scope is of sk_class kind and is the defining
+ scope for this_entity. */
+ unsigned scope_defines_class_p : 1;
+
+ /* 23 bits left to fill a 32-bit word. */
};
/* The binding level currently in effect. */
@@ -32000,7 +32000,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:
@@ -32011,12 +32011,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->scope_defines_class_p)
{
parent_scope = scope;
scope = scope->level_chain;
@@ -8905,9 +8905,12 @@ instantiate_class_template_1 (tree type)
return type;
/* Now we're really doing the instantiation. Mark the type as in
- the process of being defined. */
+ the process of being defined... */
TYPE_BEING_DEFINED (type) = 1;
+ /* ... and the scope defining it. */
+ class_binding_level->scope_defines_class_p = 1;
+
/* We may be in the middle of deferred access check. Disable
it now. */
push_deferring_access_checks (dk_no_deferred);
@@ -2777,6 +2777,7 @@ begin_class_definition (tree t)
maybe_process_partial_specialization (t);
pushclass (t);
TYPE_BEING_DEFINED (t) = 1;
+ class_binding_level->scope_defines_class_p = 1;
if (flag_pack_struct)
{
new file mode 100644
@@ -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" }
+};