After looking a bit more at this, it turns out that it is still
possible to trigger the assertion that checks that the composite
type is compatible to the original types when using self-referential
types where it then sees composite types which are still under
construction.

This patch now moves the checking assertion out of the recursion,
which seems better anyhow. I could not do the check unconditionally
for all types. because we sometimes call composite_type for with
mismatching qualifiers.

There is also still a remaining issue with setting
C_VARIABLY_MODIFIED_TYPE_P correctly for composite types for
such self-referential types.


Bootstrapped and regression tested for x86_64.

Martin


    c: Move checking assertions from recursion when forming composite types to 
avoid ICE.
    
    The checking assertion in composite_type_internal for structures and unions 
may
    fail if there are self-referential types.  To avoid this, we move them out 
of
    the recursion.  This should also be more efficient and covers other types.
    We have to ignore some cases where we form composite types despite 
qualifiers
    not matching.
    
    gcc/c/ChangeLog:
            * c-typeck.cc (composite_type_internal,composite_type): Move
            checking assertions.
    
    gcc/testsuite/ChangeLog:
            * gcc.dg/gnu23-tag-composite-6.c: Update.

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 2f243cab8da..417db8795c5 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -846,12 +846,7 @@ composite_type_internal (tree t1, tree t2, struct 
composite_cache* cache)
          n = finish_struct (input_location, n, fields, attributes, NULL,
                             &expr);
 
-         n = qualify_type (n, t1);
-
-         gcc_checking_assert (!TYPE_NAME (n) || comptypes (n, t1));
-         gcc_checking_assert (!TYPE_NAME (n) || comptypes (n, t2));
-
-         return n;
+         return qualify_type (n, t1);
        }
       /* FALLTHRU */
     case ENUMERAL_TYPE:
@@ -1004,7 +999,15 @@ tree
 composite_type (tree t1, tree t2)
 {
   struct composite_cache cache = { };
-  return composite_type_internal (t1, t2, &cache);
+  tree n = composite_type_internal (t1, t2, &cache);
+  /* For function and arrays there are some exceptions where
+     qualifiers do not match.  */
+  if (FUNCTION_TYPE != TREE_CODE (n) && ARRAY_TYPE != TREE_CODE (n))
+    {
+      gcc_checking_assert (comptypes (n, t1));
+      gcc_checking_assert (comptypes (n, t2));
+    }
+  return n;
 }
 
 /* Return the type of a conditional expression between pointers to
diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c 
b/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c
index 2411b04d388..076c066f9c8 100644
--- a/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c
+++ b/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c
@@ -1,11 +1,31 @@
 /* { dg-do compile } */
 /* { dg-options "-std=gnu23" } */
 
+#define NEST(...) typeof(({ (__VA_ARGS__){ }; }))
+
 int f()
 {
     typedef struct foo bar;
-    struct foo { typeof(({ (struct foo { bar * x; }){ }; })) * x; } *q;
-    typeof(q->x) p;
-    1 ? p : q;
+    struct foo { NEST(struct foo { bar *x; }) *x; } *q;
+    typeof(q->x) p0;
+    typeof(q->x) p1;
+    1 ? p0 : q;
+    1 ? p1 : q;
+    1 ? p0 : p1;
+}
+
+int g()
+{
+    typedef struct fo2 bar;
+    struct fo2 { NEST(struct fo2 { NEST(struct fo2 { bar *x; }) * x; }) *x; } 
*q;
+    typeof(q->x) p0;
+    typeof(q->x->x) p1;
+    typeof(q->x->x->x) p2;
+    1 ? p0 : q;
+    1 ? p1 : q;
+    1 ? p2 : q;
+    1 ? p0 : p1;
+    1 ? p2 : p1;
+    1 ? p0 : p2;
 }
 

Reply via email to