Hi Jason,
On 1 Nov 2024, at 16:31, Jason Merrill wrote:
> On 11/1/24 5:07 AM, Simon Martin wrote:
>> 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, and end up
>> calling
>> contains_placeholder_p with a SCOPE_REF, that it does not handle
>> well.
>>
>> This patch fixes this by skipping the first operand of SCOPE_REFs in
>> contains_placeholder_p.
>
> Code in gcc/ shouldn't refer to tree codes from cp-tree.def.
>
> We probably shouldn't do the strong-eval-order transformation when
> processing_template_decl anyway.
Thanks, that makes sense. The attached updated patch skips the
wrapping when processing_template_decl, and also adds a test
case checking that -fstrong-eval-order processing is properly
done for instantiated templates.
Successfully tested on x86_64-pc-linux-gnu. OK for trunk?
Thanks, Simon
From b5c8777bc04bd633781d3f3af2a72efd8888e2ab Mon Sep 17 00:00:00 2001
From: Simon Martin <si...@nasilyan.com>
Date: Thu, 31 Oct 2024 09:04:49 +0100
Subject: [PATCH] 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.
Successfully tested on x86_64-pc-linux-gnu.
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.
---
gcc/cp/typeck.cc | 3 ++-
gcc/testsuite/g++.dg/cpp1z/eval-order13.C | 29 +++++++++++++++++++++++
gcc/testsuite/g++.dg/parse/crash77.C | 13 ++++++++++
3 files changed, 44 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/cpp1z/eval-order13.C
create mode 100644 gcc/testsuite/g++.dg/parse/crash77.C
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 6ce1bb61fe7..439681216be 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 00000000000..6e8ebeb3096
--- /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 00000000000..729362eb599
--- /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);
+ }
+};
--
2.44.0