https://gcc.gnu.org/g:accbc1b90bd942aa36ac1485a21056b774ce02df
commit r15-8963-gaccbc1b90bd942aa36ac1485a21056b774ce02df Author: Martin Uecker <uec...@tugraz.at> Date: Sun Mar 16 10:54:17 2025 +0100 c: Fix tagname confusion for typedef redefinitions [PR118765] When we redefine a typedef for a tagged type that has just been redefined, merge_decls may produce invalid TYPE_DECLS that are not consistent with what set_underlying_type produces. This is fixed by updating DECL_ORIGINAL_TYPE. PR c/118765 gcc/c/ChangeLog: * c-decl.cc (merge_decls): For TYPE_DECLS copy DECL_ORIGINAL_TYPE from the old declaration. * c-typeck.cc (tagged_types_tu_compatible_p): Add checking assertions. gcc/testsuite/ChangeLog: * gcc.dg/pr118765-2.c: New test. * gcc.dg/pr118765-3.c: New test. * gcc.dg/typedef-redecl3.c: New test. Diff: --- gcc/c/c-decl.cc | 3 +++ gcc/c/c-typeck.cc | 4 ++++ gcc/testsuite/gcc.dg/pr118765-2.c | 33 +++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/pr118765-3.c | 33 +++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/typedef-redecl3.c | 23 +++++++++++++++++++++++ 5 files changed, 96 insertions(+) diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 1ae520828c34..c778c7febfa0 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -2788,6 +2788,9 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) break; } } + + /* Make sure we refer to the same type as the olddecl. */ + DECL_ORIGINAL_TYPE (newdecl) = DECL_ORIGINAL_TYPE (olddecl); } /* Merge the data types specified in the two decls. */ diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 71782bc42d24..aaf8e54416a2 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -1812,6 +1812,10 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, to go look at the original type. */ t1 = c_type_original (t1); t2 = c_type_original (t2); + gcc_checking_assert (!TYPE_NAME (t1) + || TREE_CODE (TYPE_NAME (t1)) == IDENTIFIER_NODE); + gcc_checking_assert (!TYPE_NAME (t2) + || TREE_CODE (TYPE_NAME (t2)) == IDENTIFIER_NODE); if (TYPE_NAME (t1) != TYPE_NAME (t2)) return false; diff --git a/gcc/testsuite/gcc.dg/pr118765-2.c b/gcc/testsuite/gcc.dg/pr118765-2.c new file mode 100644 index 000000000000..0c3e49881188 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr118765-2.c @@ -0,0 +1,33 @@ +/* { dg-do "compile" } */ +/* { dg-options "-std=gnu23" } */ + +typedef struct q { int x; } q_t; +typedef struct q { int x; } q_t; +typedef struct q { int x; } q_t; +typedef struct q { int x; } q_t; +typedef struct q { int x; } q_t; + +typedef struct r r_t; +typedef struct r r_t; +typedef struct r r_t; +typedef struct r r_t; +typedef struct r r_t; + +extern struct s { int x; } s; +extern struct s { int x; } s; +extern struct s { int x; } s; +extern struct s { int x; } s; +extern struct s { int x; } s; + +struct t { int x; }; +struct t { int x; }; +struct t { int x; }; +struct t { int x; }; +struct t { int x; }; + +typedef enum e { E = 1 } e_t; +typedef enum e { E = 1 } e_t; +typedef enum e { E = 1 } e_t; +typedef enum e { E = 1 } e_t; +typedef enum e { E = 1 } e_t; + diff --git a/gcc/testsuite/gcc.dg/pr118765-3.c b/gcc/testsuite/gcc.dg/pr118765-3.c new file mode 100644 index 000000000000..e86d11004829 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr118765-3.c @@ -0,0 +1,33 @@ +/* { dg-do "compile" } */ +/* { dg-options "-std=gnu23" } */ + +typedef struct q { int x; } q_t; +typedef struct q q_t; +typedef struct q { int x; } q_t; +typedef struct q q_t; +typedef struct q { int x; } q_t; + +typedef struct r r_t; +typedef struct r r_t; +typedef struct r r_t; +typedef struct r r_t; +typedef struct r r_t; + +extern struct s { int x; } s; +extern struct s s; +extern struct s { int x; } s; +extern struct s s; +extern struct s { int x; } s; + +struct t { int x; }; +struct t; +struct t { int x; }; +struct t; +struct t { int x; }; + +typedef enum e { E = 1 } e_t; +typedef enum e_t; /* { dg-warning "useless storage class specifier in empty declaration" } */ +typedef enum e { E = 1 } e_t; +typedef enum e_t; /* { dg-warning "empty declaration with storage class specifier does not redeclare tag" } */ +typedef enum e { E = 1 } e_t; + diff --git a/gcc/testsuite/gcc.dg/typedef-redecl3.c b/gcc/testsuite/gcc.dg/typedef-redecl3.c new file mode 100644 index 000000000000..a2424d6b7ab1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/typedef-redecl3.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ + +#define N 64 + +struct f { int x; }; +typedef struct f T; +typedef struct f T __attribute__((aligned (N))); +typedef struct f T __attribute__((aligned (N * 2))); +typedef struct f T __attribute__((aligned (N))); +typedef struct f T; + +_Static_assert (_Alignof (T) == N * 2, "N * 2"); + +enum g { A = 1 }; +typedef enum g S; +typedef enum g S __attribute__((aligned (N))); +typedef enum g S __attribute__((aligned (N * 2))); +typedef enum g S __attribute__((aligned (N))); +typedef enum g S; + +_Static_assert (_Alignof (S) == N * 2, "N * 2"); +