From 2f7e71cd24295df5112cf13ce9a48279cf9d0dc7 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Thu, 9 Sep 2021 18:39:19 -0500 Subject: [PATCH] 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. --- Expression.pas | 11 ++++++--- Parser.pas | 44 +++------------------------------ Symbol.pas | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ cc.notes | 2 ++ 4 files changed, 79 insertions(+), 44 deletions(-) diff --git a/Expression.pas b/Expression.pas index 4354b51..1bf1390 100644 --- a/Expression.pas +++ b/Expression.pas @@ -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; diff --git a/Parser.pas b/Parser.pas index 32f8620..01e34ba 100644 --- a/Parser.pas +++ b/Parser.pas @@ -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} diff --git a/Symbol.pas b/Symbol.pas index 811ad4f..5dd31b1 100644 --- a/Symbol.pas +++ b/Symbol.pas @@ -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}; diff --git a/cc.notes b/cc.notes index 86173eb..4b6f80a 100644 --- a/cc.notes +++ b/cc.notes @@ -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.