From 692ebaba85c4d76a28534e4004b369cc156548a3 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sun, 17 Oct 2021 22:22:42 -0500 Subject: [PATCH] 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. --- CCommon.pas | 1 + Header.pas | 4 +++- Parser.pas | 21 +++++++++++++++++---- Scanner.pas | 1 + Symbol.pas | 2 ++ 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/CCommon.pas b/CCommon.pas index 7666d35..07aed11 100644 --- a/CCommon.pas +++ b/CCommon.pas @@ -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; diff --git a/Header.pas b/Header.pas index d93d0b4..38637c7 100644 --- a/Header.pas +++ b/Header.pas @@ -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: ; diff --git a/Parser.pas b/Parser.pas index dc40054..0377ed3 100644 --- a/Parser.pas +++ b/Parser.pas @@ -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 } diff --git a/Scanner.pas b/Scanner.pas index 8a0573a..d59c02a 100644 --- a/Scanner.pas +++ b/Scanner.pas @@ -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^); diff --git a/Symbol.pas b/Symbol.pas index 228905b..7578a64 100644 --- a/Symbol.pas +++ b/Symbol.pas @@ -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;