Structs or arrays may not contain structs with a flexible array member.

We previously ignored this, but it is a constraint violation under the C standards, so it should be reported as an error.

GCC and Clang allow this as an extension, as we were effectively doing previously. We will follow the standards for now, but if there was demand for such an extension in ORCA/C, it could be re-introduced subject to a #pragma ignore flag.
This commit is contained in:
Stephen Heumann 2021-10-17 22:22:42 -05:00
parent ad5063a9a3
commit 692ebaba85
5 changed files with 24 additions and 5 deletions

View File

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

View File

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

View File

@ -2847,8 +2847,10 @@ var
maxDisp := disp; maxDisp := disp;
if variable^.itype^.size = 0 then if variable^.itype^.size = 0 then
if (variable^.itype^.kind = arrayType) if (variable^.itype^.kind = arrayType)
and (disp > 0) then {handle flexible array member} and (disp > 0) then begin {handle flexible array member}
didFlexibleArray := true didFlexibleArray := true;
tp^.flexibleArrayMember := true;
end {if}
else else
Error(117); Error(117);
end {if} end {if}
@ -2868,10 +2870,16 @@ var
tPtr := tPtr^.aType; tPtr := tPtr^.aType;
end; {while} end; {while}
if tqConst in tPtr^.qualifiers then if tqConst in tPtr^.qualifiers then
tp^.constMember := true tp^.constMember := true;
else if tPtr^.kind in [structType,unionType] then if tPtr^.kind in [structType,unionType] then begin
if tPtr^.constMember then if tPtr^.constMember then
tp^.constMember := true; tp^.constMember := true;
if tPtr^.flexibleArrayMember then
if kind = structType then
Error(169)
else {if kind = unionType then}
tp^.flexibleArrayMember := true;
end; {if}
if token.kind = commach then {allow repeated declarations} if token.kind = commach then {allow repeated declarations}
begin begin
@ -3220,6 +3228,7 @@ while token.kind in allowedTokens do begin
{structTypePtr^.fieldList := nil;} {structTypePtr^.fieldList := nil;}
{structTypePtr^.sName := nil;} {structTypePtr^.sName := nil;}
{structTypePtr^.constMember := false;} {structTypePtr^.constMember := false;}
{structTypePtr^.flexibleArrayMember := false;}
structPtr := NewSymbol(ttoken.name, structTypePtr, ident, structPtr := NewSymbol(ttoken.name, structTypePtr, ident,
tagSpace, defined); tagSpace, defined);
structTypePtr^.sName := structPtr^.name; structTypePtr^.sName := structPtr^.name;
@ -3253,6 +3262,7 @@ while token.kind in allowedTokens do begin
{structTypePtr^.fieldList := nil;} {structTypePtr^.fieldList := nil;}
{structTypePtr^.sName := nil;} {structTypePtr^.sName := nil;}
{structTypePtr^.constMember := false;} {structTypePtr^.constMember := false;}
{structTypePtr^.flexibleArrayMember := false;}
end; {if} end; {if}
if structPtr <> nil then if structPtr <> nil then
structPtr^.itype := structTypePtr; structPtr^.itype := structTypePtr;
@ -3389,6 +3399,9 @@ var
Error(123); Error(123);
goto 1; goto 1;
end; {if} end; {if}
if tp^.aType^.kind in [structType,unionType] then
if tp^.aType^.flexibleArrayMember then
Error(169);
end; {if} end; {if}
firstVariable := false; {unspecified sizes are only allowed in } firstVariable := false; {unspecified sizes are only allowed in }
{ the first subscript } { the first subscript }

View File

@ -740,6 +740,7 @@ if list or (numErr <> 0) then begin
166: msg := @'string literals with these prefixes may not be merged'; 166: msg := @'string literals with these prefixes may not be merged';
167: msg := @'''L''-prefixed character or string constants are not supported by ORCA/C'; 167: msg := @'''L''-prefixed character or string constants are not supported by ORCA/C';
168: msg := @'malformed hexadecimal floating constant'; 168: msg := @'malformed hexadecimal floating constant';
169: msg := @'struct or array may not contain a struct with a flexible array member';
otherwise: Error(57); otherwise: Error(57);
end; {case} end; {case}
writeln(msg^); writeln(msg^);

View File

@ -1612,6 +1612,8 @@ with defaultStruct^ do begin {(for structures with errors)}
qualifiers := []; qualifiers := [];
kind := structType; kind := structType;
sName := nil; sName := nil;
constMember := false;
flexibleArrayMember := false;
new(fieldList); new(fieldList);
with fieldlist^ do begin with fieldlist^ do begin
next := nil; next := nil;