On Wed, Jan 15, 2025 at 10:27:56AM -0500, Jason Merrill wrote: > > @@ -7432,12 +7426,18 @@ reshape_init_r (tree type, reshape_iter > > { > > vec<constructor_elt, va_gc> *v = 0; > > CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init); > > - tree raw_init = cp_maybe_split_raw_data (d); > > + bool inc_cur; > > + reshape_iter dsave = *d; > > + tree raw_init = cp_maybe_split_raw_data (d, &inc_cur); > > CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, > > raw_init ? raw_init : d->cur->value); > > if (has_designator_problem (d, complain)) > > - return error_mark_node; > > - if (!raw_init) > > + { > > + if (!inc_cur) > > + *d = dsave; > > Why restore *d on the error path? Won't the caller just return > error_mark_node as well?
Here is a patch with a better replacement for that hunk. As I wrote, the reason I haven't used consume_init there was that has_designator_problem needs to test the old, not new d->cur, and it was called after the splitting. Calling it before that or allocating the va_gc vector is better and matches what reshape_init_r does at the start of the function. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2025-01-15 Jakub Jelinek <ja...@redhat.com> PR c++/118214 * decl.cc (struct reshape_iter): Add raw_idx member. (cp_maybe_split_raw_data): Add inc_cur parameter, set *inc_cur, don't modify original CONSTRUCTOR, use d->raw_idx to track index into a RAW_DATA_CST d->cur->value. (consume_init): Adjust cp_maybe_split_raw_data caller, increment d->cur when cur_inc is true. (reshape_init_array_1): Don't modify original CONSTRUCTOR when handling RAW_DATA_CST d->cur->value and !reuse, instead use d->raw_idx to track index into RAW_DATA_CST. (reshape_single_init): Initialize iter.raw_idx. (reshape_init_class): Adjust for introduction of d->raw_idx, adjust cp_maybe_split_raw_data caller, do d->cur++ if inc_cur rather than when it returns non-NULL. (reshape_init_r): Check for has_designator_problem for second half of _Complex earlier, also check for error_operand_p (d->cur->value). Use consume_init instead of cp_maybe_split_raw_data with later conditional d->cur++. (reshape_init): Initialize d.raw_idx. * g++.dg/cpp/embed-17.C: New test. * g++.dg/cpp0x/pr118214.C: New test. --- gcc/cp/decl.cc.jj 2024-12-27 16:03:52.622536496 +0100 +++ gcc/cp/decl.cc 2025-01-15 19:26:49.765532110 +0100 @@ -6823,11 +6823,13 @@ check_for_uninitialized_const_var (tree /* Structure holding the current initializer being processed by reshape_init. CUR is a pointer to the current element being processed, END is a pointer - after the last element present in the initializer. */ + after the last element present in the initializer and RAW_IDX is index into + RAW_DATA_CST if that is CUR elt. */ struct reshape_iter { constructor_elt *cur; constructor_elt *end; + unsigned raw_idx; }; static tree reshape_init_r (tree, reshape_iter *, tree, tsubst_flags_t); @@ -6895,18 +6897,20 @@ is_direct_enum_init (tree type, tree ini } /* Helper function for reshape_init*. Split first element of - RAW_DATA_CST and save the rest to d->cur->value. */ + RAW_DATA_CST or return NULL for other elements. Set *INC_CUR + to true if the whole d->cur has been consumed. */ static tree -cp_maybe_split_raw_data (reshape_iter *d) +cp_maybe_split_raw_data (reshape_iter *d, bool *inc_cur) { + *inc_cur = true; if (TREE_CODE (d->cur->value) != RAW_DATA_CST) return NULL_TREE; - tree ret = *raw_data_iterator (d->cur->value, 0); - ++RAW_DATA_POINTER (d->cur->value); - --RAW_DATA_LENGTH (d->cur->value); - if (RAW_DATA_LENGTH (d->cur->value) == 1) - d->cur->value = *raw_data_iterator (d->cur->value, 0); + tree ret = *raw_data_iterator (d->cur->value, d->raw_idx++); + if (d->raw_idx != (unsigned) RAW_DATA_LENGTH (d->cur->value)) + *inc_cur = false; + else + d->raw_idx = 0; return ret; } @@ -6918,9 +6922,11 @@ cp_maybe_split_raw_data (reshape_iter *d static tree consume_init (tree init, reshape_iter *d) { - if (tree raw_init = cp_maybe_split_raw_data (d)) - return raw_init; - d->cur++; + bool inc_cur; + if (tree raw_init = cp_maybe_split_raw_data (d, &inc_cur)) + init = raw_init; + if (inc_cur) + d->cur++; return init; } @@ -6979,10 +6985,8 @@ reshape_init_array_1 (tree elt_type, tre { tree elt_init; constructor_elt *old_cur = d->cur; - const char *old_raw_data_ptr = NULL; - - if (TREE_CODE (d->cur->value) == RAW_DATA_CST) - old_raw_data_ptr = RAW_DATA_POINTER (d->cur->value); + unsigned int old_raw_idx = d->raw_idx; + bool old_raw_data_cst = TREE_CODE (d->cur->value) == RAW_DATA_CST; if (d->cur->index) CONSTRUCTOR_IS_DESIGNATED_INIT (new_init) = true; @@ -6995,25 +6999,23 @@ reshape_init_array_1 (tree elt_type, tre && !vector_p) { elt_init = d->cur->value; - if (!sized_array_p - || ((unsigned) RAW_DATA_LENGTH (d->cur->value) - <= max_index_cst - index + 1)) - d->cur++; + unsigned int off = d->raw_idx; + unsigned int len = RAW_DATA_LENGTH (elt_init) - off; + if (!sized_array_p || len <= max_index_cst - index + 1) + { + d->cur++; + d->raw_idx = 0; + } else { - unsigned int len = max_index_cst - index + 1; - if ((unsigned) RAW_DATA_LENGTH (d->cur->value) == len + 1) - d->cur->value - = build_int_cst (integer_type_node, - *(const unsigned char *) - RAW_DATA_POINTER (d->cur->value) + len); - else - { - d->cur->value = copy_node (elt_init); - RAW_DATA_LENGTH (d->cur->value) -= len; - RAW_DATA_POINTER (d->cur->value) += len; - } + len = max_index_cst - index + 1; + d->raw_idx += len; + } + if (!reuse || off || d->cur == old_cur) + { + elt_init = copy_node (elt_init); RAW_DATA_LENGTH (elt_init) = len; + RAW_DATA_POINTER (elt_init) += off; } TREE_TYPE (elt_init) = elt_type; } @@ -7024,7 +7026,7 @@ reshape_init_array_1 (tree elt_type, tre if (elt_init == error_mark_node) return error_mark_node; tree idx = size_int (index); - if (reuse && old_raw_data_ptr && d->cur == old_cur) + if (reuse && old_raw_data_cst && d->cur == old_cur) { /* We need to stop reusing as some RAW_DATA_CST in the original ctor had to be split. */ @@ -7065,9 +7067,7 @@ reshape_init_array_1 (tree elt_type, tre /* This can happen with an invalid initializer (c++/54501). */ if (d->cur == old_cur && !sized_array_p - && (old_raw_data_ptr == NULL - || (TREE_CODE (d->cur->value) == RAW_DATA_CST - && RAW_DATA_POINTER (d->cur->value) == old_raw_data_ptr))) + && d->raw_idx == old_raw_idx) break; if (TREE_CODE (elt_init) == RAW_DATA_CST) @@ -7136,7 +7136,7 @@ reshape_single_init (tree type, tree ini /* We could also implement this by wrapping init in a new CONSTRUCTOR and calling reshape_init, but this way can just live on the stack. */ constructor_elt elt = { /*index=*/NULL_TREE, init }; - reshape_iter iter = { &elt, &elt + 1 }; + reshape_iter iter = { &elt, &elt + 1, 0 }; return reshape_init_r (type, &iter, /*first_initializer_p=*/NULL_TREE, complain); @@ -7197,12 +7197,9 @@ reshape_init_class (tree type, reshape_i { tree field_init; constructor_elt *old_cur = d->cur; - const char *old_raw_data_ptr = NULL; + unsigned old_raw_idx = d->raw_idx; bool direct_desig = false; - if (TREE_CODE (d->cur->value) == RAW_DATA_CST) - old_raw_data_ptr = RAW_DATA_POINTER (d->cur->value); - /* Handle C++20 designated initializers. */ if (d->cur->index) { @@ -7329,11 +7326,7 @@ reshape_init_class (tree type, reshape_i if (field_init == error_mark_node) return error_mark_node; - if (d->cur == old_cur - && d->cur->index - && (old_raw_data_ptr == NULL - || (TREE_CODE (d->cur->value) == RAW_DATA_CST - && RAW_DATA_POINTER (d->cur->value) == old_raw_data_ptr))) + if (d->cur == old_cur && d->cur->index && d->raw_idx == old_raw_idx) { /* This can happen with an invalid initializer for a flexible array member (c++/54441). */ @@ -7369,7 +7362,8 @@ reshape_init_class (tree type, reshape_i if (last_was_pack_expansion) { tree init = d->cur->value; - if (tree raw_init = cp_maybe_split_raw_data (d)) + bool inc_cur; + if (tree raw_init = cp_maybe_split_raw_data (d, &inc_cur)) init = raw_init; CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), last_was_pack_expansion, init); @@ -7437,15 +7431,13 @@ reshape_init_r (tree type, reshape_iter } else if (first_initializer_p && d->cur != d->end) { + if (error_operand_p (d->cur->value) + || has_designator_problem (d, complain)) + return error_mark_node; vec<constructor_elt, va_gc> *v = 0; CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init); - tree raw_init = cp_maybe_split_raw_data (d); - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, - raw_init ? raw_init : d->cur->value); - if (has_designator_problem (d, complain)) - return error_mark_node; - if (!raw_init) - d->cur++; + init = consume_init (d->cur->value, d); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init); init = build_constructor (init_list_type_node, v); } return init; @@ -7712,6 +7704,7 @@ reshape_init (tree type, tree init, tsub /* Recurse on this CONSTRUCTOR. */ d.cur = &(*v)[0]; d.end = d.cur + v->length (); + d.raw_idx = 0; new_init = reshape_init_r (type, &d, init, complain); if (new_init == error_mark_node) --- gcc/testsuite/g++.dg/cpp/embed-17.C.jj 2024-12-30 11:35:19.872880361 +0100 +++ gcc/testsuite/g++.dg/cpp/embed-17.C 2024-12-30 11:40:15.301700534 +0100 @@ -0,0 +1,24 @@ +// PR c++/118214 +// { dg-do run { target c++11 } } +// { dg-options "" } + +struct A { int a[256]; }; +unsigned char b[] = { +#embed __FILE__ limit (160) +}; + +void +foo (A a) +{ + for (int i = 0; i < 256; ++i) + if (a.a[i] != (i < sizeof (b) ? b[i] : 0)) + __builtin_abort (); +} + +int +main () +{ + foo ({ +#embed __FILE__ limit (160) + }); +} --- gcc/testsuite/g++.dg/cpp0x/pr118214.C.jj 2024-12-30 13:41:25.572219186 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr118214.C 2024-12-30 13:40:40.018838914 +0100 @@ -0,0 +1,26 @@ +// PR c++/118214 +// { dg-do run { target c++11 } } + +struct A { int a[256]; }; + +void +foo (A a) +{ + for (int i = 0; i < 256; ++i) + if (a.a[i] != (i < 130 && (i & 1) == 0)) + __builtin_abort (); +} + +int +main () +{ + foo ({ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, }); +} Jakub