https://gcc.gnu.org/g:5fdd38d576c20d5a337b5c7d14108981d0751434

commit r12-10804-g5fdd38d576c20d5a337b5c7d14108981d0751434
Author: Simon Martin <si...@nasilyan.com>
Date:   Tue Nov 5 10:07:42 2024 +0100

    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.
    
    (cherry picked from commit b1d92aeb8583c8d1491c97703680c5fb88ed1fe4)

Diff:
---
 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(-)

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index ff8f0ef00838..df819701d4a6 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -3919,7 +3919,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 000000000000..6e8ebeb30967
--- /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 000000000000..729362eb5991
--- /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);
+  }
+};

Reply via email to