[C++ PATCH] Fix rejects-valid of binding a reference to a static member fn (PR c++/80176)

Jakub Jelinek jakub@redhat.com
Sat Apr 1 20:13:00 GMT 2017


Hi!

Apparently when initialize_reference -> reference_binding -> lvalue*
is called with a static data member function with object. in front of it,
it still sees a COMPONENT_REF with BASELINK as second argument and its
BASELINK_FUNCTIONS either a FUNCTION_DECL or OVERLOAD.  Only later on when
actually performing the conversion it is converted into the ADDR_EXPR
of the FUNCTION_DECL.

The following patch fixes that by handling that form of a static data member
like the static data member itself.
Not sure if the OVL_CURRENT is needed at that point, I think I saw
in lvalue_kind OVERLOAD in BASELINK_FUNCTIONS just for methods, though
at least reference_binding still sees COMPONENT_REF with BASELINK of
OVERLOAD even for the static data members.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2017-04-01  Jakub Jelinek  <jakub@redhat.com>

	PR c++/80176
	* tree.c (lvalue_kind): For COMPONENT_REF with BASELINK second
	operand, if it is a static member function, recurse on the
	BASELINK.

	* g++.dg/init/ref23.C: New test.

--- gcc/cp/tree.c.jj	2017-03-09 09:51:23.000000000 +0100
+++ gcc/cp/tree.c	2017-04-01 17:25:04.698517181 +0200
@@ -105,6 +105,14 @@ lvalue_kind (const_tree ref)
       return op1_lvalue_kind;
 
     case COMPONENT_REF:
+      if (BASELINK_P (TREE_OPERAND (ref, 1)))
+	{
+	  tree fn = OVL_CURRENT (BASELINK_FUNCTIONS (TREE_OPERAND (ref, 1)));
+
+	  /* For static member function recurse on the BASELINK.  */
+	  if (TREE_CODE (fn) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (fn))
+	    return lvalue_kind (TREE_OPERAND (ref, 1));
+	}
       op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0));
       /* Look at the member designator.  */
       if (!op1_lvalue_kind)
--- gcc/testsuite/g++.dg/init/ref23.C.jj	2017-04-01 17:30:40.397299607 +0200
+++ gcc/testsuite/g++.dg/init/ref23.C	2017-04-01 17:29:47.000000000 +0200
@@ -0,0 +1,13 @@
+// PR c++/80176
+// { dg-do compile }
+
+struct X { static void foo(); static void baz(int); static int baz(double); } x;
+void X::foo() {}
+static void bar() {}
+void (&r1)() = x.foo;
+void (&r2)() = X::foo;
+void (&r3)() = bar;
+void (&r4)(int) = x.baz;
+int (&r5)(double) = x.baz;
+void (&r6)(int) = X::baz;
+int (&r7)(double) = X::baz;

	Jakub



More information about the Gcc-patches mailing list