aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-10-29 20:14:09 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2024-10-29 20:14:09 +0100
commit28b7aed124d4d86be552f24469c2cfa59a49edaf (patch)
tree8af23ef0151e2ddc15494f50222d356956f4d9e1 /gcc
parente6d21cbf5cf035b6fa9946a4321f87cbcfa9f275 (diff)
downloadgcc-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.cc25
-rw-r--r--gcc/testsuite/c-c++-common/init-6.c29
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
+ }
+};