Browse Source

fcl-passrc: resolver: typecast string(unicodestring), unicodestring(string)

git-svn-id: trunk@41223 -
Mattias Gaertner 6 years ago
parent
commit
cfe65c8cd8

+ 30 - 0
packages/fcl-passrc/src/pasresolveeval.pas

@@ -181,6 +181,7 @@ const
   nDefaultPropertyNotAllowedInHelperForX = 3115;
   nDefaultPropertyNotAllowedInHelperForX = 3115;
   nHelpersCannotBeUsedAsTypes = 3116;
   nHelpersCannotBeUsedAsTypes = 3116;
   nBitWiseOperationsAre32Bit = 3117;
   nBitWiseOperationsAre32Bit = 3117;
+  nImplictConversionUnicodeToAnsi = 3118;
 
 
   // using same IDs as FPC
   // using same IDs as FPC
   nVirtualMethodXHasLowerVisibility = 3250; // was 3050
   nVirtualMethodXHasLowerVisibility = 3250; // was 3050
@@ -309,6 +310,7 @@ resourcestring
   sDefaultPropertyNotAllowedInHelperForX = 'Default property not allowed in helper for %s';
   sDefaultPropertyNotAllowedInHelperForX = 'Default property not allowed in helper for %s';
   sHelpersCannotBeUsedAsTypes = 'helpers cannot be used as types';
   sHelpersCannotBeUsedAsTypes = 'helpers cannot be used as types';
   sBitWiseOperationsAre32Bit = 'Bitwise operations are 32-bit';
   sBitWiseOperationsAre32Bit = 'Bitwise operations are 32-bit';
+  sImplictConversionUnicodeToAnsi = 'Implicit string type conversion with potential data loss from "UnicodeString" to "AnsiString"';
 
 
 type
 type
   { TResolveData - base class for data stored in TPasElement.CustomData }
   { TResolveData - base class for data stored in TPasElement.CustomData }
@@ -721,6 +723,7 @@ type
     {$ifdef FPC_HAS_CPSTRING}
     {$ifdef FPC_HAS_CPSTRING}
     function CheckValidUTF8(const s: RawByteString; ErrorEl: TPasElement): boolean;
     function CheckValidUTF8(const s: RawByteString; ErrorEl: TPasElement): boolean;
     function GetCodePage(const s: RawByteString): TSystemCodePage;
     function GetCodePage(const s: RawByteString): TSystemCodePage;
+    function GetRawByteString(const s: UnicodeString; CodePage: TSystemCodePage; ErrorEl: TPasElement): RawByteString;
     function GetUTF8Str(const s: RawByteString; ErrorEl: TPasElement): String;
     function GetUTF8Str(const s: RawByteString; ErrorEl: TPasElement): String;
     function GetUnicodeStr(const s: RawByteString; ErrorEl: TPasElement): UnicodeString;
     function GetUnicodeStr(const s: RawByteString; ErrorEl: TPasElement): UnicodeString;
     function GetWideChar(const s: RawByteString; out w: WideChar): boolean;
     function GetWideChar(const s: RawByteString; out w: WideChar): boolean;
@@ -4957,6 +4960,33 @@ begin
     end;
     end;
 end;
 end;
 
 
+function TResExprEvaluator.GetRawByteString(const s: UnicodeString;
+  CodePage: TSystemCodePage; ErrorEl: TPasElement): RawByteString;
+var
+  ok: Boolean;
+begin
+  Result:=UTF8Encode(s);
+  if (CodePage=CP_UTF8)
+      or ((DefaultSystemCodePage=CP_UTF8) and ((CodePage=CP_ACP) or (CodePage=CP_NONE))) then
+    begin
+    // to UTF-8
+    SetCodePage(Result,CodePage,false);
+    end
+  else
+    begin
+    // to non UTF-8 -> possible loss
+    ok:=false;
+    try
+      SetCodePage(Result,CodePage,true);
+      ok:=true;
+    except
+    end;
+    if (not ok) or (GetUnicodeStr(Result,ErrorEl)<>s) then
+      LogMsg(20190204165110,mtWarning,nImplictConversionUnicodeToAnsi,
+        sImplictConversionUnicodeToAnsi,[],ErrorEl);
+    end;
+end;
+
 function TResExprEvaluator.GetUTF8Str(const s: RawByteString;
 function TResExprEvaluator.GetUTF8Str(const s: RawByteString;
   ErrorEl: TPasElement): String;
   ErrorEl: TPasElement): String;
 var
 var

+ 40 - 0
packages/fcl-passrc/src/pasresolver.pp

@@ -13122,6 +13122,7 @@ begin
       begin
       begin
       if (bt=btAnsiChar) or ((bt=btChar) and (BaseTypeChar=btWideChar)) then
       if (bt=btAnsiChar) or ((bt=btChar) and (BaseTypeChar=btWideChar)) then
         begin
         begin
