https://gcc.gnu.org/g:e81f2f4855876c5d85ab9870c5a150ee1a59ee73

commit r16-364-ge81f2f4855876c5d85ab9870c5a150ee1a59ee73
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.

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 05fb129ada8d..0e1f842e22d3 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 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
+};

Reply via email to