Initial support for compound literals.

Compound literals outside of functions should work at this point.

Compound literals inside of functions are not fully implemented, so they are disabled for now. (There is some code to support them, but the code to actually initialize them at the appropriate time is not written yet.)
This commit is contained in:
Stephen Heumann 2021-09-15 22:22:16 -05:00
parent 3c3697535e
commit 7ae830ae7e
4 changed files with 117 additions and 5 deletions

View File

@ -360,7 +360,8 @@ type
isForwardDeclared: boolean; {does this var use a forward declared type?}
class: tokenEnum; {storage class}
case storage: storageType of
stackFrame: (lln: integer); {local label #}
stackFrame: (lln: integer; {local label #}
clnext: identPtr); {next compound literal}
parameter: (pln: integer; {paramater label #}
pdisp: integer; {disp of parameter}
pnext: identPtr); {next parameter}

View File

@ -268,6 +268,14 @@ function MakeFuncIdentifier: identPtr; extern;
{ }
{ This must only be called within a function body. }
function MakeCompoundLiteral(tp: typePtr): identPtr; extern;
{ Make the identifier for a compound literal. }
{ }
{ parameters: }
{ tp - the type of the compound literal }
{-- External unsigned math routines ----------------------------}
function lshr (x,y: longint): longint; extern;
@ -2001,6 +2009,49 @@ var
end; {DoGeneric}
procedure DoCompoundLiteral;
{ process a compound literal expression }
label 1;
var
id: identPtr;
sp: tokenPtr;
begin {DoCompoundLiteral}
if kind in [preprocessorExpression,arrayExpression] then begin
op := opStack;
while op <> nil do begin
if op^.token.kind = sizeofsy then
goto 1;
op := op^.next;
end; {while}
Error(41);
errorFound := true;
end; {if}
1:
id := MakeCompoundLiteral(opStack^.castType);
opStack := opStack^.next;
{create an operand on the stack}
new(sp);
sp^.token.kind := ident;
sp^.token.class := identifier;
sp^.token.symbolPtr := id;
sp^.token.name := id^.name;
sp^.id := id;
sp^.next := stack;
sp^.left := nil;
sp^.middle := nil;
sp^.right := nil;
stack := sp;
ComplexTerm;
expectingTerm := false;
end; {DoCompoundLiteral}
begin {ExpressionTree}
opStack := nil;
stack := nil;
@ -2147,6 +2198,10 @@ if token.kind in startExpression then begin
parenCount := parenCount+1;
end;
end {else if}
else if (token.kind = lbracech) {handle a compound literal}
and (opstack <> nil) and (opStack^.token.kind = castoper) then begin
DoCompoundLiteral
end {else if}
else if token.kind = _Genericsy then {handle _Generic}
DoGeneric
else begin {handle an operation...}

View File

@ -69,6 +69,14 @@ function MakeFuncIdentifier: identPtr;
{ This must only be called within a function body. }
function MakeCompoundLiteral(tp: typePtr): identPtr;
{ Make the identifier for a compound literal. }
{ }
{ parameters: }
{ tp - the type of the compound literal }
procedure InitParser;
{ Initialize the parser }
@ -176,6 +184,8 @@ var
statementList: statementPtr; {list of open statements}
savedVolatile: boolean; {saved copy of volatile}
doingForLoopClause1: boolean; {doing the first clause of a for loop?}
compoundLiteralNumber: integer; {number of compound literal}
compoundLiteralToAllocate: identPtr; {compound literal that needs space allocated}
{parameter processing variables}
{------------------------------}
@ -325,6 +335,11 @@ var
stPtr: statementPtr; {work pointer}
begin {EndCompoundStatement}
while compoundLiteralToAllocate <> nil do begin {allocate compound literals}
Gen2(dc_loc, compoundLiteralToAllocate^.lln,
long(compoundLiteralToAllocate^.itype^.size).lsw);
compoundLiteralToAllocate := compoundLiteralToAllocate^.clnext;
end {while};
dumpLocal := false;
stPtr := statementList; {pop the statement record}
statementList := stPtr^.next;
@ -4093,7 +4108,7 @@ begin {TypeName}
DeclarationSpecifiers(specifierQualifierListElement, rparench);
{_Alignas is not allowed in most uses of type names. }
{It would be allowed in compound literals, if we supported them.}
{TODO: _Alignas should be allowed in compound literals. }
if _Alignassy in declarationModifiers then
Error(142);
@ -4534,6 +4549,44 @@ MakeFuncIdentifier := id;
end; {MakeFuncIdentifier}
function MakeCompoundLiteral{tp: typePtr): identPtr};
{ Make the identifier for a compound literal. }
{ }
{ parameters: }
{ tp - the type of the compound literal }
type
nameString = packed array [0..24] of char;
var
id: identPtr; {the identifier for the literal}
name: ^nameString; {the name for the identifier}
class: tokenEnum; {storage class}
begin {MakeCompoundLiteral}
if functionTable <> nil then begin
Error(164);
class := autosy
end {if}
else
class := staticsy;
name := pointer(Malloc(25));
name^ := concat('~CompoundLiteral', cnvis(compoundLiteralNumber));
id := NewSymbol(name, tp, class, variableSpace, defined);
Initializer(id);
MakeCompoundLiteral := id;
compoundLiteralNumber := compoundLiteralNumber + 1;
if compoundLiteralNumber = 0 then
Error(57);
if class = autosy then begin
id^.lln := GetLocalLabel;
id^.clnext := compoundLiteralToAllocate;
compoundLiteralToAllocate := id;
end;
end; {MakeFuncIdentifier}
procedure InitParser;
{ Initialize the parser }
@ -4554,6 +4607,8 @@ statementList := nil; {no open statements}
codegenStarted := false; {code generator is not started}
doingForLoopClause1 := false; {not doing a for loop}
fIsNoreturn := false; {not doing a noreturn function}
compoundLiteralNumber := 1; {no compound literals yet}
compoundLiteralToAllocate := nil; {no compound literals needing space yet}
{init syntactic classes of tokens}
{See C17 section 6.7 ff.}

View File

@ -720,6 +720,7 @@ if list or (numErr <> 0) then begin
161: msg := @'illegal operator in a constant expression';
162: msg := @'invalid escape sequence';
163: msg := @'pointer assignment discards qualifier(s)';
164: msg := @'compound literals within functions are not supported by ORCA/C';
otherwise: Error(57);
end; {case}
writeln(msg^);