ncnv.pas 141 KB

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