https://gcc.gnu.org/g:59b82e3f4f88a02158c56921effcc078ab1a5580

commit r17-3841-g59b82e3f4f88a02158c56921effcc078ab1a5580
Author: Andrea Pinski <[email protected]>
Date:   Tue Sep 1 14:14:50 2026 -0700

    tree-eh: Fix up lhs_could_trap_p for *this [PR127133]
    
    Currently we were treating `this->a` as being non-trapping.
    This is ok for the rhs but on the lhs it depends on the memory
    was read only or not which we don't have access to right away.
    So right now lhs_could_trap_p would call tree_could_trap_p
    and then have some special cases for some read only/trapping
    cases.  Instead let's split up tree_could_trap_p and then
    have the special cases directly in the new function.
    
    Bootstrapped and tested on x86_64-linux-gnu.
    
            PR tree-optimization/127133
            PR tree-optimization/127134
    
    gcc/ChangeLog:
    
            * tree-eh.cc (tree_could_trap_p): Split into ...
            (tree_could_trap_1): This. Take into account lhs
            in some cases.
            (lhs_could_trap_p): Just call tree_could_trap_1.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/torture/const-method-this-1.C: New test.
            * g++.dg/torture/const-method-this-2.C: New test.
    
    Signed-off-by: Andrea Pinski <[email protected]>

Diff:
---
 gcc/testsuite/g++.dg/torture/const-method-this-1.C | 27 ++++++++++
 gcc/testsuite/g++.dg/torture/const-method-this-2.C | 28 +++++++++++
 gcc/tree-eh.cc                                     | 57 +++++++++++++++-------
 3 files changed, 94 insertions(+), 18 deletions(-)

diff --git a/gcc/testsuite/g++.dg/torture/const-method-this-1.C 
b/gcc/testsuite/g++.dg/torture/const-method-this-1.C
new file mode 100644
index 000000000000..106ce011625c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/const-method-this-1.C
@@ -0,0 +1,27 @@
+// PR tree-optimization/127133
+// { dg-do run }
+// { dg-additional-options "-fallow-store-data-races" }
+
+struct s1
+{
+  void f(int b, int d) const;
+  int t;
+};
+
+__attribute__((noipa))
+void
+s1::f(int b, int d) const
+{
+  s1 &c = const_cast<s1&>(*this);
+  int p = t;
+  if (b)
+    c.t = d | p;
+}
+
+
+const s1 a = {1};
+
+int main()
+{
+  a.f(0,0);
+}
diff --git a/gcc/testsuite/g++.dg/torture/const-method-this-2.C 
b/gcc/testsuite/g++.dg/torture/const-method-this-2.C
new file mode 100644
index 000000000000..70bf467f51f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/const-method-this-2.C
@@ -0,0 +1,28 @@
+// PR tree-optimization/127134
+// { dg-do run }
+// { dg-additional-options "-fallow-store-data-races" }
+
+struct s1
+{
+  void f(int b, int d) const;
+  int t;
+};
+
+__attribute__((noipa))
+void
+s1::f(int b, int d) const
+{
+  for(int i = 0; i < b; i++) {
+    s1 &c = const_cast<s1&>(*this);
+    int p = 1;
+    if (d)
+      c.t = p;
+  }
+}
+
+const s1 a = {1};
+
+int main()
+{
+  a.f(1,0);
+}
diff --git a/gcc/tree-eh.cc b/gcc/tree-eh.cc
index 0835f55af086..2d2d391f0a97 100644
--- a/gcc/tree-eh.cc
+++ b/gcc/tree-eh.cc
@@ -2754,10 +2754,11 @@ ref_outside_object_p (tree size, poly_offset_int off, 
tree refsz)
 
 /* Return true if EXPR can trap, as in dereferencing an invalid pointer
    location or floating point arithmetic.  C.f. the rtl version, may_trap_p.
-   This routine expects only GIMPLE lhs or rhs input.  */
+   This routine expects only GIMPLE lhs or rhs input.
+   LHS is true when LHS is a lhs.  */
 
