diff --git a/compiler/defutil.pas b/compiler/defutil.pas index 46e319d0d4..f2e15daff0 100644 --- a/compiler/defutil.pas +++ b/compiler/defutil.pas @@ -349,6 +349,10 @@ interface signdness, the result will also get that signdness } function get_common_intdef(ld, rd: torddef; keep_sign_if_equal: boolean): torddef; + { # calculates "not v" based on the provided def; returns true if the def + was negatable, false otherwise } + function calc_not_ordvalue(var v:Tconstexprint; var def:tdef):boolean; + { # returns whether the type is potentially a valid type of/for an "univ" parameter (basically: it must have a compile-time size) } function is_valid_univ_para_type(def: tdef): boolean; @@ -1747,6 +1751,59 @@ implementation end; + function calc_not_ordvalue(var v:Tconstexprint;var def:tdef):boolean; + begin + if not assigned(def) or (def.typ<>orddef) then + exit(false); + result:=true; + case torddef(def).ordtype of + pasbool1, + pasbool8, + pasbool16, + pasbool32, + pasbool64: + v:=byte(not(boolean(int64(v)))); + bool8bit, + bool16bit, + bool32bit, + bool64bit: + begin + if v=0 then + v:=-1 + else + v:=0; + end; + uchar, + uwidechar, + u8bit, + s8bit, + u16bit, + s16bit, + s32bit, + u32bit, + s64bit, + u64bit: + begin + { unsigned, equal or bigger than the native int size? } + if (torddef(def).ordtype in [u64bit,u32bit,u16bit,u8bit,uchar,uwidechar]) and + (is_nativeord(def) or is_oversizedord(def)) then + begin + { Delphi-compatible: not dword = dword (not word = longint) } + { Extension: not qword = qword } + v:=qword(not qword(v)); + { will be truncated by the ordconstnode for u32bit } + end + else + begin + v:=int64(not int64(v)); + def:=get_common_intdef(torddef(def),torddef(sinttype),false); + end; + end; + else + result:=false; + end; + end; + function is_valid_univ_para_type(def: tdef): boolean; begin result:= diff --git a/compiler/nmat.pas b/compiler/nmat.pas index 60925f8a8e..b4a51f2521 100644 --- a/compiler/nmat.pas +++ b/compiler/nmat.pas @@ -1176,52 +1176,8 @@ implementation begin v:=tordconstnode(left).value; def:=left.resultdef; - case torddef(left.resultdef).ordtype of - pasbool1, - pasbool8, - pasbool16, - pasbool32, - pasbool64: - v:=byte(not(boolean(int64(v)))); - bool8bit, - bool16bit, - bool32bit, - bool64bit: - begin - if v=0 then - v:=-1 - else - v:=0; - end; - uchar, - uwidechar, - u8bit, - s8bit, - u16bit, - s16bit, - s32bit, - u32bit, - s64bit, - u64bit: - begin - { unsigned, equal or bigger than the native int size? } - if (torddef(left.resultdef).ordtype in [u64bit,u32bit,u16bit,u8bit,uchar,uwidechar]) and - (is_nativeord(left.resultdef) or is_oversizedord(left.resultdef)) then - begin - { Delphi-compatible: not dword = dword (not word = longint) } - { Extension: not qword = qword } - v:=qword(not qword(v)); - { will be truncated by the ordconstnode for u32bit } - end - else - begin - v:=int64(not int64(v)); - def:=get_common_intdef(torddef(left.resultdef),torddef(sinttype),false); - end; - end; - else - CGMessage(type_e_mismatch); - end; + if not calc_not_ordvalue(v,def) then + CGMessage(type_e_mismatch); { not-nodes are not range checked by the code generator -> also don't range check while inlining; the resultdef is a bit tricky though: the node's resultdef gets changed in most cases compared