Hi Joseph and Richard,
these are new versions of the two patches for PR122572. The
first fixes an oversight in the C FE that already addresses
the more important case for tagless structures / unions. The
second patch fixes the unlikely and more subtle case for types
with tag. The revisedĀ version does not include any changes to
the middle-end anymore.
Bootstrapped and regression tested on x86_64 and aarch64.
Martin
When computing TYPE_CANONICAL we form equivalence classes of types
ignoring some aspects. In particular, we treat two structure / union
types as equivalent if a member is a pointer to another tagged type
which has the same tag, even if this pointed-to type is otherwise not
compatible. The fundamental reason why we do this is that even in a
single TU the equivalence class needs to be consistent with compatibility
of incomplete types across TUs. (LTO globs such pointers to void*).
The bug is that the test incorrectly treated also two pointed-to types
without tag as equivalent. One would expect that this just pessimizes
aliasing decisions, but due to how the middle-end handles TBAA for
components of structures, this leads to wrong code.
PR c/122572
gcc/c/ChangeLog:
* c-typeck.cc (tagged_types_tu_compatible_p): Fix check.
gcc/testsuite/ChangeLog:
* gcc.dg/pr122572.c: New test.
* gcc.dg/pr123356-1.c: New test.
---
gcc/c/c-typeck.cc | 2 +-
gcc/testsuite/gcc.dg/pr122572.c | 46 ++++++++++++++++++++++++
gcc/testsuite/gcc.dg/pr123356-1.c | 58 +++++++++++++++++++++++++++++++
3 files changed, 105 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/pr122572.c
create mode 100644 gcc/testsuite/gcc.dg/pr123356-1.c
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index dc803dc6388..5b6b2b1d6e0 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -1857,7 +1857,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree
t2,
/* When forming equivalence classes for TYPE_CANONICAL in C23, we treat
structs with the same tag as equivalent, but only when they are targets
of pointers inside other structs. */
- if (data->equiv && data->pointedto)
+ if (data->equiv && data->pointedto && NULL_TREE != c_type_tag (t1))
return true;
/* Different types without tag are incompatible except as an anonymous
diff --git a/gcc/testsuite/gcc.dg/pr122572.c b/gcc/testsuite/gcc.dg/pr122572.c
new file mode 100644
index 00000000000..822042c3a8b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr122572.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-std=c23 -O2" } */
+
+typedef struct {
+ int *arg;
+ int flags;
+} optStruct;
+
+typedef struct {
+ int *specified;
+ int flags;
+} optEntry;
+
+typedef struct {
+ int short_allowed;
+ optStruct *opt_table;
+} optStruct2;
+
+typedef struct {
+ int short_allowed;
+ optEntry *opt_table;
+} optStruct3;
+
+[[gnu::noipa]]
+void f(int, int, optStruct3 a)
+{
+ a.opt_table[0].flags = 1;
+}
+
+[[gnu::noipa]]
+int alias_bug (void)
+{
+ static optEntry option_def[50];
+ static optStruct3 opt;
+ option_def[0].flags = 0;
+ opt.opt_table = option_def;
+ f (0, 0, opt);
+ return opt.opt_table[0].flags;
+}
+
+int main()
+{
+ if (1 != alias_bug())
+ __builtin_abort();
+}
+
diff --git a/gcc/testsuite/gcc.dg/pr123356-1.c
b/gcc/testsuite/gcc.dg/pr123356-1.c
new file mode 100644
index 00000000000..dab0c606320
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr123356-1.c
@@ -0,0 +1,58 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+typedef struct
+{
+ long coeffs;
+}
+fmpz_poly_struct;
+typedef struct
+{
+} n_poly_struct;
+typedef struct
+{
+ n_poly_struct * coeffs;
+ long alloc;
+ long length;
+} n_bpoly_struct;
+typedef struct
+{
+ fmpz_poly_struct * coeffs;
+ long alloc;
+ long length;
+} fmpz_bpoly_struct;
+typedef fmpz_bpoly_struct fmpz_bpoly_t[];
+
+__attribute__((noinline))
+fmpz_poly_struct * fmpz_bpoly_swap_(fmpz_bpoly_t B, fmpz_bpoly_t Q)
+{
+ fmpz_bpoly_struct t = *B;
+ *B = *Q;
+ *Q = t;
+ return B->coeffs;
+}
+
+__attribute__((noinline,optimize("no-strict-aliasing")))
+fmpz_poly_struct * fmpz_bpoly_swap_2(fmpz_bpoly_t B, fmpz_bpoly_t Q)
+{
+ fmpz_bpoly_struct t = *B;
+ *B = *Q;
+ *Q = t;
+ return B->coeffs;
+}
+
+int main(){
+ fmpz_poly_struct B_coeffs = {0}, Q_coeffs = {0};
+ fmpz_bpoly_t B = {0};
+ fmpz_bpoly_t Q = {0};
+ B->coeffs = &B_coeffs;
+ Q->coeffs = &Q_coeffs;
+ if (fmpz_bpoly_swap_(B, Q) != &Q_coeffs)
+ __builtin_abort();
+ B->coeffs = &B_coeffs;
+ Q->coeffs = &Q_coeffs;
+ if (fmpz_bpoly_swap_2(B, Q) != &Q_coeffs)
+ __builtin_abort();
+ return 0;
+}
+
--
2.47.3