]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c: fix ICE for mutually recursive structures [PR120381]
authorMartin Uecker <uecker@tugraz.at>
Thu, 29 May 2025 17:13:46 +0000 (19:13 +0200)
committerMartin Uecker <uecker@gcc.gnu.org>
Fri, 30 May 2025 06:59:46 +0000 (08:59 +0200)
For invalid nesting of a structure definition in a definition
of itself or when using a rather obscure construction using statement
expressions, we can create mutually recursive pairs of non-identical
but compatible structure types.  This can lead to invalid composite
types and an ICE.  If we detect recursion even for swapped pairs
when forming composite types, this is avoided.

PR c/120381

gcc/c/ChangeLog:
* c-typeck.cc (composite_type_internal): Stop recursion for
swapped pairs.

gcc/testsuite/ChangeLog:
* gcc.dg/pr120381.c: New test.
* gcc.dg/gnu23-tag-composite-6.c: New test.

gcc/c/c-typeck.cc
gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr120381.c [new file with mode: 0644]

index 360216b966212b76b5319c0e21507ac72679b256..e5dd8d54c516ae3f7a84e54842ce48bcaf64304f 100644 (file)
@@ -776,7 +776,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
             construction, return it.  */
 
          for (struct composite_cache *c = cache; c != NULL; c = c->next)
-           if (c->t1 == t1 && c->t2 == t2)
+           if ((c->t1 == t1 && c->t2 == t2) || (c->t1 == t2 && c->t2 == t1))
               return c->composite;
 
          /* Otherwise, create a new type node and link it into the cache.  */
diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c b/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c
new file mode 100644 (file)
index 0000000..2411b04
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu23" } */
+
+int f()
+{
+    typedef struct foo bar;
+    struct foo { typeof(({ (struct foo { bar * x; }){ }; })) * x; } *q;
+    typeof(q->x) p;
+    1 ? p : q;
+}
+
diff --git a/gcc/testsuite/gcc.dg/pr120381.c b/gcc/testsuite/gcc.dg/pr120381.c
new file mode 100644 (file)
index 0000000..5c017e6
--- /dev/null
@@ -0,0 +1,10 @@
+/* PR120381 */
+/* { dg-do compile } */
+
+struct A {
+  struct A {           /* { dg-error "nested redefinition" } */
+    struct A *p;
+  } *p;
+};
+int foo(const struct A *q) { return q->p == q; }
+