]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c: Implement C2y handling of incomplete tentative definitions [PR26581]
authorJoseph Myers <josmyers@redhat.com>
Tue, 7 Oct 2025 23:04:54 +0000 (23:04 +0000)
committerJoseph Myers <josmyers@redhat.com>
Tue, 7 Oct 2025 23:04:54 +0000 (23:04 +0000)
Before C2y, a tentative definition (file-scope, not extern, no
initializer) with internal linkage and incomplete type was undefined
behavior ("shall" outside Constraints violated).  In C2y, this has
changed to a constraint violation if the type has not been completed
by the end of the translation unit, and is valid if the type has been
completed by the end of the translation unit.  This change originates
from N3347 but the wording accepted into C2y was that from reflector
message 26758.

In GCC, the case of incomplete array types was a hard error with
-pedantic, rather than a pedwarn, contrary to how -pedantic is
supposed to behave; bug 26581 requested a change to allow this case
with -pedantic (i.e. the change made in C2y).  For incomplete structs
and unions, GCC only diagnoses them if the type remains incomplete at
the end of the translation unit; bug 88727 (*not* fixed here) requests
the case where the type gets completed should also be diagnosed as a
quality of implementation matter (and that bug is still applicable for
pre-C2y langauge versions and -Wc23-c2y-compat).

Change the handling of arrays following C2y; the previous error
becomes a pedwarn_c23 while there is a new error at the end of the
translation unit if the type remains incomplete there in C2y mode.

There is an ambiguity in the wording in C2y for the case where the
type gets completed only in an inner scope; I've raised that in
reflector message 34118.

Bootstrapped with no regressions for x86_64-pc-linux-gnu.

PR c/26581

gcc/c/
* c-decl.cc (c_finish_incomplete_decl): Give error for tentative
definition of incomplete array for C2y with internal linkage.
(finish_decl): Do not set DO_DEFAULT based on -pedantic.  Use
pedwarn_c23 for missing array sizes for internal linkage.

gcc/testsuite/
* gcc.dg/c23-incomplete-2.c, gcc.dg/c23-incomplete-3.c,
gcc.dg/c23-incomplete-4.c, gcc.dg/c2y-incomplete-4.c,
gcc.dg/c2y-incomplete-5.c: New tests.
* gcc.dg/c23-thread-local-2.c, gcc.dg/c2y-incomplete-1.c: Update
expected errors.

gcc/c/c-decl.cc
gcc/testsuite/gcc.dg/c23-incomplete-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c23-incomplete-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c23-incomplete-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c23-thread-local-2.c
gcc/testsuite/gcc.dg/c2y-incomplete-1.c
gcc/testsuite/gcc.dg/c2y-incomplete-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2y-incomplete-5.c [new file with mode: 0644]

