aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJoseph Myers <josmyers@redhat.com>2024-11-27 14:10:37 +0000
committerJoseph Myers <josmyers@redhat.com>2024-11-27 14:10:37 +0000
commiteaa675ad3f0a033537440f93172a7b122c04cab5 (patch)
treec29ead4aff69f9a094da660127530e5a48bce0e4 /gcc
parent96ccb208e43a7cb7a1b15e28c94d57661bf9caae (diff)
downloadgcc-eaa675ad3f0a033537440f93172a7b122c04cab5.zip
gcc-eaa675ad3f0a033537440f93172a7b122c04cab5.tar.gz
gcc-eaa675ad3f0a033537440f93172a7b122c04cab5.tar.bz2
c: Do not remove _Atomic from array element type for typeof_unqual [PR117781]
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c/c-parser.cc16
-rw-r--r--gcc/testsuite/gcc.dg/c23-typeof-5.c18
2 files changed, 31 insertions, 3 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 47668ec..730f70b 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -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
index 0000000..e807698
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-typeof-5.c
@@ -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;