https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109359

--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> ---
output_constant gets called with

{(float) 1.91399999999999990279997419406754488591104745864868164062e-3, (float)
6.305389999999999606217215841752476990222930908203125e-1}

it then eventually does

  /* Eliminate any conversions since we'll be outputting the underlying
     constant.  */
  while (CONVERT_EXPR_P (exp)
         || TREE_CODE (exp) == NON_LVALUE_EXPR
         || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
    {
      HOST_WIDE_INT type_size = int_size_in_bytes (TREE_TYPE (exp));
      HOST_WIDE_INT op_size = int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp,
0)));

      /* Make sure eliminating the conversion is really a no-op, except with
         VIEW_CONVERT_EXPRs to allow for wild Ada unchecked conversions and
         union types to allow for Ada unchecked unions.  */
      if (type_size > op_size
          && TREE_CODE (exp) != VIEW_CONVERT_EXPR
          && TREE_CODE (TREE_TYPE (exp)) != UNION_TYPE)
        /* Keep the conversion. */
        break;
      else
        exp = TREE_OPERAND (exp, 0);
    }

where we strip conversions with type_size < op_size (aka float from double).
For float conversions not sure if just keying on type size is good enough
though (ibm double double vs long double 128 for example).

Fixing that "improves" the behavior to

t.ii:1:34: error: initializer for floating value is not a floating constant
    1 | float xs[] = {0.001914, 0.630539};
      |                                  ^
t.ii:1:34: error: initializer for floating value is not a floating constant

aka from wrong-code to rejects-valid.

diff --git a/gcc/varasm.cc b/gcc/varasm.cc
index cd0cd88321c..e6ab581dc5f 100644
--- a/gcc/varasm.cc
+++ b/gcc/varasm.cc
@@ -5202,7 +5202,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size,
unsigned int align,
       /* Make sure eliminating the conversion is really a no-op, except with
         VIEW_CONVERT_EXPRs to allow for wild Ada unchecked conversions and
         union types to allow for Ada unchecked unions.  */
-      if (type_size > op_size
+      if (type_size != op_size
          && TREE_CODE (exp) != VIEW_CONVERT_EXPR
          && TREE_CODE (TREE_TYPE (exp)) != UNION_TYPE)
        /* Keep the conversion. */

note that for integral and pointer types we do

      cst = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
      if (reverse)
        cst = flip_storage_order (TYPE_MODE (TREE_TYPE (exp)), cst);
      if (!assemble_integer (cst, MIN (size, thissize), align, 0))
        error ("initializer for integer/fixed-point value is too complicated");

so we handle "narrowing" in a weird way.  So in case FEs leave around
nop-casts the following should be safer

diff --git a/gcc/varasm.cc b/gcc/varasm.cc
index cd0cd88321c..81f7288449c 100644
--- a/gcc/varasm.cc
+++ b/gcc/varasm.cc
@@ -5196,13 +5196,17 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size,
unsigned int align,
         || TREE_CODE (exp) == NON_LVALUE_EXPR
         || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
     {
-      HOST_WIDE_INT type_size = int_size_in_bytes (TREE_TYPE (exp));
-      HOST_WIDE_INT op_size = int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp,
0)));
+      tree type = TREE_TYPE (exp);
+      tree op_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+      HOST_WIDE_INT type_size = int_size_in_bytes (type);
+      HOST_WIDE_INT op_size = int_size_in_bytes (op_type);

       /* Make sure eliminating the conversion is really a no-op, except with
         VIEW_CONVERT_EXPRs to allow for wild Ada unchecked conversions and
         union types to allow for Ada unchecked unions.  */
-      if (type_size > op_size
+      if ((type_size > op_size
+          || (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (op_type)
+              && FLOAT_TYPE_P (type)))
          && TREE_CODE (exp) != VIEW_CONVERT_EXPR
          && TREE_CODE (TREE_TYPE (exp)) != UNION_TYPE)
        /* Keep the conversion. */

The real fix is of course in the frontend, the above is just a safety net.

Reply via email to