Permit unions to be initialized by assignment from expressions of the appropriate union type.

This patch should also permit the union initialization code to handle unions containing bit fields, but for the time being they are still prohibited by code elsewhere in the compiler.
This commit is contained in:
Stephen Heumann
2016-10-14 18:30:13 -05:00
parent 5e7d9e8278
commit 05a0ce738a
2 changed files with 17 additions and 25 deletions

View File

@@ -286,7 +286,7 @@ type
count: integer; {# of duplicate records} count: integer; {# of duplicate records}
bitdisp: integer; {disp in byte (field lists only)} bitdisp: integer; {disp in byte (field lists only)}
bitsize: integer; {width in bits; 0 for byte sizes} bitsize: integer; {width in bits; 0 for byte sizes}
isStruct: boolean; {is this a struct initializer?} isStructOrUnion: boolean; {is this a struct or union initializer?}
case isConstant: boolean of {is this a constant initializer?} case isConstant: boolean of {is this a constant initializer?}
false: (iTree: tokenPtr); false: (iTree: tokenPtr);
true : ( true : (

View File

@@ -1683,7 +1683,7 @@ var
iPtr^.count := 1; iPtr^.count := 1;
iPtr^.bitdisp := 0; iPtr^.bitdisp := 0;
iPtr^.bitsize := 0; iPtr^.bitsize := 0;
iPtr^.isStruct := false; iPtr^.isStructOrUnion := false;
iPtr^.iVal := bitvalue; iPtr^.iVal := bitvalue;
if bitcount > 16 then if bitcount > 16 then
iPtr^.itype := cgULong iPtr^.itype := cgULong
@@ -1819,7 +1819,7 @@ var
iPtr^.count := 1; iPtr^.count := 1;
iPtr^.bitdisp := 0; iPtr^.bitdisp := 0;
iPtr^.bitsize := 0; iPtr^.bitsize := 0;
iPtr^.isStruct := false; iPtr^.isStructOrUnion := false;
end; {if} end; {if}
etype := expressionType; etype := expressionType;
AssignmentConversion(tp, expressionType, isConstant, expressionValue, AssignmentConversion(tp, expressionType, isConstant, expressionValue,
@@ -1912,7 +1912,7 @@ var
errorFound := true; errorFound := true;
end; {else} end; {else}
structType,enumType: begin structType,unionType,enumType: begin
Error(46); Error(46);
errorFound := true; errorFound := true;
end; end;
@@ -2047,8 +2047,8 @@ var
goto 1; goto 1;
end; {if} end; {if}
end {if} end {if}
else if tp^.kind = structType then else if tp^.kind in [structType,unionType] then
iPtr^.isStruct := true; iPtr^.isStructOrUnion := true;
{handle auto variables} {handle auto variables}
if bitsize <> 0 then begin if bitsize <> 0 then begin
@@ -2059,7 +2059,7 @@ var
iPtr^.count := 1; iPtr^.count := 1;
iPtr^.bitdisp := bitdisp; iPtr^.bitdisp := bitdisp;
iPtr^.bitsize := bitsize; iPtr^.bitsize := bitsize;
iPtr^.isStruct := false; iPtr^.isStructOrUnion := false;
end; {if} end; {if}
if variable^.storage in [external,global,private] then begin if variable^.storage in [external,global,private] then begin
Error(41); Error(41);
@@ -2144,7 +2144,7 @@ var
iPtr^.isConstant := variable^.storage in [external,global,private]; iPtr^.isConstant := variable^.storage in [external,global,private];
{iPtr^.bitdisp := 0;} {iPtr^.bitdisp := 0;}
{iPtr^.bitsize := 0;} {iPtr^.bitsize := 0;}
{iPtr^.isStruct := false;} {iPtr^.isStructOrUnion := false;}
if iPtr^.isConstant then begin if iPtr^.isConstant then begin
if tp^.kind = scalarType then if tp^.kind = scalarType then
iPtr^.itype := tp^.baseType iPtr^.itype := tp^.baseType
@@ -2231,7 +2231,7 @@ var
iPtr^.count := 1; iPtr^.count := 1;
iPtr^.bitdisp := 0; iPtr^.bitdisp := 0;
iPtr^.bitsize := 0; iPtr^.bitsize := 0;
iPtr^.isStruct := false; iPtr^.isStructOrUnion := false;
if (variable^.storage in [external,global,private]) then begin if (variable^.storage in [external,global,private]) then begin
iPtr^.isConstant := true; iPtr^.isConstant := true;
iPtr^.itype := cgString; iPtr^.itype := cgString;
@@ -2292,8 +2292,8 @@ var
end; {else} end; {else}
end {if} end {if}
{handle structures} {handle structures and unions}
else if kind = structType then begin else if kind in [structType, unionType] then begin
if braces or (not main) then begin if braces or (not main) then begin
count := tp^.size; count := tp^.size;
ip := tp^.fieldList; ip := tp^.fieldList;
@@ -2318,7 +2318,10 @@ var
count := count-ip^.itype^.size; count := count-ip^.itype^.size;
end; {else} end; {else}
{ writeln('Initializer: ', ip^.bitsize:10, ip^.bitdisp:10, bitCount:10); {debug} { writeln('Initializer: ', ip^.bitsize:10, ip^.bitdisp:10, bitCount:10); {debug}
ip := ip^.next; if kind = unionType then
ip := nil
else
ip := ip^.next;
if token.kind = commach then begin if token.kind = commach then begin
if ip <> nil then if ip <> nil then
NextToken; NextToken;
@@ -2335,21 +2338,10 @@ var
if count > 0 then if count > 0 then
Fill(count, bytePtr); Fill(count, bytePtr);
end {if} end {if}
else {struct assignment initializer} else {struct/union assignment initializer}
GetInitializerValue(tp, bitsize, bitdisp); GetInitializerValue(tp, bitsize, bitdisp);
end {else if} end {else if}
{handle unions}
else if kind = unionType then begin
ip := tp^.fieldList;
if ip^.isForwardDeclared then
ResolveForwardReference(ip);
InitializeTerm(ip^.itype, 0, 0, false);
count := tp^.size - ip^.itype^.size;
if count > 0 then
Fill(count, bytePtr);
end {else if}
{handle single-valued types} {handle single-valued types}
else if kind in [scalarType,pointerType,enumType] then else if kind in [scalarType,pointerType,enumType] then
GetInitializerValue(tp, bitsize, bitdisp) GetInitializerValue(tp, bitsize, bitdisp)
@@ -3757,7 +3749,7 @@ procedure DoStatement;
1: end; 1: end;
structType,unionType: begin structType,unionType: begin
if iPtr^.isStruct then begin if iPtr^.isStructOrUnion then begin
LoadAddress; {load the destination address} LoadAddress; {load the destination address}
GenerateCode(iptr^.iTree); {load the stuct address} GenerateCode(iptr^.iTree); {load the stuct address}
{do the assignment} {do the assignment}