Since a backend may ignore user type alignment for arguments passed on stack, check backend for argument alignment on stack when evaluating __alignof.
gcc/c-family/ PR c/89544 * c-common.cc (c_alignof_expr): Check backend for argument alignment on stack. gcc/testsuite/ PR c/89544 * gcc.target/i386/pr89544.c: New test. -- H.J.
From 1f395b8268ba87121546a082e9111fe4b9ad0ab5 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.to...@gmail.com> Date: Sat, 28 Jun 2025 08:07:51 +0800 Subject: [PATCH] c-family: Check backend for argument alignment on stack Since a backend may ignore user type alignment for arguments passed on stack, check backend for argument alignment on stack when evaluating __alignof. gcc/c-family/ PR c/89544 * c-common.cc (c_alignof_expr): Check backend for argument alignment on stack. gcc/testsuite/ PR c/89544 * gcc.target/i386/pr89544.c: New test. Signed-off-by: H.J. Lu <hjl.to...@gmail.com> --- gcc/c-family/c-common.cc | 11 ++++++++ gcc/testsuite/gcc.target/i386/pr89544.c | 36 +++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/pr89544.c diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index f71cb2652d5..768cf994ffa 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -4076,6 +4076,17 @@ c_alignof_expr (location_t loc, tree expr) } return c_alignof (loc, TREE_TYPE (TREE_TYPE (best))); } + else if (TREE_CODE (expr) == PARM_DECL) + { + /* User alignment on type may be ignored for parameter passed on + stack. */ + tree type = TREE_TYPE (expr); + unsigned int alignment + = targetm.calls.function_arg_boundary (TYPE_MODE (type), + type); + tree value = size_int (alignment / BITS_PER_UNIT); + return value; + } else return c_alignof (loc, TREE_TYPE (expr)); diff --git a/gcc/testsuite/gcc.target/i386/pr89544.c b/gcc/testsuite/gcc.target/i386/pr89544.c new file mode 100644 index 00000000000..59ebf429526 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr89544.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef struct { + long double a; + long double b; +} c1 __attribute__((aligned(32))); +extern c1 x1; +void +foo1 (c1 f) +{ + c1 x = f; + x1 = x; + _Static_assert (__alignof (x) == 32, "__alignof (x) == 32"); + _Static_assert (__alignof (f) == __alignof (long double), + "__alignof (f) == __alignof (long double)"); + _Static_assert (__alignof (f.a) == __alignof (long double), + "__alignof (f.a) == __alignof (long double)"); +} + +typedef struct { + long double a; + long double b; +} c2 __attribute__((aligned(1))); +extern c2 x2; +void +foo2 (c2 f) +{ + c2 x = f; + x2 = x; + _Static_assert (__alignof (x) == 1, "__alignof (x) == 1"); + _Static_assert (__alignof (f) == __alignof (long double), + "__alignof (f) == __alignof (long double)"); + _Static_assert (__alignof (f.a) == __alignof (long double), + "__alignof (f.a) == __alignof (long double)"); +} -- 2.50.0