diff --git a/compiler/ninl.pas b/compiler/ninl.pas index ee0c386682..49378ccb45 100644 --- a/compiler/ninl.pas +++ b/compiler/ninl.pas @@ -1781,12 +1781,49 @@ implementation function tinlinenode.handle_copy: tnode; + + procedure do_error(typemismatch:boolean;func:string;fi:tfileposinfo); + + procedure write_dynarray_copy; + begin + MessagePos1(fileinfo,sym_e_param_list,'Copy(Dynamic Array;'+sizesinttype.typename+'=`<low>`;'+sizesinttype.typename+'=`<length>`);'); + end; + + begin + if typemismatch then + CGMessagePos(fi,type_e_mismatch) + else + CGMessagePos1(fi,parser_e_wrong_parameter_size,'Copy'); + if func='' then + begin + write_system_parameter_lists('fpc_shortstr_copy'); + write_system_parameter_lists('fpc_char_copy'); + write_system_parameter_lists('fpc_unicodestr_copy'); + if tf_winlikewidestring in target_info.flags then + write_system_parameter_lists('fpc_widestr_copy'); + write_system_parameter_lists('fpc_ansistr_copy'); + write_dynarray_copy; + end + else if func='fpc_dynarray_copy' then + write_dynarray_copy + else + write_system_parameter_lists(func); + end; + var paras : tnode; ppn : tcallparanode; paradef : tdef; counter : integer; + minargs, + maxargs : longint; + func : string; begin + if not assigned(left) then + begin + do_error(false,'',fileinfo); + exit(cerrornode.create); + end; result:=nil; { determine copy function to use based on the first argument, also count the number of arguments in this loop } @@ -1801,44 +1838,63 @@ implementation end; set_varstate(ppn.left,vs_read,[vsf_must_be_valid]); paradef:=ppn.left.resultdef; + { the string variants all require 2 or 3 args, only the array one allows less } + minargs:=2; + maxargs:=3; if is_ansistring(paradef) then - // set resultdef to argument def - resultdef:=paradef + begin + // set resultdef to argument def + resultdef:=paradef; + func:='fpc_ansistr_copy'; + end else if (is_chararray(paradef) and (paradef.size>255)) or ((cs_refcountedstrings in current_settings.localswitches) and is_pchar(paradef)) then - // set resultdef to ansistring type since result will be in ansistring codepage - resultdef:=getansistringdef - else - if is_widestring(paradef) then - resultdef:=cwidestringtype - else - if is_unicodestring(paradef) or + begin + // set resultdef to ansistring type since result will be in ansistring codepage + resultdef:=getansistringdef; + func:='fpc_ansistr_copy'; + end + else if is_widestring(paradef) then + begin + resultdef:=cwidestringtype; + func:='fpc_widestr_copy'; + end + else if is_unicodestring(paradef) or is_widechararray(paradef) or is_pwidechar(paradef) then - resultdef:=cunicodestringtype + begin + resultdef:=cunicodestringtype; + func:='fpc_unicodestr_copy'; + end else if is_char(paradef) then - resultdef:=cshortstringtype + begin + resultdef:=cshortstringtype; + func:='fpc_char_copy'; + end else if is_dynamic_array(paradef) then begin - { Only allow 1 or 3 arguments } - if not(counter in [1..3]) then - begin - CGMessage1(parser_e_wrong_parameter_size,'Copy'); - exit; - end; + minargs:=1; resultdef:=paradef; + func:='fpc_dynarray_copy'; + end + else if counter in [2..3] then + begin + resultdef:=cshortstringtype; + func:='fpc_shortstr_copy'; end else - begin - { generic fallback that will give an error if a wrong - type is passed } - if (counter=3) or (counter=2) then - resultdef:=cshortstringtype - else - CGMessagePos(ppn.left.fileinfo,type_e_mismatch); - end; + begin + do_error(true,'',ppn.left.fileinfo); + exit(cerrornode.create); + end; + + if (counter<minargs) or (counter>maxargs) then + begin + do_error(false,func,fileinfo); + exit(cerrornode.create); + end; end; {$maxfpuregisters 0} diff --git a/compiler/pinline.pas b/compiler/pinline.pas index 91b5055dc0..32d0adb788 100644 --- a/compiler/pinline.pas +++ b/compiler/pinline.pas @@ -655,7 +655,7 @@ implementation function inline_copy: tnode; begin - result:=inline_copy_insert_delete(in_copy_x,'Copy',true); + result:=inline_copy_insert_delete(in_copy_x,'Copy',false); end;