Browse Source

* fix #40618: apply adjusted patch by Евгений Савин (@jack128a) so that a non-load case expression is loaded into a temp first when converting a single range branch into an if-clause
+ added test

Sven/Sarah Barth 1 year ago
parent
commit
27a2a04279
2 changed files with 51 additions and 1 deletions
  1. 25 1
      compiler/nset.pas
  2. 26 0
      tests/webtbs/tw40618.pp

+ 25 - 1
compiler/nset.pas

@@ -958,7 +958,7 @@ implementation
                    caddnode.create_internal(equaln,left.getcopy,cordconstnode.create(flabels^._low,left.resultdef,false)),
                    caddnode.create_internal(equaln,left.getcopy,cordconstnode.create(flabels^._low,left.resultdef,false)),
                    pcaseblock(blocks[flabels^.blockid])^.statement,elseblock);
                    pcaseblock(blocks[flabels^.blockid])^.statement,elseblock);
                end
                end
-             else
+             else if left.nodetype in [loadn,temprefn] then
                begin
                begin
                  result:=cifnode.create_internal(
                  result:=cifnode.create_internal(
                    caddnode.create_internal(andn,
                    caddnode.create_internal(andn,
@@ -966,6 +966,30 @@ implementation
                      caddnode.create_internal(lten,left.getcopy,cordconstnode.create(flabels^._high,left.resultdef,false))
                      caddnode.create_internal(lten,left.getcopy,cordconstnode.create(flabels^._high,left.resultdef,false))
                    ),
                    ),
                    pcaseblock(blocks[flabels^.blockid])^.statement,elseblock);
                    pcaseblock(blocks[flabels^.blockid])^.statement,elseblock);
+               end
+             else
+               begin
+                 init_block:=internalstatements(stmt);
+                 tempcaseexpr:=ctempcreatenode.create(
+                   left.resultdef,left.resultdef.size,tt_persistent,true);
+                 temp_cleanup:=ctempdeletenode.create(tempcaseexpr);
+                 typecheckpass(tnode(tempcaseexpr));
+
+                 addstatement(stmt,tempcaseexpr);
+                 addstatement(stmt,cassignmentnode.create(
+                   ctemprefnode.create(tempcaseexpr),left.getcopy));
+
+                 left:=ctemprefnode.create(tempcaseexpr);
+                 typecheckpass(left);
+
+                 addstatement(stmt,cifnode.create_internal(
+                   caddnode.create_internal(andn,
+                     caddnode.create_internal(gten,left.getcopy,cordconstnode.create(flabels^._low,left.resultdef,false)),
+                     caddnode.create_internal(lten,left.getcopy,cordconstnode.create(flabels^._high,left.resultdef,false))
+                   ),
+                   pcaseblock(blocks[flabels^.blockid])^.statement,elseblock));
+                 addstatement(stmt,temp_cleanup);
+                 result:=init_block;
                end;
                end;
              elseblock:=nil;
              elseblock:=nil;
              pcaseblock(blocks[flabels^.blockid])^.statement:=nil;
              pcaseblock(blocks[flabels^.blockid])^.statement:=nil;

+ 26 - 0
tests/webtbs/tw40618.pp

@@ -0,0 +1,26 @@
+program tw40618;
+
+var
+	HiTimes: int32 = 0;
+
+function Hi: int32;
+begin
+	writeln('Hi called.');
+	inc(HiTimes);
+	Hi := 0;
+end;
+
+begin
+	case Hi of
+		0 .. 2: ;
+		else halt(1);
+	end;
+	if HiTimes <> 1 then
+	begin
+		writeln('Hi called ', HiTimes, ' times, expected 1.');
+		halt(2);
+	end
+	else
+		writeln('OK');
+end.
+