Give an error if assigning to a whole struct or union that has a const member.

Such structs or unions are not modifiable lvalues, so they cannot be assigned to as a whole. Any non-const fields can be assigned to individually.
This commit is contained in:
Stephen Heumann 2021-09-11 18:12:58 -05:00
parent 7848e50218
commit 894baac94f
4 changed files with 33 additions and 6 deletions

View File

@ -305,6 +305,7 @@ type
structType,
unionType : (fieldList: identPtr; {field list}
sName: stringPtr; {struct name; for forward refs}
constMember: boolean; {does it have a const member?}
);
end;

View File

@ -575,11 +575,14 @@ var
begin {AssignmentConversion}
kind1 := t1^.kind;
kind2 := t2^.kind;
if tqConst in t1^.qualifiers then
if genCode then
if checkConst then
if kind2 <> definedType then
Error(93);
if genCode then
if checkConst then
if kind2 <> definedType then
if tqConst in t1^.qualifiers then
Error(93)
else if kind1 in [structType,unionType] then
if t1^.constMember then
Error(93);
if kind2 = definedType then
AssignmentConversion(t1, t2^.dType, false, 0, genCode, checkConst)
else if kind1 = definedType then

View File

@ -18,7 +18,7 @@ uses CCommon, MM, Scanner, Symbol, CGI;
{$segment 'SCANNER'}
const
symFileVersion = 15; {version number of .sym file format}
symFileVersion = 16; {version number of .sym file format}
var
inhibitHeader: boolean; {should .sym includes be blocked?}
@ -1057,6 +1057,7 @@ procedure EndInclude {chPtr: ptr};
ip := ip^.next;
end; {while}
WriteByte(0);
WriteByte(ord(tp^.constMember));
end;
otherwise: ;
@ -1692,6 +1693,7 @@ var
ep^.next := ip;
ep := ip;
end; {while}
tp^.constMember := boolean(ReadByte);
end;
enumType: ;

View File

@ -2819,6 +2819,25 @@ var
end {if}
else
Error(116);
if variable <> nil then {check for a const member}
tPtr := variable^.itype
else
tPtr := typeSpec;
while tPtr^.kind in [definedType,arrayType] do begin
if tqConst in tPtr^.qualifiers then
tp^.constMember := true;
if tPtr^.kind = definedType then
tPtr := tPtr^.dType
else {if tPtr^.kind = arrayType then}
tPtr := tPtr^.aType;
end; {while}
if tqConst in tPtr^.qualifiers then
tp^.constMember := true
else if tPtr^.kind in [structType,unionType] then
if tPtr^.constMember then
tp^.constMember := true;
if token.kind = commach then {allow repeated declarations}
begin
NextToken;
@ -3165,6 +3184,7 @@ while token.kind in allowedTokens do begin
structTypePtr^.kind := tkind;
{structTypePtr^.fieldList := nil;}
{structTypePtr^.sName := nil;}
{structTypePtr^.constMember := false;}
structPtr := NewSymbol(ttoken.name, structTypePtr, ident,
tagSpace, defined);
structTypePtr^.sName := structPtr^.name;
@ -3197,6 +3217,7 @@ while token.kind in allowedTokens do begin
structTypePtr^.kind := tkind;
{structTypePtr^.fieldList := nil;}
{structTypePtr^.sName := nil;}
{structTypePtr^.constMember := false;}
end; {if}
if structPtr <> nil then
structPtr^.itype := structTypePtr;