diff mbox

[C++] PR c++/62101

Message ID CAFk2RUYvT2PkQq5Z+riNXq2BMKu4TrqLbVMJkh9J5kugLZfG=A@mail.gmail.com
State New
Headers show

Commit Message

Ville Voutilainen Aug. 14, 2014, 12:48 a.m. UTC
On 14 August 2014 03:41, Jason Merrill <jason@redhat.com> wrote:
> On 08/13/2014 07:06 PM, Ville Voutilainen wrote:
>
> Looks good, but
>
>> +  int friendp = 0;
>
>
> Let's declare friendp when it's initialized.
>
> And I still need a ChangeLog entry.

Ok, modified patch attached. The changelog entry was attached to the previous
mail as an evil binary attachment (gmail...), here, for convenience:

/cp
2014-08-14  Ville Voutilainen  <ville.voutilainen@gmail.com>

    PR c++/62101
    * decl.c (grokdeclarator): Move the check for friend initializers..
    * decl2.c (grokfield) ..here. Remove bogus comment about pure
specifiers, and postpone the previous early return for friends until
after the initializer check.

/testsuite
2014-08-14  Ville Voutilainen  <ville.voutilainen@gmail.com>

    PR c++/62101
    * g++.dg/cpp0x/pr62101.C: New

Comments

Jason Merrill Aug. 14, 2014, 10:10 p.m. UTC | #1
On 08/13/2014 08:48 PM, Ville Voutilainen wrote:
> Ok, modified patch attached. The changelog entry was attached to the previous
> mail as an evil binary attachment (gmail...)

Ah, so it was.

> here, for convenience:

Thanks; having it in the body of the mail is more convenient for me as 
'git am' will then automatically put it in the commit message.

Applied.

Jason
diff mbox

Patch

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 79e7362..92a6dbc 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9765,8 +9765,6 @@  grokdeclarator (const cp_declarator *declarator,
 	      }
 	    else if (friendp)
 	      {
-		if (initialized)
-		  error ("can%'t initialize friend function %qs", name);
 		if (virtualp)
 		  {
 		    /* Cannot be both friend and virtual.  */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 1740a2e..875daf1 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -870,11 +870,6 @@  grokfield (const cp_declarator *declarator,
   if (value == void_type_node)
     return value;
 
-  /* Pass friend decls back.  */
-  if ((TREE_CODE (value) == FUNCTION_DECL
-       || TREE_CODE (value) == TEMPLATE_DECL)
-      && DECL_CONTEXT (value) != current_class_type)
-    return value;
 
   name = DECL_NAME (value);
 
@@ -926,7 +921,9 @@  grokfield (const cp_declarator *declarator,
       return value;
     }
 
-  if (DECL_IN_AGGR_P (value))
+  int friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
+
+  if (!friendp && DECL_IN_AGGR_P (value))
     {
       error ("%qD is already defined in %qT", value, DECL_CONTEXT (value));
       return void_type_node;
@@ -939,8 +936,6 @@  grokfield (const cp_declarator *declarator,
     {
       if (TREE_CODE (value) == FUNCTION_DECL)
 	{
-	  /* Initializers for functions are rejected early in the parser.
-	     If we get here, it must be a pure specifier for a method.  */
 	  if (init == ridpointers[(int)RID_DELETE])
 	    {
 	      DECL_DELETED_FN (value) = 1;
@@ -971,8 +966,12 @@  grokfield (const cp_declarator *declarator,
 	  else
 	    {
 	      gcc_assert (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE);
-	      error ("initializer specified for static member function %qD",
-		     value);
+	      if (friendp)
+		error ("initializer specified for friend function %qD", 
+		       value);
+	      else
+		error ("initializer specified for static member function %qD",
+		       value);
 	    }
 	}
       else if (TREE_CODE (value) == FIELD_DECL)
@@ -981,6 +980,12 @@  grokfield (const cp_declarator *declarator,
 	gcc_unreachable ();
     }
 
+  /* Pass friend decls back.  */
+  if ((TREE_CODE (value) == FUNCTION_DECL
+       || TREE_CODE (value) == TEMPLATE_DECL)
+      && DECL_CONTEXT (value) != current_class_type)
+    return value;
+
   if (processing_template_decl && VAR_OR_FUNCTION_DECL_P (value))
     {
       value = push_template_decl (value);
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr62101.C b/gcc/testsuite/g++.dg/cpp0x/pr62101.C
new file mode 100644
index 0000000..abec7f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr62101.C
@@ -0,0 +1,32 @@ 
+// PR c++/62101
+// { dg-do compile { target c++11 } }
+
+struct X
+{
+  friend void g(X, int) = 0; // { dg-error "initializer specified for friend function" }
+  friend void g(X, int) = default; // { dg-error "cannot be defaulted" }
+  // { dg-prune-output "note" }
+  friend void f(X, int) = delete; 
+  friend void f(X, double) {}
+};
+
+struct Y;
+void g(Y, int);
+void g(Y, double);
+
+struct Y
+{
+  // { dg-prune-output "note" }
+  friend void g(Y, int) = delete;
+  friend void g(Y, double) {}
+};
+
+int main()
+{
+  X x;
+  f(x, 5.0);
+  f(x, 5); // { dg-error "use of deleted function" }
+  Y y;
+  g(y, 5.0);
+  g(y, 5); // { dg-error "use of deleted function" }
+}