ncnv.pas 130 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. Type checking and register allocation for type converting nodes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ncnv;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,
  22. symtype,
  23. defutil,defcmp,
  24. nld
  25. ;
  26. type
  27. ttypeconvnode = class(tunarynode)
  28. totypedef : tdef;
  29. totypedefderef : tderef;
  30. convtype : tconverttype;
  31. warn_pointer_to_signed: boolean;
  32. constructor create(node : tnode;def:tdef);virtual;
  33. constructor create_explicit(node : tnode;def:tdef);
  34. constructor create_internal(node : tnode;def:tdef);
  35. constructor create_proc_to_procvar(node : tnode);
  36. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  37. procedure ppuwrite(ppufile:tcompilerppufile);override;
  38. procedure buildderefimpl;override;
  39. procedure derefimpl;override;
  40. function dogetcopy : tnode;override;
  41. function actualtargetnode: tnode;override;
  42. procedure printnodeinfo(var t : text);override;
  43. function pass_1 : tnode;override;
  44. function pass_typecheck:tnode;override;
  45. function simplify:tnode; override;
  46. procedure mark_write;override;
  47. function docompare(p: tnode) : boolean; override;
  48. function retains_value_location:boolean;
  49. function assign_allowed:boolean;
  50. procedure second_call_helper(c : tconverttype);
  51. private
  52. function typecheck_int_to_int : tnode;
  53. function typecheck_cord_to_pointer : tnode;
  54. function typecheck_chararray_to_string : tnode;
  55. function typecheck_string_to_chararray : tnode;
  56. function typecheck_char_to_string : tnode;
  57. function typecheck_char_to_chararray : tnode;
  58. function typecheck_int_to_real : tnode;
  59. function typecheck_real_to_real : tnode;
  60. function typecheck_real_to_currency : tnode;
  61. function typecheck_cchar_to_pchar : tnode;
  62. function typecheck_cstring_to_pchar : tnode;
  63. function typecheck_cstring_to_int : tnode;
  64. function typecheck_char_to_char : tnode;
  65. function typecheck_arrayconstructor_to_set : tnode;
  66. function typecheck_set_to_set : tnode;
  67. function typecheck_pchar_to_string : tnode;
  68. function typecheck_interface_to_string : tnode;
  69. function typecheck_interface_to_guid : tnode;
  70. function typecheck_dynarray_to_openarray : tnode;
  71. function typecheck_pwchar_to_string : tnode;
  72. function typecheck_variant_to_dynarray : tnode;
  73. function typecheck_dynarray_to_variant : tnode;
  74. function typecheck_call_helper(c : tconverttype) : tnode;
  75. function typecheck_variant_to_enum : tnode;
  76. function typecheck_enum_to_variant : tnode;
  77. function typecheck_proc_to_procvar : tnode;
  78. function typecheck_variant_to_interface : tnode;
  79. function typecheck_interface_to_variant : tnode;
  80. function typecheck_array_2_dynarray : tnode;
  81. protected
  82. function first_int_to_int : tnode;virtual;
  83. function first_cstring_to_pchar : tnode;virtual;
  84. function first_cstring_to_int : tnode;virtual;
  85. function first_string_to_chararray : tnode;virtual;
  86. function first_char_to_string : tnode;virtual;
  87. function first_nothing : tnode;virtual;
  88. function first_array_to_pointer : tnode;virtual;
  89. function first_int_to_real : tnode;virtual;
  90. function first_real_to_real : tnode;virtual;
  91. function first_pointer_to_array : tnode;virtual;
  92. function first_cchar_to_pchar : tnode;virtual;
  93. function first_bool_to_int : tnode;virtual;
  94. function first_int_to_bool : tnode;virtual;
  95. function first_bool_to_bool : tnode;virtual;
  96. function first_proc_to_procvar : tnode;virtual;
  97. function first_nil_to_methodprocvar : tnode;virtual;
  98. function first_set_to_set : tnode;virtual;
  99. function first_cord_to_pointer : tnode;virtual;
  100. function first_ansistring_to_pchar : tnode;virtual;
  101. function first_arrayconstructor_to_set : tnode;virtual;
  102. function first_class_to_intf : tnode;virtual;
  103. function first_char_to_char : tnode;virtual;
  104. function first_string_to_string : tnode;virtual;
  105. function first_call_helper(c : tconverttype) : tnode;
  106. { these wrapper are necessary, because the first_* stuff is called }
  107. { through a table. Without the wrappers override wouldn't have }
  108. { any effect }
  109. function _first_int_to_int : tnode;
  110. function _first_cstring_to_pchar : tnode;
  111. function _first_cstring_to_int : tnode;
  112. function _first_string_to_chararray : tnode;
  113. function _first_char_to_string : tnode;
  114. function _first_nothing : tnode;
  115. function _first_array_to_pointer : tnode;
  116. function _first_int_to_real : tnode;
  117. function _first_real_to_real: tnode;
  118. function _first_pointer_to_array : tnode;
  119. function _first_cchar_to_pchar : tnode;
  120. function _first_bool_to_int : tnode;
  121. function _first_int_to_bool : tnode;
  122. function _first_bool_to_bool : tnode;
  123. function _first_proc_to_procvar : tnode;
  124. function _first_nil_to_methodprocvar : tnode;
  125. function _first_cord_to_pointer : tnode;
  126. function _first_ansistring_to_pchar : tnode;
  127. function _first_arrayconstructor_to_set : tnode;
  128. function _first_class_to_intf : tnode;
  129. function _first_char_to_char : tnode;
  130. function _first_set_to_set : tnode;
  131. function _first_string_to_string : tnode;
  132. procedure _second_int_to_int;virtual;
  133. procedure _second_string_to_string;virtual;
  134. procedure _second_cstring_to_pchar;virtual;
  135. procedure _second_cstring_to_int;virtual;
  136. procedure _second_string_to_chararray;virtual;
  137. procedure _second_array_to_pointer;virtual;
  138. procedure _second_pointer_to_array;virtual;
  139. procedure _second_chararray_to_string;virtual;
  140. procedure _second_char_to_string;virtual;
  141. procedure _second_int_to_real;virtual;
  142. procedure _second_real_to_real;virtual;
  143. procedure _second_cord_to_pointer;virtual;
  144. procedure _second_proc_to_procvar;virtual;
  145. procedure _second_nil_to_methodprocvar;virtual;
  146. procedure _second_bool_to_int;virtual;
  147. procedure _second_int_to_bool;virtual;
  148. procedure _second_bool_to_bool;virtual;
  149. procedure _second_set_to_set;virtual;
  150. procedure _second_ansistring_to_pchar;virtual;
  151. procedure _second_class_to_intf;virtual;
  152. procedure _second_char_to_char;virtual;
  153. procedure _second_nothing; virtual;
  154. procedure second_int_to_int;virtual;abstract;
  155. procedure second_string_to_string;virtual;abstract;
  156. procedure second_cstring_to_pchar;virtual;abstract;
  157. procedure second_cstring_to_int;virtual;abstract;
  158. procedure second_string_to_chararray;virtual;abstract;
  159. procedure second_array_to_pointer;virtual;abstract;
  160. procedure second_pointer_to_array;virtual;abstract;
  161. procedure second_chararray_to_string;virtual;abstract;
  162. procedure second_char_to_string;virtual;abstract;
  163. procedure second_int_to_real;virtual;abstract;
  164. procedure second_real_to_real;virtual;abstract;
  165. procedure second_cord_to_pointer;virtual;abstract;
  166. procedure second_proc_to_procvar;virtual;abstract;
  167. procedure second_nil_to_methodprocvar;virtual;abstract;
  168. procedure second_bool_to_int;virtual;abstract;
  169. procedure second_int_to_bool;virtual;abstract;
  170. procedure second_bool_to_bool;virtual;abstract;
  171. procedure second_set_to_set;virtual;abstract;
  172. procedure second_ansistring_to_pchar;virtual;abstract;
  173. procedure second_class_to_intf;virtual;abstract;
  174. procedure second_char_to_char;virtual;abstract;
  175. procedure second_nothing; virtual;abstract;
  176. end;
  177. ttypeconvnodeclass = class of ttypeconvnode;
  178. tasnode = class(tbinarynode)
  179. call: tnode;
  180. constructor create(l,r : tnode);virtual;
  181. function pass_1 : tnode;override;
  182. function pass_typecheck:tnode;override;
  183. function dogetcopy: tnode;override;
  184. function docompare(p: tnode): boolean; override;
  185. destructor destroy; override;
  186. end;
  187. tasnodeclass = class of tasnode;
  188. tisnode = class(tbinarynode)
  189. constructor create(l,r : tnode);virtual;
  190. function pass_1 : tnode;override;
  191. function pass_typecheck:tnode;override;
  192. procedure pass_generate_code;override;
  193. end;
  194. tisnodeclass = class of tisnode;
  195. var
  196. ctypeconvnode : ttypeconvnodeclass;
  197. casnode : tasnodeclass;
  198. cisnode : tisnodeclass;
  199. procedure inserttypeconv(var p:tnode;def:tdef);
  200. procedure inserttypeconv_internal(var p:tnode;def:tdef);
  201. procedure arrayconstructor_to_set(var p : tnode);
  202. procedure insert_varargstypeconv(var p : tnode; iscvarargs: boolean);
  203. implementation
  204. uses
  205. globtype,systems,constexp,
  206. cutils,verbose,globals,widestr,
  207. symconst,symdef,symsym,symbase,symtable,
  208. ncon,ncal,nset,nadd,ninl,nmem,nmat,nbas,nutils,
  209. cgbase,procinfo,
  210. htypechk,pass_1,cpuinfo;
  211. {*****************************************************************************
  212. Helpers
  213. *****************************************************************************}
  214. procedure inserttypeconv(var p:tnode;def:tdef);
  215. begin
  216. if not assigned(p.resultdef) then
  217. begin
  218. typecheckpass(p);
  219. if codegenerror then
  220. exit;
  221. end;
  222. { don't insert obsolete type conversions }
  223. if equal_defs(p.resultdef,def) then
  224. p.resultdef:=def
  225. else
  226. begin
  227. p:=ctypeconvnode.create(p,def);
  228. p.fileinfo:=ttypeconvnode(p).left.fileinfo;
  229. typecheckpass(p);
  230. end;
  231. end;
  232. procedure inserttypeconv_internal(var p:tnode;def:tdef);
  233. begin
  234. if not assigned(p.resultdef) then
  235. begin
  236. typecheckpass(p);
  237. if codegenerror then
  238. exit;
  239. end;
  240. { don't insert obsolete type conversions }
  241. if equal_defs(p.resultdef,def) then
  242. p.resultdef:=def
  243. else
  244. begin
  245. p:=ctypeconvnode.create_internal(p,def);
  246. p.fileinfo:=ttypeconvnode(p).left.fileinfo;
  247. typecheckpass(p);
  248. end;
  249. end;
  250. {*****************************************************************************
  251. Array constructor to Set Conversion
  252. *****************************************************************************}
  253. procedure arrayconstructor_to_set(var p : tnode);
  254. var
  255. constp : tsetconstnode;
  256. buildp,
  257. p2,p3,p4 : tnode;
  258. hdef : tdef;
  259. constset : Pconstset;
  260. constsetlo,
  261. constsethi : TConstExprInt;
  262. procedure update_constsethi(def:tdef; maybetruncenumrange: boolean);
  263. begin
  264. if (def.typ=orddef) and
  265. ((torddef(def).high>=constsethi) or
  266. (torddef(def).low <=constsetlo)) then
  267. begin
  268. if torddef(def).ordtype=uwidechar then
  269. begin
  270. constsethi:=255;
  271. constsetlo:=0;
  272. if hdef=nil then
  273. hdef:=def;
  274. end
  275. else
  276. begin
  277. if (torddef(def).high>=constsethi) then
  278. constsethi:=torddef(def).high;
  279. if (torddef(def).low<=constsetlo) then
  280. constsetlo:=torddef(def).low;
  281. if hdef=nil then
  282. begin
  283. if (constsethi>255) or
  284. (torddef(def).low<0) then
  285. hdef:=u8inttype
  286. else
  287. hdef:=def;
  288. end;
  289. if constsethi>255 then
  290. constsethi:=255;
  291. if constsetlo<0 then
  292. constsetlo:=0;
  293. end;
  294. end
  295. else if (def.typ=enumdef) and
  296. ((tenumdef(def).max>=constsethi) or
  297. (tenumdef(def).min<=constsetlo)) then
  298. begin
  299. if hdef=nil then
  300. hdef:=def;
  301. if (tenumdef(def).max>=constsethi) then
  302. constsethi:=tenumdef(def).max;
  303. if (tenumdef(def).min<=constsetlo) then
  304. constsetlo:=tenumdef(def).min;
  305. { for constant set elements, delphi allows the usage of elements of enumerations which
  306. have value>255 if there is no element with a value > 255 used }
  307. if (maybetruncenumrange) and
  308. (m_delphi in current_settings.modeswitches) then
  309. begin
  310. if constsethi>255 then
  311. constsethi:=255;
  312. if constsetlo<0 then
  313. constsetlo:=0;
  314. end;
  315. end;
  316. end;
  317. procedure do_set(pos : longint);
  318. begin
  319. if (pos and not $ff)<>0 then
  320. Message(parser_e_illegal_set_expr);
  321. if pos>constsethi then
  322. constsethi:=pos;
  323. if pos<constsetlo then
  324. constsetlo:=pos;
  325. if pos in constset^ then
  326. Message(parser_e_illegal_set_expr);
  327. include(constset^,pos);
  328. end;
  329. var
  330. l : Longint;
  331. lr,hr : TConstExprInt;
  332. hp : tarrayconstructornode;
  333. oldfilepos: tfileposinfo;
  334. begin
  335. if p.nodetype<>arrayconstructorn then
  336. internalerror(200205105);
  337. new(constset);
  338. constset^:=[];
  339. hdef:=nil;
  340. { make sure to set constsetlo correctly for empty sets }
  341. if assigned(tarrayconstructornode(p).left) then
  342. constsetlo:=high(aint)
  343. else
  344. constsetlo:=0;
  345. constsethi:=0;
  346. constp:=csetconstnode.create(nil,hdef);
  347. constp.value_set:=constset;
  348. buildp:=constp;
  349. hp:=tarrayconstructornode(p);
  350. if assigned(hp.left) then
  351. begin
  352. while assigned(hp) do
  353. begin
  354. p4:=nil; { will contain the tree to create the set }
  355. {split a range into p2 and p3 }
  356. if hp.left.nodetype=arrayconstructorrangen then
  357. begin
  358. p2:=tarrayconstructorrangenode(hp.left).left;
  359. p3:=tarrayconstructorrangenode(hp.left).right;
  360. tarrayconstructorrangenode(hp.left).left:=nil;
  361. tarrayconstructorrangenode(hp.left).right:=nil;
  362. end
  363. else
  364. begin
  365. p2:=hp.left;
  366. hp.left:=nil;
  367. p3:=nil;
  368. end;
  369. typecheckpass(p2);
  370. set_varstate(p2,vs_read,[vsf_must_be_valid]);
  371. if assigned(p3) then
  372. begin
  373. typecheckpass(p3);
  374. set_varstate(p3,vs_read,[vsf_must_be_valid]);
  375. end;
  376. if codegenerror then
  377. break;
  378. oldfilepos:=current_filepos;
  379. current_filepos:=p2.fileinfo;
  380. case p2.resultdef.typ of
  381. enumdef,
  382. orddef:
  383. begin
  384. { widechars are not yet supported }
  385. if is_widechar(p2.resultdef) then
  386. begin
  387. inserttypeconv(p2,cchartype);
  388. if (p2.nodetype<>ordconstn) then
  389. incompatibletypes(cwidechartype,cchartype);
  390. end;
  391. getrange(p2.resultdef,lr,hr);
  392. if assigned(p3) then
  393. begin
  394. if is_widechar(p3.resultdef) then
  395. begin
  396. inserttypeconv(p3,cchartype);
  397. if (p3.nodetype<>ordconstn) then
  398. begin
  399. current_filepos:=p3.fileinfo;
  400. incompatibletypes(cwidechartype,cchartype);
  401. end;
  402. end;
  403. { this isn't good, you'll get problems with
  404. type t010 = 0..10;
  405. ts = set of t010;
  406. var s : ts;b : t010
  407. begin s:=[1,2,b]; end.
  408. if is_integer(p3^.resultdef) then
  409. begin
  410. inserttypeconv(p3,u8bitdef);
  411. end;
  412. }
  413. if assigned(hdef) and not(equal_defs(hdef,p3.resultdef)) then
  414. begin
  415. CGMessagePos(p3.fileinfo,type_e_typeconflict_in_set);
  416. end
  417. else
  418. begin
  419. if (p2.nodetype=ordconstn) and (p3.nodetype=ordconstn) then
  420. begin
  421. if not(is_integer(p3.resultdef)) then
  422. hdef:=p3.resultdef
  423. else
  424. begin
  425. inserttypeconv(p3,u8inttype);
  426. inserttypeconv(p2,u8inttype);
  427. end;
  428. for l:=tordconstnode(p2).value.svalue to tordconstnode(p3).value.svalue do
  429. do_set(l);
  430. p2.free;
  431. p3.free;
  432. end
  433. else
  434. begin
  435. update_constsethi(p2.resultdef,false);
  436. inserttypeconv(p2,hdef);
  437. update_constsethi(p3.resultdef,false);
  438. inserttypeconv(p3,hdef);
  439. if assigned(hdef) then
  440. inserttypeconv(p3,hdef)
  441. else
  442. inserttypeconv(p3,u8inttype);
  443. p4:=csetelementnode.create(p2,p3);
  444. end;
  445. end;
  446. end
  447. else
  448. begin
  449. { Single value }
  450. if p2.nodetype=ordconstn then
  451. begin
  452. if not(is_integer(p2.resultdef)) then
  453. update_constsethi(p2.resultdef,true);
  454. if assigned(hdef) then
  455. inserttypeconv(p2,hdef)
  456. else
  457. inserttypeconv(p2,u8inttype);
  458. do_set(tordconstnode(p2).value.svalue);
  459. p2.free;
  460. end
  461. else
  462. begin
  463. update_constsethi(p2.resultdef,false);
  464. if assigned(hdef) then
  465. inserttypeconv(p2,hdef)
  466. else
  467. inserttypeconv(p2,u8inttype);
  468. p4:=csetelementnode.create(p2,nil);
  469. end;
  470. end;
  471. end;
  472. stringdef :
  473. begin
  474. if (p2.nodetype<>stringconstn) then
  475. Message(parser_e_illegal_expression)
  476. { if we've already set elements which are constants }
  477. { throw an error }
  478. else if ((hdef=nil) and assigned(buildp)) or
  479. not(is_char(hdef)) then
  480. CGMessage(type_e_typeconflict_in_set)
  481. else
  482. for l:=1 to length(pshortstring(tstringconstnode(p2).value_str)^) do
  483. do_set(ord(pshortstring(tstringconstnode(p2).value_str)^[l]));
  484. if hdef=nil then
  485. hdef:=cchartype;
  486. p2.free;
  487. end;
  488. else
  489. CGMessage(type_e_ordinal_expr_expected);
  490. end;
  491. { insert the set creation tree }
  492. if assigned(p4) then
  493. buildp:=caddnode.create(addn,buildp,p4);
  494. { load next and dispose current node }
  495. p2:=hp;
  496. hp:=tarrayconstructornode(tarrayconstructornode(p2).right);
  497. tarrayconstructornode(p2).right:=nil;
  498. p2.free;
  499. current_filepos:=oldfilepos;
  500. end;
  501. if (hdef=nil) then
  502. hdef:=u8inttype;
  503. end
  504. else
  505. begin
  506. { empty set [], only remove node }
  507. p.free;
  508. end;
  509. { set the initial set type }
  510. constp.resultdef:=tsetdef.create(hdef,constsetlo.svalue,constsethi.svalue);
  511. { determine the resultdef for the tree }
  512. typecheckpass(buildp);
  513. { set the new tree }
  514. p:=buildp;
  515. end;
  516. procedure insert_varargstypeconv(var p : tnode; iscvarargs: boolean);
  517. begin
  518. { procvars without arguments in variant arrays are always called by
  519. Delphi }
  520. if not(iscvarargs) then
  521. maybe_call_procvar(p,true);
  522. if not(iscvarargs) and
  523. (p.nodetype=stringconstn) then
  524. p:=ctypeconvnode.create_internal(p,cansistringtype)
  525. else
  526. case p.resultdef.typ of
  527. enumdef :
  528. p:=ctypeconvnode.create_internal(p,s32inttype);
  529. arraydef :
  530. begin
  531. if is_chararray(p.resultdef) then
  532. p:=ctypeconvnode.create_internal(p,charpointertype)
  533. else
  534. if is_widechararray(p.resultdef) then
  535. p:=ctypeconvnode.create_internal(p,widecharpointertype)
  536. else
  537. CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
  538. end;
  539. orddef :
  540. begin
  541. if is_integer(p.resultdef) and
  542. not(is_64bitint(p.resultdef)) then
  543. p:=ctypeconvnode.create(p,s32inttype)
  544. else if is_void(p.resultdef) then
  545. CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename)
  546. else if iscvarargs and is_currency(p.resultdef)
  547. and (current_settings.fputype<>fpu_none) then
  548. p:=ctypeconvnode.create(p,s64floattype);
  549. end;
  550. floatdef :
  551. if not(iscvarargs) then
  552. begin
  553. if not(is_currency(p.resultdef)) then
  554. p:=ctypeconvnode.create(p,pbestrealtype^);
  555. end
  556. else
  557. begin
  558. if is_constrealnode(p) and
  559. not(nf_explicit in p.flags) then
  560. MessagePos(p.fileinfo,type_w_double_c_varargs);
  561. if (tfloatdef(p.resultdef).floattype in [s32real,s64currency]) or
  562. (is_constrealnode(p) and
  563. not(nf_explicit in p.flags)) then
  564. p:=ctypeconvnode.create(p,s64floattype);
  565. end;
  566. procvardef :
  567. p:=ctypeconvnode.create(p,voidpointertype);
  568. stringdef:
  569. if iscvarargs then
  570. p:=ctypeconvnode.create(p,charpointertype);
  571. variantdef:
  572. if iscvarargs then
  573. CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
  574. { maybe warn in case it's not using "packrecords c"? }
  575. recorddef:
  576. if not iscvarargs then
  577. CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
  578. pointerdef:
  579. ;
  580. classrefdef:
  581. if iscvarargs then
  582. p:=ctypeconvnode.create(p,voidpointertype);
  583. objectdef :
  584. if (iscvarargs and
  585. not is_objc_class_or_protocol(p.resultdef)) or
  586. is_object(p.resultdef) then
  587. CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
  588. else
  589. CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
  590. end;
  591. typecheckpass(p);
  592. end;
  593. {*****************************************************************************
  594. TTYPECONVNODE
  595. *****************************************************************************}
  596. constructor ttypeconvnode.create(node : tnode;def:tdef);
  597. begin
  598. inherited create(typeconvn,node);
  599. convtype:=tc_none;
  600. totypedef:=def;
  601. if def=nil then
  602. internalerror(200103281);
  603. fileinfo:=node.fileinfo;
  604. {An attempt to convert the result of a floating point division
  605. (with the / operator) to an integer type will fail. Give a hint
  606. to use the div operator.}
  607. if (node.nodetype=slashn) and (def.typ=orddef) then
  608. cgmessage(type_h_use_div_for_int);
  609. {In expressions like int64:=longint+longint, an integer overflow could be avoided
  610. by simply converting the operands to int64 first. Give a hint to do this.}
  611. if (node.nodetype in [addn,subn,muln]) and
  612. (def.typ=orddef) and (node.resultdef<>nil) and (node.resultdef.typ=orddef) and
  613. ((Torddef(node.resultdef).low>=Torddef(def).low) and (Torddef(node.resultdef).high<=Torddef(def).high)) and
  614. ((Torddef(node.resultdef).low>Torddef(def).low) or (Torddef(node.resultdef).high<Torddef(def).high)) then
  615. case node.nodetype of
  616. addn:
  617. cgmessage1(type_h_convert_add_operands_to_prevent_overflow,def.gettypename);
  618. subn:
  619. cgmessage1(type_h_convert_sub_operands_to_prevent_overflow,def.gettypename);
  620. muln:
  621. cgmessage1(type_h_convert_mul_operands_to_prevent_overflow,def.gettypename);
  622. end;
  623. end;
  624. constructor ttypeconvnode.create_explicit(node : tnode;def:tdef);
  625. begin
  626. self.create(node,def);
  627. include(flags,nf_explicit);
  628. end;
  629. constructor ttypeconvnode.create_internal(node : tnode;def:tdef);
  630. begin
  631. self.create(node,def);
  632. { handle like explicit conversions }
  633. include(flags,nf_explicit);
  634. include(flags,nf_internal);
  635. end;
  636. constructor ttypeconvnode.create_proc_to_procvar(node : tnode);
  637. begin
  638. self.create(node,voidtype);
  639. convtype:=tc_proc_2_procvar;
  640. end;
  641. constructor ttypeconvnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  642. begin
  643. inherited ppuload(t,ppufile);
  644. ppufile.getderef(totypedefderef);
  645. convtype:=tconverttype(ppufile.getbyte);
  646. end;
  647. procedure ttypeconvnode.ppuwrite(ppufile:tcompilerppufile);
  648. begin
  649. inherited ppuwrite(ppufile);
  650. ppufile.putderef(totypedefderef);
  651. ppufile.putbyte(byte(convtype));
  652. end;
  653. procedure ttypeconvnode.buildderefimpl;
  654. begin
  655. inherited buildderefimpl;
  656. totypedefderef.build(totypedef);
  657. end;
  658. procedure ttypeconvnode.derefimpl;
  659. begin
  660. inherited derefimpl;
  661. totypedef:=tdef(totypedefderef.resolve);
  662. end;
  663. function ttypeconvnode.dogetcopy : tnode;
  664. var
  665. n : ttypeconvnode;
  666. begin
  667. n:=ttypeconvnode(inherited dogetcopy);
  668. n.convtype:=convtype;
  669. n.totypedef:=totypedef;
  670. dogetcopy:=n;
  671. end;
  672. procedure ttypeconvnode.printnodeinfo(var t : text);
  673. const
  674. convtyp2str : array[tconverttype] of pchar = (
  675. 'tc_none',
  676. 'tc_equal',
  677. 'tc_not_possible',
  678. 'tc_string_2_string',
  679. 'tc_char_2_string',
  680. 'tc_char_2_chararray',
  681. 'tc_pchar_2_string',
  682. 'tc_cchar_2_pchar',
  683. 'tc_cstring_2_pchar',
  684. 'tc_cstring_2_int',
  685. 'tc_ansistring_2_pchar',
  686. 'tc_string_2_chararray',
  687. 'tc_chararray_2_string',
  688. 'tc_array_2_pointer',
  689. 'tc_pointer_2_array',
  690. 'tc_int_2_int',
  691. 'tc_int_2_bool',
  692. 'tc_bool_2_bool',
  693. 'tc_bool_2_int',
  694. 'tc_real_2_real',
  695. 'tc_int_2_real',
  696. 'tc_real_2_currency',
  697. 'tc_proc_2_procvar',
  698. 'tc_nil_2_methodprocvar',
  699. 'tc_arrayconstructor_2_set',
  700. 'tc_set_2_set',
  701. 'tc_cord_2_pointer',
  702. 'tc_intf_2_string',
  703. 'tc_intf_2_guid',
  704. 'tc_class_2_intf',
  705. 'tc_char_2_char',
  706. 'tc_dynarray_2_openarray',
  707. 'tc_pwchar_2_string',
  708. 'tc_variant_2_dynarray',
  709. 'tc_dynarray_2_variant',
  710. 'tc_variant_2_enum',
  711. 'tc_enum_2_variant',
  712. 'tc_interface_2_variant',
  713. 'tc_variant_2_interface',
  714. 'tc_array_2_dynarray'
  715. );
  716. begin
  717. inherited printnodeinfo(t);
  718. write(t,', convtype = ',strpas(convtyp2str[convtype]));
  719. end;
  720. function ttypeconvnode.typecheck_cord_to_pointer : tnode;
  721. begin
  722. result:=nil;
  723. if left.nodetype=ordconstn then
  724. begin
  725. { check if we have a valid pointer constant (JM) }
  726. {$if sizeof(pointer) > sizeof(TConstPtrUInt)}
  727. {$if sizeof(TConstPtrUInt) = 4}
  728. if (tordconstnode(left).value < int64(low(longint))) or
  729. (tordconstnode(left).value > int64(high(cardinal))) then
  730. CGMessage(parser_e_range_check_error);
  731. {$else} {$if sizeof(TConstPtrUInt) = 8}
  732. if (tordconstnode(left).value < int64(low(int64))) or
  733. (tordconstnode(left).value > int64(high(qword))) then
  734. CGMessage(parser_e_range_check_error);
  735. {$else}
  736. internalerror(2001020801);
  737. {$endif} {$endif}
  738. {$endif}
  739. if not(nf_explicit in flags) then
  740. if (tordconstnode(left).value.svalue=0) then
  741. CGMessage(type_w_zero_to_nil)
  742. else
  743. { in Delphi mode, these aren't caught in compare_defs_ext }
  744. IncompatibleTypes(left.resultdef,resultdef);
  745. result:=cpointerconstnode.create(TConstPtrUInt(tordconstnode(left).value.uvalue),resultdef);
  746. end
  747. else
  748. internalerror(200104023);
  749. end;
  750. function ttypeconvnode.typecheck_chararray_to_string : tnode;
  751. var
  752. chartype : string[8];
  753. newblock : tblocknode;
  754. newstat : tstatementnode;
  755. restemp : ttempcreatenode;
  756. begin
  757. if is_widechar(tarraydef(left.resultdef).elementdef) then
  758. chartype:='widechar'
  759. else
  760. chartype:='char';
  761. if tstringdef(resultdef).stringtype=st_shortstring then
  762. begin
  763. newblock:=internalstatements(newstat);
  764. restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  765. addstatement(newstat,restemp);
  766. addstatement(newstat,ccallnode.createintern('fpc_'+chartype+'array_to_shortstr',
  767. ccallparanode.create(cordconstnode.create(
  768. ord(tarraydef(left.resultdef).lowrange=0),booltype,false),
  769. ccallparanode.create(left,ccallparanode.create(
  770. ctemprefnode.create(restemp),nil)))));
  771. addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
  772. addstatement(newstat,ctemprefnode.create(restemp));
  773. result:=newblock;
  774. end
  775. else
  776. result:=ccallnode.createinternres(
  777. 'fpc_'+chartype+'array_to_'+tstringdef(resultdef).stringtypname,
  778. ccallparanode.create(cordconstnode.create(
  779. ord(tarraydef(left.resultdef).lowrange=0),booltype,false),
  780. ccallparanode.create(left,nil)),resultdef);
  781. left:=nil;
  782. end;
  783. function ttypeconvnode.typecheck_string_to_chararray : tnode;
  784. var
  785. newblock : tblocknode;
  786. newstat : tstatementnode;
  787. restemp : ttempcreatenode;
  788. pchtemp : pchar;
  789. arrsize : aint;
  790. chartype : string[8];
  791. begin
  792. result := nil;
  793. with tarraydef(resultdef) do
  794. begin
  795. if highrange<lowrange then
  796. internalerror(200501051);
  797. arrsize := highrange-lowrange+1;
  798. end;
  799. if (left.nodetype = stringconstn) and
  800. (tstringconstnode(left).cst_type=cst_conststring) then
  801. begin
  802. { if the array of char is large enough we can use the string
  803. constant directly. This is handled in ncgcnv }
  804. if (arrsize>=tstringconstnode(left).len) and
  805. is_char(tarraydef(resultdef).elementdef) then
  806. begin
  807. { pad the constant string with #0 to the array len }
  808. { (2.0.x compatible) }
  809. if (arrsize>tstringconstnode(left).len) then
  810. begin
  811. pchtemp:=concatansistrings(tstringconstnode(left).value_str,pchar(StringOfChar(#0,arrsize-tstringconstnode(left).len)),tstringconstnode(left).len,arrsize-tstringconstnode(left).len);
  812. left.free;
  813. left:=cstringconstnode.createpchar(pchtemp,arrsize);
  814. typecheckpass(left);
  815. end;
  816. exit;
  817. end;
  818. { Convert to wide/short/ansistring and call default helper }
  819. if is_widechar(tarraydef(resultdef).elementdef) then
  820. inserttypeconv(left,cwidestringtype)
  821. else
  822. begin
  823. if tstringconstnode(left).len>255 then
  824. inserttypeconv(left,cansistringtype)
  825. else
  826. inserttypeconv(left,cshortstringtype);
  827. end;
  828. end;
  829. if is_widechar(tarraydef(resultdef).elementdef) then
  830. chartype:='widechar'
  831. else
  832. chartype:='char';
  833. newblock:=internalstatements(newstat);
  834. restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  835. addstatement(newstat,restemp);
  836. addstatement(newstat,ccallnode.createintern('fpc_'+tstringdef(left.resultdef).stringtypname+
  837. '_to_'+chartype+'array',ccallparanode.create(left,ccallparanode.create(
  838. ctemprefnode.create(restemp),nil))));
  839. addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
  840. addstatement(newstat,ctemprefnode.create(restemp));
  841. result:=newblock;
  842. left:=nil;
  843. end;
  844. function ttypeconvnode.typecheck_char_to_string : tnode;
  845. var
  846. procname: string[31];
  847. para : tcallparanode;
  848. hp : tstringconstnode;
  849. ws : pcompilerwidestring;
  850. newblock : tblocknode;
  851. newstat : tstatementnode;
  852. restemp : ttempcreatenode;
  853. begin
  854. result:=nil;
  855. { we can't do widechar to ansichar conversions at compile time, since }
  856. { this maps all non-ascii chars to '?' -> loses information }
  857. if (left.nodetype=ordconstn) and
  858. ((tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring]) or
  859. (torddef(left.resultdef).ordtype=uchar) or
  860. { widechar >=128 is destroyed }
  861. (tordconstnode(left).value.uvalue<128)) then
  862. begin
  863. if (tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring]) then
  864. begin
  865. initwidestring(ws);
  866. if torddef(left.resultdef).ordtype=uwidechar then
  867. concatwidestringchar(ws,tcompilerwidechar(tordconstnode(left).value.uvalue))
  868. else
  869. concatwidestringchar(ws,asciichar2unicode(chr(tordconstnode(left).value.uvalue)));
  870. hp:=cstringconstnode.createwstr(ws);
  871. hp.changestringtype(resultdef);
  872. donewidestring(ws);
  873. end
  874. else
  875. begin
  876. if (torddef(left.resultdef).ordtype=uwidechar) then
  877. hp:=cstringconstnode.createstr(unicode2asciichar(tcompilerwidechar(tordconstnode(left).value.uvalue)))
  878. else
  879. hp:=cstringconstnode.createstr(chr(tordconstnode(left).value.uvalue));
  880. tstringconstnode(hp).changestringtype(resultdef);
  881. end;
  882. result:=hp;
  883. end
  884. else
  885. { shortstrings are handled 'inline' (except for widechars) }
  886. if (tstringdef(resultdef).stringtype <> st_shortstring) or
  887. (torddef(left.resultdef).ordtype = uwidechar) then
  888. begin
  889. if (tstringdef(resultdef).stringtype <> st_shortstring) then
  890. begin
  891. { create the procname }
  892. if torddef(left.resultdef).ordtype<>uwidechar then
  893. procname := 'fpc_char_to_'
  894. else
  895. procname := 'fpc_uchar_to_';
  896. procname:=procname+tstringdef(resultdef).stringtypname;
  897. { and the parameter }
  898. para := ccallparanode.create(left,nil);
  899. { and finally the call }
  900. result := ccallnode.createinternres(procname,para,resultdef);
  901. end
  902. else
  903. begin
  904. newblock:=internalstatements(newstat);
  905. restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  906. addstatement(newstat,restemp);
  907. addstatement(newstat,ccallnode.createintern('fpc_wchar_to_shortstr',ccallparanode.create(left,ccallparanode.create(
  908. ctemprefnode.create(restemp),nil))));
  909. addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
  910. addstatement(newstat,ctemprefnode.create(restemp));
  911. result:=newblock;
  912. end;
  913. left := nil;
  914. end
  915. else
  916. begin
  917. { create word(byte(char) shl 8 or 1) for litte endian machines }
  918. { and word(byte(char) or 256) for big endian machines }
  919. left := ctypeconvnode.create_internal(left,u8inttype);
  920. if (target_info.endian = endian_little) then
  921. left := caddnode.create(orn,
  922. cshlshrnode.create(shln,left,cordconstnode.create(8,s32inttype,false)),
  923. cordconstnode.create(1,s32inttype,false))
  924. else
  925. left := caddnode.create(orn,left,
  926. cordconstnode.create(1 shl 8,s32inttype,false));
  927. left := ctypeconvnode.create_internal(left,u16inttype);
  928. typecheckpass(left);
  929. end;
  930. end;
  931. function ttypeconvnode.typecheck_char_to_chararray : tnode;
  932. begin
  933. if resultdef.size <> 1 then
  934. begin
  935. { convert first to string, then to chararray }
  936. inserttypeconv(left,cshortstringtype);
  937. inserttypeconv(left,resultdef);
  938. result:=left;
  939. left := nil;
  940. exit;
  941. end;
  942. result := nil;
  943. end;
  944. function ttypeconvnode.typecheck_char_to_char : tnode;
  945. var
  946. hp : tordconstnode;
  947. begin
  948. result:=nil;
  949. if (left.nodetype=ordconstn) and
  950. ((torddef(resultdef).ordtype<>uchar) or
  951. (torddef(left.resultdef).ordtype<>uwidechar) or
  952. { >= 128 is replaced by '?' currently -> loses information }
  953. (tordconstnode(left).value.uvalue<128)) then
  954. begin
  955. if (torddef(resultdef).ordtype=uchar) and
  956. (torddef(left.resultdef).ordtype=uwidechar) then
  957. begin
  958. hp:=cordconstnode.create(
  959. ord(unicode2asciichar(tcompilerwidechar(tordconstnode(left).value.uvalue))),
  960. cchartype,true);
  961. result:=hp;
  962. end
  963. else if (torddef(resultdef).ordtype=uwidechar) and
  964. (torddef(left.resultdef).ordtype=uchar) then
  965. begin
  966. hp:=cordconstnode.create(
  967. asciichar2unicode(chr(tordconstnode(left).value.uvalue)),
  968. cwidechartype,true);
  969. result:=hp;
  970. end
  971. else
  972. internalerror(200105131);
  973. exit;
  974. end;
  975. end;
  976. function ttypeconvnode.typecheck_int_to_int : tnode;
  977. var
  978. v : TConstExprInt;
  979. begin
  980. result:=nil;
  981. if left.nodetype=ordconstn then
  982. begin
  983. v:=tordconstnode(left).value;
  984. if is_currency(resultdef) then
  985. v:=v*10000;
  986. if (resultdef.typ=pointerdef) then
  987. result:=cpointerconstnode.create(TConstPtrUInt(v.uvalue),resultdef)
  988. else
  989. begin
  990. if is_currency(left.resultdef) then
  991. v:=v div 10000;
  992. result:=cordconstnode.create(v,resultdef,false);
  993. end;
  994. end
  995. else if left.nodetype=pointerconstn then
  996. begin
  997. v:=tpointerconstnode(left).value;
  998. if (resultdef.typ=pointerdef) then
  999. result:=cpointerconstnode.create(v.uvalue,resultdef)
  1000. else
  1001. begin
  1002. if is_currency(resultdef) then
  1003. v:=v*10000;
  1004. result:=cordconstnode.create(v,resultdef,false);
  1005. end;
  1006. end
  1007. else
  1008. begin
  1009. { multiply by 10000 for currency. We need to use getcopy to pass
  1010. the argument because the current node is always disposed. Only
  1011. inserting the multiply in the left node is not possible because
  1012. it'll get in an infinite loop to convert int->currency }
  1013. if is_currency(resultdef) then
  1014. begin
  1015. result:=caddnode.create(muln,getcopy,cordconstnode.create(10000,resultdef,false));
  1016. include(result.flags,nf_is_currency);
  1017. end
  1018. else if is_currency(left.resultdef) then
  1019. begin
  1020. result:=cmoddivnode.create(divn,getcopy,cordconstnode.create(10000,resultdef,false));
  1021. include(result.flags,nf_is_currency);
  1022. end;
  1023. end;
  1024. end;
  1025. function ttypeconvnode.typecheck_int_to_real : tnode;
  1026. var
  1027. rv : bestreal;
  1028. begin
  1029. result:=nil;
  1030. if left.nodetype=ordconstn then
  1031. begin
  1032. rv:=tordconstnode(left).value;
  1033. if is_currency(resultdef) then
  1034. rv:=rv*10000.0
  1035. else if is_currency(left.resultdef) then
  1036. rv:=rv/10000.0;
  1037. result:=crealconstnode.create(rv,resultdef);
  1038. end
  1039. else
  1040. begin
  1041. { multiply by 10000 for currency. We need to use getcopy to pass
  1042. the argument because the current node is always disposed. Only
  1043. inserting the multiply in the left node is not possible because
  1044. it'll get in an infinite loop to convert int->currency }
  1045. if is_currency(resultdef) then
  1046. begin
  1047. result:=caddnode.create(muln,getcopy,crealconstnode.create(10000.0,resultdef));
  1048. include(result.flags,nf_is_currency);
  1049. end
  1050. else if is_currency(left.resultdef) then
  1051. begin
  1052. result:=caddnode.create(slashn,getcopy,crealconstnode.create(10000.0,resultdef));
  1053. include(result.flags,nf_is_currency);
  1054. end;
  1055. end;
  1056. end;
  1057. function ttypeconvnode.typecheck_real_to_currency : tnode;
  1058. begin
  1059. if not is_currency(resultdef) then
  1060. internalerror(200304221);
  1061. result:=nil;
  1062. left:=caddnode.create(muln,left,crealconstnode.create(10000.0,left.resultdef));
  1063. include(left.flags,nf_is_currency);
  1064. typecheckpass(left);
  1065. { Convert constants directly, else call Round() }
  1066. if left.nodetype=realconstn then
  1067. result:=cordconstnode.create(round(trealconstnode(left).value_real),resultdef,false)
  1068. else
  1069. begin
  1070. result:=ccallnode.createinternres('fpc_round_real',
  1071. ccallparanode.create(left,nil),resultdef);
  1072. left:=nil;
  1073. end;
  1074. end;
  1075. function ttypeconvnode.typecheck_real_to_real : tnode;
  1076. begin
  1077. result:=nil;
  1078. if is_currency(left.resultdef) and not(is_currency(resultdef)) then
  1079. begin
  1080. left:=caddnode.create(slashn,left,crealconstnode.create(10000.0,left.resultdef));
  1081. include(left.flags,nf_is_currency);
  1082. typecheckpass(left);
  1083. end
  1084. else
  1085. if is_currency(resultdef) and not(is_currency(left.resultdef)) then
  1086. begin
  1087. left:=caddnode.create(muln,left,crealconstnode.create(10000.0,left.resultdef));
  1088. include(left.flags,nf_is_currency);
  1089. typecheckpass(left);
  1090. end;
  1091. end;
  1092. function ttypeconvnode.typecheck_cchar_to_pchar : tnode;
  1093. begin
  1094. result:=nil;
  1095. if is_pwidechar(resultdef) then
  1096. inserttypeconv(left,cwidestringtype)
  1097. else
  1098. inserttypeconv(left,cshortstringtype);
  1099. { evaluate again, reset resultdef so the convert_typ
  1100. will be calculated again and cstring_to_pchar will
  1101. be used for futher conversion }
  1102. convtype:=tc_none;
  1103. result:=pass_typecheck;
  1104. end;
  1105. function ttypeconvnode.typecheck_cstring_to_pchar : tnode;
  1106. begin
  1107. result:=nil;
  1108. if is_pwidechar(resultdef) then
  1109. inserttypeconv(left,cwidestringtype)
  1110. else
  1111. if is_pchar(resultdef) and
  1112. (is_widestring(left.resultdef) or
  1113. is_unicodestring(left.resultdef)) then
  1114. begin
  1115. inserttypeconv(left,cansistringtype);
  1116. { the second pass of second_cstring_to_pchar expects a }
  1117. { strinconstn, but this may become a call to the }
  1118. { widestring manager in case left contains "high ascii" }
  1119. if (left.nodetype<>stringconstn) then
  1120. begin
  1121. result:=left;
  1122. left:=nil;
  1123. end;
  1124. end;
  1125. end;
  1126. function ttypeconvnode.typecheck_cstring_to_int : tnode;
  1127. var
  1128. fcc : cardinal;
  1129. pb : pbyte;
  1130. begin
  1131. result:=nil;
  1132. if left.nodetype<>stringconstn then
  1133. internalerror(200510012);
  1134. if tstringconstnode(left).len=4 then
  1135. begin
  1136. pb:=pbyte(tstringconstnode(left).value_str);
  1137. fcc:=(pb[0] shl 24) or (pb[1] shl 16) or (pb[2] shl 8) or pb[3];
  1138. result:=cordconstnode.create(fcc,u32inttype,false);
  1139. end
  1140. else
  1141. CGMessage2(type_e_illegal_type_conversion,left.resultdef.GetTypeName,resultdef.GetTypeName);
  1142. end;
  1143. function ttypeconvnode.typecheck_arrayconstructor_to_set : tnode;
  1144. var
  1145. hp : tnode;
  1146. begin
  1147. result:=nil;
  1148. if left.nodetype<>arrayconstructorn then
  1149. internalerror(5546);
  1150. { remove typeconv node }
  1151. hp:=left;
  1152. left:=nil;
  1153. { create a set constructor tree }
  1154. arrayconstructor_to_set(hp);
  1155. result:=hp;
  1156. end;
  1157. function ttypeconvnode.typecheck_set_to_set : tnode;
  1158. begin
  1159. result:=nil;
  1160. { constant sets can be converted by changing the type only }
  1161. if (left.nodetype=setconstn) then
  1162. begin
  1163. left.resultdef:=resultdef;
  1164. result:=left;
  1165. left:=nil;
  1166. exit;
  1167. end;
  1168. end;
  1169. function ttypeconvnode.typecheck_pchar_to_string : tnode;
  1170. var
  1171. newblock : tblocknode;
  1172. newstat : tstatementnode;
  1173. restemp : ttempcreatenode;
  1174. begin
  1175. if tstringdef(resultdef).stringtype=st_shortstring then
  1176. begin
  1177. newblock:=internalstatements(newstat);
  1178. restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  1179. addstatement(newstat,restemp);
  1180. addstatement(newstat,ccallnode.createintern('fpc_pchar_to_shortstr',ccallparanode.create(left,ccallparanode.create(
  1181. ctemprefnode.create(restemp),nil))));
  1182. addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
  1183. addstatement(newstat,ctemprefnode.create(restemp));
  1184. result:=newblock;
  1185. end
  1186. else
  1187. result := ccallnode.createinternres(
  1188. 'fpc_pchar_to_'+tstringdef(resultdef).stringtypname,
  1189. ccallparanode.create(left,nil),resultdef);
  1190. left:=nil;
  1191. end;
  1192. function ttypeconvnode.typecheck_interface_to_string : tnode;
  1193. begin
  1194. if assigned(tobjectdef(left.resultdef).iidstr) then
  1195. begin
  1196. if not(oo_has_valid_guid in tobjectdef(left.resultdef).objectoptions) then
  1197. CGMessage1(type_interface_has_no_guid,tobjectdef(left.resultdef).typename);
  1198. result:=cstringconstnode.createstr(tobjectdef(left.resultdef).iidstr^);
  1199. tstringconstnode(result).changestringtype(cshortstringtype);
  1200. end;
  1201. end;
  1202. function ttypeconvnode.typecheck_interface_to_guid : tnode;
  1203. begin
  1204. if assigned(tobjectdef(left.resultdef).iidguid) then
  1205. begin
  1206. if not(oo_has_valid_guid in tobjectdef(left.resultdef).objectoptions) then
  1207. CGMessage1(type_interface_has_no_guid,tobjectdef(left.resultdef).typename);
  1208. result:=cguidconstnode.create(tobjectdef(left.resultdef).iidguid^);
  1209. end;
  1210. end;
  1211. function ttypeconvnode.typecheck_dynarray_to_openarray : tnode;
  1212. begin
  1213. { a dynamic array is a pointer to an array, so to convert it to }
  1214. { an open array, we have to dereference it (JM) }
  1215. result := ctypeconvnode.create_internal(left,voidpointertype);
  1216. typecheckpass(result);
  1217. { left is reused }
  1218. left := nil;
  1219. result := cderefnode.create(result);
  1220. include(result.flags,nf_no_checkpointer);
  1221. result.resultdef := resultdef;
  1222. end;
  1223. function ttypeconvnode.typecheck_pwchar_to_string : tnode;
  1224. var
  1225. newblock : tblocknode;
  1226. newstat : tstatementnode;
  1227. restemp : ttempcreatenode;
  1228. begin
  1229. if tstringdef(resultdef).stringtype=st_shortstring then
  1230. begin
  1231. newblock:=internalstatements(newstat);
  1232. restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  1233. addstatement(newstat,restemp);
  1234. addstatement(newstat,ccallnode.createintern('fpc_pwidechar_to_shortstr',ccallparanode.create(left,ccallparanode.create(
  1235. ctemprefnode.create(restemp),nil))));
  1236. addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
  1237. addstatement(newstat,ctemprefnode.create(restemp));
  1238. result:=newblock;
  1239. end
  1240. else
  1241. result := ccallnode.createinternres(
  1242. 'fpc_pwidechar_to_'+tstringdef(resultdef).stringtypname,
  1243. ccallparanode.create(left,nil),resultdef);
  1244. left:=nil;
  1245. end;
  1246. function ttypeconvnode.typecheck_variant_to_dynarray : tnode;
  1247. begin
  1248. result := ccallnode.createinternres(
  1249. 'fpc_variant_to_dynarray',
  1250. ccallparanode.create(caddrnode.create_internal(crttinode.create(tstoreddef(resultdef),initrtti,rdt_normal)),
  1251. ccallparanode.create(left,nil)
  1252. ),resultdef);
  1253. typecheckpass(result);
  1254. left:=nil;
  1255. end;
  1256. function ttypeconvnode.typecheck_dynarray_to_variant : tnode;
  1257. begin
  1258. result := ccallnode.createinternres(
  1259. 'fpc_dynarray_to_variant',
  1260. ccallparanode.create(caddrnode.create_internal(crttinode.create(tstoreddef(left.resultdef),initrtti,rdt_normal)),
  1261. ccallparanode.create(ctypeconvnode.create_explicit(left,voidpointertype),nil)
  1262. ),resultdef);
  1263. typecheckpass(result);
  1264. left:=nil;
  1265. end;
  1266. function ttypeconvnode.typecheck_variant_to_interface : tnode;
  1267. begin
  1268. if tobjectdef(resultdef).is_related(tobjectdef(search_system_type('IDISPATCH').typedef)) then
  1269. result := ccallnode.createinternres(
  1270. 'fpc_variant_to_idispatch',
  1271. ccallparanode.create(left,nil)
  1272. ,resultdef)
  1273. else
  1274. result := ccallnode.createinternres(
  1275. 'fpc_variant_to_interface',
  1276. ccallparanode.create(left,nil)
  1277. ,resultdef);
  1278. typecheckpass(result);
  1279. left:=nil;
  1280. end;
  1281. function ttypeconvnode.typecheck_interface_to_variant : tnode;
  1282. begin
  1283. if tobjectdef(left.resultdef).is_related(tobjectdef(search_system_type('IDISPATCH').typedef)) then
  1284. result := ccallnode.createinternres(
  1285. 'fpc_idispatch_to_variant',
  1286. ccallparanode.create(left,nil)
  1287. ,resultdef)
  1288. else
  1289. result := ccallnode.createinternres(
  1290. 'fpc_interface_to_variant',
  1291. ccallparanode.create(left,nil)
  1292. ,resultdef);
  1293. typecheckpass(result);
  1294. left:=nil;
  1295. end;
  1296. function ttypeconvnode.typecheck_variant_to_enum : tnode;
  1297. begin
  1298. result := ctypeconvnode.create_internal(left,sinttype);
  1299. result := ctypeconvnode.create_internal(result,resultdef);
  1300. typecheckpass(result);
  1301. { left is reused }
  1302. left := nil;
  1303. end;
  1304. function ttypeconvnode.typecheck_enum_to_variant : tnode;
  1305. begin
  1306. result := ctypeconvnode.create_internal(left,sinttype);
  1307. result := ctypeconvnode.create_internal(result,cvarianttype);
  1308. typecheckpass(result);
  1309. { left is reused }
  1310. left := nil;
  1311. end;
  1312. function ttypeconvnode.typecheck_array_2_dynarray : tnode;
  1313. var
  1314. newstatement : tstatementnode;
  1315. temp : ttempcreatenode;
  1316. temp2 : ttempcreatenode;
  1317. begin
  1318. { create statements with call to getmem+initialize }
  1319. result:=internalstatements(newstatement);
  1320. { create temp for result }
  1321. temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
  1322. addstatement(newstatement,temp);
  1323. { get temp for array of lengths }
  1324. temp2:=ctempcreatenode.create(sinttype,sinttype.size,tt_persistent,false);
  1325. addstatement(newstatement,temp2);
  1326. { one dimensional }
  1327. addstatement(newstatement,cassignmentnode.create(
  1328. ctemprefnode.create_offset(temp2,0),
  1329. cordconstnode.create
  1330. (tarraydef(left.resultdef).highrange+1,s32inttype,true)));
  1331. { create call to fpc_dynarr_setlength }
  1332. addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',
  1333. ccallparanode.create(caddrnode.create_internal
  1334. (ctemprefnode.create(temp2)),
  1335. ccallparanode.create(cordconstnode.create
  1336. (1,s32inttype,true),
  1337. ccallparanode.create(caddrnode.create_internal
  1338. (crttinode.create(tstoreddef(resultdef),initrtti,rdt_normal)),
  1339. ccallparanode.create(
  1340. ctypeconvnode.create_internal(
  1341. ctemprefnode.create(temp),voidpointertype),
  1342. nil))))
  1343. ));
  1344. addstatement(newstatement,ctempdeletenode.create(temp2));
  1345. { copy ... }
  1346. addstatement(newstatement,cassignmentnode.create(
  1347. ctypeconvnode.create_internal(cderefnode.create(ctypeconvnode.create_internal(ctemprefnode.create(temp),voidpointertype)),left.resultdef),
  1348. left
  1349. ));
  1350. { left is reused }
  1351. left:=nil;
  1352. { the last statement should return the value as
  1353. location and type, this is done be referencing the
  1354. temp and converting it first from a persistent temp to
  1355. normal temp }
  1356. addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
  1357. addstatement(newstatement,ctemprefnode.create(temp));
  1358. end;
  1359. procedure copyparasym(p:TObject;arg:pointer);
  1360. var
  1361. newparast : TSymtable absolute arg;
  1362. vs : tparavarsym;
  1363. begin
  1364. if tsym(p).typ<>paravarsym then
  1365. exit;
  1366. with tparavarsym(p) do
  1367. begin
  1368. vs:=tparavarsym.create(realname,paranr,varspez,vardef,varoptions);
  1369. vs.defaultconstsym:=defaultconstsym;
  1370. newparast.insert(vs);
  1371. end;
  1372. end;
  1373. function ttypeconvnode.typecheck_proc_to_procvar : tnode;
  1374. var
  1375. pd : tabstractprocdef;
  1376. begin
  1377. result:=nil;
  1378. pd:=tabstractprocdef(left.resultdef);
  1379. { create procvardef }
  1380. resultdef:=tprocvardef.create(pd.parast.symtablelevel);
  1381. tprocvardef(resultdef).proctypeoption:=pd.proctypeoption;
  1382. tprocvardef(resultdef).proccalloption:=pd.proccalloption;
  1383. tprocvardef(resultdef).procoptions:=pd.procoptions;
  1384. tprocvardef(resultdef).returndef:=pd.returndef;
  1385. { method ? then set the methodpointer flag }
  1386. if (pd.owner.symtabletype=ObjectSymtable) then
  1387. include(tprocvardef(resultdef).procoptions,po_methodpointer);
  1388. { was it a local procedure? }
  1389. if (pd.owner.symtabletype=localsymtable) then
  1390. include(tprocvardef(resultdef).procoptions,po_local);
  1391. { only need the address of the method? this is needed
  1392. for @tobject.create. In this case there will be a loadn without
  1393. a methodpointer. }
  1394. if (left.nodetype=loadn) and
  1395. not assigned(tloadnode(left).left) then
  1396. include(tprocvardef(resultdef).procoptions,po_addressonly);
  1397. { Add parameters use only references, we don't need to keep the
  1398. parast. We use the parast from the original function to calculate
  1399. our parameter data and reset it afterwards }
  1400. pd.parast.SymList.ForEachCall(@copyparasym,tprocvardef(resultdef).parast);
  1401. tprocvardef(resultdef).calcparas;
  1402. end;
  1403. function ttypeconvnode.typecheck_call_helper(c : tconverttype) : tnode;
  1404. const
  1405. resultdefconvert : array[tconverttype] of pointer = (
  1406. {none} nil,
  1407. {equal} nil,
  1408. {not_possible} nil,
  1409. { string_2_string } nil,
  1410. { char_2_string } @ttypeconvnode.typecheck_char_to_string,
  1411. { char_2_chararray } @ttypeconvnode.typecheck_char_to_chararray,
  1412. { pchar_2_string } @ttypeconvnode.typecheck_pchar_to_string,
  1413. { cchar_2_pchar } @ttypeconvnode.typecheck_cchar_to_pchar,
  1414. { cstring_2_pchar } @ttypeconvnode.typecheck_cstring_to_pchar,
  1415. { cstring_2_int } @ttypeconvnode.typecheck_cstring_to_int,
  1416. { ansistring_2_pchar } nil,
  1417. { string_2_chararray } @ttypeconvnode.typecheck_string_to_chararray,
  1418. { chararray_2_string } @ttypeconvnode.typecheck_chararray_to_string,
  1419. { array_2_pointer } nil,
  1420. { pointer_2_array } nil,
  1421. { int_2_int } @ttypeconvnode.typecheck_int_to_int,
  1422. { int_2_bool } nil,
  1423. { bool_2_bool } nil,
  1424. { bool_2_int } nil,
  1425. { real_2_real } @ttypeconvnode.typecheck_real_to_real,
  1426. { int_2_real } @ttypeconvnode.typecheck_int_to_real,
  1427. { real_2_currency } @ttypeconvnode.typecheck_real_to_currency,
  1428. { proc_2_procvar } @ttypeconvnode.typecheck_proc_to_procvar,
  1429. { nil_2_methodprocvar } nil,
  1430. { arrayconstructor_2_set } @ttypeconvnode.typecheck_arrayconstructor_to_set,
  1431. { set_to_set } @ttypeconvnode.typecheck_set_to_set,
  1432. { cord_2_pointer } @ttypeconvnode.typecheck_cord_to_pointer,
  1433. { intf_2_string } @ttypeconvnode.typecheck_interface_to_string,
  1434. { intf_2_guid } @ttypeconvnode.typecheck_interface_to_guid,
  1435. { class_2_intf } nil,
  1436. { char_2_char } @ttypeconvnode.typecheck_char_to_char,
  1437. { dynarray_2_openarray} @ttypeconvnode.typecheck_dynarray_to_openarray,
  1438. { pwchar_2_string} @ttypeconvnode.typecheck_pwchar_to_string,
  1439. { variant_2_dynarray} @ttypeconvnode.typecheck_variant_to_dynarray,
  1440. { dynarray_2_variant} @ttypeconvnode.typecheck_dynarray_to_variant,
  1441. { variant_2_enum} @ttypeconvnode.typecheck_variant_to_enum,
  1442. { enum_2_variant} @ttypeconvnode.typecheck_enum_to_variant,
  1443. { variant_2_interface} @ttypeconvnode.typecheck_interface_to_variant,
  1444. { interface_2_variant} @ttypeconvnode.typecheck_variant_to_interface,
  1445. { array_2_dynarray} @ttypeconvnode.typecheck_array_2_dynarray
  1446. );
  1447. type
  1448. tprocedureofobject = function : tnode of object;
  1449. var
  1450. r : packed record
  1451. proc : pointer;
  1452. obj : pointer;
  1453. end;
  1454. begin
  1455. result:=nil;
  1456. { this is a little bit dirty but it works }
  1457. { and should be quite portable too }
  1458. r.proc:=resultdefconvert[c];
  1459. r.obj:=self;
  1460. if assigned(r.proc) then
  1461. result:=tprocedureofobject(r)();
  1462. end;
  1463. function ttypeconvnode.actualtargetnode: tnode;
  1464. begin
  1465. result:=self;
  1466. while (result.nodetype=typeconvn) and
  1467. ttypeconvnode(result).retains_value_location do
  1468. result:=ttypeconvnode(result).left;
  1469. end;
  1470. function ttypeconvnode.pass_typecheck:tnode;
  1471. var
  1472. hdef : tdef;
  1473. hp : tnode;
  1474. currprocdef : tabstractprocdef;
  1475. aprocdef : tprocdef;
  1476. eq : tequaltype;
  1477. cdoptions : tcompare_defs_options;
  1478. newblock: tblocknode;
  1479. newstatement: tstatementnode;
  1480. tempnode: ttempcreatenode;
  1481. begin
  1482. result:=nil;
  1483. resultdef:=totypedef;
  1484. typecheckpass(left);
  1485. if codegenerror then
  1486. exit;
  1487. { When absolute force tc_equal }
  1488. if (nf_absolute in flags) then
  1489. begin
  1490. convtype:=tc_equal;
  1491. if not(tstoreddef(resultdef).is_intregable) and
  1492. not(tstoreddef(resultdef).is_fpuregable) then
  1493. make_not_regable(left,[ra_addr_regable]);
  1494. exit;
  1495. end;
  1496. { tp procvar support. Skip typecasts to procvar, record or set. Those
  1497. convert on the procvar value. This is used to access the
  1498. fields of a methodpointer }
  1499. if not(nf_load_procvar in flags) and
  1500. not(resultdef.typ in [procvardef,recorddef,setdef]) then
  1501. maybe_call_procvar(left,true);
  1502. { convert array constructors to sets, because there is no conversion
  1503. possible for array constructors }
  1504. if (resultdef.typ<>arraydef) and
  1505. is_array_constructor(left.resultdef) then
  1506. begin
  1507. arrayconstructor_to_set(left);
  1508. typecheckpass(left);
  1509. end;
  1510. if convtype=tc_none then
  1511. begin
  1512. cdoptions:=[cdo_check_operator,cdo_allow_variant];
  1513. if nf_explicit in flags then
  1514. include(cdoptions,cdo_explicit);
  1515. if nf_internal in flags then
  1516. include(cdoptions,cdo_internal);
  1517. eq:=compare_defs_ext(left.resultdef,resultdef,left.nodetype,convtype,aprocdef,cdoptions);
  1518. case eq of
  1519. te_exact,
  1520. te_equal :
  1521. begin
  1522. result := simplify;
  1523. if assigned(result) then
  1524. exit;
  1525. { Only leave when there is no conversion to do.
  1526. We can still need to call a conversion routine,
  1527. like the routine to convert a stringconstnode }
  1528. if (convtype in [tc_equal,tc_not_possible]) and
  1529. { some conversions, like dynarray to pointer in Delphi
  1530. mode, must not be removed, because then we get memory
  1531. leaks due to missing temp finalization }
  1532. (not is_refcounted_type(left.resultdef) or
  1533. { different kinds of refcounted types may need calls
  1534. to different kinds of refcounting helpers }
  1535. (resultdef=left.resultdef)) then
  1536. begin
  1537. left.resultdef:=resultdef;
  1538. if (nf_explicit in flags) and (left.nodetype = addrn) then
  1539. include(left.flags, nf_typedaddr);
  1540. result:=left;
  1541. left:=nil;
  1542. exit;
  1543. end;
  1544. end;
  1545. te_convert_l1,
  1546. te_convert_l2,
  1547. te_convert_l3,
  1548. te_convert_l4,
  1549. te_convert_l5:
  1550. { nothing to do }
  1551. ;
  1552. te_convert_operator :
  1553. begin
  1554. include(current_procinfo.flags,pi_do_call);
  1555. aprocdef.procsym.IncRefCountBy(1);
  1556. hp:=ccallnode.create(ccallparanode.create(left,nil),Tprocsym(aprocdef.procsym),nil,nil,[]);
  1557. { tell explicitly which def we must use !! (PM) }
  1558. tcallnode(hp).procdefinition:=aprocdef;
  1559. left:=nil;
  1560. result:=hp;
  1561. exit;
  1562. end;
  1563. te_incompatible :
  1564. begin
  1565. { Procedures have a resultdef of voiddef and functions of their
  1566. own resultdef. They will therefore always be incompatible with
  1567. a procvar. Because isconvertable cannot check for procedures we
  1568. use an extra check for them.}
  1569. if (left.nodetype=calln) and
  1570. (tcallnode(left).required_para_count=0) and
  1571. (resultdef.typ=procvardef) and
  1572. (
  1573. (m_tp_procvar in current_settings.modeswitches) or
  1574. (m_mac_procvar in current_settings.modeswitches)
  1575. ) then
  1576. begin
  1577. if assigned(tcallnode(left).right) then
  1578. begin
  1579. { this is already a procvar, if it is really equal
  1580. is checked below }
  1581. convtype:=tc_equal;
  1582. hp:=tcallnode(left).right.getcopy;
  1583. currprocdef:=tabstractprocdef(hp.resultdef);
  1584. end
  1585. else
  1586. begin
  1587. convtype:=tc_proc_2_procvar;
  1588. currprocdef:=Tprocsym(Tcallnode(left).symtableprocentry).Find_procdef_byprocvardef(Tprocvardef(resultdef));
  1589. hp:=cloadnode.create_procvar(tprocsym(tcallnode(left).symtableprocentry),
  1590. tprocdef(currprocdef),tcallnode(left).symtableproc);
  1591. if (tcallnode(left).symtableprocentry.owner.symtabletype=ObjectSymtable) then
  1592. begin
  1593. if assigned(tcallnode(left).methodpointer) then
  1594. tloadnode(hp).set_mp(tcallnode(left).methodpointer.getcopy)
  1595. else
  1596. tloadnode(hp).set_mp(load_self_node);
  1597. end;
  1598. typecheckpass(hp);
  1599. end;
  1600. left.free;
  1601. left:=hp;
  1602. { Now check if the procedure we are going to assign to
  1603. the procvar, is compatible with the procvar's type }
  1604. if not(nf_explicit in flags) and
  1605. (proc_to_procvar_equal(currprocdef,tprocvardef(resultdef))=te_incompatible) then
  1606. IncompatibleTypes(left.resultdef,resultdef);
  1607. exit;
  1608. end;
  1609. { Handle explicit type conversions }
  1610. if nf_explicit in flags then
  1611. begin
  1612. { do common tc_equal cast }
  1613. convtype:=tc_equal;
  1614. { ordinal constants can be resized to 1,2,4,8 bytes }
  1615. if (left.nodetype=ordconstn) then
  1616. begin
  1617. { Insert typeconv for ordinal to the correct size first on left, after
  1618. that the other conversion can be done }
  1619. hdef:=nil;
  1620. case longint(resultdef.size) of
  1621. 1 :
  1622. hdef:=s8inttype;
  1623. 2 :
  1624. hdef:=s16inttype;
  1625. 4 :
  1626. hdef:=s32inttype;
  1627. 8 :
  1628. hdef:=s64inttype;
  1629. end;
  1630. { we need explicit, because it can also be an enum }
  1631. if assigned(hdef) then
  1632. inserttypeconv_internal(left,hdef)
  1633. else
  1634. CGMessage2(type_e_illegal_type_conversion,left.resultdef.GetTypeName,resultdef.GetTypeName);
  1635. end;
  1636. { check if the result could be in a register }
  1637. if (not(tstoreddef(resultdef).is_intregable) and
  1638. not(tstoreddef(resultdef).is_fpuregable)) or
  1639. ((left.resultdef.typ = floatdef) and
  1640. (resultdef.typ <> floatdef)) then
  1641. make_not_regable(left,[ra_addr_regable]);
  1642. { class/interface to class/interface, with checkobject support }
  1643. if is_class_or_interface_or_objc(resultdef) and
  1644. is_class_or_interface_or_objc(left.resultdef) then
  1645. begin
  1646. { check if the types are related }
  1647. if not(nf_internal in flags) and
  1648. (not(tobjectdef(left.resultdef).is_related(tobjectdef(resultdef)))) and
  1649. (not(tobjectdef(resultdef).is_related(tobjectdef(left.resultdef)))) then
  1650. begin
  1651. { Give an error when typecasting class to interface, this is compatible
  1652. with delphi }
  1653. if is_interface(resultdef) and
  1654. not is_interface(left.resultdef) then
  1655. CGMessage2(type_e_classes_not_related,
  1656. FullTypeName(left.resultdef,resultdef),
  1657. FullTypeName(resultdef,left.resultdef))
  1658. else
  1659. CGMessage2(type_w_classes_not_related,
  1660. FullTypeName(left.resultdef,resultdef),
  1661. FullTypeName(resultdef,left.resultdef))
  1662. end;
  1663. { Add runtime check? }
  1664. if not is_objc_class_or_protocol(resultdef) and
  1665. not is_objc_class_or_protocol(left.resultdef) and
  1666. (cs_check_object in current_settings.localswitches) and
  1667. not(nf_internal in flags) then
  1668. begin
  1669. { we can translate the typeconvnode to 'as' when
  1670. typecasting to a class or interface }
  1671. { we need to make sure the result can still be
  1672. passed as a var parameter }
  1673. newblock:=internalstatements(newstatement);
  1674. if (valid_for_var(left,false)) then
  1675. begin
  1676. tempnode:=ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
  1677. addstatement(newstatement,tempnode);
  1678. addstatement(newstatement,cassignmentnode.create(
  1679. ctemprefnode.create(tempnode),
  1680. caddrnode.create_internal(left)));
  1681. left:=ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),left.resultdef);
  1682. end
  1683. else
  1684. begin
  1685. tempnode:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,true);
  1686. addstatement(newstatement,tempnode);
  1687. addstatement(newstatement,cassignmentnode.create(
  1688. ctemprefnode.create(tempnode),
  1689. left));
  1690. left:=ctemprefnode.create(tempnode);
  1691. end;
  1692. addstatement(newstatement,casnode.create(left.getcopy,cloadvmtaddrnode.create(ctypenode.create(resultdef))));
  1693. addstatement(newstatement,ctempdeletenode.create_normal_temp(tempnode));
  1694. addstatement(newstatement,ctypeconvnode.create_internal(left,resultdef));
  1695. left:=nil;
  1696. result:=newblock;
  1697. exit;
  1698. end;
  1699. end
  1700. else
  1701. begin
  1702. { only if the same size or formal def, and }
  1703. { don't allow type casting of constants to }
  1704. { structured types }
  1705. if not(
  1706. (left.resultdef.typ=formaldef) or
  1707. (
  1708. not(is_open_array(left.resultdef)) and
  1709. not(is_array_constructor(left.resultdef)) and
  1710. (left.resultdef.size=resultdef.size) and
  1711. { disallow casts of const nodes }
  1712. (not is_constnode(left) or
  1713. { however, there are some exceptions }
  1714. (not(resultdef.typ in [arraydef,recorddef,setdef,stringdef,
  1715. filedef,variantdef,objectdef]) or
  1716. is_class_or_interface_or_objc(resultdef) or
  1717. { the softfloat code generates casts <const. float> to record }
  1718. (nf_internal in flags)
  1719. ))
  1720. ) or
  1721. (
  1722. is_void(left.resultdef) and
  1723. (left.nodetype=derefn)
  1724. )
  1725. ) then
  1726. CGMessage2(type_e_illegal_type_conversion,left.resultdef.GetTypeName,resultdef.GetTypeName);
  1727. end;
  1728. end
  1729. else
  1730. IncompatibleTypes(left.resultdef,resultdef);
  1731. end;
  1732. else
  1733. internalerror(200211231);
  1734. end;
  1735. end;
  1736. { Give hint or warning for unportable code, exceptions are
  1737. - typecasts from constants
  1738. - void }
  1739. if not(nf_internal in flags) and
  1740. (left.nodetype<>ordconstn) and
  1741. not(is_void(left.resultdef)) and
  1742. (((left.resultdef.typ=orddef) and
  1743. (resultdef.typ in [pointerdef,procvardef,classrefdef])) or
  1744. ((resultdef.typ=orddef) and
  1745. (left.resultdef.typ in [pointerdef,procvardef,classrefdef]))) then
  1746. begin
  1747. {Converting pointers to signed integers is a bad idea. Warn.}
  1748. warn_pointer_to_signed:=(resultdef.typ=orddef) and (Torddef(resultdef).ordtype in [s8bit,s16bit,s32bit,s64bit]);
  1749. { Give a warning when sizes don't match, because then info will be lost }
  1750. if left.resultdef.size=resultdef.size then
  1751. CGMessage(type_h_pointer_to_longint_conv_not_portable)
  1752. else
  1753. CGMessage(type_w_pointer_to_longint_conv_not_portable);
  1754. end;
  1755. { tc_cord_2_pointer still requires a type check, which
  1756. simplify does not do }
  1757. if (convtype<>tc_cord_2_pointer) then
  1758. begin
  1759. result := simplify;
  1760. if assigned(result) then
  1761. exit;
  1762. end;
  1763. { now call the resultdef helper to do constant folding }
  1764. result:=typecheck_call_helper(convtype);
  1765. end;
  1766. {$ifndef cpu64bitalu}
  1767. { checks whether we can safely remove 64 bit typeconversions }
  1768. { in case range and overflow checking are off, and in case }
  1769. { the result of this node tree is downcasted again to a }
  1770. { 8/16/32 bit value afterwards }
  1771. function checkremove64bittypeconvs(n: tnode; out gotsint: boolean): boolean;
  1772. var
  1773. gotmuldivmod: boolean;
  1774. { checks whether a node is either an u32bit, or originally }
  1775. { was one but was implicitly converted to s64bit }
  1776. function wasoriginallyint32(n: tnode): boolean;
  1777. begin
  1778. if (n.resultdef.typ<>orddef) then
  1779. exit(false);
  1780. if (torddef(n.resultdef).ordtype in [s32bit,u32bit]) then
  1781. begin
  1782. if (torddef(n.resultdef).ordtype=s32bit) then
  1783. gotsint:=true;
  1784. exit(true);
  1785. end;
  1786. if (torddef(n.resultdef).ordtype=s64bit) and
  1787. { nf_explicit is also set for explicitly typecasted }
  1788. { ordconstn's }
  1789. ([nf_internal,nf_explicit]*n.flags=[]) and
  1790. { either a typeconversion node coming from u32bit }
  1791. (((n.nodetype=typeconvn) and
  1792. (ttypeconvnode(n).left.resultdef.typ=orddef) and
  1793. (torddef(ttypeconvnode(n).left.resultdef).ordtype in [s32bit,u32bit])) or
  1794. { or an ordconstnode which was/is a valid cardinal }
  1795. ((n.nodetype=ordconstn) and
  1796. (tordconstnode(n).value>=int64(low(longint))) and
  1797. (tordconstnode(n).value<=high(cardinal)))) then
  1798. begin
  1799. if ((n.nodetype=typeconvn) and
  1800. (torddef(ttypeconvnode(n).left.resultdef).ordtype=s32bit)) or
  1801. ((n.nodetype=ordconstn) and
  1802. (tordconstnode(n).value<0)) then
  1803. gotsint:=true;
  1804. exit(true);
  1805. end;
  1806. result:=false;
  1807. end;
  1808. function docheckremove64bittypeconvs(n: tnode): boolean;
  1809. begin
  1810. result:=false;
  1811. if wasoriginallyint32(n) then
  1812. exit(true);
  1813. case n.nodetype of
  1814. subn,orn,xorn:
  1815. begin
  1816. { nf_internal is set by taddnode.typecheckpass in }
  1817. { case the arguments of this subn were u32bit, but }
  1818. { upcasted to s64bit for calculation correctness }
  1819. { (normally only needed when range checking, but }
  1820. { also done otherwise so there is no difference }
  1821. { in overload choosing etc between $r+ and $r-) }
  1822. if (nf_internal in n.flags) then
  1823. result:=true
  1824. else
  1825. result:=
  1826. docheckremove64bittypeconvs(tbinarynode(n).left) and
  1827. docheckremove64bittypeconvs(tbinarynode(n).right);
  1828. end;
  1829. addn,muln,divn,modn,andn:
  1830. begin
  1831. if n.nodetype in [muln,divn,modn] then
  1832. gotmuldivmod:=true;
  1833. result:=
  1834. docheckremove64bittypeconvs(tbinarynode(n).left) and
  1835. docheckremove64bittypeconvs(tbinarynode(n).right);
  1836. end;
  1837. end;
  1838. end;
  1839. begin { checkremove64bittypeconvs }
  1840. gotmuldivmod:=false;
  1841. gotsint:=false;
  1842. result:=
  1843. docheckremove64bittypeconvs(n) and
  1844. not(gotmuldivmod and gotsint);
  1845. end;
  1846. procedure doremove64bittypeconvs(var n: tnode; todef: tdef; forceunsigned: boolean);
  1847. begin
  1848. case n.nodetype of
  1849. subn,addn,muln,divn,modn,xorn,andn,orn:
  1850. begin
  1851. exclude(n.flags,nf_internal);
  1852. if not forceunsigned and
  1853. is_signed(n.resultdef) then
  1854. begin
  1855. doremove64bittypeconvs(tbinarynode(n).left,s32inttype,false);
  1856. doremove64bittypeconvs(tbinarynode(n).right,s32inttype,false);
  1857. n.resultdef:=s32inttype
  1858. end
  1859. else
  1860. begin
  1861. doremove64bittypeconvs(tbinarynode(n).left,u32inttype,forceunsigned);
  1862. doremove64bittypeconvs(tbinarynode(n).right,u32inttype,forceunsigned);
  1863. n.resultdef:=u32inttype
  1864. end;
  1865. end;
  1866. ordconstn:
  1867. inserttypeconv_internal(n,todef);
  1868. typeconvn:
  1869. n.resultdef:=todef;
  1870. end;
  1871. end;
  1872. {$endif not cpu64bitalu}
  1873. function ttypeconvnode.simplify: tnode;
  1874. var
  1875. hp: tnode;
  1876. {$ifndef cpu64bitalu}
  1877. foundsint: boolean;
  1878. {$endif not cpu64bitalu}
  1879. begin
  1880. result := nil;
  1881. { Constant folding and other node transitions to
  1882. remove the typeconv node }
  1883. case left.nodetype of
  1884. stringconstn :
  1885. if (convtype=tc_string_2_string) and
  1886. (
  1887. ((not is_widechararray(left.resultdef) and
  1888. not is_wide_or_unicode_string(left.resultdef)) or
  1889. (tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring]) or
  1890. { non-ascii chars would be replaced with '?' -> loses info }
  1891. not hasnonasciichars(pcompilerwidestring(tstringconstnode(left).value_str)))
  1892. ) then
  1893. begin
  1894. tstringconstnode(left).changestringtype(resultdef);
  1895. result:=left;
  1896. left:=nil;
  1897. exit;
  1898. end;
  1899. realconstn :
  1900. begin
  1901. if (convtype = tc_real_2_currency) then
  1902. result := typecheck_real_to_currency
  1903. else if (convtype = tc_real_2_real) then
  1904. result := typecheck_real_to_real
  1905. else
  1906. exit;
  1907. if not(assigned(result)) then
  1908. begin
  1909. result := left;
  1910. left := nil;
  1911. end;
  1912. if (result.nodetype = realconstn) then
  1913. begin
  1914. hp:=result;
  1915. result:=crealconstnode.create(trealconstnode(hp).value_real,resultdef);
  1916. if ([nf_explicit,nf_internal] * flags <> []) then
  1917. include(result.flags, nf_explicit);
  1918. hp.free;
  1919. end;
  1920. end;
  1921. niln :
  1922. begin
  1923. { nil to ordinal node }
  1924. if (resultdef.typ=orddef) then
  1925. begin
  1926. hp:=cordconstnode.create(0,resultdef,true);
  1927. if ([nf_explicit,nf_internal] * flags <> []) then
  1928. include(hp.flags, nf_explicit);
  1929. result:=hp;
  1930. exit;
  1931. end
  1932. else
  1933. { fold nil to any pointer type }
  1934. if (resultdef.typ=pointerdef) then
  1935. begin
  1936. hp:=cnilnode.create;
  1937. hp.resultdef:=resultdef;
  1938. if ([nf_explicit,nf_internal] * flags <> []) then
  1939. include(hp.flags, nf_explicit);
  1940. result:=hp;
  1941. exit;
  1942. end
  1943. else
  1944. { remove typeconv after niln, but not when the result is a
  1945. methodpointer. The typeconv of the methodpointer will then
  1946. take care of updateing size of niln to OS_64 }
  1947. if not((resultdef.typ=procvardef) and
  1948. (po_methodpointer in tprocvardef(resultdef).procoptions)) then
  1949. begin
  1950. left.resultdef:=resultdef;
  1951. if ([nf_explicit,nf_internal] * flags <> []) then
  1952. include(left.flags, nf_explicit);
  1953. result:=left;
  1954. left:=nil;
  1955. exit;
  1956. end;
  1957. end;
  1958. ordconstn :
  1959. begin
  1960. { ordinal contants can be directly converted }
  1961. { but not char to char because it is a widechar to char or via versa }
  1962. { which needs extra code to do the code page transistion }
  1963. { constant ordinal to pointer }
  1964. if (resultdef.typ=pointerdef) and
  1965. (convtype<>tc_cchar_2_pchar) then
  1966. begin
  1967. hp:=cpointerconstnode.create(TConstPtrUInt(tordconstnode(left).value.uvalue),resultdef);
  1968. if ([nf_explicit,nf_internal] * flags <> []) then
  1969. include(hp.flags, nf_explicit);
  1970. result:=hp;
  1971. exit;
  1972. end
  1973. else if is_ordinal(resultdef) and
  1974. not(convtype=tc_char_2_char) then
  1975. begin
  1976. { replace the resultdef and recheck the range }
  1977. if ([nf_explicit,nf_internal] * flags <> []) then
  1978. include(left.flags, nf_explicit)
  1979. else
  1980. { no longer an ordconst with an explicit typecast }
  1981. exclude(left.flags, nf_explicit);
  1982. { when converting from one boolean type to another, force }
  1983. { booleans to 0/1, and byte/word/long/qwordbool to 0/-1 }
  1984. { (Delphi-compatibile) }
  1985. if is_boolean(left.resultdef) and
  1986. is_boolean(resultdef) and
  1987. (is_cbool(left.resultdef) or
  1988. is_cbool(resultdef)) then
  1989. begin
  1990. if is_pasbool(resultdef) then
  1991. tordconstnode(left).value:=ord(tordconstnode(left).value<>0)
  1992. else
  1993. {$ifdef VER2_2}
  1994. tordconstnode(left).value:=ord(tordconstnode(left).value<>0);
  1995. tordconstnode(left).value:=-tordconstnode(left).value;
  1996. {$else}
  1997. tordconstnode(left).value:=-ord(tordconstnode(left).value<>0);
  1998. {$endif VER2_2}
  1999. end
  2000. else
  2001. testrange(resultdef,tordconstnode(left).value,(nf_explicit in flags));
  2002. left.resultdef:=resultdef;
  2003. result:=left;
  2004. left:=nil;
  2005. exit;
  2006. end;
  2007. end;
  2008. pointerconstn :
  2009. begin
  2010. { pointerconstn to any pointer is folded too }
  2011. if (resultdef.typ=pointerdef) then
  2012. begin
  2013. left.resultdef:=resultdef;
  2014. if ([nf_explicit,nf_internal] * flags <> []) then
  2015. include(left.flags, nf_explicit)
  2016. else
  2017. { no longer an ordconst with an explicit typecast }
  2018. exclude(left.flags, nf_explicit);
  2019. result:=left;
  2020. left:=nil;
  2021. exit;
  2022. end
  2023. { constant pointer to ordinal }
  2024. else if is_ordinal(resultdef) then
  2025. begin
  2026. hp:=cordconstnode.create(TConstExprInt(tpointerconstnode(left).value),
  2027. resultdef,not(nf_explicit in flags));
  2028. if ([nf_explicit,nf_internal] * flags <> []) then
  2029. include(hp.flags, nf_explicit);
  2030. result:=hp;
  2031. exit;
  2032. end;
  2033. end;
  2034. end;
  2035. {$ifndef cpu64bitalu}
  2036. { must be done before code below, because we need the
  2037. typeconversions for ordconstn's as well }
  2038. case convtype of
  2039. tc_int_2_int:
  2040. begin
  2041. if (localswitches * [cs_check_range,cs_check_overflow] = []) and
  2042. (resultdef.typ in [pointerdef,orddef,enumdef]) and
  2043. (resultdef.size <= 4) and
  2044. is_64bitint(left.resultdef) and
  2045. (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn]) and
  2046. checkremove64bittypeconvs(left,foundsint) then
  2047. begin
  2048. { avoid unnecessary widening of intermediary calculations }
  2049. { to 64 bit }
  2050. doremove64bittypeconvs(left,generrordef,not foundsint);
  2051. end;
  2052. end;
  2053. end;
  2054. {$endif not cpu64bitalu}
  2055. end;
  2056. procedure Ttypeconvnode.mark_write;
  2057. begin
  2058. left.mark_write;
  2059. end;
  2060. function ttypeconvnode.first_cord_to_pointer : tnode;
  2061. begin
  2062. result:=nil;
  2063. internalerror(200104043);
  2064. end;
  2065. function ttypeconvnode.first_int_to_int : tnode;
  2066. begin
  2067. first_int_to_int:=nil;
  2068. expectloc:=left.expectloc;
  2069. if not is_void(left.resultdef) then
  2070. begin
  2071. if (left.expectloc<>LOC_REGISTER) and
  2072. (resultdef.size>left.resultdef.size) then
  2073. expectloc:=LOC_REGISTER
  2074. else
  2075. if (left.expectloc=LOC_CREGISTER) and
  2076. (resultdef.size<left.resultdef.size) then
  2077. expectloc:=LOC_REGISTER;
  2078. end;
  2079. end;
  2080. function ttypeconvnode.first_cstring_to_pchar : tnode;
  2081. begin
  2082. result:=nil;
  2083. expectloc:=LOC_REGISTER;
  2084. end;
  2085. function ttypeconvnode.first_cstring_to_int : tnode;
  2086. begin
  2087. result:=nil;
  2088. internalerror(200510014);
  2089. end;
  2090. function ttypeconvnode.first_string_to_chararray : tnode;
  2091. begin
  2092. first_string_to_chararray:=nil;
  2093. expectloc:=left.expectloc;
  2094. end;
  2095. function ttypeconvnode.first_char_to_string : tnode;
  2096. begin
  2097. first_char_to_string:=nil;
  2098. expectloc:=LOC_REFERENCE;
  2099. end;
  2100. function ttypeconvnode.first_nothing : tnode;
  2101. begin
  2102. first_nothing:=nil;
  2103. end;
  2104. function ttypeconvnode.first_array_to_pointer : tnode;
  2105. begin
  2106. first_array_to_pointer:=nil;
  2107. expectloc:=LOC_REGISTER;
  2108. end;
  2109. function ttypeconvnode.first_int_to_real: tnode;
  2110. var
  2111. fname: string[32];
  2112. begin
  2113. if target_info.system in systems_wince then
  2114. begin
  2115. { converting a 64bit integer to a float requires a helper }
  2116. if is_64bitint(left.resultdef) or
  2117. is_currency(left.resultdef) then
  2118. begin
  2119. { hack to avoid double division by 10000, as it's
  2120. already done by typecheckpass.resultdef_int_to_real }
  2121. if is_currency(left.resultdef) then
  2122. left.resultdef := s64inttype;
  2123. if is_signed(left.resultdef) then
  2124. fname:='I64TO'
  2125. else
  2126. fname:='UI64TO';
  2127. end
  2128. else
  2129. { other integers are supposed to be 32 bit }
  2130. begin
  2131. if is_signed(left.resultdef) then
  2132. fname:='ITO'
  2133. else
  2134. fname:='UTO';
  2135. firstpass(left);
  2136. end;
  2137. if tfloatdef(resultdef).floattype=s64real then
  2138. fname:=fname+'D'
  2139. else
  2140. fname:=fname+'S';
  2141. result:=ccallnode.createintern(fname,ccallparanode.create(
  2142. left,nil));
  2143. left:=nil;
  2144. firstpass(result);
  2145. exit;
  2146. end
  2147. else
  2148. begin
  2149. { converting a 64bit integer to a float requires a helper }
  2150. if is_64bitint(left.resultdef) or
  2151. is_currency(left.resultdef) then
  2152. begin
  2153. { hack to avoid double division by 10000, as it's
  2154. already done by typecheckpass.resultdef_int_to_real }
  2155. if is_currency(left.resultdef) then
  2156. left.resultdef := s64inttype;
  2157. if is_signed(left.resultdef) then
  2158. fname:='int64_to_'
  2159. else
  2160. { we can't do better currently }
  2161. fname:='int64_to_';
  2162. end
  2163. else
  2164. { other integers are supposed to be 32 bit }
  2165. begin
  2166. if is_signed(left.resultdef) then
  2167. fname:='int32_to_'
  2168. else
  2169. fname:='int64_to_';
  2170. firstpass(left);
  2171. end;
  2172. if tfloatdef(resultdef).floattype=s64real then
  2173. fname:=fname+'float64'
  2174. else
  2175. fname:=fname+'float32';
  2176. result:=ctypeconvnode.create_internal(ccallnode.createintern(fname,ccallparanode.create(
  2177. left,nil)),resultdef);
  2178. left:=nil;
  2179. firstpass(result);
  2180. exit;
  2181. end;
  2182. end;
  2183. function ttypeconvnode.first_real_to_real : tnode;
  2184. begin
  2185. {$ifdef cpufpemu}
  2186. if cs_fp_emulation in current_settings.moduleswitches then
  2187. begin
  2188. if target_info.system in systems_wince then
  2189. begin
  2190. case tfloatdef(left.resultdef).floattype of
  2191. s32real:
  2192. case tfloatdef(resultdef).floattype of
  2193. s64real:
  2194. result:=ccallnode.createintern('STOD',ccallparanode.create(left,nil));
  2195. s32real:
  2196. begin
  2197. result:=left;
  2198. left:=nil;
  2199. end;
  2200. else
  2201. internalerror(2005082704);
  2202. end;
  2203. s64real:
  2204. case tfloatdef(resultdef).floattype of
  2205. s32real:
  2206. result:=ccallnode.createintern('DTOS',ccallparanode.create(left,nil));
  2207. s64real:
  2208. begin
  2209. result:=left;
  2210. left:=nil;
  2211. end;
  2212. else
  2213. internalerror(2005082703);
  2214. end;
  2215. else
  2216. internalerror(2005082702);
  2217. end;
  2218. left:=nil;
  2219. firstpass(result);
  2220. exit;
  2221. end
  2222. else
  2223. begin
  2224. case tfloatdef(left.resultdef).floattype of
  2225. s32real:
  2226. case tfloatdef(resultdef).floattype of
  2227. s64real:
  2228. result:=ctypeconvnode.create_explicit(ccallnode.createintern('float32_to_float64',ccallparanode.create(
  2229. ctypeconvnode.create_internal(left,search_system_type('FLOAT32REC').typedef),nil)),resultdef);
  2230. s32real:
  2231. begin
  2232. result:=left;
  2233. left:=nil;
  2234. end;
  2235. else
  2236. internalerror(200610151);
  2237. end;
  2238. s64real:
  2239. case tfloatdef(resultdef).floattype of
  2240. s32real:
  2241. result:=ctypeconvnode.create_explicit(ccallnode.createintern('float64_to_float32',ccallparanode.create(
  2242. ctypeconvnode.create_internal(left,search_system_type('FLOAT64').typedef),nil)),resultdef);
  2243. s64real:
  2244. begin
  2245. result:=left;
  2246. left:=nil;
  2247. end;
  2248. else
  2249. internalerror(200610152);
  2250. end;
  2251. else
  2252. internalerror(200610153);
  2253. end;
  2254. left:=nil;
  2255. firstpass(result);
  2256. exit;
  2257. end;
  2258. end
  2259. else
  2260. {$endif cpufpemu}
  2261. begin
  2262. first_real_to_real:=nil;
  2263. if not use_vectorfpu(resultdef) then
  2264. expectloc:=LOC_FPUREGISTER
  2265. else
  2266. expectloc:=LOC_MMREGISTER;
  2267. end;
  2268. end;
  2269. function ttypeconvnode.first_pointer_to_array : tnode;
  2270. begin
  2271. first_pointer_to_array:=nil;
  2272. expectloc:=LOC_REFERENCE;
  2273. end;
  2274. function ttypeconvnode.first_cchar_to_pchar : tnode;
  2275. begin
  2276. first_cchar_to_pchar:=nil;
  2277. internalerror(200104021);
  2278. end;
  2279. function ttypeconvnode.first_bool_to_int : tnode;
  2280. begin
  2281. first_bool_to_int:=nil;
  2282. { byte(boolean) or word(wordbool) or longint(longbool) must
  2283. be accepted for var parameters }
  2284. if (nf_explicit in flags) and
  2285. (left.resultdef.size=resultdef.size) and
  2286. (left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  2287. exit;
  2288. { when converting to 64bit, first convert to a 32bit int and then }
  2289. { convert to a 64bit int (only necessary for 32bit processors) (JM) }
  2290. if resultdef.size > sizeof(aint) then
  2291. begin
  2292. result := ctypeconvnode.create_internal(left,s32inttype);
  2293. result := ctypeconvnode.create(result,resultdef);
  2294. left := nil;
  2295. firstpass(result);
  2296. exit;
  2297. end;
  2298. expectloc:=LOC_REGISTER;
  2299. end;
  2300. function ttypeconvnode.first_int_to_bool : tnode;
  2301. begin
  2302. first_int_to_bool:=nil;
  2303. { byte(boolean) or word(wordbool) or longint(longbool) must
  2304. be accepted for var parameters }
  2305. if (nf_explicit in flags) and
  2306. (left.resultdef.size=resultdef.size) and
  2307. (left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  2308. exit;
  2309. { when converting 64bit int to C-ctyle boolean, first convert to an int32 and then }
  2310. { convert to a boolean (only necessary for 32bit processors) }
  2311. if (left.resultdef.size > sizeof(aint)) and (left.resultdef.size<>resultdef.size)
  2312. and is_cbool(resultdef) then
  2313. begin
  2314. left:=ctypeconvnode.create_internal(left,s32inttype);
  2315. firstpass(left);
  2316. exit;
  2317. end;
  2318. expectloc:=LOC_REGISTER;
  2319. end;
  2320. function ttypeconvnode.first_bool_to_bool : tnode;
  2321. begin
  2322. first_bool_to_bool:=nil;
  2323. if (left.expectloc in [LOC_FLAGS,LOC_JUMP]) then
  2324. expectloc := left.expectloc
  2325. else
  2326. expectloc:=LOC_REGISTER;
  2327. end;
  2328. function ttypeconvnode.first_char_to_char : tnode;
  2329. var
  2330. fname: string[18];
  2331. begin
  2332. if (torddef(resultdef).ordtype=uchar) and
  2333. (torddef(left.resultdef).ordtype=uwidechar) then
  2334. fname := 'fpc_uchar_to_char'
  2335. else if (torddef(resultdef).ordtype=uwidechar) and
  2336. (torddef(left.resultdef).ordtype=uchar) then
  2337. fname := 'fpc_char_to_uchar'
  2338. else
  2339. internalerror(2007081201);
  2340. result := ccallnode.createintern(fname,ccallparanode.create(left,nil));
  2341. left:=nil;
  2342. firstpass(result);
  2343. end;
  2344. function ttypeconvnode.first_proc_to_procvar : tnode;
  2345. begin
  2346. first_proc_to_procvar:=nil;
  2347. { if we take the address of a nested function, it'll }
  2348. { probably be used in a foreach() construct and then }
  2349. { the parent needs a stackframe }
  2350. if (tprocdef(left.resultdef).parast.symtablelevel>=normal_function_level) then
  2351. include(current_procinfo.flags,pi_needs_stackframe);
  2352. if tabstractprocdef(resultdef).is_addressonly then
  2353. expectloc:=LOC_REGISTER
  2354. else
  2355. begin
  2356. if not(left.expectloc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  2357. CGMessage(parser_e_illegal_expression);
  2358. expectloc:=left.expectloc;
  2359. end;
  2360. end;
  2361. function ttypeconvnode.first_nil_to_methodprocvar : tnode;
  2362. begin
  2363. first_nil_to_methodprocvar:=nil;
  2364. expectloc:=LOC_REFERENCE;
  2365. end;
  2366. function ttypeconvnode.first_set_to_set : tnode;
  2367. var
  2368. newstatement : tstatementnode;
  2369. temp : ttempcreatenode;
  2370. begin
  2371. { in theory, we should do range checking here,
  2372. but Delphi doesn't do it either (FK) }
  2373. if left.nodetype=setconstn then
  2374. begin
  2375. left.resultdef:=resultdef;
  2376. result:=left;
  2377. left:=nil;
  2378. end
  2379. { equal sets for the code generator? }
  2380. else if (left.resultdef.size=resultdef.size) and
  2381. (tsetdef(left.resultdef).setbase=tsetdef(resultdef).setbase) then
  2382. { TODO: This causes wrong (but Delphi-compatible) results for disjoint subsets}
  2383. { e.g., this prints true because of this:
  2384. var
  2385. sa: set of 1..2;
  2386. sb: set of 5..6;
  2387. b: byte;
  2388. begin
  2389. b:=1;
  2390. sa:=[1..2];
  2391. sb:=sa;
  2392. writeln(b in sb);
  2393. end.
  2394. }
  2395. begin
  2396. result:=left;
  2397. left:=nil;
  2398. end
  2399. else
  2400. begin
  2401. result:=internalstatements(newstatement);
  2402. { in case left is a smallset expression, it can be an addn or so. }
  2403. { fpc_varset_load expects a formal const parameter, which doesn't }
  2404. { accept set addn's -> assign to a temp first and pass the temp }
  2405. if not(left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  2406. begin
  2407. temp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,false);
  2408. addstatement(newstatement,temp);
  2409. { temp := left }
  2410. addstatement(newstatement,cassignmentnode.create(
  2411. ctemprefnode.create(temp),left));
  2412. addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
  2413. addstatement(newstatement,ctemprefnode.create(temp));
  2414. left:=result;
  2415. firstpass(left);
  2416. { recreate the result's internalstatements list }
  2417. result:=internalstatements(newstatement);
  2418. end;
  2419. { create temp for result }
  2420. temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
  2421. addstatement(newstatement,temp);
  2422. addstatement(newstatement,ccallnode.createintern('fpc_varset_load',
  2423. ccallparanode.create(cordconstnode.create(tsetdef(left.resultdef).setbase div 8 - tsetdef(resultdef).setbase div 8,sinttype,false),
  2424. ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
  2425. ccallparanode.create(ctemprefnode.create(temp),
  2426. ccallparanode.create(cordconstnode.create(left.resultdef.size,sinttype,false),
  2427. ccallparanode.create(left,nil))))))
  2428. );
  2429. addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
  2430. addstatement(newstatement,ctemprefnode.create(temp));
  2431. left:=nil;
  2432. end;
  2433. end;
  2434. function ttypeconvnode.first_ansistring_to_pchar : tnode;
  2435. begin
  2436. first_ansistring_to_pchar:=nil;
  2437. expectloc:=LOC_REGISTER;
  2438. end;
  2439. function ttypeconvnode.first_arrayconstructor_to_set : tnode;
  2440. begin
  2441. first_arrayconstructor_to_set:=nil;
  2442. internalerror(200104022);
  2443. end;
  2444. function ttypeconvnode.first_class_to_intf : tnode;
  2445. var
  2446. hd : tobjectdef;
  2447. ImplIntf : TImplementedInterface;
  2448. begin
  2449. result:=nil;
  2450. expectloc:=LOC_REGISTER;
  2451. hd:=tobjectdef(left.resultdef);
  2452. while assigned(hd) do
  2453. begin
  2454. ImplIntf:=hd.find_implemented_interface(tobjectdef(resultdef));
  2455. if assigned(ImplIntf) then
  2456. begin
  2457. case ImplIntf.IType of
  2458. etStandard:
  2459. { handle in pass 2 }
  2460. ;
  2461. etFieldValue, etFieldValueClass:
  2462. if is_interface(tobjectdef(resultdef)) then
  2463. begin
  2464. result:=left;
  2465. propaccesslist_to_node(result,tpropertysym(implintf.implementsgetter).owner,tpropertysym(implintf.implementsgetter).propaccesslist[palt_read]);
  2466. { this ensures proper refcounting when field is of class type }
  2467. if not is_interface(result.resultdef) then
  2468. inserttypeconv(result, resultdef);
  2469. left:=nil;
  2470. end
  2471. else
  2472. begin
  2473. internalerror(200802213);
  2474. end;
  2475. etStaticMethodResult, etStaticMethodClass,
  2476. etVirtualMethodResult, etVirtualMethodClass:
  2477. if is_interface(tobjectdef(resultdef)) then
  2478. begin
  2479. { TODO: generating a call to TObject.GetInterface instead could yield
  2480. smaller code size. OTOH, refcounting gotchas are possible that way. }
  2481. { constructor create(l:tnode; v : tprocsym;st : TSymtable; mp: tnode; callflags:tcallnodeflags); }
  2482. result:=ccallnode.create(nil,tprocsym(tpropertysym(implintf.implementsgetter).propaccesslist[palt_read].firstsym^.sym),
  2483. tprocsym(tpropertysym(implintf.implementsgetter).propaccesslist[palt_read].firstsym^.sym).owner,
  2484. left,[]);
  2485. addsymref(tpropertysym(implintf.implementsgetter).propaccesslist[palt_read].firstsym^.sym);
  2486. { if it is a class, process it further in a similar way }
  2487. if not is_interface(result.resultdef) then
  2488. inserttypeconv(result, resultdef);
  2489. left:=nil;
  2490. end
  2491. else if is_class(tobjectdef(resultdef)) then
  2492. begin
  2493. internalerror(200802211);
  2494. end
  2495. else
  2496. internalerror(200802231);
  2497. else
  2498. internalerror(200802165);
  2499. end;
  2500. break;
  2501. end;
  2502. hd:=hd.childof;
  2503. end;
  2504. if hd=nil then
  2505. internalerror(200802164);
  2506. end;
  2507. function ttypeconvnode.first_string_to_string : tnode;
  2508. var
  2509. procname: string[31];
  2510. newblock : tblocknode;
  2511. newstat : tstatementnode;
  2512. restemp : ttempcreatenode;
  2513. begin
  2514. { get the correct procedure name }
  2515. procname := 'fpc_'+tstringdef(left.resultdef).stringtypname+
  2516. '_to_'+tstringdef(resultdef).stringtypname;
  2517. if tstringdef(resultdef).stringtype=st_shortstring then
  2518. begin
  2519. newblock:=internalstatements(newstat);
  2520. restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  2521. addstatement(newstat,restemp);
  2522. addstatement(newstat,ccallnode.createintern(procname,ccallparanode.create(left,ccallparanode.create(
  2523. ctemprefnode.create(restemp),nil))));
  2524. addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
  2525. addstatement(newstat,ctemprefnode.create(restemp));
  2526. result:=newblock;
  2527. end
  2528. else
  2529. result := ccallnode.createinternres(procname,ccallparanode.create(left,nil),resultdef);
  2530. left:=nil;
  2531. end;
  2532. function ttypeconvnode._first_int_to_int : tnode;
  2533. begin
  2534. result:=first_int_to_int;
  2535. end;
  2536. function ttypeconvnode._first_cstring_to_pchar : tnode;
  2537. begin
  2538. result:=first_cstring_to_pchar;
  2539. end;
  2540. function ttypeconvnode._first_cstring_to_int : tnode;
  2541. begin
  2542. result:=first_cstring_to_int;
  2543. end;
  2544. function ttypeconvnode._first_string_to_chararray : tnode;
  2545. begin
  2546. result:=first_string_to_chararray;
  2547. end;
  2548. function ttypeconvnode._first_char_to_string : tnode;
  2549. begin
  2550. result:=first_char_to_string;
  2551. end;
  2552. function ttypeconvnode._first_nothing : tnode;
  2553. begin
  2554. result:=first_nothing;
  2555. end;
  2556. function ttypeconvnode._first_array_to_pointer : tnode;
  2557. begin
  2558. result:=first_array_to_pointer;
  2559. end;
  2560. function ttypeconvnode._first_int_to_real : tnode;
  2561. begin
  2562. result:=first_int_to_real;
  2563. end;
  2564. function ttypeconvnode._first_real_to_real : tnode;
  2565. begin
  2566. result:=first_real_to_real;
  2567. end;
  2568. function ttypeconvnode._first_pointer_to_array : tnode;
  2569. begin
  2570. result:=first_pointer_to_array;
  2571. end;
  2572. function ttypeconvnode._first_cchar_to_pchar : tnode;
  2573. begin
  2574. result:=first_cchar_to_pchar;
  2575. end;
  2576. function ttypeconvnode._first_bool_to_int : tnode;
  2577. begin
  2578. result:=first_bool_to_int;
  2579. end;
  2580. function ttypeconvnode._first_int_to_bool : tnode;
  2581. begin
  2582. result:=first_int_to_bool;
  2583. end;
  2584. function ttypeconvnode._first_bool_to_bool : tnode;
  2585. begin
  2586. result:=first_bool_to_bool;
  2587. end;
  2588. function ttypeconvnode._first_proc_to_procvar : tnode;
  2589. begin
  2590. result:=first_proc_to_procvar;
  2591. end;
  2592. function ttypeconvnode._first_nil_to_methodprocvar : tnode;
  2593. begin
  2594. result:=first_nil_to_methodprocvar;
  2595. end;
  2596. function ttypeconvnode._first_set_to_set : tnode;
  2597. begin
  2598. result:=first_set_to_set;
  2599. end;
  2600. function ttypeconvnode._first_cord_to_pointer : tnode;
  2601. begin
  2602. result:=first_cord_to_pointer;
  2603. end;
  2604. function ttypeconvnode._first_ansistring_to_pchar : tnode;
  2605. begin
  2606. result:=first_ansistring_to_pchar;
  2607. end;
  2608. function ttypeconvnode._first_arrayconstructor_to_set : tnode;
  2609. begin
  2610. result:=first_arrayconstructor_to_set;
  2611. end;
  2612. function ttypeconvnode._first_class_to_intf : tnode;
  2613. begin
  2614. result:=first_class_to_intf;
  2615. end;
  2616. function ttypeconvnode._first_char_to_char : tnode;
  2617. begin
  2618. result:=first_char_to_char;
  2619. end;
  2620. function ttypeconvnode._first_string_to_string : tnode;
  2621. begin
  2622. result:=first_string_to_string;
  2623. end;
  2624. function ttypeconvnode.first_call_helper(c : tconverttype) : tnode;
  2625. const
  2626. firstconvert : array[tconverttype] of pointer = (
  2627. nil, { none }
  2628. @ttypeconvnode._first_nothing, {equal}
  2629. @ttypeconvnode._first_nothing, {not_possible}
  2630. @ttypeconvnode._first_string_to_string,
  2631. @ttypeconvnode._first_char_to_string,
  2632. @ttypeconvnode._first_nothing, { char_2_chararray, needs nothing extra }
  2633. nil, { removed in typecheck_chararray_to_string }
  2634. @ttypeconvnode._first_cchar_to_pchar,
  2635. @ttypeconvnode._first_cstring_to_pchar,
  2636. @ttypeconvnode._first_cstring_to_int,
  2637. @ttypeconvnode._first_ansistring_to_pchar,
  2638. @ttypeconvnode._first_string_to_chararray,
  2639. nil, { removed in typecheck_chararray_to_string }
  2640. @ttypeconvnode._first_array_to_pointer,
  2641. @ttypeconvnode._first_pointer_to_array,
  2642. @ttypeconvnode._first_int_to_int,
  2643. @ttypeconvnode._first_int_to_bool,
  2644. @ttypeconvnode._first_bool_to_bool,
  2645. @ttypeconvnode._first_bool_to_int,
  2646. @ttypeconvnode._first_real_to_real,
  2647. @ttypeconvnode._first_int_to_real,
  2648. nil, { removed in typecheck_real_to_currency }
  2649. @ttypeconvnode._first_proc_to_procvar,
  2650. @ttypeconvnode._first_nil_to_methodprocvar,
  2651. @ttypeconvnode._first_arrayconstructor_to_set,
  2652. @ttypeconvnode._first_set_to_set,
  2653. @ttypeconvnode._first_cord_to_pointer,
  2654. @ttypeconvnode._first_nothing,
  2655. @ttypeconvnode._first_nothing,
  2656. @ttypeconvnode._first_class_to_intf,
  2657. @ttypeconvnode._first_char_to_char,
  2658. @ttypeconvnode._first_nothing,
  2659. @ttypeconvnode._first_nothing,
  2660. nil,
  2661. nil,
  2662. nil,
  2663. nil,
  2664. nil,
  2665. nil,
  2666. nil
  2667. );
  2668. type
  2669. tprocedureofobject = function : tnode of object;
  2670. var
  2671. r : packed record
  2672. proc : pointer;
  2673. obj : pointer;
  2674. end;
  2675. begin
  2676. { this is a little bit dirty but it works }
  2677. { and should be quite portable too }
  2678. r.proc:=firstconvert[c];
  2679. r.obj:=self;
  2680. if not assigned(r.proc) then
  2681. internalerror(200312081);
  2682. first_call_helper:=tprocedureofobject(r)()
  2683. end;
  2684. function ttypeconvnode.pass_1 : tnode;
  2685. begin
  2686. if warn_pointer_to_signed then
  2687. cgmessage(type_w_pointer_to_signed);
  2688. result:=nil;
  2689. firstpass(left);
  2690. if codegenerror then
  2691. exit;
  2692. expectloc:=left.expectloc;
  2693. result:=first_call_helper(convtype);
  2694. end;
  2695. function ttypeconvnode.retains_value_location:boolean;
  2696. begin
  2697. result:=(convtype=tc_equal) or
  2698. { typecasting from void is always allowed }
  2699. is_void(left.resultdef) or
  2700. (left.resultdef.typ=formaldef) or
  2701. { int 2 int with same size reuses same location, or for
  2702. tp7 mode also allow size < orignal size }
  2703. (
  2704. (convtype=tc_int_2_int) and
  2705. (
  2706. (resultdef.size=left.resultdef.size) or
  2707. ((m_tp7 in current_settings.modeswitches) and
  2708. (resultdef.size<left.resultdef.size))
  2709. )
  2710. ) or
  2711. { int 2 bool/bool 2 int, explicit typecast, see also nx86cnv }
  2712. ((convtype in [tc_int_2_bool,tc_bool_2_int,tc_bool_2_bool]) and
  2713. (nf_explicit in flags) and
  2714. (resultdef.size=left.resultdef.size));
  2715. end;
  2716. function ttypeconvnode.assign_allowed:boolean;
  2717. begin
  2718. result:=retains_value_location;
  2719. { When using only a part of the value it can't be in a register since
  2720. that will load the value in a new register first }
  2721. { the same goes for changing the sign of equal-sized values which
  2722. are smaller than an entire register }
  2723. if result and
  2724. (resultdef.size<left.resultdef.size) or
  2725. ((resultdef.size=left.resultdef.size) and
  2726. (left.resultdef.size<sizeof(aint)) and
  2727. (is_signed(resultdef) xor is_signed(left.resultdef))) then
  2728. make_not_regable(left,[ra_addr_regable]);
  2729. end;
  2730. function ttypeconvnode.docompare(p: tnode) : boolean;
  2731. begin
  2732. docompare :=
  2733. inherited docompare(p) and
  2734. (convtype = ttypeconvnode(p).convtype) and
  2735. equal_defs(totypedef,ttypeconvnode(p).totypedef);
  2736. end;
  2737. procedure ttypeconvnode._second_int_to_int;
  2738. begin
  2739. second_int_to_int;
  2740. end;
  2741. procedure ttypeconvnode._second_string_to_string;
  2742. begin
  2743. second_string_to_string;
  2744. end;
  2745. procedure ttypeconvnode._second_cstring_to_pchar;
  2746. begin
  2747. second_cstring_to_pchar;
  2748. end;
  2749. procedure ttypeconvnode._second_cstring_to_int;
  2750. begin
  2751. second_cstring_to_int;
  2752. end;
  2753. procedure ttypeconvnode._second_string_to_chararray;
  2754. begin
  2755. second_string_to_chararray;
  2756. end;
  2757. procedure ttypeconvnode._second_array_to_pointer;
  2758. begin
  2759. second_array_to_pointer;
  2760. end;
  2761. procedure ttypeconvnode._second_pointer_to_array;
  2762. begin
  2763. second_pointer_to_array;
  2764. end;
  2765. procedure ttypeconvnode._second_chararray_to_string;
  2766. begin
  2767. second_chararray_to_string;
  2768. end;
  2769. procedure ttypeconvnode._second_char_to_string;
  2770. begin
  2771. second_char_to_string;
  2772. end;
  2773. procedure ttypeconvnode._second_int_to_real;
  2774. begin
  2775. second_int_to_real;
  2776. end;
  2777. procedure ttypeconvnode._second_real_to_real;
  2778. begin
  2779. second_real_to_real;
  2780. end;
  2781. procedure ttypeconvnode._second_cord_to_pointer;
  2782. begin
  2783. second_cord_to_pointer;
  2784. end;
  2785. procedure ttypeconvnode._second_proc_to_procvar;
  2786. begin
  2787. second_proc_to_procvar;
  2788. end;
  2789. procedure ttypeconvnode._second_nil_to_methodprocvar;
  2790. begin
  2791. second_nil_to_methodprocvar;
  2792. end;
  2793. procedure ttypeconvnode._second_bool_to_int;
  2794. begin
  2795. second_bool_to_int;
  2796. end;
  2797. procedure ttypeconvnode._second_int_to_bool;
  2798. begin
  2799. second_int_to_bool;
  2800. end;
  2801. procedure ttypeconvnode._second_bool_to_bool;
  2802. begin
  2803. second_bool_to_bool;
  2804. end;
  2805. procedure ttypeconvnode._second_set_to_set;
  2806. begin
  2807. second_set_to_set;
  2808. end;
  2809. procedure ttypeconvnode._second_ansistring_to_pchar;
  2810. begin
  2811. second_ansistring_to_pchar;
  2812. end;
  2813. procedure ttypeconvnode._second_class_to_intf;
  2814. begin
  2815. second_class_to_intf;
  2816. end;
  2817. procedure ttypeconvnode._second_char_to_char;
  2818. begin
  2819. second_char_to_char;
  2820. end;
  2821. procedure ttypeconvnode._second_nothing;
  2822. begin
  2823. second_nothing;
  2824. end;
  2825. procedure ttypeconvnode.second_call_helper(c : tconverttype);
  2826. const
  2827. secondconvert : array[tconverttype] of pointer = (
  2828. @ttypeconvnode._second_nothing, {none}
  2829. @ttypeconvnode._second_nothing, {equal}
  2830. @ttypeconvnode._second_nothing, {not_possible}
  2831. @ttypeconvnode._second_nothing, {second_string_to_string, handled in resultdef pass }
  2832. @ttypeconvnode._second_char_to_string,
  2833. @ttypeconvnode._second_nothing, {char_to_charray}
  2834. @ttypeconvnode._second_nothing, { pchar_to_string, handled in resultdef pass }
  2835. @ttypeconvnode._second_nothing, {cchar_to_pchar}
  2836. @ttypeconvnode._second_cstring_to_pchar,
  2837. @ttypeconvnode._second_cstring_to_int,
  2838. @ttypeconvnode._second_ansistring_to_pchar,
  2839. @ttypeconvnode._second_string_to_chararray,
  2840. @ttypeconvnode._second_nothing, { chararray_to_string, handled in resultdef pass }
  2841. @ttypeconvnode._second_array_to_pointer,
  2842. @ttypeconvnode._second_pointer_to_array,
  2843. @ttypeconvnode._second_int_to_int,
  2844. @ttypeconvnode._second_int_to_bool,
  2845. @ttypeconvnode._second_bool_to_bool,
  2846. @ttypeconvnode._second_bool_to_int,
  2847. @ttypeconvnode._second_real_to_real,
  2848. @ttypeconvnode._second_int_to_real,
  2849. @ttypeconvnode._second_nothing, { real_to_currency, handled in resultdef pass }
  2850. @ttypeconvnode._second_proc_to_procvar,
  2851. @ttypeconvnode._second_nil_to_methodprocvar,
  2852. @ttypeconvnode._second_nothing, { arrayconstructor_to_set }
  2853. @ttypeconvnode._second_nothing, { second_set_to_set, handled in first pass }
  2854. @ttypeconvnode._second_cord_to_pointer,
  2855. @ttypeconvnode._second_nothing, { interface 2 string }
  2856. @ttypeconvnode._second_nothing, { interface 2 guid }
  2857. @ttypeconvnode._second_class_to_intf,
  2858. @ttypeconvnode._second_char_to_char,
  2859. @ttypeconvnode._second_nothing, { dynarray_2_openarray }
  2860. @ttypeconvnode._second_nothing, { pwchar_2_string }
  2861. @ttypeconvnode._second_nothing, { variant_2_dynarray }
  2862. @ttypeconvnode._second_nothing, { dynarray_2_variant}
  2863. @ttypeconvnode._second_nothing, { variant_2_enum }
  2864. @ttypeconvnode._second_nothing, { enum_2_variant }
  2865. @ttypeconvnode._second_nothing, { variant_2_interface }
  2866. @ttypeconvnode._second_nothing, { interface_2_variant }
  2867. @ttypeconvnode._second_nothing { array_2_dynarray }
  2868. );
  2869. type
  2870. tprocedureofobject = procedure of object;
  2871. var
  2872. r : packed record
  2873. proc : pointer;
  2874. obj : pointer;
  2875. end;
  2876. begin
  2877. { this is a little bit dirty but it works }
  2878. { and should be quite portable too }
  2879. r.proc:=secondconvert[c];
  2880. r.obj:=self;
  2881. tprocedureofobject(r)();
  2882. end;
  2883. {*****************************************************************************
  2884. TISNODE
  2885. *****************************************************************************}
  2886. constructor tisnode.create(l,r : tnode);
  2887. begin
  2888. inherited create(isn,l,r);
  2889. end;
  2890. function tisnode.pass_typecheck:tnode;
  2891. var
  2892. paras: tcallparanode;
  2893. begin
  2894. result:=nil;
  2895. typecheckpass(left);
  2896. typecheckpass(right);
  2897. set_varstate(left,vs_read,[vsf_must_be_valid]);
  2898. set_varstate(right,vs_read,[vsf_must_be_valid]);
  2899. if codegenerror then
  2900. exit;
  2901. { Passing a class type to an "is" expression cannot result in a class
  2902. of that type to be constructed.
  2903. }
  2904. include(right.flags,nf_ignore_for_wpo);
  2905. if (right.resultdef.typ=classrefdef) then
  2906. begin
  2907. { left must be a class }
  2908. if is_class(left.resultdef) then
  2909. begin
  2910. { the operands must be related }
  2911. if (not(tobjectdef(left.resultdef).is_related(
  2912. tobjectdef(tclassrefdef(right.resultdef).pointeddef)))) and
  2913. (not(tobjectdef(tclassrefdef(right.resultdef).pointeddef).is_related(
  2914. tobjectdef(left.resultdef)))) then
  2915. CGMessage2(type_e_classes_not_related,left.resultdef.typename,
  2916. tclassrefdef(right.resultdef).pointeddef.typename);
  2917. end
  2918. else
  2919. CGMessage1(type_e_class_type_expected,left.resultdef.typename);
  2920. { call fpc_do_is helper }
  2921. paras := ccallparanode.create(
  2922. left,
  2923. ccallparanode.create(
  2924. right,nil));
  2925. result := ccallnode.createintern('fpc_do_is',paras);
  2926. left := nil;
  2927. right := nil;
  2928. end
  2929. else if is_interface(right.resultdef) then
  2930. begin
  2931. { left is a class }
  2932. if is_class(left.resultdef) then
  2933. begin
  2934. { the class must implement the interface }
  2935. if tobjectdef(left.resultdef).find_implemented_interface(tobjectdef(right.resultdef))=nil then
  2936. CGMessage2(type_e_classes_not_related,
  2937. FullTypeName(left.resultdef,right.resultdef),
  2938. FullTypeName(right.resultdef,left.resultdef))
  2939. end
  2940. { left is an interface }
  2941. else if is_interface(left.resultdef) then
  2942. begin
  2943. { the operands must be related }
  2944. if (not(tobjectdef(left.resultdef).is_related(tobjectdef(right.resultdef)))) and
  2945. (not(tobjectdef(right.resultdef).is_related(tobjectdef(left.resultdef)))) then
  2946. CGMessage2(type_e_classes_not_related,
  2947. FullTypeName(left.resultdef,right.resultdef),
  2948. FullTypeName(right.resultdef,left.resultdef));
  2949. end
  2950. else
  2951. CGMessage1(type_e_class_type_expected,left.resultdef.typename);
  2952. { call fpc_do_is helper }
  2953. paras := ccallparanode.create(
  2954. left,
  2955. ccallparanode.create(
  2956. right,nil));
  2957. result := ccallnode.createintern('fpc_do_is',paras);
  2958. left := nil;
  2959. right := nil;
  2960. end
  2961. else
  2962. CGMessage1(type_e_class_or_interface_type_expected,right.resultdef.typename);
  2963. resultdef:=booltype;
  2964. end;
  2965. function tisnode.pass_1 : tnode;
  2966. begin
  2967. internalerror(200204254);
  2968. result:=nil;
  2969. end;
  2970. { dummy pass_2, it will never be called, but we need one since }
  2971. { you can't instantiate an abstract class }
  2972. procedure tisnode.pass_generate_code;
  2973. begin
  2974. end;
  2975. {*****************************************************************************
  2976. TASNODE
  2977. *****************************************************************************}
  2978. constructor tasnode.create(l,r : tnode);
  2979. begin
  2980. inherited create(asn,l,r);
  2981. call := nil;
  2982. end;
  2983. destructor tasnode.destroy;
  2984. begin
  2985. call.free;
  2986. inherited destroy;
  2987. end;
  2988. function tasnode.pass_typecheck:tnode;
  2989. var
  2990. hp : tnode;
  2991. begin
  2992. result:=nil;
  2993. typecheckpass(right);
  2994. typecheckpass(left);
  2995. set_varstate(right,vs_read,[vsf_must_be_valid]);
  2996. set_varstate(left,vs_read,[vsf_must_be_valid]);
  2997. if codegenerror then
  2998. exit;
  2999. if (right.resultdef.typ=classrefdef) then
  3000. begin
  3001. { left must be a class }
  3002. if is_class(left.resultdef) then
  3003. begin
  3004. { the operands must be related }
  3005. if (not(tobjectdef(left.resultdef).is_related(
  3006. tobjectdef(tclassrefdef(right.resultdef).pointeddef)))) and
  3007. (not(tobjectdef(tclassrefdef(right.resultdef).pointeddef).is_related(
  3008. tobjectdef(left.resultdef)))) then
  3009. CGMessage2(type_e_classes_not_related,
  3010. FullTypeName(left.resultdef,tclassrefdef(right.resultdef).pointeddef),
  3011. FullTypeName(tclassrefdef(right.resultdef).pointeddef,left.resultdef));
  3012. end
  3013. else
  3014. CGMessage1(type_e_class_type_expected,left.resultdef.typename);
  3015. resultdef:=tclassrefdef(right.resultdef).pointeddef;
  3016. end
  3017. else if is_interface(right.resultdef) or is_dispinterface(right.resultdef) then
  3018. begin
  3019. { left is a class }
  3020. if not(is_class(left.resultdef) or
  3021. is_interfacecom(left.resultdef)) then
  3022. CGMessage1(type_e_class_or_cominterface_type_expected,left.resultdef.typename);
  3023. resultdef:=right.resultdef;
  3024. { load the GUID of the interface }
  3025. if (right.nodetype=typen) then
  3026. begin
  3027. if tobjectdef(right.resultdef).objecttype=odt_interfacecorba then
  3028. begin
  3029. if assigned(tobjectdef(right.resultdef).iidstr) then
  3030. begin
  3031. hp:=cstringconstnode.createstr(tobjectdef(right.resultdef).iidstr^);
  3032. tstringconstnode(hp).changestringtype(cshortstringtype);
  3033. right.free;
  3034. right:=hp;
  3035. end
  3036. else
  3037. internalerror(200902081);
  3038. end
  3039. else
  3040. begin
  3041. if assigned(tobjectdef(right.resultdef).iidguid) then
  3042. begin
  3043. if not(oo_has_valid_guid in tobjectdef(right.resultdef).objectoptions) then
  3044. CGMessage1(type_interface_has_no_guid,tobjectdef(right.resultdef).typename);
  3045. hp:=cguidconstnode.create(tobjectdef(right.resultdef).iidguid^);
  3046. right.free;
  3047. right:=hp;
  3048. end
  3049. else
  3050. internalerror(200206282);
  3051. end;
  3052. typecheckpass(right);
  3053. end;
  3054. end
  3055. else
  3056. CGMessage1(type_e_class_or_interface_type_expected,right.resultdef.typename);
  3057. end;
  3058. function tasnode.dogetcopy: tnode;
  3059. begin
  3060. result := inherited dogetcopy;
  3061. if assigned(call) then
  3062. tasnode(result).call := call.getcopy
  3063. else
  3064. tasnode(result).call := nil;
  3065. end;
  3066. function tasnode.docompare(p: tnode): boolean;
  3067. begin
  3068. result:=
  3069. inherited docompare(p) and
  3070. tasnode(p).call.isequal(call);
  3071. end;
  3072. function tasnode.pass_1 : tnode;
  3073. var
  3074. procname: string;
  3075. begin
  3076. result:=nil;
  3077. { Passing a class type to an "as" expression cannot result in a class
  3078. of that type to be constructed.
  3079. }
  3080. include(right.flags,nf_ignore_for_wpo);
  3081. if not assigned(call) then
  3082. begin
  3083. if is_class(left.resultdef) and
  3084. (right.resultdef.typ=classrefdef) then
  3085. call := ccallnode.createinternres('fpc_do_as',
  3086. ccallparanode.create(left,ccallparanode.create(right,nil)),
  3087. resultdef)
  3088. else
  3089. begin
  3090. if is_class(left.resultdef) then
  3091. if is_shortstring(right.resultdef) then
  3092. procname := 'fpc_class_as_corbaintf'
  3093. else
  3094. procname := 'fpc_class_as_intf'
  3095. else
  3096. procname := 'fpc_intf_as';
  3097. call := ccallnode.createintern(procname,
  3098. ccallparanode.create(right,ccallparanode.create(left,nil)));
  3099. call := ctypeconvnode.create_internal(call,resultdef);
  3100. end;
  3101. left := nil;
  3102. right := nil;
  3103. firstpass(call);
  3104. if codegenerror then
  3105. exit;
  3106. expectloc:=call.expectloc;
  3107. end;
  3108. end;
  3109. begin
  3110. ctypeconvnode:=ttypeconvnode;
  3111. casnode:=tasnode;
  3112. cisnode:=tisnode;
  3113. end.