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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jsm28 at gcc dot gnu.org

--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
This is a mess.

I've tried:
--- a/gcc/c/c-convert.cc        2026-03-27 10:17:13.726337397 +0100
+++ b/gcc/c/c-convert.cc        2026-09-14 15:20:29.220977603 +0200
@@ -86,7 +86,21 @@ c_convert (tree type, tree expr, bool in
     }

   if (type == TREE_TYPE (expr))
-    return expr;
+    {
+      /* Don't optimize away cast of a bit-precise integer bit-field to
+        its unpromoted type, because we could then try to perform
+        integer promotions on it again.  */
+      if (TREE_CODE (expr) == COMPONENT_REF
+         && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1))
+         && BITINT_TYPE_P (type)
+         && BITINT_TYPE_P (DECL_BIT_FIELD_TYPE (TREE_OPERAND (expr, 1))))
+       {
+         tree btype = DECL_BIT_FIELD_TYPE (TREE_OPERAND (expr, 1));
+         if (btype != type)
+           return non_lvalue_loc (loc, expr);
+       }
+      return expr;
+    }
   ret = targetm.convert_to_type (type, expr);
   if (ret)
       return ret;
--- a/gcc/c/c-typeck.cc 2026-08-17 10:00:21.658857069 +0200
+++ b/gcc/c/c-typeck.cc 2026-09-14 17:02:03.305443443 +0200
@@ -2907,7 +2907,17 @@ default_conversion (tree exp)
     return convert (promoted_type, exp);

   if (INTEGRAL_TYPE_P (type))
-    return perform_integral_promotions (exp);
+    {
+      /* Avoid performing integral promotion of bit-precise integer
+        type bit-field to its corresponding bit-precise integer if
+        orig_exp is a cast to it to its underlying type.  */
+      if (orig_exp != exp
+         && TREE_CODE (exp) == COMPONENT_REF
+         && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
+         && BITINT_TYPE_P (DECL_BIT_FIELD_TYPE (TREE_OPERAND (exp, 1))))
+       return perform_integral_promotions (orig_exp);
+      return perform_integral_promotions (exp);
+    }

   return exp;
 }
--- a/gcc/testsuite/gcc.dg/torture/bitint-108.c 2026-09-14 15:36:50.839136669
+0200
+++ b/gcc/testsuite/gcc.dg/torture/bitint-108.c 2026-09-14 15:36:35.910331972
+0200
@@ -0,0 +1,16 @@
+/* PR c/127383 */
+/* { dg-do run { target bitint } } */
+
+#if __BITINT_MAXWIDTH__ >= 65
+struct { unsigned _BitInt(65) f : 63; } s;
+#endif
+
+int
+main ()
+{
+#if __SIZEOF_LONG_LONG__ * __CHAR_BIT__ == 64 && __BITINT_MAXWIDTH__ >= 65
+  unsigned long long w = ~(unsigned _BitInt(63)) s.f;
+  if (w != (-1ULL >> 1))
+    __builtin_abort ();
+#endif
+}
but that breaks
FAIL: gcc.dg/bitint-136.c (test for excess errors)
FAIL: gcc.dg/bitint-17.c (test for excess errors)
FAIL: gcc.dg/torture/bitint-68.c   -O0  execution test
FAIL: gcc.dg/torture/bitint-68.c   -O2  execution test
Apparently there is a difference between an explicit cast like what happens in
the new bitint-108.c and an implicitly added cast like what happens e.g. on the
bitint-17.c testcase (convert_lvalue_to_rvalue -> convert -> c_convert).
The explicit cast case also calls convert_lvalue_to_rvalue -> convert ->
c_convert and then c_cast_expr.

Joseph, any thoughts of this?
Perhaps I should completely remove the c-convert.cc part and in c-typeck.cc
look through casts as long as there is no NON_LVALUE_EXPR among them?

Reply via email to