Procházet zdrojové kódy

* don't mess with boolean and/or operations in mixed short/full evaluated expressions, resolves #41012

florian před 8 měsíci
rodič
revize
e4af0fc1e9
2 změnil soubory, kde provedl 23 přidání a 5 odebrání
  1. 8 5
      compiler/optcse.pas
  2. 15 0
      tests/webtbs/tw41012.pp

+ 8 - 5
compiler/optcse.pas

@@ -356,9 +356,9 @@ unit optcse;
                    (is_set(n.resultdef))
                    ) then
                   while (n.nodetype=tbinarynode(n).left.nodetype) and
-                    { if node (1) is fully boolean evaluated and node (2) not, we cannot do the swap as this might result in B being evaluated always,
-                      the other way round is no problem, C is still evaluated only if needed }
-                    (not(is_boolean(n.resultdef)) or not(n.nodetype in [andn,orn]) or doshortbooleval(n) or not(doshortbooleval(tbinarynode(n).left))) and
+                    { if not both or none of the nodes is short/full boolean evaluated, we cannot do this optimization as it might change
+                      semantics, there are border cases where this might not apply, but so far it is not worth the effort to check }
+                    (not(is_boolean(n.resultdef)) or not(n.nodetype in [andn,orn]) or (doshortbooleval(n)=doshortbooleval(tbinarynode(n).left))) and
                         { the resulttypes of the operands we'll swap must be equal,
                           required in case of a 32x32->64 multiplication, then we
                           cannot swap out one of the 32 bit operands for a 64 bit one
@@ -374,10 +374,13 @@ unit optcse;
                           foreachnodestatic(pm_postprocess,tbinarynode(tbinarynode(n).left).right,@searchsubdomain,@csedomain);
                           if csedomain then
                             begin
-                              { move the full boolean evaluation of (2) to (1), if it was there (so it again applies to A and
+                              {
+                                move the full boolean evaluation of (2) to (1), if it was there (so it again applies to A and
                                 what follows) }
+                              { this cannot happen anymore, see above, so the condition is not needed anymore
+
                               if not(doshortbooleval(tbinarynode(n).left)) and
-                                 doshortbooleval(n) then
+                                 doshortbooleval(n) then }
                                 begin
                                   n.localswitches:=n.localswitches+(tbinarynode(n).left.localswitches*[cs_full_boolean_eval]);
                                   exclude(tbinarynode(n).left.localswitches,cs_full_boolean_eval);

+ 15 - 0
tests/webtbs/tw41012.pp

@@ -0,0 +1,15 @@
+program test;
+{$mode objfpc}
+
+function GetFalse: Boolean;
+begin
+  Result := False;
+end;
+
+var
+  obj: TInterfacedObject;
+  i: Integer;
+
+begin
+  if GetFalse and (i >= 0) and (i < obj.RefCount) then;
+end.