[gcc r17-2981] tree-optimization/126650 - get_inner_reference_aff and bitfields

Richard Biener via Gcc-cvs <[email protected]> Wed, 5 Aug 2026 11:35:06 +0000 (GMT)
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:9baaca2adeca178edf8c0816ef328dba1cf270bc

commit r17-2981-g9baaca2adeca178edf8c0816ef328dba1cf270bc
Author: Richard Biener <[email protected]>
Date:   Wed Aug 5 10:31:47 2026 +0200

    tree-optimization/126650 - get_inner_reference_aff and bitfields
    
    get_inner_reference_aff tries to compensate for bit precision
    offsets and sizes by rounding down and up, but fails to do this
    correctly.  The following makes it more obviously correct by
    rounding positions and computing the rounded size based on those.
    
            PR tree-optimization/126650
            * tree-affine.cc (get_inner_reference_aff): Fixup rounding
            of size.
    
            * gcc.dg/torture/pr126650.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr126650.c | 35 +++++++++++++++++++++++++++++++++
 gcc/tree-affine.cc                      |  5 +++--
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/torture/pr126650.c b/gcc/testsuite/gcc.dg/torture/pr126650.c
new file mode 100644
index 000000000000..166705d9cfe6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr126650.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+long a;
+
+void __attribute__((noipa)) foo (int n, ...)
+{
+  va_list list;
+  va_start (list, n);
+  int val = va_arg (list, int);
+  if (val != -64)
+    abort ();
+  va_end (list);
+}
+
+int main()
+{
+  struct b {
+    int : 7;
+    int : 2;
+    int : 6;
+    int : 3;
+    int c : 7;
+  };
+  union {
+    int d;
+    struct b bf;
+    char e[4];
+  } f;
+  f.d = a;
+  f.e[3] = 7;
+  foo (1, f.bf.c);
+}
diff --git a/gcc/tree-affine.cc b/gcc/tree-affine.cc
index b5b7249c6750..181fd6fb33ce 100644
--- a/gcc/tree-affine.cc
+++ b/gcc/tree-affine.cc
@@ -1030,10 +1030,11 @@ get_inner_reference_aff (tree ref, aff_tree *addr, poly_widest_int *size)
       aff_combination_add (addr, &tmp);
     }
 
-  aff_combination_const (&tmp, sizetype, bits_to_bytes_round_down (bitpos));
+  poly_int64 bytepos = bits_to_bytes_round_down (bitpos);
+  aff_combination_const (&tmp, sizetype, bytepos);
   aff_combination_add (addr, &tmp);
 
-  *size = bits_to_bytes_round_up (bitsize);
+  *size = bits_to_bytes_round_up (bitpos + bitsize) - bytepos;
 
   return base;
 }