compiler: change ShortString->(Some)String and AnsiString->(Some)String overload precedence both for variables and string constants, change unicode constant type from widestring to unicodestring (Delphi compatibility)

new ShortString->(Some)String precedence: ShortString, UTF8String, AnsiString, AnsiString(CodePage) and RawByteString, UnicodeString, WideString and other string types
new AnsiString->(Some)String precedence: RawByteString, UTF8String, AnsiString, AnsiString(CodePage), UnicodeString, WideString, ShortString and other string types

The new logic makes UTF8String more preferrable than other AnsiString types, AnsiString more preferrable than other  AnsiStrings(codepage) and also makes UnicodeString more preferrable than WideString.

git-svn-id: trunk@21057 -
This commit is contained in:
paul 2012-04-26 02:33:57 +00:00
parent 9d1063f94c
commit a26bc50ca6
10 changed files with 118 additions and 120 deletions

View File

@ -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;

View File

@ -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_distance<bestpd^.ordinal_distance) then
res:=1
else
if (currpd^.ordinal_distance>bestpd^.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_distance<bestpd^.ordinal_distance) then
res:=1
else
if (currpd^.ordinal_distance>bestpd^.ordinal_distance) then
res:=-1
else
res:=0;
end;
end;
end;
end;
end;
end;
end;
end;
end;
end;
end;
end;

View File

@ -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

View File

@ -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 }
;

View File

@ -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;

View File

@ -381,7 +381,7 @@ implementation
else
inserttypeconv(n,getansistringdef)
else if is_widechararray(n.resultdef) then
inserttypeconv(n,cwidestringtype);
inserttypeconv(n,cunicodestringtype);
end;

View File

@ -2815,7 +2815,7 @@ implementation
_CWSTRING:
begin
p1:=cstringconstnode.createwstr(patternw);
p1:=cstringconstnode.createunistr(patternw);
consume(_CWSTRING);
end;

View File

@ -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)

View File

@ -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] = (

View File

@ -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