Move type qualifiers from array types to their element types.

This behavior is specified by the C standards. It can come up when declaring an array using a typedef'd array type and a qualifier.

This is necessary for correct behavior of _Generic, as well as to give an error if code tries to write to const arrays declared in this way.

Here is an example showing these issues:

#define f(e) _Generic((e), int *: 1, const int *:2, default: 0)
int main(void) {
        typedef int A[2][3];
        const A a = {{4, 5, 6}, {7, 8, 9}};
        _Static_assert(f(&a[0][0]) == 2, "qualifier error"); // OK
        a[1][1] = 42; // error
}
This commit is contained in:
Stephen Heumann 2021-08-30 18:30:05 -05:00
parent b16210a50b
commit 00cc05a6a1

View File

@ -3280,6 +3280,27 @@ if typeQualifiers <> [] then begin {handle a qualified type}
tPtr^.qualifiers := tPtr^.qualifiers + typeQualifiers;
end; {else}
typeSpec := tPtr;
{move array type quals to element type}
myTypeSpec := typeSpec;
while myTypeSpec^.kind = arrayType do begin
new(tPtr);
if myTypeSpec^.aType^.kind in [structType,unionType] then begin
with tPtr^ do begin
size := myTypeSpec^.aType^.size;
kind := definedType;
dType := myTypeSpec^.aType;
saveDisp := 0;
qualifiers := typeQualifiers;
end; {with}
end {if}
else begin
tPtr^ := myTypeSpec^.aType^;
tPtr^.qualifiers := tPtr^.qualifiers + typeQualifiers;
end; {else}
myTypeSpec^.aType := tPtr;
myTypeSpec^.qualifiers := []; {remove for C23}
myTypeSpec := tPtr;
end; {if}
end; {if}
end; {DeclarationSpecifiers}