-bool
-tree_could_trap_p (tree expr)
+static bool
+tree_could_trap_1 (tree expr, bool lhs)
 {
   enum tree_code code;
   bool fp_operation = false;
@@ -2813,7 +2814,7 @@ tree_could_trap_p (tree expr)
 
     case ARRAY_RANGE_REF:
       base = TREE_OPERAND (expr, 0);
-      if (tree_could_trap_p (base))
+      if (tree_could_trap_1 (base, lhs))
        return true;
       if (TREE_THIS_NOTRAP (expr))
        return false;
@@ -2821,7 +2822,7 @@ tree_could_trap_p (tree expr)
 
     case ARRAY_REF:
       base = TREE_OPERAND (expr, 0);
-      if (tree_could_trap_p (base))
+      if (tree_could_trap_1 (base, lhs))
        return true;
       if (TREE_THIS_NOTRAP (expr))
        return false;
@@ -2830,7 +2831,7 @@ tree_could_trap_p (tree expr)
     case TARGET_MEM_REF:
     case MEM_REF:
       if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR
-         && tree_could_trap_p (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)))
+         && tree_could_trap_1 (TREE_OPERAND (TREE_OPERAND (expr, 0), 0), lhs))
        return true;
       if (TREE_THIS_NOTRAP (expr))
        return false;
@@ -2851,7 +2852,9 @@ tree_could_trap_p (tree expr)
          tree refsz = TYPE_SIZE_UNIT (TREE_TYPE (expr));
          return ref_outside_object_p (size, off, refsz);
        }
-      if (cfun
+      /* See if the base is this for C++ methods. For LHS, this can still
+        trap.  */
+      if (!lhs && cfun
          && TREE_CODE (TREE_TYPE (cfun->decl)) == METHOD_TYPE
          && ((TREE_CODE (TREE_OPERAND (expr, 0)) == SSA_NAME
               && SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (expr, 0))
@@ -2884,10 +2887,13 @@ tree_could_trap_p (tree expr)
       if (!t || !DECL_P (t))
        return true;
       if (DECL_WEAK (t))
-       return tree_could_trap_p (t);
+       return tree_could_trap_1 (t, lhs);
       return false;
 
     case FUNCTION_DECL:
+      /* Functions will cause a trap if on the lhs.  */
+      if (lhs)
+       return true;
       /* Assume that accesses to weak functions may trap, unless we know
         they are certainly defined in current TU or in some other
         LTO partition.  */
@@ -2901,6 +2907,9 @@ tree_could_trap_p (tree expr)
       return false;
 
     case VAR_DECL:
+      /* Readonly non-local decls can cause a trap on the lhs.  */
+      if (lhs && !auto_var_p (expr) && TREE_READONLY (expr))
+       return true;
       /* Assume that accesses to weak vars may trap, unless we know
         they are certainly defined in current TU or in some other
         LTO partition.  */
@@ -2912,25 +2921,37 @@ tree_could_trap_p (tree expr)
          return !(node && node->in_other_partition);
        }
       return false;
-
+    /* Strings, const and labels will cause a trap if on the lhs.  */
+    case LABEL_DECL:
+    case CONST_DECL:
+    case STRING_CST:
+      return lhs;
+    /* Result and arguments will never cause a trap.  */
+    case RESULT_DECL:
+    case PARM_DECL:
+      return false;
     default:
       return false;
     }
 }
 
+
+
+/* Return true if EXPR can trap, as in dereferencing an invalid pointer
+   location or floating point arithmetic.  C.f. the rtl version, may_trap_p.
+   This routine expects only GIMPLE lhs or rhs input.  */
+
+bool
+tree_could_trap_p (tree expr)
+{
+  return tree_could_trap_1 (expr, false);
+}
+
 /* Returns true if LHS is known not to trap as a store.  */
 bool
 lhs_could_trap_p (tree lhs)
 {
-  tree lhsbase = get_base_address (lhs);
-  if (tree_could_trap_p (lhs))
-    return true;
-  /* tree_could_trap_p is a predicate for loads, so check
-     for readonly memory explicitly.  */
-  if ((DECL_P (lhsbase) && TREE_READONLY (lhsbase))
-      || TREE_CODE (lhsbase) == STRING_CST)
-    return true;
-  return false;
+  return tree_could_trap_1 (lhs, true);
 }
 
 /* Return non-NULL if there is an integer operation with trapping overflow

Reply via email to