Bug 112841 - typeof_unqual is not removing qualifiers from the element type of array types
Summary: typeof_unqual is not removing qualifiers from the element type of array types
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 14.0
: P3 normal
Target Milestone: 15.0
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2023-12-04 05:16 UTC by Halalaluyafail3
Modified: 2024-11-27 14:11 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work: 15.0
Known to fail:
Last reconfirmed: 2023-12-04 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Halalaluyafail3 2023-12-04 05:16:28 UTC
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.
Comment 1 Andrew Pinski 2023-12-04 06:43:58 UTC
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 ...
Comment 2 Andrew Pinski 2023-12-04 06:51:27 UTC
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;
}
```
Comment 3 GCC Commits 2024-11-22 20:33:58 UTC
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.
Comment 4 Joseph S. Myers 2024-11-22 20:35:53 UTC
Fixed for GCC 15.
Comment 5 Halalaluyafail3 2024-11-24 06:25:09 UTC
(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.
Comment 6 Joseph S. Myers 2024-11-25 18:45:59 UTC
Please file a new bug for this.
Comment 7 GCC Commits 2024-11-27 14:11:19 UTC
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.