From 736e7575cff86e5b3b9aa267f4dc12eccef5a709 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sun, 4 Dec 2022 16:36:16 -0600 Subject: [PATCH] Fix issues with type conversions in static initialization. *Initialization of floating-point variables from unsigned long expressions with value > LONG_MAX would give the wrong value. *Initialization of floating-point variables from (unsigned) long long expressions would give the wrong value. *Initialization of _Bool variables should give 0 or 1, as per the usual rules for conversion to _Bool. *Initialization of integer variables from floating-point expressions should be allowed, applying the usual conversions. --- Parser.pas | 36 +++++++++++++++++++++++++++++++++--- Tests/Conformance/c99bool.c | 10 ++++++++++ cc.notes | 4 ++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/Parser.pas b/Parser.pas index 7d344c8..4e7e388 100644 --- a/Parser.pas +++ b/Parser.pas @@ -220,6 +220,16 @@ function slt64(a,b: longlong): boolean; extern; function sgt64(a,b: longlong): boolean; extern; +{-- External conversion functions; imported from CGC.pas -------} + +procedure CnvXLL (var result: longlong; val: extended); extern; + +procedure CnvXULL (var result: longlong; val: extended); extern; + +function CnvLLX (val: longlong): extended; extern; + +function CnvULLX (val: longlong): extended; extern; + {-- Parser Utility Procedures ----------------------------------} procedure Match {kind: tokenEnum; err: integer}; @@ -2073,16 +2083,36 @@ var iPtr^.qVal.hi := -1 else iPtr^.qVal.hi := 0; + if tp^.cType = ctBool then + iPtr^.iVal := ord(expressionValue <> 0); goto 2; end; {if} if bKind in [cgReal,cgDouble,cgComp,cgExtended] then begin - if etype^.baseType in [cgByte..cgULong] then - iPtr^.rVal := expressionValue + if etype^.baseType in [cgByte..cgULong] then begin + iPtr^.rVal := expressionValue; + if etype^.baseType = cgULong then + if expressionValue < 0 then + iPtr^.rVal := iPtr^.rVal + 4294967296.0; + end {if} else if etype^.baseType in [cgReal,cgDouble,cgComp,cgExtended] then - iPtr^.rval := realExpressionValue; + iPtr^.rval := realExpressionValue + else if eType^.baseType = cgQuad then + iPtr^.rVal := CnvLLX(llExpressionValue) + else if eType^.baseType = cgUQuad then + iPtr^.rVal := CnvULLX(llExpressionValue); goto 2; end; {if} + if (etype^.baseType in [cgReal,cgDouble,cgComp,cgExtended]) + and (bKind in [cgByte..cgULong,cgQuad,cgUQuad]) then begin + if tp^.cType = ctBool then + iPtr^.iVal := ord(realExpressionValue <> 0) + else if bKind = cgUQuad then + CnvXULL(iPtr^.qVal, realExpressionValue) + else + CnvXLL(iPtr^.qVal, realExpressionValue); + goto 2; + end; Error(47); errorFound := true; end; diff --git a/Tests/Conformance/c99bool.c b/Tests/Conformance/c99bool.c index 78d6e76..8492cfd 100644 --- a/Tests/Conformance/c99bool.c +++ b/Tests/Conformance/c99bool.c @@ -85,6 +85,16 @@ int main(void) { if (s.a || !s.b) goto Fail; + + _Bool b1 = 123; + _Bool b2 = -123.5; + _Bool b3 = 0.0; + static _Bool b4 = 0x100000000; + static _Bool b5 = 0.0001; + static _Bool b6 = -0.0; + + if (b1 != 1 || b2 != 1 || b3 != 0 || b4 != 1 || b5 != 1 || b6 != 0) + goto Fail; printf ("Passed Conformance Test c99bool\n"); return 0; diff --git a/cc.notes b/cc.notes index b1f0235..225f627 100644 --- a/cc.notes +++ b/cc.notes @@ -2009,6 +2009,10 @@ int foo(int[42]); 221. Structures with unnamed bit-fields were sometimes initialized incorrectly. +222. If an expression of type unsigned long and value greater than LONG_MAX was used in the initializer for a floating-point variable with static storage duration, the wrong value would be produced. + +223. Expressions of floating-point type could not be used in initializers for integer variables with static storage duration. This should be allowed, with a conversion performed as in the case of assignment. + -- Bugs from C 2.1.0 that have been fixed ----------------------------------- 1. In some situations, fread() reread the first 1K or so of the file.