From 4020098dd6b3dd33f6b4f2c79cfef6abe2adf483 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sun, 21 Feb 2021 18:43:53 -0600 Subject: [PATCH] Evaluate constant expressions with long long and floating operands. Note that we currently defer evaluation of such expressions to run time if the long long value cannot be represented exactly in a double, because statically-evaluated floating point expressions use the double format rather than the extended (long double) format used at run time. --- Expression.pas | 37 +++++++++++++++++++++---------------- Scanner.pas | 1 - 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Expression.pas b/Expression.pas index 37d10b4..7a669e8 100644 --- a/Expression.pas +++ b/Expression.pas @@ -983,7 +983,7 @@ var end; {Pop} - function RealVal (token: tokenType): double; + function RealVal (token: tokenType): extended; { convert an operand to a real value } @@ -1004,6 +1004,10 @@ var else RealVal := token.lval; end {else if} + else if token.kind = longlongconst then + RealVal := CnvLLX(token.qval) + else if token.kind = ulonglongconst then + RealVal := CnvULLX(token.qval) else RealVal := token.rval; end; {RealVal} @@ -1434,14 +1438,24 @@ var end; {if} end; {if} - if op^.right^.token.kind in - [intconst,uintconst,longconst,ulongconst,doubleconst] then - if op^.left^.token.kind in - [intconst,uintconst,longconst,ulongconst,doubleconst] then + if op^.right^.token.kind in [intconst,uintconst,longconst,ulongconst, + longlongconst,ulonglongconst,doubleconst] then + if op^.left^.token.kind in [intconst,uintconst,longconst,ulongconst, + longlongconst,ulonglongconst,doubleconst] then begin ekind := doubleconst; {evaluate a constant operation} - rop1 := RealVal(op^.left^.token); - rop2 := RealVal(op^.right^.token); + extop1 := RealVal(op^.left^.token); + rop1 := extop1; + if op^.left^.token.kind in [longlongconst,ulonglongconst] then + if rop1 <> extop1 then + if not (op^.token.kind in [barbarop,andandop]) then + goto 1; + extop1 := RealVal(op^.right^.token); + rop2 := extop1; + if op^.right^.token.kind in [longlongconst,ulonglongconst] then + if rop2 <> extop1 then + if not (op^.token.kind in [barbarop,andandop]) then + goto 1; dispose(op^.right); op^.right := nil; dispose(op^.left); @@ -1496,16 +1510,7 @@ var op^.token.class := doubleConstant; op^.token.kind := doubleConst; end; {else} - goto 1; end; {if} - - if op^.right^.token.kind in [intconst,uintconst,longconst, - ulongconst,longlongconst,ulonglongconst,doubleconst] then - if op^.left^.token.kind in [intconst,uintconst,longconst, - ulongconst,longlongconst,ulonglongconst,doubleconst] then - if not (kind in [normalExpression,autoInitializerExpression]) - then - Error(157); 1: end; diff --git a/Scanner.pas b/Scanner.pas index a727a1b..872d921 100644 --- a/Scanner.pas +++ b/Scanner.pas @@ -692,7 +692,6 @@ if list or (numErr <> 0) then begin 154: msg := @'lint: function declared _Noreturn can return or has unreachable code'; 155: msg := @'lint: non-void function may not return a value or has unreachable code'; 156: msg := @'invalid suffix on numeric constant'; - 157: msg := @'ORCA/C cannot evaluate this constant expression with long long operand(s)'; otherwise: Error(57); end; {case} writeln(msg^);