aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Martin <simon@nasilyan.com>2024-11-05 10:07:42 +0100
committerSimon Martin <simon@nasilyan.com>2024-11-05 10:07:42 +0100
commitb1d92aeb8583c8d1491c97703680c5fb88ed1fe4 (patch)
tree81f4c8130fc209a5a849e1d77759c548229afc49
parent5c19ba52519be975d4464b063d3d5a2c700dd241 (diff)
downloadgcc-b1d92aeb8583c8d1491c97703680c5fb88ed1fe4.zip
gcc-b1d92aeb8583c8d1491c97703680c5fb88ed1fe4.tar.gz
gcc-b1d92aeb8583c8d1491c97703680c5fb88ed1fe4.tar.bz2
c++: Defer -fstrong-eval-order processing to template instantiation time [PR117158]
Since r10-3793-g1a37b6d9a7e57c, we ICE upon the following valid code with -std=c++17 and above === cut here === struct Base { unsigned int *intarray; }; template <typename T> struct Sub : public Base { bool Get(int i) { return (Base::intarray[++i] == 0); } }; === cut here === The problem is that from c++17 on, we use -fstrong-eval-order and need to wrap the array access expression into a SAVE_EXPR. We do so at template declaration time, and end up calling contains_placeholder_p with a SCOPE_REF, that it does not handle well. This patch fixes this by deferring the wrapping into SAVE_EXPR to instantiation time for templates, when the SCOPE_REF will have been turned into a COMPONENT_REF. PR c++/117158 gcc/cp/ChangeLog: * typeck.cc (cp_build_array_ref): Only wrap array expression into a SAVE_EXPR at template instantiation time. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/eval-order13.C: New test. * g++.dg/parse/crash77.C: New test.
-rw-r--r--gcc/cp/typeck.cc3
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/eval-order13.C29
-rw-r--r--gcc/testsuite/g++.dg/parse/crash77.C13
3 files changed, 44 insertions, 1 deletions
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 6ce1bb6..4396812 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -4092,7 +4092,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
tree ar = cp_default_conversion (array, complain);
tree ind = cp_default_conversion (idx, complain);
- if (!first && flag_strong_eval_order == 2 && TREE_SIDE_EFFECTS (ind))
+ if (!processing_template_decl
+ && !first && flag_strong_eval_order == 2 && TREE_SIDE_EFFECTS (ind))
ar = first = save_expr (ar);
/* Put the integer in IND to simplify error checking. */
diff --git a/gcc/testsuite/g++.dg/cpp1z/eval-order13.C b/gcc/testsuite/g++.dg/cpp1z/eval-order13.C
new file mode 100644
index 0000000..6e8ebeb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/eval-order13.C
@@ -0,0 +1,29 @@
+// PR c++/117158 - Similar to eval-order7.C, only with templates.
+// { dg-do run { target c++11 } }
+// { dg-options "-fstrong-eval-order" }
+
+int a[4] = { 1, 2, 3, 4 };
+int b[4] = { 5, 6, 7, 8 };
+
+struct Base {
+ int *intarray;
+};
+
+template <typename T>
+struct Sub : public Base {
+ int Get(int i) {
+ Base::intarray = a;
+ int r = Base::intarray[(Base::intarray = b, i)];
+ if (Base::intarray != b)
+ __builtin_abort ();
+ return r;
+ }
+};
+
+int
+main ()
+{
+ Sub<int> s;
+ if (s.Get (3) != 4)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/parse/crash77.C b/gcc/testsuite/g++.dg/parse/crash77.C
new file mode 100644
index 0000000..729362e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash77.C
@@ -0,0 +1,13 @@
+// PR c++/117158
+// { dg-do "compile" }
+
+struct Base {
+ unsigned int *intarray;
+};
+
+template <typename T>
+struct Sub : public Base {
+ bool Get(int i) {
+ return (Base::intarray[++i] == 0);
+ }
+};