Message ID | 01020192f7c20514-b212126d-89d0-4e5b-9479-9a3272dc1424-000000@eu-west-1.amazonses.com |
---|---|
State | New |
Headers | show |
Series | [v2] c++: Defer -fstrong-eval-order processing to template instantiation time [PR117158] | expand |
On 11/4/24 10:19 AM, Simon Martin wrote: > 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? OK. > Thanks, Simon
Hi Jason, On 5 Nov 2024, at 1:23, Jason Merrill wrote: > On 11/4/24 10:19 AM, Simon Martin wrote: >> 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? > > OK. Thanks, pushed to trunk as r15-4957-gb1d92aeb8583c8. Since it’s a reject-valid regression, OK to back port to active branches as well? Thanks, Simon
On 11/5/24 4:13 AM, Simon Martin wrote: > Hi Jason, > > On 5 Nov 2024, at 1:23, Jason Merrill wrote: > >> On 11/4/24 10:19 AM, Simon Martin wrote: >>> 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? >> >> OK. > Thanks, pushed to trunk as r15-4957-gb1d92aeb8583c8. > > Since it’s a reject-valid regression, OK to back port to active > branches as well? OK. Jason
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); + } +};