218
cclasses,globtype,systems,
219
220
cutils,verbose,globals,widestr,
220
221
symconst,symdef,symsym,symbase,symtable,
221
222
ncon,ncal,nset,nadd,ninl,nmem,nmat,nbas,nutils,
295
296
constsethi : TConstExprInt;
297
procedure update_constsethi(def:tdef);
298
procedure update_constsethi(def:tdef; maybetruncenumrange: boolean);
299
if ((def.typ=orddef) and
300
(torddef(def).high>=constsethi)) then
300
if (def.typ=orddef) and
301
((torddef(def).high>=constsethi) or
302
(torddef(def).low <=constsetlo)) then
302
304
if torddef(def).ordtype=uwidechar then
310
constsethi:=torddef(def).high;
313
if (torddef(def).high>=constsethi) then
314
constsethi:=torddef(def).high;
315
if (torddef(def).low<=constsetlo) then
316
constsetlo:=torddef(def).low;
313
319
if (constsethi>255) or
319
325
if constsethi>255 then
323
else if ((def.typ=enumdef) and
324
(tenumdef(def).max>=constsethi)) then
331
else if (def.typ=enumdef) and
332
((tenumdef(def).max>=constsethi) or
333
(tenumdef(def).min<=constsetlo)) then
328
constsethi:=tenumdef(def).max;
337
if (tenumdef(def).max>=constsethi) then
338
constsethi:=tenumdef(def).max;
339
if (tenumdef(def).min<=constsetlo) then
340
constsetlo:=tenumdef(def).min;
341
{ for constant set elements, delphi allows the usage of elements of enumerations which
342
have value>255 if there is no element with a value > 255 used }
343
if (maybetruncenumrange) and
344
(m_delphi in current_settings.modeswitches) then
346
if constsethi>255 then
387
413
if codegenerror then
415
current_filepos:=p2.fileinfo;
389
416
case p2.resultdef.typ of
420
{ widechars are not yet supported }
421
if is_widechar(p2.resultdef) then
423
inserttypeconv(p2,cchartype);
424
if (p2.nodetype<>ordconstn) then
425
incompatibletypes(cwidechartype,cchartype);
393
428
getrange(p2.resultdef,lr,hr);
394
429
if assigned(p3) then
431
if is_widechar(p3.resultdef) then
433
inserttypeconv(p3,cchartype);
434
if (p3.nodetype<>ordconstn) then
436
current_filepos:=p3.fileinfo;
437
incompatibletypes(cwidechartype,cchartype);
396
440
{ this isn't good, you'll get problems with
397
441
type t010 = 0..10;
398
442
ts = set of t010;
447
490
if p2.nodetype=ordconstn then
449
492
if not(is_integer(p2.resultdef)) then
451
{ for constant set elements, delphi allows the usage of elements of enumerations which
452
have value>255 if there is no element with a value > 255 used }
453
if (m_delphi in current_settings.modeswitches) and (p2.resultdef.typ=enumdef) then
455
if tordconstnode(p2).value>constsethi then
456
constsethi:=tordconstnode(p2).value;
461
update_constsethi(p2.resultdef);
493
update_constsethi(p2.resultdef,true);
464
495
if assigned(hdef) then
465
496
inserttypeconv(p2,hdef)
568
599
if is_constrealnode(p) and
569
600
not(nf_explicit in p.flags) then
570
601
MessagePos(p.fileinfo,type_w_double_c_varargs);
571
if (tfloatdef(p.resultdef).floattype in [{$ifndef x86_64}s32real,{$endif}s64currency]) or
572
{ win64 requires the double type cast for singles as well }
573
((tfloatdef(p.resultdef).floattype=s32real) and (target_info.system=system_x86_64_win64)) or
602
if (tfloatdef(p.resultdef).floattype in [s32real,s64currency]) or
574
603
(is_constrealnode(p) and
575
604
not(nf_explicit in p.flags)) then
576
605
p:=ctypeconvnode.create(p,s64floattype);
613
642
internalerror(200103281);
614
643
fileinfo:=node.fileinfo;
644
{An attempt to convert the result of a floating point division
645
(with the / operator) to an integer type will fail. Give a hint
646
to use the div operator.}
647
if (node.nodetype=slashn) and (def.typ=orddef) then
648
cgmessage(type_h_use_div_for_int);
649
{In expressions like int64:=longint+longint, an integer overflow could be avoided
650
by simply converting the operands to int64 first. Give a hint to do this.}
651
if (node.nodetype in [addn,subn,muln]) and
652
(def.typ=orddef) and (node.resultdef<>nil) and (node.resultdef.typ=orddef) and
653
((Torddef(node.resultdef).low>=Torddef(def).low) and (Torddef(node.resultdef).high<=Torddef(def).high)) and
654
((Torddef(node.resultdef).low>Torddef(def).low) or (Torddef(node.resultdef).high<Torddef(def).high)) then
655
case node.nodetype of
657
cgmessage1(type_h_convert_add_operands_to_prevent_overflow,def.gettypename);
659
cgmessage1(type_h_convert_sub_operands_to_prevent_overflow,def.gettypename);
661
cgmessage1(type_h_convert_mul_operands_to_prevent_overflow,def.gettypename);
767
815
function ttypeconvnode.typecheck_chararray_to_string : tnode;
769
817
chartype : string[8];
818
newblock : tblocknode;
819
newstat : tstatementnode;
820
restemp : ttempcreatenode;
771
822
if is_widechar(tarraydef(left.resultdef).elementdef) then
772
823
chartype:='widechar'
774
825
chartype:='char';
775
result := ccallnode.createinternres(
776
'fpc_'+chartype+'array_to_'+tstringdef(resultdef).stringtypname,
777
ccallparanode.create(cordconstnode.create(
778
ord(tarraydef(left.resultdef).lowrange=0),booltype,false),
779
ccallparanode.create(left,nil)),resultdef);
826
if tstringdef(resultdef).stringtype=st_shortstring then
828
newblock:=internalstatements(newstat);
829
restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
830
addstatement(newstat,restemp);
831
addstatement(newstat,ccallnode.createintern('fpc_'+chartype+'array_to_shortstr',
832
ccallparanode.create(cordconstnode.create(
833
ord(tarraydef(left.resultdef).lowrange=0),booltype,false),
834
ccallparanode.create(left,ccallparanode.create(
835
ctemprefnode.create(restemp),nil)))));
836
addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
837
addstatement(newstat,ctemprefnode.create(restemp));
841
result:=ccallnode.createinternres(
842
'fpc_'+chartype+'array_to_'+tstringdef(resultdef).stringtypname,
843
ccallparanode.create(cordconstnode.create(
844
ord(tarraydef(left.resultdef).lowrange=0),booltype,false),
845
ccallparanode.create(left,nil)),resultdef);
847
913
function ttypeconvnode.typecheck_string_to_string : tnode;
850
915
procname: string[31];
851
stringpara : tcallparanode;
916
newblock : tblocknode;
917
newstat : tstatementnode;
918
restemp : ttempcreatenode;
855
if left.nodetype=stringconstn then
921
if (left.nodetype=stringconstn) and
922
((not is_widechararray(left.resultdef) and
923
not is_widestring(left.resultdef)) or
924
(tstringdef(resultdef).stringtype=st_widestring) or
925
{ non-ascii chars would be replaced with '?' -> loses info }
926
not hasnonasciichars(pcompilerwidestring(tstringconstnode(left).value_str))) then
857
928
tstringconstnode(left).changestringtype(resultdef);
863
934
{ get the correct procedure name }
864
935
procname := 'fpc_'+tstringdef(left.resultdef).stringtypname+
865
936
'_to_'+tstringdef(resultdef).stringtypname;
867
{ create parameter (and remove left node from typeconvnode }
868
{ since it's reused as parameter) }
869
stringpara := ccallparanode.create(left,nil);
872
{ when converting to shortstrings, we have to pass high(destination) too }
873
if (tstringdef(resultdef).stringtype = st_shortstring) then
874
stringpara.right := ccallparanode.create(cinlinenode.create(
875
in_high_x,false,self.getcopy),nil);
877
{ and create the callnode }
878
result := ccallnode.createinternres(procname,stringpara,resultdef);
938
if tstringdef(resultdef).stringtype=st_shortstring then
940
newblock:=internalstatements(newstat);
941
restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
942
addstatement(newstat,restemp);
943
addstatement(newstat,ccallnode.createintern(procname,ccallparanode.create(left,ccallparanode.create(
944
ctemprefnode.create(restemp),nil))));
945
addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
946
addstatement(newstat,ctemprefnode.create(restemp));
950
result := ccallnode.createinternres(procname,ccallparanode.create(left,nil),resultdef);
887
960
para : tcallparanode;
888
961
hp : tstringconstnode;
889
962
ws : pcompilerwidestring;
963
newblock : tblocknode;
964
newstat : tstatementnode;
965
restemp : ttempcreatenode;
893
if left.nodetype=ordconstn then
969
{ we can't do widechar to ansichar conversions at compile time, since }
970
{ this maps all non-ascii chars to '?' -> loses information }
971
if (left.nodetype=ordconstn) and
972
((tstringdef(resultdef).stringtype=st_widestring) or
973
(torddef(left.resultdef).ordtype=uchar) or
974
{ >=128 is destroyed }
975
(tordconstnode(left).value<128)) then
895
977
if tstringdef(resultdef).stringtype=st_widestring then
907
hp:=cstringconstnode.createstr(chr(tordconstnode(left).value));
989
if torddef(left.resultdef).ordtype=uwidechar then
990
hp:=cstringconstnode.createstr(unicode2asciichar(tcompilerwidechar(tordconstnode(left).value)))
992
hp:=cstringconstnode.createstr(chr(tordconstnode(left).value));
908
993
tstringconstnode(hp).changestringtype(resultdef);
913
{ shortstrings are handled 'inline' }
914
if tstringdef(resultdef).stringtype <> st_shortstring then
998
{ shortstrings are handled 'inline' (except for widechars) }
999
if (tstringdef(resultdef).stringtype <> st_shortstring) or
1000
(torddef(left.resultdef).ordtype = uwidechar) then
916
{ create the parameter }
917
para := ccallparanode.create(left,nil);
1002
if (tstringdef(resultdef).stringtype <> st_shortstring) then
1004
{ create the procname }
1005
if torddef(left.resultdef).ordtype<>uwidechar then
1006
procname := 'fpc_char_to_'
1008
procname := 'fpc_wchar_to_';
1009
procname:=procname+tstringdef(resultdef).stringtypname;
1011
{ and the parameter }
1012
para := ccallparanode.create(left,nil);
1014
{ and finally the call }
1015
result := ccallnode.createinternres(procname,para,resultdef);
1019
newblock:=internalstatements(newstat);
1020
restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
1021
addstatement(newstat,restemp);
1022
addstatement(newstat,ccallnode.createintern('fpc_wchar_to_shortstr',ccallparanode.create(left,ccallparanode.create(
1023
ctemprefnode.create(restemp),nil))));
1024
addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
1025
addstatement(newstat,ctemprefnode.create(restemp));
921
procname := 'fpc_char_to_' +tstringdef(resultdef).stringtypname;
923
{ and finally the call }
924
result := ccallnode.createinternres(procname,para,resultdef);
967
if left.nodetype=ordconstn then
1071
if (left.nodetype=ordconstn) and
1072
((torddef(resultdef).ordtype<>uchar) or
1073
(torddef(left.resultdef).ordtype<>uwidechar) or
1074
{ >= 128 is replaced by '?' currently -> loses information }
1075
(tordconstnode(left).value<128)) then
969
1077
if (torddef(resultdef).ordtype=uchar) and
970
1078
(torddef(left.resultdef).ordtype=uwidechar) then
1139
1247
if is_pchar(resultdef) and
1140
1248
is_widestring(left.resultdef) then
1141
inserttypeconv(left,cansistringtype);
1250
inserttypeconv(left,cansistringtype);
1251
{ the second pass of second_cstring_to_pchar expects a }
1252
{ strinconstn, but this may become a call to the }
1253
{ widestring manager in case left contains "high ascii" }
1254
if (left.nodetype<>stringconstn) then
1194
1312
function ttypeconvnode.typecheck_pchar_to_string : tnode;
1314
newblock : tblocknode;
1315
newstat : tstatementnode;
1316
restemp : ttempcreatenode;
1196
result := ccallnode.createinternres(
1197
'fpc_pchar_to_'+tstringdef(resultdef).stringtypname,
1198
ccallparanode.create(left,nil),resultdef);
1318
if tstringdef(resultdef).stringtype=st_shortstring then
1320
newblock:=internalstatements(newstat);
1321
restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
1322
addstatement(newstat,restemp);
1323
addstatement(newstat,ccallnode.createintern('fpc_pchar_to_shortstr',ccallparanode.create(left,ccallparanode.create(
1324
ctemprefnode.create(restemp),nil))));
1325
addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
1326
addstatement(newstat,ctemprefnode.create(restemp));
1330
result := ccallnode.createinternres(
1331
'fpc_pchar_to_'+tstringdef(resultdef).stringtypname,
1332
ccallparanode.create(left,nil),resultdef);
1203
1337
function ttypeconvnode.typecheck_interface_to_guid : tnode;
1205
1339
if assigned(tobjectdef(left.resultdef).iidguid) then
1206
result:=cguidconstnode.create(tobjectdef(left.resultdef).iidguid^);
1341
if not(oo_has_valid_guid in tobjectdef(left.resultdef).objectoptions) then
1342
CGMessage1(type_interface_has_no_guid,tobjectdef(left.resultdef).typename);
1343
result:=cguidconstnode.create(tobjectdef(left.resultdef).iidguid^);
1224
1362
function ttypeconvnode.typecheck_pwchar_to_string : tnode;
1364
newblock : tblocknode;
1365
newstat : tstatementnode;
1366
restemp : ttempcreatenode;
1226
result := ccallnode.createinternres(
1227
'fpc_pwidechar_to_'+tstringdef(resultdef).stringtypname,
1228
ccallparanode.create(left,nil),resultdef);
1368
if tstringdef(resultdef).stringtype=st_shortstring then
1370
newblock:=internalstatements(newstat);
1371
restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
1372
addstatement(newstat,restemp);
1373
addstatement(newstat,ccallnode.createintern('fpc_pwidechar_to_shortstr',ccallparanode.create(left,ccallparanode.create(
1374
ctemprefnode.create(restemp),nil))));
1375
addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
1376
addstatement(newstat,ctemprefnode.create(restemp));
1380
result := ccallnode.createinternres(
1381
'fpc_pwidechar_to_'+tstringdef(resultdef).stringtypname,
1382
ccallparanode.create(left,nil),resultdef);
1658
1814
not(tstoreddef(resultdef).is_fpuregable)) or
1659
1815
((left.resultdef.typ = floatdef) and
1660
1816
(resultdef.typ <> floatdef)) then
1661
make_not_regable(left,vr_addr);
1817
make_not_regable(left,[ra_addr_regable]);
1663
1819
{ class/interface to class/interface, with checkobject support }
1664
1820
if is_class_or_interface(resultdef) and
1723
{ only if the same size or formal def }
1879
{ only if the same size or formal def, and }
1880
{ don't allow type casting of constants to }
1881
{ structured types }
1725
1883
(left.resultdef.typ=formaldef) or
1727
1885
not(is_open_array(left.resultdef)) and
1728
1886
not(is_array_constructor(left.resultdef)) and
1729
(left.resultdef.size=resultdef.size)
1887
(left.resultdef.size=resultdef.size) and
1888
{ disallow casts of const nodes }
1889
(not is_constnode(left) or
1890
{ however, there are some exceptions }
1891
(not(resultdef.typ in [arraydef,recorddef,setdef,stringdef,
1892
filedef,variantdef,objectdef]) or
1893
is_class_or_interface(resultdef) or
1894
{ the softfloat code generates casts <const. float> to record }
1895
(nf_internal in flags)
1732
1899
is_void(left.resultdef) and
1755
1922
((resultdef.typ=orddef) and
1756
1923
(left.resultdef.typ in [pointerdef,procvardef,classrefdef]))) then
1925
{Converting pointers to signed integers is a bad idea. Warn.}
1926
warn_pointer_to_signed:=(resultdef.typ=orddef) and (Torddef(resultdef).ordtype in [s8bit,s16bit,s32bit,s64bit]);
1758
1927
{ Give a warning when sizes don't match, because then info will be lost }
1759
1928
if left.resultdef.size=resultdef.size then
1760
1929
CGMessage(type_h_pointer_to_longint_conv_not_portable)
2227
2396
function ttypeconvnode.first_char_to_char : tnode;
2230
first_char_to_char:=first_int_to_int;
2400
if (torddef(resultdef).ordtype=uchar) and
2401
(torddef(left.resultdef).ordtype=uwidechar) then
2402
fname := 'fpc_wchar_to_char'
2403
else if (torddef(resultdef).ordtype=uwidechar) and
2404
(torddef(left.resultdef).ordtype=uchar) then
2405
fname := 'fpc_char_to_wchar'
2407
internalerror(2007081201);
2409
result := ccallnode.createintern(fname,ccallparanode.create(left,nil));
2280
2460
{ equal sets for the code generator? }
2281
2461
else if (left.resultdef.size=resultdef.size) and
2282
2462
(tsetdef(left.resultdef).setbase=tsetdef(resultdef).setbase) then
2463
{$warning This causes wrong (but Delphi-compatible) results for disjoint subsets}
2464
{ e.g., this prints true because of this:
2285
2478
// if is_varset(resultdef) then
2287
2480
result:=internalstatements(newstatement);
2482
{ in case left is a smallset expression, it can be an addn or so. }
2483
{ fpc_varset_load expects a formal const parameter, which doesn't }
2484
{ accept set addn's -> assign to a temp first and pass the temp }
2485
if not(left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE]) then
2487
temp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,false);
2488
addstatement(newstatement,temp);
2490
addstatement(newstatement,cassignmentnode.create(
2491
ctemprefnode.create(temp),left));
2492
addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
2493
addstatement(newstatement,ctemprefnode.create(temp));
2496
{ recreate the result's internalstatements list }
2497
result:=internalstatements(newstatement);
2289
2500
{ create temp for result }
2290
2501
temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
2291
addstatement(newstatement,temp);
2502
addstatement(newstatement,temp);
2293
2504
addstatement(newstatement,ccallnode.createintern('fpc_varset_load',
2505
ccallparanode.create(cordconstnode.create(tsetdef(left.resultdef).setbase div 8 - tsetdef(resultdef).setbase div 8,sinttype,false),
2294
2506
ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
2295
2507
ccallparanode.create(ctemprefnode.create(temp),
2296
2508
ccallparanode.create(cordconstnode.create(left.resultdef.size,sinttype,false),
2297
ccallparanode.create(left,nil)))))
2509
ccallparanode.create(left,nil))))))
2299
2511
addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
2300
2512
addstatement(newstatement,ctemprefnode.create(temp));