index 632bbf057a33b5eb194f6b172fb988d6f9783f1a..d0dc5eeda39b0eb3a79903c123092794480d28bb 100644 (file)
@@ -908,8 +908,12 @@ c_finish_incomplete_decl (tree decl)
          && !DECL_EXTERNAL (decl)
          && TYPE_DOMAIN (type) == NULL_TREE)
        {
-         warning_at (DECL_SOURCE_LOCATION (decl),
-                     0, "array %q+D assumed to have one element", decl);
+         if (flag_isoc2y && !TREE_PUBLIC (decl))
+           error_at (DECL_SOURCE_LOCATION (decl),
+                     "array size missing in %q+D", decl);
+         else
+           warning_at (DECL_SOURCE_LOCATION (decl),
+                       0, "array %q+D assumed to have one element", decl);
 
          complete_array_type (&TREE_TYPE (decl), NULL_TREE, true);
 
@@ -5984,11 +5988,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
       && !(TREE_PUBLIC (decl) && current_scope != file_scope))
     {
       bool do_default
-       = (TREE_STATIC (decl)
-          /* Even if pedantic, an external linkage array
-             may have incomplete type at first.  */
-          ? pedantic && !TREE_PUBLIC (decl)
-          : !DECL_EXTERNAL (decl));
+       = !TREE_STATIC (decl) && !DECL_EXTERNAL (decl);
       int failure
        = complete_array_type (&TREE_TYPE (decl), DECL_INITIAL (decl),
                               do_default);
@@ -6005,6 +6005,9 @@ finish_decl (tree decl, location_t init_loc, tree init,
        case 2:
          if (do_default)
            error ("array size missing in %q+D", decl);
+         else if (!TREE_PUBLIC (decl))
+           pedwarn_c23 (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+                        "array size missing in %q+D", decl);
          break;
 
        case 3:
diff --git a/gcc/testsuite/gcc.dg/c23-incomplete-2.c b/gcc/testsuite/gcc.dg/c23-incomplete-2.c
new file mode 100644 (file)
index 0000000..3b435a1
--- /dev/null
@@ -0,0 +1,31 @@
+/* Test tentative definitions with incomplete type: OK in C2y with internal
+   linkage if completed by the end of the translation unit, but not allowed in
+   C23.  Note that incomplete structs and unions are not diagnosed for C23 when
+   completed by the end of the translation unit (bug 88727).  */
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic-errors" } */
+
+struct s1;
+struct s2;
+union u1;
+union u2;
+
+struct s1 v1;
+struct s2 v2; /* { dg-error "storage size" } */
+int v3[];
+int v4[]; /* { dg-warning "assumed to have one element" } */
+union u1 v5;
+union u2 v6; /* { dg-error "storage size" } */
+
+static struct s1 sv1;
+static struct s2 sv2; /* { dg-error "storage size" } */
+static int sv3[]; /* { dg-error "array size missing" } */
+static int sv4[]; /* { dg-error "array size missing" } */
+/* { dg-warning "assumed to have one element" "one element" { target *-*-* } .-1 } */
+static union u1 sv5;
+static union u2 sv6; /* { dg-error "storage size" } */
+
+struct s1 { int x; };
+union u1 { int y; };
+extern int v3[1];
+extern int sv3[1];
diff --git a/gcc/testsuite/gcc.dg/c23-incomplete-3.c b/gcc/testsuite/gcc.dg/c23-incomplete-3.c
new file mode 100644 (file)
index 0000000..ebb4cf9
--- /dev/null
@@ -0,0 +1,31 @@
+/* Test tentative definitions with incomplete type: OK in C2y with internal
+   linkage if completed by the end of the translation unit, but not allowed in
+   C23.  Note that incomplete structs and unions are not diagnosed for C23 when
+   completed by the end of the translation unit (bug 88727).  */
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic" } */
+
+struct s1;
+struct s2;
+union u1;
+union u2;
+
+struct s1 v1;
+struct s2 v2; /* { dg-error "storage size" } */
+int v3[];
+int v4[]; /* { dg-warning "assumed to have one element" } */
+union u1 v5;
+union u2 v6; /* { dg-error "storage size" } */
+
+static struct s1 sv1;
+static struct s2 sv2; /* { dg-error "storage size" } */
+static int sv3[]; /* { dg-warning "array size missing" } */
+static int sv4[]; /* { dg-warning "array size missing" } */
+/* { dg-warning "assumed to have one element" "one element" { target *-*-* } .-1 } */
+static union u1 sv5;
+static union u2 sv6; /* { dg-error "storage size" } */
+
+struct s1 { int x; };
+union u1 { int y; };
+extern int v3[1];
+extern int sv3[1];
diff --git a/gcc/testsuite/gcc.dg/c23-incomplete-4.c b/gcc/testsuite/gcc.dg/c23-incomplete-4.c
new file mode 100644 (file)
index 0000000..6a8b6cc
--- /dev/null
@@ -0,0 +1,30 @@
+/* Test tentative definitions with incomplete type: OK in C2y with internal
+   linkage if completed by the end of the translation unit, but not allowed in
+   C23.  Note that incomplete structs and unions are not diagnosed for C23 when
+   completed by the end of the translation unit (bug 88727).  */
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic-errors -Wno-c23-c2y-compat" } */
+
+struct s1;
+struct s2;
+union u1;
+union u2;
+
+struct s1 v1;
+struct s2 v2; /* { dg-error "storage size" } */
+int v3[];
+int v4[]; /* { dg-warning "assumed to have one element" } */
+union u1 v5;
+union u2 v6; /* { dg-error "storage size" } */
+
+static struct s1 sv1;
+static struct s2 sv2; /* { dg-error "storage size" } */
+static int sv3[];
+static int sv4[]; /* { dg-warning "assumed to have one element" } */
+static union u1 sv5;
+static union u2 sv6; /* { dg-error "storage size" } */
+
+struct s1 { int x; };
+union u1 { int y; };
+extern int v3[1];
+extern int sv3[1];
index 1d063f05e4245587561ff84498e8715f57789109..8fb34af5eeb70000e25da7243d014bdff5932d5b 100644 (file)
@@ -25,6 +25,7 @@ static thread_local int f; /* { dg-error "redefinition" } */
    rather than defaulting to size 1.  */
 thread_local int g[]; /* { dg-error "storage size" } */
 static thread_local int h[]; /* { dg-error "array size missing" } */
+/* { dg-error "storage size" "storage size" { target *-*-* } .-1 } */
 extern thread_local int i[];
 
 thread_local int j[] = { 0 };
index 2d7b1812ac2e4f9803ca020bce2d3da34baefd82..4c3133d934dfbf6d94fa5d6e76256df53dac77e6 100644 (file)
@@ -10,7 +10,7 @@ f ()
   struct s1 a; /* { dg-error "storage size" } */
   int b[]; /* { dg-error "array size missing" } */
   static struct s1 c; /* { dg-error "storage size" } */
-  static int d[]; /* { dg-error "array size missing" } */
+  static int d[]; /* { dg-error "storage size" } */
   struct s2;
   struct s2 e; /* { dg-error "storage size" } */
   static struct s2 g; /* { dg-error "storage size" } */
diff --git a/gcc/testsuite/gcc.dg/c2y-incomplete-4.c b/gcc/testsuite/gcc.dg/c2y-incomplete-4.c
new file mode 100644 (file)
index 0000000..a270896
--- /dev/null
@@ -0,0 +1,28 @@
+/* Test tentative definitions with incomplete type: OK in C2y with internal
+   linkage if completed by the end of the translation unit.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+struct s1;
+struct s2;
+union u1;
+union u2;
+
+struct s1 v1;
+struct s2 v2; /* { dg-error "storage size" } */
+int v3[];
+int v4[]; /* { dg-warning "assumed to have one element" } */
+union u1 v5;
+union u2 v6; /* { dg-error "storage size" } */
+
+static struct s1 sv1;
+static struct s2 sv2; /* { dg-error "storage size" } */
+static int sv3[];
+static int sv4[]; /* { dg-error "array size missing" } */
+static union u1 sv5;
+static union u2 sv6; /* { dg-error "storage size" } */
+
+struct s1 { int x; };
+union u1 { int y; };
+extern int v3[1];
+extern int sv3[1];
diff --git a/gcc/testsuite/gcc.dg/c2y-incomplete-5.c b/gcc/testsuite/gcc.dg/c2y-incomplete-5.c
new file mode 100644 (file)
index 0000000..4051cc0
--- /dev/null
@@ -0,0 +1,29 @@
+/* Test tentative definitions with incomplete type: OK in C2y with internal
+   linkage if completed by the end of the translation unit.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors -Wc23-c2y-compat" } */
+
+struct s1;
+struct s2;
+union u1;
+union u2;
+
+struct s1 v1;
+struct s2 v2; /* { dg-error "storage size" } */
+int v3[];
+int v4[]; /* { dg-warning "assumed to have one element" } */
+union u1 v5;
+union u2 v6; /* { dg-error "storage size" } */
+
+static struct s1 sv1;
+static struct s2 sv2; /* { dg-error "storage size" } */
+static int sv3[]; /* { dg-warning "array size missing" } */
+static int sv4[]; /* { dg-error "array size missing" } */
+/* { dg-warning "array size missing" "warning" { target *-*-* } .-1 } */
+static union u1 sv5;
+static union u2 sv6; /* { dg-error "storage size" } */
+
+struct s1 { int x; };
+union u1 { int y; };
+extern int v3[1];
+extern int sv3[1];