diff --git a/.gitattributes b/.gitattributes index 716ccf2664..2743f93c28 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5757,6 +5757,7 @@ tests/test/tintfdef.pp svneol=native#text/plain tests/test/tintuint.pp svneol=native#text/plain tests/test/tlibrary1.pp svneol=native#text/plain tests/test/tlibrary2.pp svneol=native#text/plain +tests/test/tmacbool.pp svneol=native#text/plain tests/test/tmacfunret.pp svneol=native#text/plain tests/test/tmaclocalprocparam.pp svneol=native#text/plain tests/test/tmacnonlocalexit.pp svneol=native#text/plain @@ -5767,6 +5768,7 @@ tests/test/tmacpas3.pp svneol=native#text/plain tests/test/tmacpas4.pp svneol=native#text/plain tests/test/tmacprocvar.pp svneol=native#text/plain tests/test/tmath1.pp svneol=native#text/plain +tests/test/tmcbool2.pp svneol=native#text/plain tests/test/tmmx1.pp svneol=native#text/plain tests/test/tmove.pp svneol=native#text/plain tests/test/tmt1.pp svneol=native#text/plain diff --git a/compiler/nadd.pas b/compiler/nadd.pas index 4f9f19ed8b..e3e0ac6e85 100644 --- a/compiler/nadd.pas +++ b/compiler/nadd.pas @@ -812,8 +812,25 @@ implementation exit; end; + { set for & and | operations in macpas mode: they only work on } + { booleans, and always short circuit evaluation } + if (nf_short_bool in flags) then + begin + if not is_boolean(ld) then + begin + inserttypeconv(left,booltype); + ld := left.resulttype.def; + end; + if not is_boolean(rd) then + begin + inserttypeconv(right,booltype); + rd := right.resulttype.def; + end; + end; + { 2 booleans? Make them equal to the largest boolean } - if is_boolean(ld) and is_boolean(rd) then + if (is_boolean(ld) and is_boolean(rd)) or + (nf_short_bool in flags) then begin if torddef(left.resulttype.def).size>torddef(right.resulttype.def).size then begin @@ -840,7 +857,8 @@ implementation unequaln, equaln: begin - if not(cs_full_boolean_eval in aktlocalswitches) then + if not(cs_full_boolean_eval in aktlocalswitches) or + (nf_short_bool in flags) then begin { Remove any compares with constants } if (left.nodetype=ordconstn) then @@ -2079,7 +2097,8 @@ implementation { 2 booleans ? } if is_boolean(ld) and is_boolean(rd) then begin - if not(cs_full_boolean_eval in aktlocalswitches) and + if (not(cs_full_boolean_eval in aktlocalswitches) or + (nf_short_bool in flags)) and (nodetype in [andn,orn]) then begin expectloc:=LOC_JUMP; diff --git a/compiler/ncgadd.pas b/compiler/ncgadd.pas index 8611b7d934..e17947df83 100644 --- a/compiler/ncgadd.pas +++ b/compiler/ncgadd.pas @@ -379,7 +379,8 @@ interface { And,Or will only evaluate from left to right only the needed nodes unless full boolean evaluation is enabled } if (nodetype in [orn,andn]) and - not(cs_full_boolean_eval in aktlocalswitches) then + (not(cs_full_boolean_eval in aktlocalswitches) or + (nf_short_bool in flags)) then begin location_reset(location,LOC_JUMP,OS_NO); case nodetype of diff --git a/compiler/node.pas b/compiler/node.pas index 85999c08d3..174963a6fd 100644 --- a/compiler/node.pas +++ b/compiler/node.pas @@ -220,6 +220,7 @@ interface { taddnode } nf_is_currency, nf_has_pointerdiv, + nf_short_bool, { tassignmentnode } nf_concat_string, diff --git a/compiler/pexpr.pas b/compiler/pexpr.pas index 00002107ff..ae207560e6 100644 --- a/compiler/pexpr.pas +++ b/compiler/pexpr.pas @@ -2567,10 +2567,18 @@ implementation p1:=cisnode.create(p1,p2); _OP_OR, _PIPE {macpas only} : - p1:=caddnode.create(orn,p1,p2); + begin + p1:=caddnode.create(orn,p1,p2); + if (oldt = _PIPE) then + include(p1.flags,nf_short_bool); + end; _OP_AND, _AMPERSAND {macpas only} : - p1:=caddnode.create(andn,p1,p2); + begin + p1:=caddnode.create(andn,p1,p2); + if (oldt = _AMPERSAND) then + include(p1.flags,nf_short_bool); + end; _OP_DIV : p1:=cmoddivnode.create(divn,p1,p2); _OP_NOT : diff --git a/compiler/powerpc/nppcadd.pas b/compiler/powerpc/nppcadd.pas index 554a798c8f..015728735c 100644 --- a/compiler/powerpc/nppcadd.pas +++ b/compiler/powerpc/nppcadd.pas @@ -261,7 +261,8 @@ interface else cgsize:=OS_32; - if (cs_full_boolean_eval in aktlocalswitches) or + if ((cs_full_boolean_eval in aktlocalswitches) and + not(nf_short_bool in flags)) or (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then begin if left.nodetype in [ordconstn,realconstn] then diff --git a/compiler/powerpc64/nppcadd.pas b/compiler/powerpc64/nppcadd.pas index a260fbb33e..896fc9819a 100644 --- a/compiler/powerpc64/nppcadd.pas +++ b/compiler/powerpc64/nppcadd.pas @@ -254,7 +254,8 @@ begin else cgsize := OS_32; - if (cs_full_boolean_eval in aktlocalswitches) or + if ((cs_full_boolean_eval in aktlocalswitches) and + not(nf_short_bool in flags)) or (nodetype in [unequaln, ltn, lten, gtn, gten, equaln, xorn]) then begin if left.nodetype in [ordconstn, realconstn] then diff --git a/compiler/ppu.pas b/compiler/ppu.pas index 762ef688e9..f646b2e898 100644 --- a/compiler/ppu.pas +++ b/compiler/ppu.pas @@ -43,7 +43,7 @@ type {$endif Test_Double_checksum} const - CurrentPPUVersion=57; + CurrentPPUVersion=58; { buffer sizes } maxentrysize = 1024; diff --git a/tests/test/tmacbool.pp b/tests/test/tmacbool.pp new file mode 100644 index 0000000000..ba773aed6c --- /dev/null +++ b/tests/test/tmacbool.pp @@ -0,0 +1,189 @@ +program macbool; + +{$mode macpas} + +{ checks boolean evaluation in macpas mode } + +var + ftruecalled, ffalsecalled: boolean; + +function ftrue: boolean; +begin + ftruecalled := true; + ftrue := true; +end; + +function ffalse: boolean; +begin + ffalsecalled := true; + ffalse := false; +end; + + +begin + { OR and |, short circuit } +{$b-} + ffalsecalled := false; + ftruecalled := false; + if (ftrue or ffalse) then + begin + if not(ftruecalled) then + halt(1); + if ffalsecalled then + halt(2); + end + else + halt(128); + + ffalsecalled := false; + ftruecalled := false; + if not(ffalse or ftrue) then + halt(3); + if not(ffalsecalled) then + halt(4); + if not(ftruecalled) then + halt(5); + + ffalsecalled := false; + ftruecalled := false; + if (ftrue | ffalse) then + begin + if not(ftruecalled) then + halt(6); + if ffalsecalled then + halt(7); + end + else + halt(129); + + ffalsecalled := false; + ftruecalled := false; + if not(ffalse | ftrue) then + halt(8); + if not(ffalsecalled) then + halt(9); + if not(ftruecalled) then + halt(10); + + + { OR and |, full evaluation } +{$b+} + ffalsecalled := false; + ftruecalled := false; + if (ftrue or ffalse) then + begin + if not(ftruecalled) then + halt(11); + if not(ffalsecalled) then + halt(12); + end + else + halt(130); + + ffalsecalled := false; + ftruecalled := false; + if not(ffalse or ftrue) then + halt(13); + if not(ffalsecalled) then + halt(14); + if not(ftruecalled) then + halt(15); + + ffalsecalled := false; + ftruecalled := false; + if (ftrue | ffalse) then + begin + if not(ftruecalled) then + halt(16); + if ffalsecalled then + halt(17); + end + else + halt(131); + + ffalsecalled := false; + ftruecalled := false; + if not(ffalse | ftrue) then + halt(18); + if not(ffalsecalled) then + halt(19); + if not(ftruecalled) then + halt(20); + + { AND and &, short circuit } +{$b-} + ffalsecalled := false; + ftruecalled := false; + if (ftrue and ffalse) then + halt(21); + if not(ftruecalled) then + halt(211); + if not(ffalsecalled) then + halt(22); + + ffalsecalled := false; + ftruecalled := false; + if (ffalse and ftrue) then + halt(23); + if not(ffalsecalled) then + halt(24); + if (ftruecalled) then + halt(25); + + ffalsecalled := false; + ftruecalled := false; + if (ftrue & ffalse) then + halt(206); + if not(ftruecalled) then + halt(26); + if not(ffalsecalled) then + halt(27); + + ffalsecalled := false; + ftruecalled := false; + if (ffalse & ftrue) then + halt(28); + if not(ffalsecalled) then + halt(29); + if (ftruecalled) then + halt(30); + + + { AND and &, full evaluation } +{$b+} + ffalsecalled := false; + ftruecalled := false; + if (ftrue and ffalse) then + halt(31); + if not(ftruecalled) then + halt(111); + if not(ffalsecalled) then + halt(32); + + ffalsecalled := false; + ftruecalled := false; + if (ffalse and ftrue) then + halt(33); + if not(ffalsecalled) then + halt(34); + if not(ftruecalled) then + halt(35); + + ffalsecalled := false; + ftruecalled := false; + if (ftrue & ffalse) then + halt(133); + if not(ftruecalled) then + halt(36); + if not(ffalsecalled) then + halt(37); + + ffalsecalled := false; + ftruecalled := false; + if (ffalse & ftrue) then + halt(38); + if not(ffalsecalled) then + halt(39); + if (ftruecalled) then + halt(40); +end. diff --git a/tests/test/tmcbool2.pp b/tests/test/tmcbool2.pp new file mode 100644 index 0000000000..e93f9b38dd --- /dev/null +++ b/tests/test/tmcbool2.pp @@ -0,0 +1,10 @@ +{ %fail} +program mcbool2; + +{$mode macpas} + +var + a, b: longint; +begin + a := a & b; +end.