Browse Source

Support explicit casts for floating point types in mode Delphi, issue #41533

Ondrej Pokorny 4 days ago
parent
commit
5bf217ed53
5 changed files with 48 additions and 147 deletions
  1. 10 19
      compiler/defcmp.pas
  2. 0 33
      tests/webtbf/tw2129.pp
  3. 0 54
      tests/webtbs/tw2129.pp
  4. 0 41
      tests/webtbs/tw2129b.pp
  5. 38 0
      tests/webtbs/tw41533.pp

+ 10 - 19
compiler/defcmp.pas

@@ -962,27 +962,18 @@ implementation
                        eq:=te_equal
                      else
                        begin
-                         { Delphi does not allow explicit type conversions for float types like:
-                             single_var:=single(double_var);
-                           But if such conversion is inserted by compiler (internal) for some purpose,
-                           it should be allowed even in Delphi mode. }
-                         if (fromtreetype=realconstn) or
-                            not((cdoptions*[cdo_explicit,cdo_internal]=[cdo_explicit]) and
-                                (m_delphi in current_settings.modeswitches)) then
+                         doconv:=tc_real_2_real;
+                         { do we lose precision? }
+                         if (def_to.size<def_from.size) or
+                           (is_currency(def_from) and (tfloatdef(def_to).floattype in [s32real,s64real])) then
                            begin
-                             doconv:=tc_real_2_real;
-                             { do we lose precision? }
-                             if (def_to.size<def_from.size) or
-                               (is_currency(def_from) and (tfloatdef(def_to).floattype in [s32real,s64real])) then
-                               begin
-                                 if is_currency(def_from) and (tfloatdef(def_to).floattype=s32real) then
-                                   eq:=te_convert_l3
-                                 else
-                                   eq:=te_convert_l2
-                               end
+                             if is_currency(def_from) and (tfloatdef(def_to).floattype=s32real) then
+                               eq:=te_convert_l3
                              else
-                               eq:=te_convert_l1;
-                           end;
+                               eq:=te_convert_l2
+                           end
+                         else
+                           eq:=te_convert_l1;
                        end;
                    end;
                  else

+ 0 - 33
tests/webtbf/tw2129.pp

@@ -1,33 +0,0 @@
-{ %fail }
-{ Source provided for Free Pascal Bug Report 2129 }
-{ Submitted by "Bill Rayer" on  2002-09-18 }
-{ e-mail: [email protected] }
-
-{$mode delphi}
-
-(*
-Comp() cast has different effect in FPC.
-Compiles using Delphi4:
-  dcc32 -CC fpc19
-Compiles in FPC 1.0.6:
-  ppc386 -WC fpc19
-
-When run, the Delphi version shows -6.5E+18, but the FPC version
-shows zero. In Delphi, the comp() cast actually moves 8 bytes from
-the double into the comp without converting the data, but FPC uses
-floating point instructions to convert the data and therefore prints
-zero.
-
-In Delphi, if you want to convert a double to a float, you just use
-the assignment "comp1 := dbl1" which corresponds to the FLD/FIST
-opcodes. FPC should not use the comp() cast for doing this, since
-it introduces a subtle incompatibility with Delphi.
-*)
-
-program fpc19;
-var
-  single1 : single;
-  dbl1 : double;
-begin
-  single1 := single(dbl1);
-end.

+ 0 - 54
tests/webtbs/tw2129.pp

