From ac741e26ab2797a0f0e7a3d9394d211b5ed39944 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Tue, 29 Nov 2022 13:19:59 -0600 Subject: [PATCH] Allow nested auto structs/unions to be initialized with an expression of the same type. When the expression is initially parsed, we do not necessarily know whether it is the initializer for the struct/union or for its first member. That needs to be determined based on the type. To support that, a new function is added to evaluate the expression separately from using it to initialize an object. --- Parser.pas | 50 ++++++++++++++++++++++++++++++++++++++++++++------ cc.notes | 2 ++ 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/Parser.pas b/Parser.pas index c3514e4..eb3ec91 100644 --- a/Parser.pas +++ b/Parser.pas @@ -1858,6 +1858,7 @@ var disp: longint; {disp within overall object being initialized} done: boolean; {for loop termination} errorFound: boolean; {used to remove bad initializations} + haveExpression: boolean; {has an expression been parsed but not used?} iPtr,jPtr,kPtr: initializerPtr; {for reversing the list} ip: identList; {used to place an id in the list} isStatic: boolean; {static storage duration (or automatic)?} @@ -1881,6 +1882,18 @@ var end; {InsertInitializerRecord} + procedure GetInitializerExpression; + + { get the expression for an initializer } + + begin {GetInitializerExpression} + if not isStatic then + Expression(autoInitializerExpression, [commach,rparench,rbracech]) + else + Expression(initializerExpression, [commach,rparench,rbracech]); + end; {GetInitializerExpression} + + procedure GetInitializerValue (tp: typePtr; bitsize,bitdisp: integer); { get the value of an initializer from a single expression } @@ -2011,10 +2024,12 @@ var begin {GetInitializerValue} - if not isStatic then - Expression(autoInitializerExpression, [commach,rparench,rbracech]) - else - Expression(initializerExpression, [commach,rparench,rbracech]); + if not haveExpression then + GetInitializerExpression + else begin + NextToken; + haveExpression := false; + end; {else} iPtr := pointer(Malloc(sizeof(initializerRecord))); if bitsize <> 0 then size := (bitdisp + bitsize + 7) div 8 @@ -2590,6 +2605,26 @@ var {handle structures and unions} else if kind in [structType, unionType] then begin + if not braces then + if not nestedDesignator then + if not isStatic then + if (token.kind in startExpression-[stringconst]) then begin + if not haveExpression then begin + GetInitializerExpression; + haveExpression := true; + PutBackToken(token, false, true); + token.kind := ident; {dummy expression-starting token} + token.class := identifier; + token.name := @'__'; + token.symbolPtr := nil; + while expressionType^.kind = definedType do + expressionType := expressionType^.dType; + end; {if} + if CompTypes(tp, expressionType) then begin + GetInitializerValue(tp, 0, 0); + goto 1; + end; {if} + end; {if} if braces or (not main) then begin ip := tp^.fieldList; maxDisp := disp; @@ -2695,8 +2730,10 @@ var end; {if} suppressMacroExpansions := lSuppressMacroExpansions; end {if} - else {struct/union assignment initializer} - GetInitializerValue(tp, bitsize, bitdisp); + else begin {struct/union assignment initializer} + Error(47); + errorFound := true; + end; {else} end {else if} {handle single-valued types} @@ -2727,6 +2764,7 @@ var begin {Initializer} disp := 0; {start at beginning of the object} errorFound := false; {no errors found so far} +haveExpression := false; {no expression parsed yet} {static or automatic initialization?} isStatic := variable^.storage in [external,global,private]; luseGlobalPool := useGlobalPool; {use global memory for global vars} diff --git a/cc.notes b/cc.notes index 4ec4255..44fc397 100644 --- a/cc.notes +++ b/cc.notes @@ -1976,6 +1976,8 @@ int foo(int[42]); 220. In certain cases where a header starts or ends in the middle of a declaration, it would not be represented correctly in the .sym file. This could cause errors or misbehavior on subsequent compiles. +221. Structures with unnamed bit-fields were sometimes initialized incorrectly. + -- Bugs from C 2.1.0 that have been fixed ----------------------------------- 1. In some situations, fread() reread the first 1K or so of the file.