I looked at this again and do not need a workaround anymore.

I did not implement any restrictions preventing typedef 
redeclarations from having different alignment, because
merge_decls does not include any such restrictions at this
time.  I could write another patch for this, but I think
this would be an unrelated change.

Bootstrapped and regression tested on x86_64.



    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 --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 1ae520828c3..c778c7febfa 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 71782bc42d2..aaf8e54416a 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 00000000000..0c3e4988118
--- /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 00000000000..e86d1100482
--- /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 00000000000..a2424d6b7ab
--- /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");
+

Reply via email to