https://gcc.gnu.org/g:14c2a12748eea0eef714a125cb1a6c834fd60560
commit r15-9615-g14c2a12748eea0eef714a125cb1a6c834fd60560 Author: Jakub Jelinek <ja...@redhat.com> Date: Fri May 2 21:19:05 2025 +0200 c: Fix up RAW_DATA_CST handling in check_constexpr_init [PR120057] The pr120057-1.c testcase is incorrectly rejected since r15-4377 (and for a while it also ICEd after the error), i.e. the optimization of large C initializers using RAW_DATA_CST. Similarly, the embed-18.c testcase is incorrectly rejected since the embed support has been introduced and RAW_DATA_CST used for that. The callers of check_constexpr_init (store_init_value and output_init_element) compute int_const_expr as int_const_expr = (TREE_CODE (init) == INTEGER_CST && !TREE_OVERFLOW (init) && INTEGRAL_TYPE_P (TREE_TYPE (init))); but that is only passed through down to check_constexpr_init. I think tweaking those 2 callers to also allow RAW_DATA_CST for int_const_expr when check_constexpr_init needs top special case it no matter what would be larger, so the patch just changes check_constexpr_init to deal with RAW_DATA_CST in the initializers. For TYPE_UNSIGNED char precision integral types RAW_DATA_CST is always valid, for !TYPE_UNSIGNED we need to check for 128-255 values being turned into negative ones. 2025-05-02 Jakub Jelinek <ja...@redhat.com> PR c/120057 * c-typeck.cc (check_constexpr_init): Handle RAW_DATA_CST. * gcc.dg/cpp/embed-18.c: New test. * gcc.dg/pr120057-1.c: New test. * gcc.dg/pr120057-2.c: New test. (cherry picked from commit e81f2f4855876c5d85ab9870c5a150ee1a59ee73) Diff: --- gcc/c/c-typeck.cc | 20 ++++++++++++++++++-- gcc/testsuite/gcc.dg/cpp/embed-18.c | 7 +++++++ gcc/testsuite/gcc.dg/pr120057-1.c | 18 ++++++++++++++++++ gcc/testsuite/gcc.dg/pr120057-2.c | 11 +++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 55d896e02df5..ea83451b06b8 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -9153,8 +9153,24 @@ check_constexpr_init (location_t loc, tree type, tree init, /* The initializer must be an integer constant expression, representable in the target type. */ if (!int_const_expr) - error_at (loc, "%<constexpr%> integer initializer is not an " - "integer constant expression"); + { + if (TREE_CODE (init) == RAW_DATA_CST + && TYPE_PRECISION (type) == CHAR_BIT) + { + if (!TYPE_UNSIGNED (type)) + for (unsigned int i = 0; + i < (unsigned) RAW_DATA_LENGTH (init); ++i) + if (RAW_DATA_SCHAR_ELT (init, i) < 0) + { + error_at (loc, "%<constexpr%> initializer not " + "representable in type of object"); + break; + } + } + else + error_at (loc, "%<constexpr%> integer initializer is not an " + "integer constant expression"); + } else if (!int_fits_type_p (init, type)) error_at (loc, "%<constexpr%> initializer not representable in " "type of object"); diff --git a/gcc/testsuite/gcc.dg/cpp/embed-18.c b/gcc/testsuite/gcc.dg/cpp/embed-18.c new file mode 100644 index 000000000000..198a6db55e19 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/embed-18.c @@ -0,0 +1,7 @@ +/* PR c/120057 */ +/* { dg-do compile } */ +/* { dg-options "-std=c23 --embed-dir=${srcdir}/c-c++-common/cpp/embed-dir" } */ + +constexpr unsigned char magna_carta[] = { +#embed <magna-carta.txt> +}; diff --git a/gcc/testsuite/gcc.dg/pr120057-1.c b/gcc/testsuite/gcc.dg/pr120057-1.c new file mode 100644 index 000000000000..8832de66a7f4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr120057-1.c @@ -0,0 +1,18 @@ +/* PR c/120057 */ +/* { dg-do compile } */ +/* { dg-options "-std=c23" } */ + +constexpr char foo[65] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 1 +}; +constexpr char bar[66] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 1, 2 +}; diff --git a/gcc/testsuite/gcc.dg/pr120057-2.c b/gcc/testsuite/gcc.dg/pr120057-2.c new file mode 100644 index 000000000000..1372baf3dddc --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr120057-2.c @@ -0,0 +1,11 @@ +/* PR c/120057 */ +/* { dg-do compile } */ +/* { dg-options "-std=c23" } */ + +constexpr signed char foo[65] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 129, 11, 12, 13, 14, 15, 16, /* { dg-error "'constexpr' initializer not representable in type of object" } */ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 1 +};