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}
sName: stringPtr; {struct name; for forward refs}
constMember: boolean; {does it have a const member?}
flexibleArrayMember: boolean; {does it have a FAM?}
);
end;

View File

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

View File

@ -2847,8 +2847,10 @@ var
maxDisp := disp;
if variable^.itype^.size = 0 then
if (variable^.itype^.kind = arrayType)
and (disp > 0) then {handle flexible array member}
didFlexibleArray := true
and (disp > 0) then begin {handle flexible array member}
didFlexibleArray := true;
tp^.flexibleArrayMember := true;
end {if}
else
Error(117);
end {if}
@ -2868,10 +2870,16 @@ var
tPtr := tPtr^.aType;
end; {while}
if tqConst in tPtr^.qualifiers then
tp^.constMember := true
else if tPtr^.kind in [structType,unionType] then
tp^.constMember := true;
if tPtr^.kind in [structType,unionType] then begin
if tPtr^.constMember then
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}
begin
@ -3220,6 +3228,7 @@ while token.kind in allowedTokens do begin
{structTypePtr^.fieldList := nil;}
{structTypePtr^.sName := nil;}
{structTypePtr^.constMember := false;}
{structTypePtr^.flexibleArrayMember := false;}
structPtr := NewSymbol(ttoken.name, structTypePtr, ident,
tagSpace, defined);
structTypePtr^.sName := structPtr^.name;
@ -3253,6 +3262,7 @@ while token.kind in allowedTokens do begin
{structTypePtr^.fieldList := nil;}
{structTypePtr^.sName := nil;}
{structTypePtr^.constMember := false;}
{structTypePtr^.flexibleArrayMember := false;}
end; {if}
if structPtr <> nil then
structPtr^.itype := structTypePtr;
@ -3389,6 +3399,9 @@ var
Error(123);
goto 1;
end; {if}
if tp^.aType^.kind in [structType,unionType] then
if tp^.aType^.flexibleArrayMember then
Error(169);
end; {if}
firstVariable := false; {unspecified sizes are only allowed in }
{ 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';
167: msg := @'''L''-prefixed character or string constants are not supported by ORCA/C';
168: msg := @'malformed hexadecimal floating constant';
169: msg := @'struct or array may not contain a struct with a flexible array member';
otherwise: Error(57);
end; {case}
writeln(msg^);

View File

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