tree-optimization/126650 - get_inner_reference_aff and bitfields

Message ID 79r2s4rn-n813-69s3-8466-0qnp22o4386r@fhfr.qr
State New
Headers
Series tree-optimization/126650 - get_inner_reference_aff and bitfields |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap fail Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap fail Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-arm fail Patch failed to apply

Commit Message

Richard Biener Aug. 5, 2026, 11:34 a.m. UTC
  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.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

	PR tree-optimization/126650
	* tree-affine.cc (get_inner_reference_aff): Fixup rounding
	of size.

	* gcc.dg/torture/pr126650.c: New testcase.
---
 gcc/testsuite/gcc.dg/torture/pr126650.c | 35 +++++++++++++++++++++++++
 gcc/tree-affine.cc                      |  5 ++--
 2 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr126650.c
  

Patch

diff --git a/gcc/testsuite/gcc.dg/torture/pr126650.c b/gcc/testsuite/gcc.dg/torture/pr126650.c
new file mode 100644
index 00000000000..166705d9cfe
--- /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 b5b7249c675..181fd6fb33c 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;
 }