https://gcc.gnu.org/g:0d51ed19504bcaa540763423763bb97227ed6c1c

commit r16-7487-g0d51ed19504bcaa540763423763bb97227ed6c1c
Author: Patrick Palka <[email protected]>
Date:   Thu Feb 12 14:44:56 2026 -0500

    c++: evaluation order of xobj memfn call [PR123989]
    
    The object argument of an xobj memfn call needs to be evaluated before its
    formal arguments, like with an iobj memfn call.  This patch generalizes the
    existing such handling in cp_gimplify_expr for METHOD_TYPE callees to also
    accept xobj memfn callees.
    
            PR c++/123989
    
    gcc/cp/ChangeLog:
    
            * cp-gimplify.cc (cp_gimplify_expr) <case CALL_EXPR>: Evaluate
            the object argument of an xobj memfn call first too.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp23/explicit-obj-eval-order.C: New test.
    
    Reviewed-by: Marek Polacek <[email protected]>
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/cp-gimplify.cc                                |  9 ++++++++-
 gcc/testsuite/g++.dg/cpp23/explicit-obj-eval-order.C | 16 ++++++++++++++++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 9d96ce99ea92..2e2f328079a8 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -921,7 +921,14 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, 
gimple_seq *post_p)
          tree fntype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
          if (INDIRECT_TYPE_P (fntype))
            fntype = TREE_TYPE (fntype);
-         if (TREE_CODE (fntype) == METHOD_TYPE)
+         tree decl = cp_get_callee_fndecl_nofold (*expr_p);
+         /* We can't just rely on 'decl' because virtual function callees
+            are expressed as OBJ_TYPE_REF.  Though checking for METHOD_TYPE
+            means we'll also sequence PMF calls, which is allowed under
+            "indeterminately sequenced".  */
+         if (TREE_CODE (fntype) == METHOD_TYPE
+             || (decl && DECL_LANG_SPECIFIC (decl)
+                 && DECL_XOBJ_MEMBER_FUNCTION_P (decl)))
            {
              int nargs = call_expr_nargs (*expr_p);
              bool side_effects = false;
diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-eval-order.C 
b/gcc/testsuite/g++.dg/cpp23/explicit-obj-eval-order.C
new file mode 100644
index 000000000000..7ce81f32cc4b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-eval-order.C
@@ -0,0 +1,16 @@
+// PR c++/123989
+// { dg-do run { target c++23 } }
+
+struct A {
+  int m = 42;
+
+  void f(this A self, int n) {
+    if (self.m != 42 || n != 43)
+      __builtin_abort();
+  }
+};
+
+int main() {
+  A a;
+  a.f(++a.m);
+}

Reply via email to