GCC does not remove qualifiers from array types when used with typeof_unqual: puts(_Generic( (typeof_unqual(const int[])*)0, int(*)[]:"non-const", const int(*)[]:"const" )); This should print non-const, but GCC prints const. The latest working draft of the standard includes an example of typeof_unqual with an array of const: > EXAMPLE 2 The following program: > const _Atomic int purr = 0; > const int meow = 1; > const char* const animals[] = { > "aardvark", > "bluejay", > "catte", > }; > typeof_unqual(meow) main (int argc, char* argv[]) { > typeof_unqual(purr) plain_purr; > typeof(_Atomic typeof(meow)) atomic_meow; > typeof(animals) animals_array; > typeof_unqual(animals) animals2_array; > return 0; > } > is equivalent to this program: > const _Atomic int purr = 0; > const int meow = 1; > const char* const animals[] = { > "aardvark", > "bluejay", > "catte", > }; > int main (int argc, char* argv[]) { > int plain_purr; > const _Atomic int atomic_meow; > const char* const animals_array[3]; > const char* animals2_array[3]; > return 0; > } Section 6.7.2.5 "Typeof specifiers" Paragraph 7, from N3096 Here, GCC does not not remove the const on the array type for animals2_array in the first part of the example.
Hmm, 6.7.3/10 "If the specification of an array type includes any type qualifiers, both the array and the element type are so-qualified." and the note 166 notes that this can happen with typedefs ... But then typeof_unqual only mentions the about the type qualifer of the array and not the element type but the example is showing it means the element type of the array should be unqualified too ... I am suspecting if we are pedantic about the language used, this would be a defect in the standard where the typeof_unqual does not mention the `element type` when it should as the example intends it as such. Note GCC does not try to remove qualifiers from the element type because of this quirk in the language of the standard dealing with array types ... Confirmed at least GCC is not following the example in the standard ...
Note clang also gets this "wrong". You can see that from: ``` const char* const animals[] = { "aardvark", "bluejay", "catte", }; int main (int argc, char* argv[]) { const char* animals2_array1[3]; typeof_unqual(animals) animals2_array; animals2_array1[0] = 0; animals2_array[0] = 0; return 0; } ```
The master branch has been updated by Joseph Myers <jsm28@gcc.gnu.org>: https://gcc.gnu.org/g:84a335eb4f9641a471184d86900609dd97215218 commit r15-5598-g84a335eb4f9641a471184d86900609dd97215218 Author: Joseph Myers <josmyers@redhat.com> Date: Fri Nov 22 20:33:10 2024 +0000 c: Fix typeof_unqual handling of qualified array types [PR112841] As reported in bug 112841, typeof_unqual fails to remove qualifiers from qualified array types. In C23 (unlike in previous standard versions), array types are considered to have the qualifiers of the element type, so typeof_unqual should remove such qualifiers (and an example in the standard shows that is as intended). Fix this by calling strip_array_types when checking for the presence of qualifiers. (The reason we check for qualifiers rather than just using TYPE_MAIN_VARIANT unconditionally is to avoid, as a quality of implementation matter, unnecessarily losing typedef information in the case where the type is already unqualified.) Bootstrapped with no regressions for x86_64-pc-linux-gnu. PR c/112841 gcc/c/ * c-parser.cc (c_parser_typeof_specifier): Call strip_array_types when checking for type qualifiers for typeof_unqual. gcc/testsuite/ * gcc.dg/c23-typeof-4.c: New test.
Fixed for GCC 15.
(In reply to Joseph S. Myers from comment #4) > Fixed for GCC 15. It seems like this patch also makes typeof_unqual(_Atomic int[2]) equivalent to int[2] which I believe is not correct, since _Atomic int[2] is not an atomic type (an array of atomics is not itself atomic). Should I make a separate bug report for this? For example the following should be invalid: typedef int x[2]; typedef typeof_unqual(_Atomic int[2])x; GCC accepts the above code with this patch, Clang rejects it.
Please file a new bug for this.
The master branch has been updated by Joseph Myers <jsm28@gcc.gnu.org>: https://gcc.gnu.org/g:eaa675ad3f0a033537440f93172a7b122c04cab5 commit r15-5725-geaa675ad3f0a033537440f93172a7b122c04cab5 Author: Joseph Myers <josmyers@redhat.com> Date: Wed Nov 27 14:10:37 2024 +0000 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.