]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c: Do not remove _Atomic from array element type for typeof_unqual [PR117781]
authorJoseph Myers <josmyers@redhat.com>
Wed, 27 Nov 2024 14:10:37 +0000 (14:10 +0000)
committerJoseph Myers <josmyers@redhat.com>
Wed, 27 Nov 2024 14:10:37 +0000 (14:10 +0000)
As reported in bug 117781, my fix for bug 112841 broke the case of
typeof_unqual applied to an array of _Atomic elements, which should
not have _Atomic removed since only the element type is atomic, not
the array type.  Fix with logic to ensure that atomic element types
are preserved as such, while other qualifiers (i.e. those that are
semantically rather than only syntactically such in C) are removed.

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

PR c/117781

gcc/c/
* c-parser.cc (c_parser_typeof_specifier): Do not remove _Atomic
from array element type for typeof_unqual.

gcc/testsuite/
* gcc.dg/c23-typeof-5.c: New test.

gcc/c/c-parser.cc
gcc/testsuite/gcc.dg/c23-typeof-5.c [new file with mode: 0644]

index 47668eceeded12cb910ad73b3a94ce6e54c18961..730f70bfdc66a0591e9a1d305a8684b509f1d50f 100644 (file)
@@ -4443,9 +4443,19 @@ c_parser_typeof_specifier (c_parser *parser)
   parens.skip_until_found_close (parser);
   if (ret.spec != error_mark_node)
     {
-      if (is_unqual
-         && TYPE_QUALS (strip_array_types (ret.spec)) != TYPE_UNQUALIFIED)
-       ret.spec = TYPE_MAIN_VARIANT (ret.spec);
+      if (is_unqual)
+       {
+         bool is_array = TREE_CODE (ret.spec) == ARRAY_TYPE;
+         int quals = TYPE_QUALS (strip_array_types (ret.spec));
+         if ((is_array ? quals & ~TYPE_QUAL_ATOMIC : quals)
+             != TYPE_UNQUALIFIED)
+           {
+             ret.spec = TYPE_MAIN_VARIANT (ret.spec);
+             if (quals & TYPE_QUAL_ATOMIC && is_array)
+               ret.spec = c_build_qualified_type (ret.spec,
+                                                  TYPE_QUAL_ATOMIC);
+           }
+       }
       if (is_std)
        {
          /* In ISO C terms, _Noreturn is not part of the type of
diff --git a/gcc/testsuite/gcc.dg/c23-typeof-5.c b/gcc/testsuite/gcc.dg/c23-typeof-5.c
new file mode 100644 (file)
index 0000000..e807698
--- /dev/null
@@ -0,0 +1,18 @@
+/* Test C23 typeof and typeof_unqual on arrays of atomic elements (bug
+   117781).  */
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic-errors" } */
+
+_Atomic int a[2], b[2][2];
+const _Atomic int c[2], d[2][2];
+
+extern typeof (a) a;
+extern typeof (b) b;
+extern typeof (c) c;
+extern typeof (d) d;
+extern typeof_unqual (a) a;
+extern typeof_unqual (b) b;
+extern typeof_unqual (c) a;
+extern typeof_unqual (d) b;
+extern typeof_unqual (volatile _Atomic int [2]) a;
+extern typeof_unqual (volatile _Atomic int [2][2]) b;