https://gcc.gnu.org/g:49058fecbfd09a3354064e7d695b4a1056ce7547

commit r15-1768-g49058fecbfd09a3354064e7d695b4a1056ce7547
Author: Simon Martin <si...@nasilyan.com>
Date:   Tue Jun 11 11:44:28 2024 +0200

    c++: Relax too strict assert in stabilize_expr [PR111160]
    
    The case in the ticket is an ICE on invalid due to an assert in 
stabilize_expr,
    but the underlying issue can actually trigger on this *valid* code:
    
    === cut here ===
    struct TheClass {
      TheClass() {}
      TheClass(volatile TheClass& t) {}
      TheClass operator=(volatile TheClass& t) volatile { return t; }
    };
    void the_func() {
      volatile TheClass x, y, z;
      (false ? x : y) = z;
    }
    === cut here ===
    
    The problem is that stabilize_expr asserts that it returns an expression
    without TREE_SIDE_EFFECTS, which can't be if the involved type is volatile.
    
    This patch relaxes the assert to accept having TREE_THIS_VOLATILE on the
    returned expression.
    
    Successfully tested on x86_64-pc-linux-gnu.
    
            PR c++/111160
    
    gcc/cp/ChangeLog:
    
            * tree.cc (stabilize_expr): Stabilized expressions can have
            TREE_SIDE_EFFECTS if they're volatile.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/overload/error8.C: New test.
            * g++.dg/overload/volatile2.C: New test.

Diff:
---
 gcc/cp/tree.cc                            |  2 +-
 gcc/testsuite/g++.dg/overload/error8.C    |  9 +++++++++
 gcc/testsuite/g++.dg/overload/volatile2.C | 12 ++++++++++++
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 28648c14c6d..dfd4a3a948b 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -5969,7 +5969,7 @@ stabilize_expr (tree exp, tree* initp)
     }
   *initp = init_expr;
 
-  gcc_assert (!TREE_SIDE_EFFECTS (exp));
+  gcc_assert (!TREE_SIDE_EFFECTS (exp) || TREE_THIS_VOLATILE (exp));
   return exp;
 }
 
diff --git a/gcc/testsuite/g++.dg/overload/error8.C 
b/gcc/testsuite/g++.dg/overload/error8.C
new file mode 100644
index 00000000000..a7e745860e0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/error8.C
@@ -0,0 +1,9 @@
+// PR c++/111160
+// { dg-do compile { target c++11 } }
+
+class TheClass {}; // { dg-error "discards|bind|discards|bind" }
+void the_func() {
+  TheClass x;
+  volatile TheClass y;
+  (false ? x : x) = y; // { dg-error "ambiguous|ambiguous" }
+}
diff --git a/gcc/testsuite/g++.dg/overload/volatile2.C 
b/gcc/testsuite/g++.dg/overload/volatile2.C
new file mode 100644
index 00000000000..9f27357aed6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/volatile2.C
@@ -0,0 +1,12 @@
+// PR c++/111160
+// { dg-do compile { target c++11 } }
+
+struct TheClass {
+  TheClass() {}
+  TheClass(volatile TheClass& t) {}
+  TheClass operator=(volatile TheClass& t) volatile { return t; }
+};
+void the_func() {
+  volatile TheClass x, y, z;
+  (false ? x : y) = z;
+}

Reply via email to