Skip to content

Commit b1d92ae

Browse files
committed
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.
1 parent 5c19ba5 commit b1d92ae

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

gcc/cp/typeck.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -4092,7 +4092,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
40924092
tree ar = cp_default_conversion (array, complain);
40934093
tree ind = cp_default_conversion (idx, complain);
40944094

4095-
if (!first && flag_strong_eval_order == 2 && TREE_SIDE_EFFECTS (ind))
4095+
if (!processing_template_decl
4096+
&& !first && flag_strong_eval_order == 2 && TREE_SIDE_EFFECTS (ind))
40964097
ar = first = save_expr (ar);
40974098

40984099
/* Put the integer in IND to simplify error checking. */
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// PR c++/117158 - Similar to eval-order7.C, only with templates.
2+
// { dg-do run { target c++11 } }
3+
// { dg-options "-fstrong-eval-order" }
4+
5+
int a[4] = { 1, 2, 3, 4 };
6+
int b[4] = { 5, 6, 7, 8 };
7+
8+
struct Base {
9+
int *intarray;
10+
};
11+
12+
template <typename T>
13+
struct Sub : public Base {
14+
int Get(int i) {
15+
Base::intarray = a;
16+
int r = Base::intarray[(Base::intarray = b, i)];
17+
if (Base::intarray != b)
18+
__builtin_abort ();
19+
return r;
20+
}
21+
};
22+
23+
int
24+
main ()
25+
{
26+
Sub<int> s;
27+
if (s.Get (3) != 4)
28+
__builtin_abort ();
29+
}

gcc/testsuite/g++.dg/parse/crash77.C

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// PR c++/117158
2+
// { dg-do "compile" }
3+
4+
struct Base {
5+
unsigned int *intarray;
6+
};
7+
8+
template <typename T>
9+
struct Sub : public Base {
10+
bool Get(int i) {
11+
return (Base::intarray[++i] == 0);
12+
}
13+
};

0 commit comments

Comments
 (0)