Ver código fonte

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 -

paul 13 anos atrás
pai
commit
a26bc50ca6

+ 48 - 59
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;

+ 45 - 38
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;

+ 4 - 4
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

+ 7 - 6
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 }
                 ;
 

+ 5 - 5
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;
 
 

+ 1 - 1
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;
 
 

+ 1 - 1
compiler/pexpr.pas

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

+ 3 - 3
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)

+ 3 - 2
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] = (

+ 1 - 1
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