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 <ja...@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