Here the RHS has function type, so the stabilize_expr call in cp_build_modify_expr was trying to generate a temporary of function type, which is nonsensical. Fixed by using decay_conversion instead of rvalue, to turn it into a pointer.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 3a2cac966b15ae84a3ab54ee92ba54934ae70d4c Author: Jason Merrill <ja...@redhat.com> Date: Tue Apr 3 15:34:32 2018 -0400 PR c++/85141 - ICE with compound assignment and static member fn. * typeck.c (cp_build_modify_expr): Call decay_conversion for RHS of compound assignment. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 2b7a771bbeb..e5ad54dbcd1 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -8083,7 +8083,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, side effect associated with any single compound assignment operator. -- end note ] */ lhs = cp_stabilize_reference (lhs); - rhs = rvalue (rhs); + rhs = decay_conversion (rhs, complain); if (rhs == error_mark_node) return error_mark_node; rhs = stabilize_expr (rhs, &init); diff --git a/gcc/testsuite/g++.dg/expr/assign2.C b/gcc/testsuite/g++.dg/expr/assign2.C new file mode 100644 index 00000000000..759584af8d2 --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/assign2.C @@ -0,0 +1,12 @@ +// PR c++/85141 +// { dg-options "-w -fpermissive" } + +struct A +{ + static int foo(); +}; + +void bar(int i) +{ + i += A().foo; +} diff --git a/gcc/testsuite/g++.dg/parse/crash60.C b/gcc/testsuite/g++.dg/parse/crash60.C index e515396771e..8e545a253c5 100644 --- a/gcc/testsuite/g++.dg/parse/crash60.C +++ b/gcc/testsuite/g++.dg/parse/crash60.C @@ -10,5 +10,5 @@ void foo() int result = 0; M m; - result += m.pop(); // { dg-error "invalid operands|in evaluation" } + result += m.pop(); // { dg-error "" } }