diff --git a/compiler/defcmp.pas b/compiler/defcmp.pas index 356601ef06..eba2cce186 100644 --- a/compiler/defcmp.pas +++ b/compiler/defcmp.pas @@ -365,36 +365,10 @@ implementation stringdef : begin { Constant string } - if (fromtreetype=stringconstn) then - begin - if (tstringdef(def_from).stringtype=tstringdef(def_to).stringtype) and - ((tstringdef(def_from).stringtype<>st_ansistring) or - (tstringdef(def_from).encoding=tstringdef(def_to).encoding) - ) then - eq:=te_equal - else - begin - doconv:=tc_string_2_string; - if (tstringdef(def_from).stringtype = st_ansistring) and - (tstringdef(def_to).stringtype = st_ansistring) then - if (tstringdef(def_to).encoding=globals.CP_UTF8) then - eq:=te_convert_l1 - else - eq:=te_convert_l2 - else - begin - { Don't prefer conversions from widestring to a - normal string as we can lose information } - if (tstringdef(def_from).stringtype in [st_widestring,st_unicodestring]) and - not (tstringdef(def_to).stringtype in [st_widestring,st_unicodestring]) then - eq:=te_convert_l3 - else if tstringdef(def_to).stringtype in [st_widestring,st_unicodestring] then - eq:=te_convert_l2 - else - eq:=te_convert_l1; - end; - end; - end + if (fromtreetype=stringconstn) and + is_shortstring(def_from) and + is_shortstring(def_to) then + eq:=te_equal else if (tstringdef(def_to).stringtype=st_ansistring) and (tstringdef(def_from).stringtype=st_ansistring) then begin @@ -414,11 +388,17 @@ implementation else begin doconv := tc_string_2_string; - if (tstringdef(def_to).encoding=globals.CP_UTF8) then + + { prefere conversion to utf8 codepage } + if tstringdef(def_to).encoding = globals.CP_UTF8 then eq:=te_convert_l1 + { else to AnsiString type } + else if def_to=getansistringdef then + eq:=te_convert_l2 + { else to AnsiString with other codepage } else - eq:=te_convert_l2; - end + eq:=te_convert_l3; + end end else { same string type ? } @@ -436,44 +416,53 @@ implementation case tstringdef(def_from).stringtype of st_widestring : begin - { Prefer conversions to unicodestring } - if tstringdef(def_to).stringtype=st_unicodestring then - eq:=te_convert_l1 - { else prefer conversions to ansistring } - else if tstringdef(def_to).stringtype=st_ansistring then - eq:=te_convert_l2 - else - eq:=te_convert_l3; + case tstringdef(def_to).stringtype of + { Prefer conversions to unicodestring } + st_unicodestring: eq:=te_convert_l1; + { else prefer conversions to ansistring } + st_ansistring: eq:=te_convert_l2; + else + eq:=te_convert_l3; + end; end; st_unicodestring : begin - { Prefer conversions to widestring } - if tstringdef(def_to).stringtype=st_widestring then - eq:=te_convert_l1 - { else prefer conversions to ansistring } - else if tstringdef(def_to).stringtype=st_ansistring then - eq:=te_convert_l2 - else - eq:=te_convert_l3; + case tstringdef(def_to).stringtype of + { Prefer conversions to widestring } + st_widestring: eq:=te_convert_l1; + { else prefer conversions to ansistring } + st_ansistring: eq:=te_convert_l2; + else + eq:=te_convert_l3; + end; end; st_shortstring : begin { Prefer shortstrings of different length or conversions from shortstring to ansistring } - if (tstringdef(def_to).stringtype=st_shortstring) then - eq:=te_convert_l1 - else if tstringdef(def_to).stringtype=st_ansistring then - eq:=te_convert_l2 - else - eq:=te_convert_l3; + case tstringdef(def_to).stringtype of + st_shortstring: eq:=te_convert_l1; + st_ansistring: + if tstringdef(def_to).encoding=globals.CP_UTF8 then + eq:=te_convert_l2 + else if def_to=getansistringdef then + eq:=te_convert_l3 + else + eq:=te_convert_l4; + st_unicodestring: eq:=te_convert_l5; + else + eq:=te_convert_l6; + end; end; st_ansistring : begin { Prefer conversion to widestrings } - if (tstringdef(def_to).stringtype in [st_widestring,st_unicodestring]) then - eq:=te_convert_l2 - else - eq:=te_convert_l3; + case tstringdef(def_to).stringtype of + st_unicodestring: eq:=te_convert_l4; + st_widestring: eq:=te_convert_l5; + else + eq:=te_convert_l6; + end; end; end; end; diff --git a/compiler/htypechk.pas b/compiler/htypechk.pas index a909abfdcf..7203c94ae9 100644 --- a/compiler/htypechk.pas +++ b/compiler/htypechk.pas @@ -51,6 +51,7 @@ interface cl3_count, cl4_count, cl5_count, + cl6_count, coper_count : integer; { should be signed } ordinal_distance : double; invalid : boolean; @@ -1694,7 +1695,8 @@ implementation { string and string[10] are assumed as equal } { when searching the correct overloaded procedure } if (p.resultdef.typ=stringdef) and - (tstringdef(def_to).stringtype=tstringdef(p.resultdef).stringtype) then + (tstringdef(def_to).stringtype=tstringdef(p.resultdef).stringtype) and + (tstringdef(def_to).encoding=tstringdef(p.resultdef).encoding) then eq:=te_equal end; setdef : @@ -2217,6 +2219,7 @@ implementation ' l3: '+tostr(hp^.cl3_count)+ ' l4: '+tostr(hp^.cl4_count)+ ' l5: '+tostr(hp^.cl5_count)+ + ' l6: '+tostr(hp^.cl6_count)+ ' oper: '+tostr(hp^.coper_count)+ ' ord: '+realtostr(hp^.ordinal_distance)); { Print parameters in left-right order } @@ -2426,15 +2429,12 @@ implementation else { generic type comparision } begin - if not(po_compilerproc in hp^.data.procoptions) and - not(po_rtlproc in hp^.data.procoptions) and - is_ansistring(currpara.vardef) and - is_ansistring(currpt.left.resultdef) and - (tstringdef(currpara.vardef).encoding<>tstringdef(currpt.left.resultdef).encoding) and - ((tstringdef(currpara.vardef).encoding=globals.CP_NONE) or - (tstringdef(currpt.left.resultdef).encoding=globals.CP_NONE) - ) then - eq:=te_convert_l1 + if (hp^.data.procoptions*[po_rtlproc,po_compilerproc]=[]) and + is_ansistring(def_from) and + is_ansistring(def_to) and + (tstringdef(def_from).encoding<>tstringdef(def_to).encoding) and + (currpara.varspez in [vs_var,vs_out]) then + eq:=te_convert_l1 // don't allow to pass different ansistring types to each-other else eq:=compare_defs_ext(def_from,def_to,currpt.left.nodetype,convtype,pdoper,cdoptions); @@ -2487,6 +2487,8 @@ implementation inc(hp^.cl4_count); te_convert_l5 : inc(hp^.cl5_count); + te_convert_l6 : + inc(hp^.cl6_count); te_convert_operator : inc(hp^.coper_count); te_incompatible : @@ -2614,48 +2616,53 @@ implementation res:=(bestpd^.coper_count-currpd^.coper_count); if (res=0) then begin - { less cl5 parameters? } - res:=(bestpd^.cl5_count-currpd^.cl5_count); + { less cl6 parameters? } + res:=(bestpd^.cl6_count-currpd^.cl6_count); if (res=0) then begin - { less cl4 parameters? } - res:=(bestpd^.cl4_count-currpd^.cl4_count); - if (res=0) then - begin - { less cl3 parameters? } - res:=(bestpd^.cl3_count-currpd^.cl3_count); - if (res=0) then - begin - { less cl2 parameters? } - res:=(bestpd^.cl2_count-currpd^.cl2_count); + { less cl5 parameters? } + res:=(bestpd^.cl5_count-currpd^.cl5_count); + if (res=0) then + begin + { less cl4 parameters? } + res:=(bestpd^.cl4_count-currpd^.cl4_count); + if (res=0) then + begin + { less cl3 parameters? } + res:=(bestpd^.cl3_count-currpd^.cl3_count); if (res=0) then begin - { less cl1 parameters? } - res:=(bestpd^.cl1_count-currpd^.cl1_count); + { less cl2 parameters? } + res:=(bestpd^.cl2_count-currpd^.cl2_count); if (res=0) then begin - { more exact parameters? } - res:=(currpd^.exact_count-bestpd^.exact_count); + { less cl1 parameters? } + res:=(bestpd^.cl1_count-currpd^.cl1_count); if (res=0) then begin - { less equal parameters? } - res:=(bestpd^.equal_count-currpd^.equal_count); + { more exact parameters? } + res:=(currpd^.exact_count-bestpd^.exact_count); if (res=0) then begin - { smaller ordinal distance? } - if (currpd^.ordinal_distancebestpd^.ordinal_distance) then - res:=-1 - else - res:=0; + { less equal parameters? } + res:=(bestpd^.equal_count-currpd^.equal_count); + if (res=0) then + begin + { smaller ordinal distance? } + if (currpd^.ordinal_distancebestpd^.ordinal_distance) then + res:=-1 + else + res:=0; + end; end; end; end; end; - end; - end; + end; + end; end; end; end; diff --git a/compiler/nadd.pas b/compiler/nadd.pas index 33f8478158..33131c9dda 100644 --- a/compiler/nadd.pas +++ b/compiler/nadd.pas @@ -676,7 +676,7 @@ implementation addn : begin concatwidestrings(ws1,ws2); - t:=cstringconstnode.createwstr(ws1); + t:=cstringconstnode.createunistr(ws1); end; ltn : t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)<0),pasbool8type,true); @@ -1323,13 +1323,13 @@ implementation { There is a widechar? } else if is_widechar(rd) or is_widechar(ld) then begin - { widechar+widechar gives widestring } + { widechar+widechar gives unicodestring } if nodetype=addn then begin - inserttypeconv(left,cwidestringtype); + inserttypeconv(left,cunicodestringtype); if (torddef(rd).ordtype<>uwidechar) then inserttypeconv(right,cwidechartype); - resultdef:=cwidestringtype; + resultdef:=cunicodestringtype; end else begin diff --git a/compiler/ncnv.pas b/compiler/ncnv.pas index dd989610b4..842a55fa38 100644 --- a/compiler/ncnv.pas +++ b/compiler/ncnv.pas @@ -995,7 +995,7 @@ implementation end; { Convert to wide/short/ansistring and call default helper } if is_widechar(tarraydef(resultdef).elementdef) then - inserttypeconv(left,cwidestringtype) + inserttypeconv(left,cunicodestringtype) else begin if tstringconstnode(left).len>255 then @@ -1046,7 +1046,7 @@ implementation concatwidestringchar(ws,tcompilerwidechar(tordconstnode(left).value.uvalue)) else concatwidestringchar(ws,asciichar2unicode(chr(tordconstnode(left).value.uvalue))); - hp:=cstringconstnode.createwstr(ws); + hp:=cstringconstnode.createunistr(ws); hp.changestringtype(resultdef); donewidestring(ws); end @@ -1392,9 +1392,9 @@ implementation begin result:=nil; if is_pwidechar(resultdef) then - inserttypeconv(left,cwidestringtype) + inserttypeconv(left,cunicodestringtype) else - inserttypeconv(left,cshortstringtype); + inserttypeconv(left,cshortstringtype); { evaluate again, reset resultdef so the convert_typ will be calculated again and cstring_to_pchar will be used for futher conversion } @@ -1408,7 +1408,7 @@ implementation begin result:=nil; if is_pwidechar(resultdef) then - inserttypeconv(left,cwidestringtype) + inserttypeconv(left,cunicodestringtype) else if is_pchar(resultdef) and (is_widestring(left.resultdef) or @@ -1943,7 +1943,8 @@ implementation te_convert_l2, te_convert_l3, te_convert_l4, - te_convert_l5: + te_convert_l5, + te_convert_l6: { nothing to do } ; diff --git a/compiler/ncon.pas b/compiler/ncon.pas index e25b9ff445..a33829269a 100644 --- a/compiler/ncon.pas +++ b/compiler/ncon.pas @@ -124,7 +124,7 @@ interface cst_type : tconststringtype; constructor createstr(const s : string);virtual; constructor createpchar(s : pchar;l : longint);virtual; - constructor createwstr(w : pcompilerwidestring);virtual; + constructor createunistr(w : pcompilerwidestring);virtual; constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override; procedure ppuwrite(ppufile:tcompilerppufile);override; procedure buildderefimpl;override; @@ -254,7 +254,7 @@ implementation begin initwidestring(pWideStringVal); concatwidestringchar(pWideStringVal, tcompilerwidechar(tordconstnode(p).value.uvalue)); - result:=cstringconstnode.createwstr(pWideStringVal); + result:=cstringconstnode.createunistr(pWideStringVal); end else if is_conststringnode(p) then result:=tstringconstnode(p.getcopy) @@ -311,7 +311,7 @@ implementation p1:=cstringconstnode.createpchar(pc,len); end; constwstring : - p1:=cstringconstnode.createwstr(pcompilerwidestring(p.value.valueptr)); + p1:=cstringconstnode.createunistr(pcompilerwidestring(p.value.valueptr)); constreal : p1:=crealconstnode.create(pbestreal(p.value.valueptr)^,p.constdef); constset : @@ -794,14 +794,14 @@ implementation end; - constructor tstringconstnode.createwstr(w : pcompilerwidestring); + constructor tstringconstnode.createunistr(w : pcompilerwidestring); begin inherited create(stringconstn); len:=getlengthwidestring(w); initwidestring(pcompilerwidestring(value_str)); copywidestring(w,pcompilerwidestring(value_str)); lab_str:=nil; - cst_type:=cst_widestring; + cst_type:=cst_unicodestring; end; diff --git a/compiler/ninl.pas b/compiler/ninl.pas index 02e45f5481..576a4fbe5a 100644 --- a/compiler/ninl.pas +++ b/compiler/ninl.pas @@ -381,7 +381,7 @@ implementation else inserttypeconv(n,getansistringdef) else if is_widechararray(n.resultdef) then - inserttypeconv(n,cwidestringtype); + inserttypeconv(n,cunicodestringtype); end; diff --git a/compiler/pexpr.pas b/compiler/pexpr.pas index ee679ac5b0..aa201432f2 100644 --- a/compiler/pexpr.pas +++ b/compiler/pexpr.pas @@ -2815,7 +2815,7 @@ implementation _CWSTRING: begin - p1:=cstringconstnode.createwstr(patternw); + p1:=cstringconstnode.createunistr(patternw); consume(_CWSTRING); end; diff --git a/compiler/ptconst.pas b/compiler/ptconst.pas index d879e42210..24a3fa5710 100644 --- a/compiler/ptconst.pas +++ b/compiler/ptconst.pas @@ -439,8 +439,8 @@ implementation current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(ll)); if (p.nodetype in [stringconstn,ordconstn]) then begin - { convert to widestring stringconstn } - inserttypeconv(p,cwidestringtype); + { convert to unicodestring stringconstn } + inserttypeconv(p,cunicodestringtype); if (p.nodetype=stringconstn) and (tstringconstnode(p).cst_type in [cst_widestring,cst_unicodestring]) then begin @@ -904,7 +904,7 @@ implementation end; 2: begin - inserttypeconv(n,cwidestringtype); + inserttypeconv(n,cunicodestringtype); if n.nodetype<>stringconstn then internalerror(2010033003); ca:=pointer(pcompilerwidestring(tstringconstnode(n).value_str)^.data) diff --git a/compiler/symconst.pas b/compiler/symconst.pas index eee018b495..66b134623c 100644 --- a/compiler/symconst.pas +++ b/compiler/symconst.pas @@ -547,6 +547,7 @@ type tequaltype = ( te_incompatible, te_convert_operator, + te_convert_l6, te_convert_l5, { ad infinitum... } te_convert_l4, { and yet even less preferred conversion } te_convert_l3, { even less preferred conversion (possibly with loss of data) } @@ -615,8 +616,8 @@ const ); EqualTypeName : array[tequaltype] of string[16] = ( - 'incompatible','convert_operator','convert_l5','convert_l4','convert_l3','convert_l2', - 'convert_l1','equal','exact' + 'incompatible','convert_operator','convert_l6', 'convert_l5','convert_l4','convert_l3', + 'convert_l2','convert_l1','equal','exact' ); visibilityName : array[tvisibility] of string[16] = ( diff --git a/tests/webtbs/tw18075.pp b/tests/webtbs/tw18075.pp index 473b3361ab..b3aabc9668 100644 --- a/tests/webtbs/tw18075.pp +++ b/tests/webtbs/tw18075.pp @@ -27,7 +27,7 @@ Begin halt(1); Writeln('widestring'); - n:=pos('狃狄',cad2); //Is correct position 3 + n:=pos(WideString('狃狄'),cad2); //Is correct position 3 Writeln(n); if n<>3 then