@@ -1,54 +0,0 @@
-{ Source provided for Free Pascal Bug Report 2129 }
-{ Submitted by "Bill Rayer" on  2002-09-18 }
-{ e-mail: [email protected] }
-
-{$mode delphi}
-
-(*
-Comp() cast has different effect in FPC.
-Compiles using Delphi4:
-  dcc32 -CC fpc19
-Compiles in FPC 1.0.6:
-  ppc386 -WC fpc19
-
-When run, the Delphi version shows -6.5E+18, but the FPC version
-shows zero. In Delphi, the comp() cast actually moves 8 bytes from
-the double into the comp without converting the data, but FPC uses
-floating point instructions to convert the data and therefore prints
-zero.
-
-In Delphi, if you want to convert a double to a float, you just use
-the assignment "comp1 := dbl1" which corresponds to the FLD/FIST
-opcodes. FPC should not use the comp() cast for doing this, since
-it introduces a subtle incompatibility with Delphi.
-*)
-
-program fpc19;
-uses
-  sysutils;
-
-var
-  comp1 : comp;
-  dbl1 : double;
-  s : string;
-begin
-  dbl1 := -1e-128;
-  comp1 := comp(dbl1);
-{$ifdef FPC_DOUBLE_HILO_SWAPPED}
-  comp1:=swap(comp1);
-{$endif FPC_DOUBLE_HILO_SWAPPED}
-  str(comp1:23,s);
-{$ifdef FPC_HAS_TYPE_EXTENDED}
-  if s<>'-6.53142228756617E+0018' then
-{$else FPC_HAS_TYPE_EXTENDED}
-  { this constant has been verified and is correct (FK) }
-  { doubles have slightly different precision on processors <> x86, because }
-  { intermediate calculations are not performed in 80 bit there (JM)        }
-  if trim(s)<>'-6531422287566170211' then
-{$endif FPC_HAS_TYPE_EXTENDED}
-    begin
-      writeln(s);
-      writeln('error');
-      halt(1);
-    end;
-end.

+ 0 - 41
tests/webtbs/tw2129b.pp

@@ -1,41 +0,0 @@
-{ Source provided for Free Pascal Bug Report 2129 }
-{ Submitted by "Bill Rayer" on  2002-09-18 }
-{ e-mail: [email protected] }
-
-(*
-Comp() cast has different effect in FPC.
-Compiles using Delphi4:
-  dcc32 -CC fpc19
-Compiles in FPC 1.0.6:
-  ppc386 -WC fpc19
-
-When run, the Delphi version shows -6.5E+18, but the FPC version
-shows zero. In Delphi, the comp() cast actually moves 8 bytes from
-the double into the comp without converting the data, but FPC uses
-floating point instructions to convert the data and therefore prints
-zero.
-
-In Delphi, if you want to convert a double to a float, you just use
-the assignment "comp1 := dbl1" which corresponds to the FLD/FIST
-opcodes. FPC should not use the comp() cast for doing this, since
-it introduces a subtle incompatibility with Delphi.
-*)
-
-program fpc19;
-{ the same as tw2129.pp for cpu's were comp = int64 }
-var
-  comp1 : comp;
-  dbl1 : double;
-  s : string;
-begin
-{$ifdef cpui386}
-  dbl1 := -1e-128;
-  comp1 := comp(dbl1);
-  str(comp1:23,s);
-  if s<>' 0.00000000000000E+0000' then
-    begin
-      writeln('error: ',s);
-      halt(1);
-    end;
-{$endif cpui386}
-end.

+ 38 - 0
tests/webtbs/tw41533.pp

@@ -0,0 +1,38 @@
+program FloatCastTest;
+{$mode Delphi}
+uses Variants, Math;
+var
+  C: Currency;
+  D, D2: Double;
+  S: Single;
+  Cp: Comp;
+  V: Variant;
+begin
+  C := 5.5556;
+  D := Double(C);
+  S := Single(D);
+  D2 := Single(D);
+  Cp := Comp(D);
+  V := Double(C);
+
+  Writeln('C: ', C);
+  Writeln('D: ', D);
+  if not SameValue(C, D) then // C and D must be the same
+    Halt(1);
+
+  Writeln('D2:', D2);
+  if SameValue(D, D2) then // D and D2 must be different -> precision reduced with Single() conversion
+    Halt(2);
+
+  Writeln('S: ', S);
+  if not SameValue(D2, S) then // D2 and S must be the same
+    Halt(3);
+
+  Writeln('Cp:', Cp);
+  if not SameValue(Cp, 6) then // Cp is 6
+    Halt(4);
+
+  Writeln('V:  ', V);
+  if not SameValue(D, V) then // D and V must be the same
+    Halt(5);
+end.