summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpaul <paul@3ad0048d-3df7-0310-abae-a5850022a9f2>2012-04-26 02:33:57 +0000
committerpaul <paul@3ad0048d-3df7-0310-abae-a5850022a9f2>2012-04-26 02:33:57 +0000
commitb400e9040d316bd92c1840bffa6ade7164ad188b (patch)
tree9f7a2a4d8fdbf834ba96400c883209fbcee9fdcb
parentfec0162a900502f03a10bca471130140a22e1173 (diff)
downloadfpc-b400e9040d316bd92c1840bffa6ade7164ad188b.tar.gz
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: http://svn.freepascal.org/svn/fpc/trunk@21057 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--compiler/defcmp.pas107
-rw-r--r--compiler/htypechk.pas83
-rw-r--r--compiler/nadd.pas8
-rw-r--r--compiler/ncnv.pas13
-rw-r--r--compiler/ncon.pas10
-rw-r--r--compiler/ninl.pas2
-rw-r--r--compiler/pexpr.pas2
-rw-r--r--compiler/ptconst.pas6
-rw-r--r--compiler/symconst.pas5
-rw-r--r--tests/webtbs/tw18075.pp2
10 files changed, 118 insertions, 120 deletions
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_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;
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