Treat the fields of const structs as const-qualified.

This causes an error to be produced when trying to assign to these fields, which was being allowed before. It is also necessary for correct behavior of _Generic in some cases.
This commit is contained in:
Stephen Heumann 2021-09-09 18:39:19 -05:00
parent 99f5e2fc87
commit 2f7e71cd24
4 changed files with 79 additions and 44 deletions

View File

@ -578,7 +578,8 @@ kind2 := t2^.kind;
if tqConst in t1^.qualifiers then
if genCode then
if checkConst then
Error(93);
if kind2 <> definedType then
Error(93);
if kind2 = definedType then
AssignmentConversion(t1, t2^.dType, false, 0, genCode, checkConst)
else if kind1 = definedType then
@ -2527,13 +2528,17 @@ label 1;
var
ip: identPtr; {for scanning for the field}
qualifiers: typeQualifierSet; {type qualifiers}
begin {DoSelection}
expressionType := intPtr; {set defaults in case there is an error}
size := 0;
if tree^.token.class = identifier then begin
while lType^.kind = definedType do
qualifiers := lType^.qualifiers;
while lType^.kind = definedType do begin
lType := lType^.dType;
qualifiers := qualifiers + lType^.qualifiers;
end; {while}
if lType^.kind in [structType,unionType] then begin
ip := lType^.fieldList; {find a matching field}
while ip <> nil do begin
@ -2541,7 +2546,7 @@ if tree^.token.class = identifier then begin
if ip^.isForwardDeclared then
ResolveForwardReference(ip);
size := ip^.disp; {match found - record parameters}
expressionType := ip^.itype;
expressionType := MakeQualifiedType(ip^.itype, qualifiers);
bitDisp := ip^.bitDisp;
bitSize := ip^.bitSize;
isBitField := (bitSize+bitDisp) <> 0;

View File

@ -3257,51 +3257,13 @@ while token.kind in allowedTokens do begin
3:
isForwardDeclared := myIsForwardDeclared;
skipDeclarator := mySkipDeclarator;
typeSpec := myTypeSpec;
declarationModifiers := myDeclarationModifiers;
if typeSpec = nil then begin
typeSpec := intPtr; {under C89, default type is int}
if myTypeSpec = nil then begin
myTypeSpec := intPtr; {under C89, default type is int}
if (lint & lintC99Syntax) <> 0 then
Error(151);
end; {if}
if typeQualifiers <> [] then begin {handle a qualified type}
new(tPtr);
if typeSpec^.kind in [structType,unionType] then begin
with tPtr^ do begin
size := typeSpec^.size;
kind := definedType;
dType := typeSpec;
saveDisp := 0;
qualifiers := typeQualifiers;
end; {with}
end {if}
else begin
tPtr^ := typeSpec^;
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}
typeSpec := MakeQualifiedType(myTypeSpec, typeQualifiers); {apply type qualifiers}
end; {DeclarationSpecifiers}

View File

@ -158,6 +158,18 @@ function LabelToDisp (lab: integer): integer; extern;
{ lab - label number }
function MakeQualifiedType (origType: typePtr; qualifiers: typeQualifierSet):
typePtr;
{ make a qualified version of a type }
{ }
{ parameters: }
{ origType - the original type }
{ qualifiers - the type qualifier(s) to add }
{ }
{ returns: pointer to the qualified type }
function NewSymbol (name: stringPtr; itype: typePtr; class: tokenEnum;
space: spaceType; state: stateKind): identPtr;
@ -1575,6 +1587,60 @@ constCharPtr^.qualifiers := [tqConst];
end; {InitSymbol}
function MakeQualifiedType {origType: typePtr; qualifiers: typeQualifierSet):
typePtr};
{ make a qualified version of a type }
{ }
{ parameters: }
{ origType - the original type }
{ qualifiers - the type qualifier(s) to add }
{ }
{ returns: pointer to the qualified type }
var
tp: typePtr; {the qualified type}
elemType: typePtr; {array element type}
begin {MakeQualifiedType}
if qualifiers <> [] then begin {make qualified version of type}
tp := pointer(Malloc(sizeof(typeRecord)));
if origType^.kind in [structType,unionType] then begin
tp^.size := origType^.size;
tp^.kind := definedType;
tp^.dType := origType;
tp^.saveDisp := 0;
tp^.qualifiers := qualifiers;
end {if}
else begin
tp^ := origType^;
tp^.qualifiers := tp^.qualifiers + qualifiers;
end; {else}
MakeQualifiedType := tp;
{move array type quals to element type}
while tp^.kind = arrayType do begin
elemType := pointer(Malloc(sizeof(typeRecord)));
if tp^.aType^.kind in [structType,unionType] then begin
elemType^.size := tp^.aType^.size;
elemType^.kind := definedType;
elemType^.dType := tp^.aType;
elemType^.saveDisp := 0;
elemType^.qualifiers := qualifiers;
end {if}
else begin
elemType^ := tp^.aType^;
elemType^.qualifiers := elemType^.qualifiers + qualifiers;
end; {else}
tp^.aType := elemType;
tp^.qualifiers := []; {remove for C23}
tp := elemType;
end; {if}
end {if}
else
MakeQualifiedType := origType;
end; {MakeQualifiedType}
function NewSymbol {name: stringPtr; itype: typePtr; class: tokenEnum;
space: spaceType; state: stateKind): identPtr};

View File

@ -1219,6 +1219,8 @@ int foo(int[42]);
(Devin Reade)
164. The fields of const-qualified structs and unions were not treated as being const-qualified. Neither were the members of arrays declared like "const T a", where T is a typedef'd array type. Now such fields and array members are treated as const-qualified, so assignments to them will give errors.
-- Bugs from C 2.1.0 that have been fixed -----------------------------------
1. In some situations, fread() reread the first 1K or so of the file.