diff options
author | Jakub Jelinek <jakub@redhat.com> | 2024-10-29 20:14:09 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2024-10-29 20:14:09 +0100 |
commit | 28b7aed124d4d86be552f24469c2cfa59a49edaf (patch) | |
tree | 8af23ef0151e2ddc15494f50222d356956f4d9e1 /gcc | |
parent | e6d21cbf5cf035b6fa9946a4321f87cbcfa9f275 (diff) | |
download | gcc-28b7aed124d4d86be552f24469c2cfa59a49edaf.zip gcc-28b7aed124d4d86be552f24469c2cfa59a49edaf.tar.gz gcc-28b7aed124d4d86be552f24469c2cfa59a49edaf.tar.bz2 |
c-family: Handle RAW_DATA_CST in complete_array_type [PR117313]
The following testcase ICEs, because
add_flexible_array_elts_to_size -> complete_array_type
is done only after braced_lists_to_strings which optimizes
RAW_DATA_CST surrounded by INTEGER_CST into a larger RAW_DATA_CST
covering even the boundaries, while I thought it is done before
that.
So, RAW_DATA_CST now can be the last constructor_elt in a CONSTRUCTOR
and so we need the function to take it into account (handle it as
RAW_DATA_CST standing for RAW_DATA_LENGTH consecutive elements).
The function wants to support both CONSTRUCTORs without indexes and with
them (for non-RAW_DATA_CST elts it was just adding 1 for the current
index). So, if the RAW_DATA_CST elt has ce->index, we need to add
RAW_DATA_LENGTH (ce->value) - 1, while if it doesn't (and it isn't cnt == 0
case where curindex is 0), add that plus 1, i.e. RAW_DATA_LENGTH (ce->value).
2024-10-29 Jakub Jelinek <jakub@redhat.com>
PR c/117313
gcc/c-family/
* c-common.cc (complete_array_type): For RAW_DATA_CST elements
advance curindex by RAW_DATA_LENGTH or one less than that if
ce->index is non-NULL. Handle even the first element if
it is RAW_DATA_CST. Formatting fix.
gcc/testsuite/
* c-c++-common/init-6.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/c-family/c-common.cc | 25 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/init-6.c | 29 |
2 files changed, 47 insertions, 7 deletions
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index 88827ac..f7feb21 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -7046,7 +7046,8 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) { int eltsize = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value))); - maxindex = size_int (TREE_STRING_LENGTH (initial_value)/eltsize - 1); + maxindex = size_int (TREE_STRING_LENGTH (initial_value) / eltsize + - 1); } else if (TREE_CODE (initial_value) == CONSTRUCTOR) { @@ -7061,23 +7062,25 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) else { tree curindex; - unsigned HOST_WIDE_INT cnt; + unsigned HOST_WIDE_INT cnt = 1; constructor_elt *ce; bool fold_p = false; if ((*v)[0].index) maxindex = (*v)[0].index, fold_p = true; + if (TREE_CODE ((*v)[0].value) == RAW_DATA_CST) + cnt = 0; curindex = maxindex; - for (cnt = 1; vec_safe_iterate (v, cnt, &ce); cnt++) + for (; vec_safe_iterate (v, cnt, &ce); cnt++) { bool curfold_p = false; if (ce->index) curindex = ce->index, curfold_p = true; - else + if (!ce->index || TREE_CODE (ce->value) == RAW_DATA_CST) { - if (fold_p) + if (fold_p || curfold_p) { /* Since we treat size types now as ordinary unsigned types, we need an explicit overflow @@ -7085,9 +7088,17 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) tree orig = curindex; curindex = fold_convert (sizetype, curindex); overflow_p |= tree_int_cst_lt (curindex, orig); + curfold_p = false; } - curindex = size_binop (PLUS_EXPR, curindex, - size_one_node); + if (TREE_CODE (ce->value) == RAW_DATA_CST) + curindex + = size_binop (PLUS_EXPR, curindex, + size_int (RAW_DATA_LENGTH (ce->value) + - ((ce->index || !cnt) + ? 1 : 0))); + else + curindex = size_binop (PLUS_EXPR, curindex, + size_one_node); } if (tree_int_cst_lt (maxindex, curindex)) maxindex = curindex, fold_p = curfold_p; diff --git a/gcc/testsuite/c-c++-common/init-6.c b/gcc/testsuite/c-c++-common/init-6.c new file mode 100644 index 0000000..d4c323b --- /dev/null +++ b/gcc/testsuite/c-c++-common/init-6.c @@ -0,0 +1,29 @@ +/* PR c/117313 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +struct S { unsigned a; const unsigned char b[]; }; +struct S s = { + 1, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, + 0x81, 0xbd, 0x99, 0x81, 0x7e, 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, + 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x10, + 0x38, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, + } +}; +struct S t = { + 2, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, + 0x81, 0xbd, 0x99, 0x81, 0x7e, 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, + 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x10, + 0x38, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, + 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x10, + 0x38, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c + } +}; |