https://gcc.gnu.org/g:0910ebacff1ef3401ee578d947c91e348feb3465

commit r14-11417-g0910ebacff1ef3401ee578d947c91e348feb3465
Author: Marek Polacek <pola...@redhat.com>
Date:   Mon Mar 17 17:46:02 2025 -0400

    c++: ICE with ptr-to-member-fn [PR119344]
    
    This ICE appeared with the removal of NON_DEPENDENT_EXPR.  Previously
    skip_simple_arithmetic would get NON_DEPENDENT_EXPR<CAST_EXPR<>> and
    since NON_DEPENDENT_EXPR is neither BINARY_CLASS_P nor UNARY_CLASS_P,
    there was no problem.  But now we pass just CAST_EXPR<> and a CAST_EXPR
    is a tcc_unary, so we extract its null operand and crash.
    
    skip_simple_arithmetic is called from save_expr.  cp_save_expr already
    avoids calling save_expr in a template, so that seems like an appropriate
    way to fix this.
    
            PR c++/119344
    
    gcc/cp/ChangeLog:
    
            * typeck.cc (cp_build_binary_op): Use cp_save_expr instead of 
save_expr.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/conversion/ptrmem10.C: New test.
    
    Reviewed-by: Patrick Palka <ppa...@redhat.com>
    Reviewed-by: Jason Merrill <ja...@redhat.com>
    (cherry picked from commit 6fc1f70f0b7b50fd85aa58a0f29dd1e17f2113d1)

Diff:
---
 gcc/cp/typeck.cc                           | 20 ++++++++++----------
 gcc/testsuite/g++.dg/conversion/ptrmem10.C | 14 ++++++++++++++
 2 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index a3b1e52f2243..6e938f168a4c 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -5431,7 +5431,7 @@ cp_build_binary_op (const op_location_t &location,
           case stv_firstarg:
             {
               op0 = convert (TREE_TYPE (type1), op0);
-             op0 = save_expr (op0);
+             op0 = cp_save_expr (op0);
               op0 = build_vector_from_val (type1, op0);
              orig_type0 = type0 = TREE_TYPE (op0);
               code0 = TREE_CODE (type0);
@@ -5441,7 +5441,7 @@ cp_build_binary_op (const op_location_t &location,
           case stv_secondarg:
             {
               op1 = convert (TREE_TYPE (type0), op1);
-             op1 = save_expr (op1);
+             op1 = cp_save_expr (op1);
               op1 = build_vector_from_val (type0, op1);
              orig_type1 = type1 = TREE_TYPE (op1);
               code1 = TREE_CODE (type1);
@@ -5965,9 +5965,9 @@ cp_build_binary_op (const op_location_t &location,
            return error_mark_node;
 
          if (TREE_SIDE_EFFECTS (op0))
-           op0 = save_expr (op0);
+           op0 = cp_save_expr (op0);
          if (TREE_SIDE_EFFECTS (op1))
-           op1 = save_expr (op1);
+           op1 = cp_save_expr (op1);
 
          pfn0 = pfn_from_ptrmemfunc (op0);
          pfn0 = cp_fully_fold (pfn0);
@@ -6203,8 +6203,8 @@ cp_build_binary_op (const op_location_t &location,
          && !processing_template_decl
          && sanitize_flags_p (SANITIZE_POINTER_COMPARE))
        {
-         op0 = save_expr (op0);
-         op1 = save_expr (op1);
+         op0 = cp_save_expr (op0);
+         op1 = cp_save_expr (op1);
 
          tree tt = builtin_decl_explicit (BUILT_IN_ASAN_POINTER_COMPARE);
          instrument_expr = build_call_expr_loc (location, tt, 2, op0, op1);
@@ -6464,14 +6464,14 @@ cp_build_binary_op (const op_location_t &location,
            return error_mark_node;
          if (first_complex)
            {
-             op0 = save_expr (op0);
+             op0 = cp_save_expr (op0);
              real = cp_build_unary_op (REALPART_EXPR, op0, true, complain);
              imag = cp_build_unary_op (IMAGPART_EXPR, op0, true, complain);
              switch (code)
                {
                case MULT_EXPR:
                case TRUNC_DIV_EXPR:
-                 op1 = save_expr (op1);
+                 op1 = cp_save_expr (op1);
                  imag = build2 (resultcode, real_type, imag, op1);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -6484,13 +6484,13 @@ cp_build_binary_op (const op_location_t &location,
            }
          else
            {
-             op1 = save_expr (op1);
+             op1 = cp_save_expr (op1);
              real = cp_build_unary_op (REALPART_EXPR, op1, true, complain);
              imag = cp_build_unary_op (IMAGPART_EXPR, op1, true, complain);
              switch (code)
                {
                case MULT_EXPR:
-                 op0 = save_expr (op0);
+                 op0 = cp_save_expr (op0);
                  imag = build2 (resultcode, real_type, op0, imag);
                  /* Fall through.  */
                case PLUS_EXPR:
diff --git a/gcc/testsuite/g++.dg/conversion/ptrmem10.C 
b/gcc/testsuite/g++.dg/conversion/ptrmem10.C
new file mode 100644
index 000000000000..b5fc050ee814
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conversion/ptrmem10.C
@@ -0,0 +1,14 @@
+// PR c++/119344
+// { dg-do compile { target c++11 } }
+
+struct S {
+    void fn();
+};
+typedef void (S::*T)(void);
+template <T Ptr>
+struct s
+{
+  static const bool t = Ptr != T();
+};
+
+int t1 = s<&S::fn>::t;

Reply via email to