defcmp.pas 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Compare definitions and parameter lists
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit defcmp;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cclasses,
  23. cpuinfo,
  24. globtype,globals,tokens,
  25. node,
  26. symconst,symbase,symtype,symdef;
  27. type
  28. { if acp is cp_all the var const or nothing are considered equal }
  29. tcompare_paras_type = ( cp_none, cp_value_equal_const, cp_all,cp_procvar);
  30. tcompare_paras_option = (cpo_allowdefaults,cpo_ignorehidden,cpo_allowconvert,cpo_comparedefaultvalue);
  31. tcompare_paras_options = set of tcompare_paras_option;
  32. tcompare_defs_option = (cdo_explicit,cdo_check_operator,cdo_allow_variant);
  33. tcompare_defs_options = set of tcompare_defs_option;
  34. tconverttype = (
  35. tc_equal,
  36. tc_not_possible,
  37. tc_string_2_string,
  38. tc_char_2_string,
  39. tc_char_2_chararray,
  40. tc_pchar_2_string,
  41. tc_cchar_2_pchar,
  42. tc_cstring_2_pchar,
  43. tc_ansistring_2_pchar,
  44. tc_string_2_chararray,
  45. tc_chararray_2_string,
  46. tc_array_2_pointer,
  47. tc_pointer_2_array,
  48. tc_int_2_int,
  49. tc_int_2_bool,
  50. tc_bool_2_bool,
  51. tc_bool_2_int,
  52. tc_real_2_real,
  53. tc_int_2_real,
  54. tc_real_2_currency,
  55. tc_proc_2_procvar,
  56. tc_arrayconstructor_2_set,
  57. tc_load_smallset,
  58. tc_cord_2_pointer,
  59. tc_intf_2_string,
  60. tc_intf_2_guid,
  61. tc_class_2_intf,
  62. tc_char_2_char,
  63. tc_normal_2_smallset,
  64. tc_dynarray_2_openarray,
  65. tc_pwchar_2_string,
  66. tc_variant_2_dynarray,
  67. tc_dynarray_2_variant,
  68. tc_variant_2_enum,
  69. tc_enum_2_variant
  70. );
  71. function compare_defs_ext(def_from,def_to : tdef;
  72. fromtreetype : tnodetype;
  73. var doconv : tconverttype;
  74. var operatorpd : tprocdef;
  75. cdoptions:tcompare_defs_options):tequaltype;
  76. { Returns if the type def_from can be converted to def_to or if both types are equal }
  77. function compare_defs(def_from,def_to:tdef;fromtreetype:tnodetype):tequaltype;
  78. { Returns true, if def1 and def2 are semantically the same }
  79. function equal_defs(def_from,def_to:tdef):boolean;
  80. { Checks for type compatibility (subgroups of type)
  81. used for case statements... probably missing stuff
  82. to use on other types }
  83. function is_subequal(def1, def2: tdef): boolean;
  84. {# true, if two parameter lists are equal
  85. if acp is cp_none, all have to match exactly
  86. if acp is cp_value_equal_const call by value
  87. and call by const parameter are assumed as
  88. equal
  89. allowdefaults indicates if default value parameters
  90. are allowed (in this case, the search order will first
  91. search for a routine with default parameters, before
  92. searching for the same definition with no parameters)
  93. }
  94. function compare_paras(paralist1,paralist2 : TLinkedList; acp : tcompare_paras_type; cpoptions: tcompare_paras_options):tequaltype;
  95. { True if a function can be assigned to a procvar }
  96. { changed first argument type to pabstractprocdef so that it can also be }
  97. { used to test compatibility between two pprocvardefs (JM) }
  98. function proc_to_procvar_equal(def1:tabstractprocdef;def2:tprocvardef;methoderr:boolean):tequaltype;
  99. implementation
  100. uses
  101. verbose,systems,
  102. symtable,symsym,
  103. defutil,symutil;
  104. function compare_defs_ext(def_from,def_to : tdef;
  105. fromtreetype : tnodetype;
  106. var doconv : tconverttype;
  107. var operatorpd : tprocdef;
  108. cdoptions:tcompare_defs_options):tequaltype;
  109. { Tbasetype:
  110. uvoid,
  111. u8bit,u16bit,u32bit,u64bit,
  112. s8bit,s16bit,s32bit,s64bit,
  113. bool8bit,bool16bit,bool32bit,
  114. uchar,uwidechar }
  115. type
  116. tbasedef=(bvoid,bchar,bint,bbool);
  117. const
  118. basedeftbl:array[tbasetype] of tbasedef =
  119. (bvoid,
  120. bint,bint,bint,bint,
  121. bint,bint,bint,bint,
  122. bbool,bbool,bbool,
  123. bchar,bchar,bint);
  124. basedefconvertsimplicit : array[tbasedef,tbasedef] of tconverttype =
  125. { void, char, int, bool }
  126. ((tc_not_possible,tc_not_possible,tc_not_possible,tc_not_possible),
  127. (tc_not_possible,tc_char_2_char,tc_not_possible,tc_not_possible),
  128. (tc_not_possible,tc_not_possible,tc_int_2_int,tc_not_possible),
  129. (tc_not_possible,tc_not_possible,tc_not_possible,tc_bool_2_bool));
  130. basedefconvertsexplicit : array[tbasedef,tbasedef] of tconverttype =
  131. { void, char, int, bool }
  132. ((tc_not_possible,tc_not_possible,tc_not_possible,tc_not_possible),
  133. (tc_not_possible,tc_char_2_char,tc_int_2_int,tc_int_2_bool),
  134. (tc_not_possible,tc_int_2_int,tc_int_2_int,tc_int_2_bool),
  135. (tc_not_possible,tc_bool_2_int,tc_bool_2_int,tc_bool_2_bool));
  136. var
  137. subeq,eq : tequaltype;
  138. hd1,hd2 : tdef;
  139. hct : tconverttype;
  140. hd3 : tobjectdef;
  141. hpd : tprocdef;
  142. begin
  143. { safety check }
  144. if not(assigned(def_from) and assigned(def_to)) then
  145. begin
  146. compare_defs_ext:=te_incompatible;
  147. exit;
  148. end;
  149. { same def? then we've an exact match }
  150. if def_from=def_to then
  151. begin
  152. compare_defs_ext:=te_exact;
  153. exit;
  154. end;
  155. { we walk the wanted (def_to) types and check then the def_from
  156. types if there is a conversion possible }
  157. eq:=te_incompatible;
  158. doconv:=tc_not_possible;
  159. case def_to.deftype of
  160. orddef :
  161. begin
  162. case def_from.deftype of
  163. orddef :
  164. begin
  165. if (torddef(def_from).typ=torddef(def_to).typ) then
  166. begin
  167. case torddef(def_from).typ of
  168. uchar,uwidechar,
  169. u8bit,u16bit,u32bit,u64bit,
  170. s8bit,s16bit,s32bit,s64bit:
  171. begin
  172. if (torddef(def_from).low=torddef(def_to).low) and
  173. (torddef(def_from).high=torddef(def_to).high) then
  174. eq:=te_equal
  175. else
  176. begin
  177. doconv:=tc_int_2_int;
  178. eq:=te_convert_l1;
  179. end;
  180. end;
  181. uvoid,
  182. bool8bit,bool16bit,bool32bit:
  183. eq:=te_equal;
  184. else
  185. internalerror(200210061);
  186. end;
  187. end
  188. else
  189. begin
  190. if cdo_explicit in cdoptions then
  191. doconv:=basedefconvertsexplicit[basedeftbl[torddef(def_from).typ],basedeftbl[torddef(def_to).typ]]
  192. else
  193. doconv:=basedefconvertsimplicit[basedeftbl[torddef(def_from).typ],basedeftbl[torddef(def_to).typ]];
  194. if (doconv=tc_not_possible) then
  195. eq:=te_incompatible
  196. else
  197. { "punish" bad type conversions :) (JM) }
  198. if (not is_in_limit(def_from,def_to)) and
  199. (def_from.size > def_to.size) then
  200. eq:=te_convert_l3
  201. else
  202. eq:=te_convert_l1;
  203. end;
  204. end;
  205. enumdef :
  206. begin
  207. { needed for char(enum) }
  208. if cdo_explicit in cdoptions then
  209. begin
  210. doconv:=tc_int_2_int;
  211. eq:=te_convert_l1;
  212. end;
  213. end;
  214. floatdef :
  215. begin
  216. if is_currency(def_to) then
  217. begin
  218. doconv:=tc_real_2_currency;
  219. eq:=te_convert_l2;
  220. end;
  221. end;
  222. classrefdef,
  223. procvardef,
  224. pointerdef :
  225. begin
  226. if cdo_explicit in cdoptions then
  227. begin
  228. eq:=te_convert_l1;
  229. if (fromtreetype=niln) then
  230. begin
  231. { will be handled by the constant folding }
  232. doconv:=tc_equal;
  233. end
  234. else
  235. doconv:=tc_int_2_int;
  236. end;
  237. end;
  238. end;
  239. end;
  240. stringdef :
  241. begin
  242. case def_from.deftype of
  243. stringdef :
  244. begin
  245. { Constant string }
  246. if (fromtreetype=stringconstn) then
  247. begin
  248. if (tstringdef(def_from).string_typ=tstringdef(def_to).string_typ) then
  249. eq:=te_equal
  250. else
  251. begin
  252. doconv:=tc_string_2_string;
  253. { Don't prefer conversions from widestring to a
  254. normal string as we can loose information }
  255. if tstringdef(def_from).string_typ=st_widestring then
  256. eq:=te_convert_l1
  257. else
  258. begin
  259. if tstringdef(def_to).string_typ=st_widestring then
  260. eq:=te_convert_l1
  261. else
  262. eq:=te_equal; { we can change the stringconst node }
  263. end;
  264. end;
  265. end
  266. else
  267. { Same string type, for shortstrings also the length must match }
  268. if (tstringdef(def_from).string_typ=tstringdef(def_to).string_typ) and
  269. ((tstringdef(def_from).string_typ<>st_shortstring) or
  270. (tstringdef(def_from).len=tstringdef(def_to).len)) then
  271. eq:=te_equal
  272. else
  273. begin
  274. doconv:=tc_string_2_string;
  275. { Prefer conversions to shortstring over other
  276. conversions. This is compatible with Delphi (PFV) }
  277. if tstringdef(def_to).string_typ=st_shortstring then
  278. eq:=te_convert_l2
  279. else
  280. eq:=te_convert_l3;
  281. end;
  282. end;
  283. orddef :
  284. begin
  285. { char to string}
  286. if is_char(def_from) or
  287. is_widechar(def_from) then
  288. begin
  289. doconv:=tc_char_2_string;
  290. eq:=te_convert_l1;
  291. end;
  292. end;
  293. arraydef :
  294. begin
  295. { array of char to string, the length check is done by the firstpass of this node }
  296. if is_chararray(def_from) or
  297. (is_char(tarraydef(def_from).elementtype.def) and
  298. is_open_array(def_from)) then
  299. begin
  300. doconv:=tc_chararray_2_string;
  301. if is_open_array(def_from) or
  302. (is_shortstring(def_to) and
  303. (def_from.size <= 255)) or
  304. (is_ansistring(def_to) and
  305. (def_from.size > 255)) then
  306. eq:=te_convert_l1
  307. else
  308. eq:=te_convert_l2;
  309. end;
  310. end;
  311. pointerdef :
  312. begin
  313. { pchar can be assigned to short/ansistrings,
  314. but not in tp7 compatible mode }
  315. if not(m_tp7 in aktmodeswitches) then
  316. begin
  317. if is_pchar(def_from) then
  318. begin
  319. doconv:=tc_pchar_2_string;
  320. { prefer ansistrings because pchars can overflow shortstrings, }
  321. { but only if ansistrings are the default (JM) }
  322. if (is_shortstring(def_to) and
  323. not(cs_ansistrings in aktlocalswitches)) or
  324. (is_ansistring(def_to) and
  325. (cs_ansistrings in aktlocalswitches)) then
  326. eq:=te_convert_l1
  327. else
  328. eq:=te_convert_l2;
  329. end
  330. else if is_pwidechar(def_from) then
  331. begin
  332. doconv:=tc_pwchar_2_string;
  333. { prefer ansistrings because pchars can overflow shortstrings, }
  334. { but only if ansistrings are the default (JM) }
  335. if is_widestring(def_to) then
  336. eq:=te_convert_l1
  337. else
  338. eq:=te_convert_l3;
  339. end;
  340. end;
  341. end;
  342. end;
  343. end;
  344. floatdef :
  345. begin
  346. case def_from.deftype of
  347. orddef :
  348. begin { ordinal to real }
  349. if is_integer(def_from) or
  350. (is_currency(def_from) and
  351. (s64currencytype.def.deftype = floatdef)) then
  352. begin
  353. doconv:=tc_int_2_real;
  354. eq:=te_convert_l1;
  355. end
  356. else if is_currency(def_from)
  357. { and (s64currencytype.def.deftype = orddef)) } then
  358. begin
  359. { prefer conversion to orddef in this case, unless }
  360. { the orddef < currency (then it will get convert l3, }
  361. { and conversion to float is favoured) }
  362. doconv:=tc_int_2_real;
  363. eq:=te_convert_l2;
  364. end;
  365. end;
  366. floatdef :
  367. begin
  368. if tfloatdef(def_from).typ=tfloatdef(def_to).typ then
  369. eq:=te_equal
  370. else
  371. begin
  372. if (fromtreetype=realconstn) or
  373. not((cdo_explicit in cdoptions) and
  374. (m_delphi in aktmodeswitches)) then
  375. begin
  376. doconv:=tc_real_2_real;
  377. { do we loose precision? }
  378. if def_to.size<def_from.size then
  379. eq:=te_convert_l2
  380. else
  381. eq:=te_convert_l1;
  382. end;
  383. end;
  384. end;
  385. end;
  386. end;
  387. enumdef :
  388. begin
  389. case def_from.deftype of
  390. enumdef :
  391. begin
  392. if cdo_explicit in cdoptions then
  393. begin
  394. eq:=te_convert_l1;
  395. doconv:=tc_int_2_int;
  396. end
  397. else
  398. begin
  399. hd1:=def_from;
  400. while assigned(tenumdef(hd1).basedef) do
  401. hd1:=tenumdef(hd1).basedef;
  402. hd2:=def_to;
  403. while assigned(tenumdef(hd2).basedef) do
  404. hd2:=tenumdef(hd2).basedef;
  405. if (hd1=hd2) then
  406. begin
  407. eq:=te_convert_l1;
  408. { because of packenum they can have different sizes! (JM) }
  409. doconv:=tc_int_2_int;
  410. end;
  411. end;
  412. end;
  413. orddef :
  414. begin
  415. if cdo_explicit in cdoptions then
  416. begin
  417. eq:=te_convert_l1;
  418. doconv:=tc_int_2_int;
  419. end;
  420. end;
  421. variantdef :
  422. begin
  423. eq:=te_convert_l1;
  424. doconv:=tc_variant_2_enum;
  425. end;
  426. end;
  427. end;
  428. arraydef :
  429. begin
  430. { open array is also compatible with a single element of its base type }
  431. if is_open_array(def_to) and
  432. equal_defs(def_from,tarraydef(def_to).elementtype.def) then
  433. begin
  434. doconv:=tc_equal;
  435. eq:=te_convert_l1;
  436. end
  437. else
  438. begin
  439. case def_from.deftype of
  440. arraydef :
  441. begin
  442. { to dynamic array }
  443. if is_dynamic_array(def_to) then
  444. begin
  445. { dynamic array -> dynamic array }
  446. if is_dynamic_array(def_from) and
  447. equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) then
  448. eq:=te_equal;
  449. end
  450. else
  451. { to open array }
  452. if is_open_array(def_to) then
  453. begin
  454. { array constructor -> open array }
  455. if is_array_constructor(def_from) then
  456. begin
  457. if is_void(tarraydef(def_from).elementtype.def) then
  458. begin
  459. doconv:=tc_equal;
  460. eq:=te_convert_l1;
  461. end
  462. else
  463. begin
  464. subeq:=compare_defs_ext(tarraydef(def_from).elementtype.def,
  465. tarraydef(def_to).elementtype.def,
  466. arrayconstructorn,hct,hpd,[cdo_check_operator]);
  467. if (subeq>=te_equal) then
  468. begin
  469. doconv:=tc_equal;
  470. eq:=te_convert_l1;
  471. end
  472. else
  473. if (subeq>te_incompatible) then
  474. begin
  475. doconv:=hct;
  476. eq:=te_convert_l2;
  477. end;
  478. end;
  479. end
  480. else
  481. { dynamic array -> open array }
  482. if is_dynamic_array(def_from) and
  483. equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) then
  484. begin
  485. doconv:=tc_dynarray_2_openarray;
  486. eq:=te_convert_l2;
  487. end
  488. else
  489. { array -> open array }
  490. if equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) then
  491. eq:=te_equal;
  492. end
  493. else
  494. { to array of const }
  495. if is_array_of_const(def_to) then
  496. begin
  497. if is_array_of_const(def_from) or
  498. is_array_constructor(def_from) then
  499. begin
  500. eq:=te_equal;
  501. end
  502. else
  503. { array of tvarrec -> array of const }
  504. if equal_defs(tarraydef(def_to).elementtype.def,tarraydef(def_from).elementtype.def) then
  505. begin
  506. doconv:=tc_equal;
  507. eq:=te_convert_l1;
  508. end;
  509. end
  510. else
  511. { other arrays }
  512. begin
  513. { open array -> array }
  514. if is_open_array(def_from) and
  515. equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) then
  516. begin
  517. eq:=te_equal
  518. end
  519. else
  520. { array -> array }
  521. if not(m_tp7 in aktmodeswitches) and
  522. not(m_delphi in aktmodeswitches) and
  523. (tarraydef(def_from).lowrange=tarraydef(def_to).lowrange) and
  524. (tarraydef(def_from).highrange=tarraydef(def_to).highrange) and
  525. equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) and
  526. equal_defs(tarraydef(def_from).rangetype.def,tarraydef(def_to).rangetype.def) then
  527. begin
  528. eq:=te_equal
  529. end;
  530. end;
  531. end;
  532. pointerdef :
  533. begin
  534. { nil and voidpointers are compatible with dyn. arrays }
  535. if is_dynamic_array(def_to) and
  536. ((fromtreetype=niln) or
  537. is_voidpointer(def_from)) then
  538. begin
  539. doconv:=tc_equal;
  540. eq:=te_convert_l1;
  541. end
  542. else
  543. if is_zero_based_array(def_to) and
  544. equal_defs(tpointerdef(def_from).pointertype.def,tarraydef(def_to).elementtype.def) then
  545. begin
  546. doconv:=tc_pointer_2_array;
  547. eq:=te_convert_l1;
  548. end;
  549. end;
  550. stringdef :
  551. begin
  552. { string to char array }
  553. if (not is_special_array(def_to)) and
  554. is_char(tarraydef(def_to).elementtype.def) then
  555. begin
  556. doconv:=tc_string_2_chararray;
  557. eq:=te_convert_l1;
  558. end;
  559. end;
  560. orddef:
  561. begin
  562. if is_chararray(def_to) and
  563. is_char(def_from) then
  564. begin
  565. doconv:=tc_char_2_chararray;
  566. eq:=te_convert_l2;
  567. end;
  568. end;
  569. recorddef :
  570. begin
  571. { tvarrec -> array of const }
  572. if is_array_of_const(def_to) and
  573. equal_defs(def_from,tarraydef(def_to).elementtype.def) then
  574. begin
  575. doconv:=tc_equal;
  576. eq:=te_convert_l1;
  577. end;
  578. end;
  579. variantdef :
  580. begin
  581. if is_dynamic_array(def_to) then
  582. begin
  583. doconv:=tc_variant_2_dynarray;
  584. eq:=te_convert_l1;
  585. end;
  586. end;
  587. end;
  588. end;
  589. end;
  590. variantdef :
  591. begin
  592. if (cdo_allow_variant in cdoptions) then
  593. begin
  594. case def_from.deftype of
  595. enumdef :
  596. begin
  597. doconv:=tc_enum_2_variant;
  598. eq:=te_convert_l1;
  599. end;
  600. arraydef :
  601. begin
  602. if is_dynamic_array(def_from) then
  603. begin
  604. doconv:=tc_dynarray_2_variant;
  605. eq:=te_convert_l1;
  606. end;
  607. end;
  608. end;
  609. end;
  610. end;
  611. pointerdef :
  612. begin
  613. case def_from.deftype of
  614. stringdef :
  615. begin
  616. { string constant (which can be part of array constructor)
  617. to zero terminated string constant }
  618. if (fromtreetype in [arrayconstructorn,stringconstn]) and
  619. (is_pchar(def_to) or is_pwidechar(def_to)) then
  620. begin
  621. doconv:=tc_cstring_2_pchar;
  622. eq:=te_convert_l1;
  623. end
  624. else
  625. if cdo_explicit in cdoptions then
  626. begin
  627. { pchar(ansistring) }
  628. if is_pchar(def_to) and
  629. is_ansistring(def_from) then
  630. begin
  631. doconv:=tc_ansistring_2_pchar;
  632. eq:=te_convert_l1;
  633. end
  634. else
  635. { pwidechar(ansistring) }
  636. if is_pwidechar(def_to) and
  637. is_widestring(def_from) then
  638. begin
  639. doconv:=tc_ansistring_2_pchar;
  640. eq:=te_convert_l1;
  641. end;
  642. end;
  643. end;
  644. orddef :
  645. begin
  646. { char constant to zero terminated string constant }
  647. if (fromtreetype=ordconstn) then
  648. begin
  649. if is_char(def_from) and
  650. is_pchar(def_to) then
  651. begin
  652. doconv:=tc_cchar_2_pchar;
  653. eq:=te_convert_l1;
  654. end
  655. else
  656. if (m_delphi in aktmodeswitches) and is_integer(def_from) then
  657. begin
  658. doconv:=tc_cord_2_pointer;
  659. eq:=te_convert_l1;
  660. end;
  661. end;
  662. if (eq=te_incompatible) and (cdo_explicit in cdoptions) then
  663. begin
  664. doconv:=tc_int_2_int;
  665. eq:=te_convert_l1;
  666. end;
  667. end;
  668. arraydef :
  669. begin
  670. { chararray to pointer }
  671. if is_zero_based_array(def_from) and
  672. equal_defs(tarraydef(def_from).elementtype.def,tpointerdef(def_to).pointertype.def) then
  673. begin
  674. doconv:=tc_array_2_pointer;
  675. eq:=te_convert_l1;
  676. end
  677. else
  678. { dynamic array to pointer, delphi only }
  679. if (m_delphi in aktmodeswitches) and
  680. is_dynamic_array(def_from) then
  681. begin
  682. eq:=te_equal;
  683. end;
  684. end;
  685. pointerdef :
  686. begin
  687. { check for far pointers }
  688. if (tpointerdef(def_from).is_far<>tpointerdef(def_to).is_far) then
  689. begin
  690. eq:=te_incompatible;
  691. end
  692. else
  693. { the types can be forward type, handle before normal type check !! }
  694. if assigned(def_to.typesym) and
  695. (tpointerdef(def_to).pointertype.def.deftype=forwarddef) then
  696. begin
  697. if (def_from.typesym=def_to.typesym) then
  698. eq:=te_equal
  699. end
  700. else
  701. { same types }
  702. if equal_defs(tpointerdef(def_from).pointertype.def,tpointerdef(def_to).pointertype.def) then
  703. begin
  704. eq:=te_equal
  705. end
  706. else
  707. { child class pointer can be assigned to anchestor pointers }
  708. if (
  709. (tpointerdef(def_from).pointertype.def.deftype=objectdef) and
  710. (tpointerdef(def_to).pointertype.def.deftype=objectdef) and
  711. tobjectdef(tpointerdef(def_from).pointertype.def).is_related(
  712. tobjectdef(tpointerdef(def_to).pointertype.def))
  713. ) or
  714. { all pointers can be assigned to/from void-pointer }
  715. is_void(tpointerdef(def_to).pointertype.def) or
  716. is_void(tpointerdef(def_from).pointertype.def) then
  717. begin
  718. doconv:=tc_equal;
  719. { give pwidechar a penalty }
  720. if is_pwidechar(def_to) then
  721. eq:=te_convert_l2
  722. else
  723. eq:=te_convert_l1;
  724. end;
  725. end;
  726. procvardef :
  727. begin
  728. { procedure variable can be assigned to an void pointer }
  729. { Not anymore. Use the @ operator now.}
  730. if not(m_tp_procvar in aktmodeswitches) and
  731. { method pointers can't be assigned to void pointers
  732. not(tprocvardef(def_from).is_methodpointer) and }
  733. (tpointerdef(def_to).pointertype.def.deftype=orddef) and
  734. (torddef(tpointerdef(def_to).pointertype.def).typ=uvoid) then
  735. begin
  736. doconv:=tc_equal;
  737. eq:=te_convert_l1;
  738. end;
  739. end;
  740. classrefdef,
  741. objectdef :
  742. begin
  743. { class types and class reference type
  744. can be assigned to void pointers, but it is less
  745. preferred than assigning to a related objectdef }
  746. if (
  747. is_class_or_interface(def_from) or
  748. (def_from.deftype=classrefdef)
  749. ) and
  750. (tpointerdef(def_to).pointertype.def.deftype=orddef) and
  751. (torddef(tpointerdef(def_to).pointertype.def).typ=uvoid) then
  752. begin
  753. doconv:=tc_equal;
  754. eq:=te_convert_l2;
  755. end;
  756. end;
  757. end;
  758. end;
  759. setdef :
  760. begin
  761. case def_from.deftype of
  762. setdef :
  763. begin
  764. if assigned(tsetdef(def_from).elementtype.def) and
  765. assigned(tsetdef(def_to).elementtype.def) then
  766. begin
  767. { sets with the same element base type are equal }
  768. if is_subequal(tsetdef(def_from).elementtype.def,tsetdef(def_to).elementtype.def) then
  769. eq:=te_equal;
  770. end
  771. else
  772. { empty set is compatible with everything }
  773. eq:=te_equal;
  774. end;
  775. arraydef :
  776. begin
  777. { automatic arrayconstructor -> set conversion }
  778. if is_array_constructor(def_from) then
  779. begin
  780. doconv:=tc_arrayconstructor_2_set;
  781. eq:=te_convert_l1;
  782. end;
  783. end;
  784. end;
  785. end;
  786. procvardef :
  787. begin
  788. case def_from.deftype of
  789. procdef :
  790. begin
  791. { proc -> procvar }
  792. if (m_tp_procvar in aktmodeswitches) then
  793. begin
  794. subeq:=proc_to_procvar_equal(tprocdef(def_from),tprocvardef(def_to),true);
  795. if subeq>te_incompatible then
  796. begin
  797. doconv:=tc_proc_2_procvar;
  798. eq:=te_convert_l1;
  799. end;
  800. end;
  801. end;
  802. procvardef :
  803. begin
  804. { procvar -> procvar }
  805. eq:=proc_to_procvar_equal(tprocvardef(def_from),tprocvardef(def_to),false);
  806. end;
  807. pointerdef :
  808. begin
  809. { nil is compatible with procvars }
  810. if (fromtreetype=niln) then
  811. begin
  812. doconv:=tc_equal;
  813. eq:=te_convert_l1;
  814. end
  815. else
  816. { for example delphi allows the assignement from pointers }
  817. { to procedure variables }
  818. if (m_pointer_2_procedure in aktmodeswitches) and
  819. (tpointerdef(def_from).pointertype.def.deftype=orddef) and
  820. (torddef(tpointerdef(def_from).pointertype.def).typ=uvoid) then
  821. begin
  822. doconv:=tc_equal;
  823. eq:=te_convert_l1;
  824. end;
  825. end;
  826. end;
  827. end;
  828. objectdef :
  829. begin
  830. { object pascal objects }
  831. if (def_from.deftype=objectdef) and
  832. (tobjectdef(def_from).is_related(tobjectdef(def_to))) then
  833. begin
  834. doconv:=tc_equal;
  835. eq:=te_convert_l1;
  836. end
  837. else
  838. { Class/interface specific }
  839. if is_class_or_interface(def_to) then
  840. begin
  841. { void pointer also for delphi mode }
  842. if (m_delphi in aktmodeswitches) and
  843. is_voidpointer(def_from) then
  844. begin
  845. doconv:=tc_equal;
  846. { prefer pointer-pointer assignments }
  847. eq:=te_convert_l2;
  848. end
  849. else
  850. { nil is compatible with class instances and interfaces }
  851. if (fromtreetype=niln) then
  852. begin
  853. doconv:=tc_equal;
  854. eq:=te_convert_l1;
  855. end
  856. { classes can be assigned to interfaces }
  857. else if is_interface(def_to) and
  858. is_class(def_from) and
  859. assigned(tobjectdef(def_from).implementedinterfaces) then
  860. begin
  861. { we've to search in parent classes as well }
  862. hd3:=tobjectdef(def_from);
  863. while assigned(hd3) do
  864. begin
  865. if hd3.implementedinterfaces.searchintf(def_to)<>-1 then
  866. begin
  867. doconv:=tc_class_2_intf;
  868. eq:=te_convert_l1;
  869. break;
  870. end;
  871. hd3:=hd3.childof;
  872. end;
  873. end
  874. { Interface 2 GUID handling }
  875. else if (def_to=tdef(rec_tguid)) and
  876. (fromtreetype=typen) and
  877. is_interface(def_from) and
  878. assigned(tobjectdef(def_from).iidguid) then
  879. begin
  880. eq:=te_convert_l1;
  881. doconv:=tc_equal;
  882. end;
  883. end;
  884. end;
  885. classrefdef :
  886. begin
  887. { similar to pointerdef wrt forwards }
  888. if assigned(def_to.typesym) and
  889. (tclassrefdef(def_to).pointertype.def.deftype=forwarddef) then
  890. begin
  891. if (def_from.typesym=def_to.typesym) then
  892. eq:=te_equal;
  893. end
  894. else
  895. { class reference types }
  896. if (def_from.deftype=classrefdef) then
  897. begin
  898. if equal_defs(tclassrefdef(def_from).pointertype.def,tclassrefdef(def_to).pointertype.def) then
  899. begin
  900. eq:=te_equal;
  901. end
  902. else
  903. begin
  904. doconv:=tc_equal;
  905. if (cdo_explicit in cdoptions) or
  906. tobjectdef(tclassrefdef(def_from).pointertype.def).is_related(
  907. tobjectdef(tclassrefdef(def_to).pointertype.def)) then
  908. eq:=te_convert_l1;
  909. end;
  910. end
  911. else
  912. { nil is compatible with class references }
  913. if (fromtreetype=niln) then
  914. begin
  915. doconv:=tc_equal;
  916. eq:=te_convert_l1;
  917. end;
  918. end;
  919. filedef :
  920. begin
  921. { typed files are all equal to the abstract file type
  922. name TYPEDFILE in system.pp in is_equal in types.pas
  923. the problem is that it sholud be also compatible to FILE
  924. but this would leed to a problem for ASSIGN RESET and REWRITE
  925. when trying to find the good overloaded function !!
  926. so all file function are doubled in system.pp
  927. this is not very beautiful !!}
  928. if (def_from.deftype=filedef) then
  929. begin
  930. if (tfiledef(def_from).filetyp=tfiledef(def_to).filetyp) then
  931. begin
  932. if
  933. (
  934. (tfiledef(def_from).typedfiletype.def=nil) and
  935. (tfiledef(def_to).typedfiletype.def=nil)
  936. ) or
  937. (
  938. (tfiledef(def_from).typedfiletype.def<>nil) and
  939. (tfiledef(def_to).typedfiletype.def<>nil) and
  940. equal_defs(tfiledef(def_from).typedfiletype.def,tfiledef(def_to).typedfiletype.def)
  941. ) or
  942. (
  943. (tfiledef(def_from).filetyp = ft_typed) and
  944. (tfiledef(def_to).filetyp = ft_typed) and
  945. (
  946. (tfiledef(def_from).typedfiletype.def = tdef(voidtype.def)) or
  947. (tfiledef(def_to).typedfiletype.def = tdef(voidtype.def))
  948. )
  949. ) then
  950. begin
  951. eq:=te_equal;
  952. end;
  953. end
  954. else
  955. if ((tfiledef(def_from).filetyp = ft_untyped) and
  956. (tfiledef(def_to).filetyp = ft_typed)) or
  957. ((tfiledef(def_from).filetyp = ft_typed) and
  958. (tfiledef(def_to).filetyp = ft_untyped)) then
  959. begin
  960. doconv:=tc_equal;
  961. eq:=te_convert_l1;
  962. end;
  963. end;
  964. end;
  965. recorddef :
  966. begin
  967. { interface -> guid }
  968. if is_interface(def_from) and
  969. (def_to=rec_tguid) then
  970. begin
  971. doconv:=tc_intf_2_guid;
  972. eq:=te_convert_l1;
  973. end;
  974. end;
  975. formaldef :
  976. begin
  977. doconv:=tc_equal;
  978. if (def_from.deftype=formaldef) then
  979. eq:=te_equal
  980. else
  981. { Just about everything can be converted to a formaldef...}
  982. if not (def_from.deftype in [abstractdef,errordef]) then
  983. eq:=te_convert_l1;
  984. end;
  985. end;
  986. { if we didn't find an appropriate type conversion yet
  987. then we search also the := operator }
  988. if (eq=te_incompatible) and
  989. (
  990. { Check for variants? }
  991. (
  992. (cdo_allow_variant in cdoptions) and
  993. ((def_from.deftype=variantdef) or (def_to.deftype=variantdef))
  994. ) or
  995. { Check for operators? }
  996. (
  997. (cdo_check_operator in cdoptions) and
  998. ((def_from.deftype in [objectdef,recorddef,arraydef,stringdef,variantdef]) or
  999. (def_to.deftype in [objectdef,recorddef,arraydef,stringdef,variantdef]))
  1000. )
  1001. ) then
  1002. begin
  1003. operatorpd:=search_assignment_operator(def_from,def_to);
  1004. if assigned(operatorpd) then
  1005. eq:=te_convert_operator;
  1006. end;
  1007. { update convtype for te_equal when it is not yet set }
  1008. if (eq=te_equal) and
  1009. (doconv=tc_not_possible) then
  1010. doconv:=tc_equal;
  1011. compare_defs_ext:=eq;
  1012. end;
  1013. function equal_defs(def_from,def_to:tdef):boolean;
  1014. var
  1015. convtyp : tconverttype;
  1016. pd : tprocdef;
  1017. begin
  1018. { Compare defs with nothingn and no explicit typecasts and
  1019. searching for overloaded operators is not needed }
  1020. equal_defs:=(compare_defs_ext(def_from,def_to,nothingn,convtyp,pd,[])>=te_equal);
  1021. end;
  1022. function compare_defs(def_from,def_to:tdef;fromtreetype:tnodetype):tequaltype;
  1023. var
  1024. doconv : tconverttype;
  1025. pd : tprocdef;
  1026. begin
  1027. compare_defs:=compare_defs_ext(def_from,def_to,fromtreetype,doconv,pd,[cdo_check_operator,cdo_allow_variant]);
  1028. end;
  1029. function is_subequal(def1, def2: tdef): boolean;
  1030. var
  1031. basedef1,basedef2 : tenumdef;
  1032. Begin
  1033. is_subequal := false;
  1034. if assigned(def1) and assigned(def2) then
  1035. Begin
  1036. if (def1.deftype = orddef) and (def2.deftype = orddef) then
  1037. Begin
  1038. { see p.47 of Turbo Pascal 7.01 manual for the separation of types }
  1039. { range checking for case statements is done with testrange }
  1040. case torddef(def1).typ of
  1041. u8bit,u16bit,u32bit,u64bit,
  1042. s8bit,s16bit,s32bit,s64bit :
  1043. is_subequal:=(torddef(def2).typ in [s64bit,u64bit,s32bit,u32bit,u8bit,s8bit,s16bit,u16bit]);
  1044. bool8bit,bool16bit,bool32bit :
  1045. is_subequal:=(torddef(def2).typ in [bool8bit,bool16bit,bool32bit]);
  1046. uchar :
  1047. is_subequal:=(torddef(def2).typ=uchar);
  1048. uwidechar :
  1049. is_subequal:=(torddef(def2).typ=uwidechar);
  1050. end;
  1051. end
  1052. else
  1053. Begin
  1054. { Check if both basedefs are equal }
  1055. if (def1.deftype=enumdef) and (def2.deftype=enumdef) then
  1056. Begin
  1057. { get both basedefs }
  1058. basedef1:=tenumdef(def1);
  1059. while assigned(basedef1.basedef) do
  1060. basedef1:=basedef1.basedef;
  1061. basedef2:=tenumdef(def2);
  1062. while assigned(basedef2.basedef) do
  1063. basedef2:=basedef2.basedef;
  1064. is_subequal:=(basedef1=basedef2);
  1065. end;
  1066. end;
  1067. end;
  1068. end;
  1069. function compare_paras(paralist1,paralist2 : TLinkedList; acp : tcompare_paras_type; cpoptions: tcompare_paras_options):tequaltype;
  1070. var
  1071. currpara1,
  1072. currpara2 : TParaItem;
  1073. eq,lowesteq : tequaltype;
  1074. hpd : tprocdef;
  1075. convtype : tconverttype;
  1076. cdoptions : tcompare_defs_options;
  1077. begin
  1078. compare_paras:=te_incompatible;
  1079. cdoptions:=[cdo_check_operator,cdo_allow_variant];
  1080. { we need to parse the list from left-right so the
  1081. not-default parameters are checked first }
  1082. lowesteq:=high(tequaltype);
  1083. currpara1:=TParaItem(paralist1.first);
  1084. currpara2:=TParaItem(paralist2.first);
  1085. if cpo_ignorehidden in cpoptions then
  1086. begin
  1087. while assigned(currpara1) and currpara1.is_hidden do
  1088. currpara1:=tparaitem(currpara1.next);
  1089. while assigned(currpara2) and currpara2.is_hidden do
  1090. currpara2:=tparaitem(currpara2.next);
  1091. end;
  1092. while (assigned(currpara1)) and (assigned(currpara2)) do
  1093. begin
  1094. eq:=te_incompatible;
  1095. { Unique types must match exact }
  1096. if ((df_unique in currpara1.paratype.def.defoptions) or (df_unique in currpara2.paratype.def.defoptions)) and
  1097. (currpara1.paratype.def<>currpara2.paratype.def) then
  1098. exit;
  1099. { Handle hidden parameters separately, because self is
  1100. defined as voidpointer for methodpointers }
  1101. if (currpara1.is_hidden or
  1102. currpara2.is_hidden) then
  1103. begin
  1104. { both must be hidden }
  1105. if currpara1.is_hidden<>currpara2.is_hidden then
  1106. exit;
  1107. eq:=te_equal;
  1108. if not(vo_is_self in tvarsym(currpara1.parasym).varoptions) and
  1109. not(vo_is_self in tvarsym(currpara2.parasym).varoptions) then
  1110. begin
  1111. if (currpara1.paratyp<>currpara2.paratyp) then
  1112. exit;
  1113. eq:=compare_defs_ext(currpara1.paratype.def,currpara2.paratype.def,nothingn,
  1114. convtype,hpd,cdoptions);
  1115. end;
  1116. end
  1117. else
  1118. begin
  1119. case acp of
  1120. cp_value_equal_const :
  1121. begin
  1122. if (
  1123. (currpara1.paratyp<>currpara2.paratyp) and
  1124. ((currpara1.paratyp in [vs_var,vs_out]) or
  1125. (currpara2.paratyp in [vs_var,vs_out]))
  1126. ) then
  1127. exit;
  1128. eq:=compare_defs_ext(currpara1.paratype.def,currpara2.paratype.def,nothingn,
  1129. convtype,hpd,cdoptions);
  1130. end;
  1131. cp_all :
  1132. begin
  1133. if (currpara1.paratyp<>currpara2.paratyp) then
  1134. exit;
  1135. eq:=compare_defs_ext(currpara1.paratype.def,currpara2.paratype.def,nothingn,
  1136. convtype,hpd,cdoptions);
  1137. end;
  1138. cp_procvar :
  1139. begin
  1140. if (currpara1.paratyp<>currpara2.paratyp) then
  1141. exit;
  1142. eq:=compare_defs_ext(currpara1.paratype.def,currpara2.paratype.def,nothingn,
  1143. convtype,hpd,cdoptions);
  1144. if (eq>te_incompatible) and
  1145. (eq<te_equal) and
  1146. not(
  1147. (convtype in [tc_equal,tc_int_2_int]) and
  1148. (currpara1.paratype.def.size=currpara2.paratype.def.size)
  1149. ) then
  1150. begin
  1151. eq:=te_incompatible;
  1152. end;
  1153. end;
  1154. else
  1155. eq:=compare_defs_ext(currpara1.paratype.def,currpara2.paratype.def,nothingn,
  1156. convtype,hpd,cdoptions);
  1157. end;
  1158. end;
  1159. { check type }
  1160. if eq=te_incompatible then
  1161. exit;
  1162. if eq<lowesteq then
  1163. lowesteq:=eq;
  1164. { also check default value if both have it declared }
  1165. if (cpo_comparedefaultvalue in cpoptions) and
  1166. assigned(currpara1.defaultvalue) and
  1167. assigned(currpara2.defaultvalue) then
  1168. begin
  1169. if not equal_constsym(tconstsym(currpara1.defaultvalue),tconstsym(currpara2.defaultvalue)) then
  1170. exit;
  1171. end;
  1172. currpara1:=TParaItem(currpara1.next);
  1173. currpara2:=TParaItem(currpara2.next);
  1174. if cpo_ignorehidden in cpoptions then
  1175. begin
  1176. while assigned(currpara1) and currpara1.is_hidden do
  1177. currpara1:=tparaitem(currpara1.next);
  1178. while assigned(currpara2) and currpara2.is_hidden do
  1179. currpara2:=tparaitem(currpara2.next);
  1180. end;
  1181. end;
  1182. { when both lists are empty then the parameters are equal. Also
  1183. when one list is empty and the other has a parameter with default
  1184. value assigned then the parameters are also equal }
  1185. if ((currpara1=nil) and (currpara2=nil)) or
  1186. ((cpo_allowdefaults in cpoptions) and
  1187. ((assigned(currpara1) and assigned(currpara1.defaultvalue)) or
  1188. (assigned(currpara2) and assigned(currpara2.defaultvalue)))) then
  1189. compare_paras:=lowesteq;
  1190. end;
  1191. function proc_to_procvar_equal(def1:tabstractprocdef;def2:tprocvardef;methoderr:boolean):tequaltype;
  1192. var
  1193. eq : tequaltype;
  1194. po_comp : tprocoptions;
  1195. begin
  1196. proc_to_procvar_equal:=te_incompatible;
  1197. if not(assigned(def1)) or not(assigned(def2)) then
  1198. exit;
  1199. { check for method pointer }
  1200. if (def1.is_methodpointer xor def2.is_methodpointer) or
  1201. (def1.is_addressonly xor def2.is_addressonly) then
  1202. begin
  1203. if methoderr then
  1204. Message(type_e_no_method_and_procedure_not_compatible);
  1205. exit;
  1206. end;
  1207. { check return value and options, methodpointer is already checked }
  1208. po_comp:=[po_staticmethod,po_interrupt,
  1209. po_iocheck,po_varargs];
  1210. if (m_delphi in aktmodeswitches) then
  1211. exclude(po_comp,po_varargs);
  1212. if (def1.proccalloption=def2.proccalloption) and
  1213. ((po_comp * def1.procoptions)= (po_comp * def2.procoptions)) and
  1214. equal_defs(def1.rettype.def,def2.rettype.def) then
  1215. begin
  1216. { return equal type based on the parameters, but a proc->procvar
  1217. is never exact, so map an exact match of the parameters to
  1218. te_equal }
  1219. eq:=compare_paras(def1.para,def2.para,cp_procvar,[]);
  1220. if eq=te_exact then
  1221. eq:=te_equal;
  1222. proc_to_procvar_equal:=eq;
  1223. end;
  1224. end;
  1225. end.
  1226. {
  1227. $Log$
  1228. Revision 1.52 2004-09-16 16:32:44 peter
  1229. * dynarr-pointer is allowed under delphi
  1230. Revision 1.51 2004/06/20 08:55:29 florian
  1231. * logs truncated
  1232. Revision 1.50 2004/04/12 11:26:10 peter
  1233. * voidpointer can be converted to dynarray
  1234. Revision 1.49 2004/03/04 17:22:32 peter
  1235. * use defs_equal when comparing pointer types
  1236. Revision 1.48 2004/03/03 22:02:16 peter
  1237. * also compare calling convention in proc_to_procvar_equal
  1238. Revision 1.47 2004/02/24 16:12:39 peter
  1239. * operator overload chooses rewrite
  1240. * overload choosing is now generic and moved to htypechk
  1241. Revision 1.46 2004/02/15 12:18:22 peter
  1242. * allow real_2_real conversion for realconstn, fixes 2971
  1243. }