[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