diff --git a/CCommon.pas b/CCommon.pas index bff3a37..327f890 100644 --- a/CCommon.pas +++ b/CCommon.pas @@ -360,10 +360,11 @@ type isForwardDeclared: boolean; {does this var use a forward declared type?} class: tokenEnum; {storage class} case storage: storageType of - stackFrame: (lln: integer); {local label #} - parameter: (pln: integer; {paramater label #} - pdisp: integer; {disp of parameter} - pnext: identPtr); {next parameter} + stackFrame: (lln: integer; {local label #} + clnext: identPtr); {next compound literal} + parameter: (pln: integer; {paramater label #} + pdisp: integer; {disp of parameter} + pnext: identPtr); {next parameter} external: (); global,private: (); none: (); diff --git a/Expression.pas b/Expression.pas index 8165d05..99dee3b 100644 --- a/Expression.pas +++ b/Expression.pas @@ -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...} diff --git a/Parser.pas b/Parser.pas index 89fd450..d7a8b27 100644 --- a/Parser.pas +++ b/Parser.pas @@ -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.} diff --git a/Scanner.pas b/Scanner.pas index b874d05..b9d957d 100644 --- a/Scanner.pas +++ b/Scanner.pas @@ -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^);