aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-05-02 21:19:05 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2025-05-02 21:19:05 +0200
commite81f2f4855876c5d85ab9870c5a150ee1a59ee73 (patch)
tree474e08653a604e67669f1de5e92de28cddf19790 /gcc
parent1e27e9a3184c948b499a21ff20181611514ed720 (diff)
downloadgcc-e81f2f4855876c5d85ab9870c5a150ee1a59ee73.zip
gcc-e81f2f4855876c5d85ab9870c5a150ee1a59ee73.tar.gz
gcc-e81f2f4855876c5d85ab9870c5a150ee1a59ee73.tar.bz2
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 <jakub@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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c/c-typeck.cc20
-rw-r--r--gcc/testsuite/gcc.dg/cpp/embed-18.c7
-rw-r--r--gcc/testsuite/gcc.dg/pr120057-1.c18
-rw-r--r--gcc/testsuite/gcc.dg/pr120057-2.c11
4 files changed, 54 insertions, 2 deletions
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 05fb129..0e1f842 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -9143,8 +9143,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 0000000..198a6db
--- /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 0000000..8832de6
--- /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 0000000..1372baf
--- /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
+};