+        // ansichar(ansistring)
         if fExprEvaluator.StringToOrd(Value,nil)>$ffff then
         if fExprEvaluator.StringToOrd(Value,nil)>$ffff then
           RaiseXExpectedButYFound(20181005141025,'char','string',Params);
           RaiseXExpectedButYFound(20181005141025,'char','string',Params);
         Result:=Value;
         Result:=Value;
@@ -13129,6 +13130,7 @@ begin
         end
         end
       else if (bt=btWideChar) or ((bt=btChar) and (BaseTypeChar=btWideChar)) then
       else if (bt=btWideChar) or ((bt=btChar) and (BaseTypeChar=btWideChar)) then
         begin
         begin
+        // widechar(ansistring)
         if fExprEvaluator.GetWideChar(TResEvalString(Value).S,w) then
         if fExprEvaluator.GetWideChar(TResEvalString(Value).S,w) then
           begin
           begin
           Result:=Value;
           Result:=Value;
@@ -13136,6 +13138,24 @@ begin
           end
           end
         else
         else
           RaiseXExpectedButYFound(20181005141058,'char','string',Params);
           RaiseXExpectedButYFound(20181005141058,'char','string',Params);
+        end
+      else if (bt=btAnsiString) or ((bt=btString) and (BaseTypeString=btAnsiString)) then
+        begin
+        // ansistring(ansistring)
+        Result:=Value;
+        Value:=nil;
+        end
+      else if (bt=btUnicodeString) or (bt=btWideString)
+          or ((bt=btString) and (BaseTypeString=btUnicodeString)) then
+        begin
+        // unicodestring(ansistring)
+        Result:=TResEvalUTF16.CreateValue(
+                  fExprEvaluator.GetUnicodeStr(TResEvalString(Value).S,Params));
+        end
+      else if bt=btRawByteString then
+        begin
+        // rawbytestring(ansistring)
+        SetCodePage(TResEvalString(Value).S,CP_NONE,false);
         end;
         end;
       end;
       end;
     {$endif}
     {$endif}
@@ -13146,6 +13166,7 @@ begin
         {$ifdef FPC_HAS_CPSTRING}
         {$ifdef FPC_HAS_CPSTRING}
         if (bt=btAnsiChar) or ((bt=btChar) and (BaseTypeChar=btAnsiChar)) then
         if (bt=btAnsiChar) or ((bt=btChar) and (BaseTypeChar=btAnsiChar)) then
           begin
           begin
+          // ansichar(unicodestring)
           if ord(w)<=255 then
           if ord(w)<=255 then
             begin
             begin
             Result:=Value;
             Result:=Value;
@@ -13158,9 +13179,28 @@ begin
         {$endif}
         {$endif}
         if (bt=btWideChar) or ((bt=btChar) and (BaseTypeChar=btWideChar)) then
         if (bt=btWideChar) or ((bt=btChar) and (BaseTypeChar=btWideChar)) then
           begin
           begin
+          // widechar(unicodestring)
           Result:=Value;
           Result:=Value;
           Value:=nil;
           Value:=nil;
           end;
           end;
+        end
+      else if (bt=btAnsiString) or ((bt=btString) and (BaseTypeString=btAnsiString)) then
+        begin
+        // ansistring(unicodestring)
+        Result:=TResEvalString.CreateValue(
+                   fExprEvaluator.GetRawByteString(TResEvalUTF16(Value).S,CP_ACP,Params));
+        end
+      else if (bt=btUnicodeString) or ((bt=btString) and (BaseTypeString=btUnicodeString)) then
+        begin
+        // unicodestring(unicodestring)
+        Result:=Value;
+        Value:=nil;
+        end
+      else if bt=btRawByteString then
+        begin
+        // rawbytestring(unicodestring)
+        Result:=TResEvalString.CreateValue(
+             fExprEvaluator.GetRawByteString(TResEvalUTF16(Value).S,CP_NONE,Params));
         end;
         end;
     revkExternal:
     revkExternal:
       exit;
       exit;

+ 2 - 0
packages/fcl-passrc/tests/tcresolver.pas

@@ -3399,6 +3399,8 @@ begin
   '  k=chr(97);',
   '  k=chr(97);',
   '  l=ord(a[1]);',
   '  l=ord(a[1]);',
   '  m=low(char)+high(char);',
   '  m=low(char)+high(char);',
+  '  n = string(''A'');',
+  '  o = UnicodeString(''A'');',
   'begin']);
   'begin']);
   ParseProgram;
   ParseProgram;
   CheckResolverUnexpectedHints;
   CheckResolverUnexpectedHints;