]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c: fix ICE when forming composite type for two structures / unions [PR117548]
authorMartin Uecker <uecker@tugraz.at>
Thu, 14 Nov 2024 19:54:33 +0000 (20:54 +0100)
committerMartin Uecker <uecker@tugraz.at>
Sat, 16 Nov 2024 08:49:48 +0000 (09:49 +0100)
When forming the composite type from two tagged type, we need to find the
original type for a typedecl to get the correct tag.

PR c/117548

gcc/c/ChangeLog:
* c-decl.cc (finish_struct): Add checking assertion.
* c-typeck.cc (c_type_original): New function.
(composite_types_internal): Get tag from original type.

gcc/testsuite/ChangeLog:
* gcc.dg/pr117548.c: New test.

gcc/c/c-decl.cc
gcc/c/c-typeck.cc
gcc/testsuite/gcc.dg/pr117548.c [new file with mode: 0644]

index 07c18a34072c81810e26dd46339d520c3c345f37..7e65bd04b11e53cc8aa76b1967d02c60ff2a5c32 100644 (file)
@@ -9872,6 +9872,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
       hashval_t hash = c_struct_hasher::hash (t);
 
       gcc_checking_assert (TYPE_STRUCTURAL_EQUALITY_P (t));
+      gcc_checking_assert (!TYPE_NAME (t)
+                          || TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE);
+
       tree *e = c_struct_htab->find_slot_with_hash (t, hash, INSERT);
       if (*e)
        TYPE_CANONICAL (t) = *e;
index 10b02da8752dba8c2903de81560441539116d16a..9212a8ebc0a90557a7f21341bb17719d187d119f 100644 (file)
@@ -576,6 +576,21 @@ c_build_functype_attribute_variant (tree ntype, tree otype, tree attrs)
 
 }
 
+/* Given a type which could be a typedef name, make sure to return the
+   original type.  */
+static const_tree
+c_type_original (const_tree t)
+{
+  /* It may even be a typedef of a typedef...
+     In the case of compiler-created builtin structs the TYPE_DECL
+     may be a dummy, with no DECL_ORIGINAL_TYPE.  Don't fault.  */
+  while (TYPE_NAME (t)
+        && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
+        && DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
+    t = DECL_ORIGINAL_TYPE (TYPE_NAME (t));
+  return t;
+}
+
 \f
 /* Return the composite type of two compatible types.
 
@@ -728,8 +743,11 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
     case UNION_TYPE:
       if (flag_isoc23 && !comptypes_same_p (t1, t2))
        {
+         /* Go to the original type to get the right tag.  */
+         tree tag = TYPE_NAME (c_type_original (const_cast<tree> (t1)));
+
          gcc_checking_assert (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2));
-         gcc_checking_assert (!TYPE_NAME (t1) || comptypes (t1, t2));
+         gcc_checking_assert (!tag || comptypes (t1, t2));
 
          /* If a composite type for these two types is already under
             construction, return it.  */
@@ -742,7 +760,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
 
          tree n = make_node (code1);
          SET_TYPE_STRUCTURAL_EQUALITY (n);
-         TYPE_NAME (n) = TYPE_NAME (t1);
+         TYPE_NAME (n) = tag;
 
          struct composite_cache cache2 = { t1, t2, n, cache };
          cache = &cache2;
@@ -1781,19 +1799,9 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
 
   /* We have to verify that the tags of the types are the same.  This
      is harder than it looks because this may be a typedef, so we have
-     to go look at the original type.  It may even be a typedef of a
-     typedef...
-     In the case of compiler-created builtin structs the TYPE_DECL
-     may be a dummy, with no DECL_ORIGINAL_TYPE.  Don't fault.  */
-  while (TYPE_NAME (t1)
-        && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
-        && DECL_ORIGINAL_TYPE (TYPE_NAME (t1)))
-    t1 = DECL_ORIGINAL_TYPE (TYPE_NAME (t1));
-
-  while (TYPE_NAME (t2)
-        && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL
-        && DECL_ORIGINAL_TYPE (TYPE_NAME (t2)))
-    t2 = DECL_ORIGINAL_TYPE (TYPE_NAME (t2));
+     to go look at the original type.  */
+  t1 = c_type_original (t1);
+  t2 = c_type_original (t2);
 
   if (TYPE_NAME (t1) != TYPE_NAME (t2))
     return false;
diff --git a/gcc/testsuite/gcc.dg/pr117548.c b/gcc/testsuite/gcc.dg/pr117548.c
new file mode 100644 (file)
index 0000000..d388d25
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23" } */
+
+typedef struct A { int q; } A;
+void f(A*);
+
+int main(void)
+{
+  struct A { int q; };
+  void f(struct A*);
+}
+