aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorSimon Martin <simon@nasilyan.com>2024-06-11 11:44:28 +0200
committerSimon Martin <simon@nasilyan.com>2024-07-02 12:48:34 +0200
commit49058fecbfd09a3354064e7d695b4a1056ce7547 (patch)
treed68f945533e46080e05628139c5d8f1fe2ca34c4 /gcc
parente9c0cbf0155cf4df57afb0ac8e18a7a1fc746e4a (diff)
downloadgcc-49058fecbfd09a3354064e7d695b4a1056ce7547.zip
gcc-49058fecbfd09a3354064e7d695b4a1056ce7547.tar.gz
gcc-49058fecbfd09a3354064e7d695b4a1056ce7547.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/tree.cc2
-rw-r--r--gcc/testsuite/g++.dg/overload/error8.C9
-rw-r--r--gcc/testsuite/g++.dg/overload/volatile2.C12
3 files changed, 22 insertions, 1 deletions
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 28648c1..dfd4a3a 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 0000000..a7e7458
--- /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 0000000..9f27357
--- /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;
+}