===================================================================
@@ -8774,7 +8774,8 @@ grokdeclarator (const cp_declarator *declarator,
tree type = NULL_TREE;
int longlong = 0;
int explicit_int128 = 0;
- int virtualp, explicitp, friendp, inlinep, staticp;
+ int virtualp, explicitp, inlinep, staticp;
+ int friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
int explicit_int = 0;
int explicit_char = 0;
int defaulted_int = 0;
@@ -8880,6 +8881,26 @@ grokdeclarator (const cp_declarator *declarator,
sfk = id_declarator->declarator->u.id.sfk;
if (sfk == sfk_destructor)
flags = DTOR_FLAG;
+ else if (sfk == sfk_constructor
+ && friendp
+ && declspecs->type)
+ /* cp_parser_direct_declarator doesn't know about the
+ 'friend' specifier and returns sfk_constructor for
+
+ struct S {
+ struct T{};
+ friend void S(T);
+ };
+
+ thus adjust it here (c++/19200). Note: the return
+ type is checked because with -fpermissive we still
+ want to accept
+
+ struct S {
+ struct T{};
+ friend S::S(T);
+ }; */
+ sfk = sfk_none;
}
break;
@@ -9378,7 +9399,6 @@ grokdeclarator (const cp_declarator *declarator,
storage_class = sc_none;
staticp = 0;
}
- friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
/* Issue errors about use of storage classes for parameters. */
if (decl_context == PARM)
===================================================================
@@ -17,16 +17,16 @@ struct B
struct C
{
- friend int C (); // { dg-error "return type|in friend decl" }
+ friend int C ();
friend int ~C (); // { dg-error "return type|in friend decl" }
- friend int C (const C &); // { dg-error "return type|in friend decl" }
+ friend int C (const C &);
};
struct D
{
- friend int D () {} // { dg-error "return type|in friend decl" }
+ friend int D () {}
friend int ~D () {} // { dg-error "return type|in friend decl" }
- friend int D (const D &) {} // { dg-error "return type|in friend decl" }
+ friend int D (const D &) {}
};
struct E
===================================================================
@@ -0,0 +1,6 @@
+// PR c++/19200
+
+struct S {
+ struct T{};
+ friend void S(T);
+};