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 "" }
 }

Reply via email to