types.pas 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. {
  2. $Id$
  3. Copyright (C) 1993-98 by Florian Klaempfl
  4. This unit provides some help routines for type handling
  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 types;
  19. interface
  20. uses
  21. cobjects,globals,symtable;
  22. type
  23. tmmxtype = (mmxno,mmxu8bit,mmxs8bit,mmxu16bit,mmxs16bit,
  24. mmxu32bit,mmxs32bit,mmxfixed16,mmxsingle);
  25. { returns true, if def defines an ordinal type }
  26. function is_ordinal(def : pdef) : boolean;
  27. { true if p points to an open array def }
  28. function is_open_array(p : pdef) : boolean;
  29. { true if o is an ansi string def }
  30. function is_ansistring(p : pdef) : boolean;
  31. { true if o is a long string def }
  32. function is_longstring(p : pdef) : boolean;
  33. { true if o is a wide string def }
  34. function is_widestring(p : pdef) : boolean;
  35. { true if o is a short string def }
  36. function is_shortstring(p : pdef) : boolean;
  37. { returns true, if def defines a signed data type (only for ordinal types) }
  38. function is_signed(def : pdef) : boolean;
  39. { returns true, if def uses FPU }
  40. function is_fpu(def : pdef) : boolean;
  41. { true if the return value is in EAX }
  42. function ret_in_acc(def : pdef) : boolean;
  43. { true if uses a parameter as return value }
  44. function ret_in_param(def : pdef) : boolean;
  45. { true if a const parameter is too large to copy }
  46. function dont_copy_const_param(def : pdef) : boolean;
  47. { true if we must never copy this parameter }
  48. const
  49. never_copy_const_param : boolean = false;
  50. { true, if def1 and def2 are semantical the same }
  51. function is_equal(def1,def2 : pdef) : boolean;
  52. { checks for type compatibility (subgroups of type) }
  53. { used for case statements... probably missing stuff }
  54. { to use on other types }
  55. function is_subequal(def1, def2: pdef): boolean;
  56. { true, if two parameter lists are equal }
  57. { if value_equal_const is true, call by value }
  58. { and call by const parameter are assumed as }
  59. { equal }
  60. function equal_paras(def1,def2 : pdefcoll;value_equal_const : boolean) : boolean;
  61. { if l isn't in the range of def a range check error is generated }
  62. procedure testrange(def : pdef;l : longint);
  63. { returns the range of def }
  64. procedure getrange(def : pdef;var l : longint;var h : longint);
  65. { generates a VMT for _class }
  66. procedure genvmt(_class : pobjectdef);
  67. { some type helper routines for MMX support }
  68. function is_mmx_able_array(p : pdef) : boolean;
  69. { returns the mmx type }
  70. function mmx_type(p : pdef) : tmmxtype;
  71. implementation
  72. uses verbose,aasm;
  73. function equal_paras(def1,def2 : pdefcoll;value_equal_const : boolean) : boolean;
  74. begin
  75. while (assigned(def1)) and (assigned(def2)) do
  76. begin
  77. if value_equal_const then
  78. begin
  79. if not(is_equal(def1^.data,def2^.data)) or
  80. ((def1^.paratyp<>def2^.paratyp) and
  81. ((def1^.paratyp=vs_var) or
  82. (def1^.paratyp=vs_var)
  83. )
  84. ) then
  85. begin
  86. equal_paras:=false;
  87. exit;
  88. end;
  89. end
  90. else
  91. begin
  92. if not(is_equal(def1^.data,def2^.data)) or
  93. (def1^.paratyp<>def2^.paratyp) then
  94. begin
  95. equal_paras:=false;
  96. exit;
  97. end;
  98. end;
  99. def1:=def1^.next;
  100. def2:=def2^.next;
  101. end;
  102. if (def1=nil) and (def2=nil) then
  103. equal_paras:=true
  104. else
  105. equal_paras:=false;
  106. end;
  107. { returns true, if def uses FPU }
  108. function is_fpu(def : pdef) : boolean;
  109. begin
  110. is_fpu:=(def^.deftype=floatdef) and (pfloatdef(def)^.typ<>f32bit);
  111. end;
  112. function is_ordinal(def : pdef) : boolean;
  113. var
  114. dt : tbasetype;
  115. begin
  116. case def^.deftype of
  117. orddef : begin
  118. dt:=porddef(def)^.typ;
  119. is_ordinal:=dt in [uchar,u8bit,u16bit,u32bit,s8bit,s16bit,s32bit,bool8bit,bool16bit,bool32bit];
  120. end;
  121. enumdef : is_ordinal:=true;
  122. else
  123. is_ordinal:=false;
  124. end;
  125. end;
  126. function is_signed(def : pdef) : boolean;
  127. var
  128. dt : tbasetype;
  129. begin
  130. case def^.deftype of
  131. orddef : begin
  132. dt:=porddef(def)^.typ;
  133. is_signed:=(dt in [s8bit,s16bit,s32bit]);
  134. end;
  135. enumdef : is_signed:=false;
  136. else
  137. is_signed:=false;
  138. end;
  139. end;
  140. { true, if p points to an open array def }
  141. function is_open_array(p : pdef) : boolean;
  142. begin
  143. is_open_array:=(p^.deftype=arraydef) and
  144. (parraydef(p)^.lowrange=0) and
  145. (parraydef(p)^.highrange=-1);
  146. end;
  147. { true if o is an ansi string def }
  148. function is_ansistring(p : pdef) : boolean;
  149. begin
  150. is_ansistring:=(p^.deftype=stringdef) and
  151. (pstringdef(p)^.string_typ=st_ansistring);
  152. end;
  153. { true if o is an long string def }
  154. function is_longstring(p : pdef) : boolean;
  155. begin
  156. is_longstring:=(p^.deftype=stringdef) and
  157. (pstringdef(p)^.string_typ=st_longstring);
  158. end;
  159. { true if o is an wide string def }
  160. function is_widestring(p : pdef) : boolean;
  161. begin
  162. is_widestring:=(p^.deftype=stringdef) and
  163. (pstringdef(p)^.string_typ=st_widestring);
  164. end;
  165. { true if o is an short string def }
  166. function is_shortstring(p : pdef) : boolean;
  167. begin
  168. is_shortstring:=(p^.deftype=stringdef) and
  169. (pstringdef(p)^.string_typ=st_shortstring);
  170. end;
  171. { true if the return value is in accumulator (EAX for i386), D0 for 68k }
  172. function ret_in_acc(def : pdef) : boolean;
  173. begin
  174. ret_in_acc:=(def^.deftype in [orddef,pointerdef,enumdef,classrefdef]) or
  175. ((def^.deftype=stringdef) and (pstringdef(def)^.string_typ in [st_ansistring,st_widestring])) or
  176. ((def^.deftype=procvardef) and ((pprocvardef(def)^.options and pomethodpointer)=0)) or
  177. ((def^.deftype=objectdef) and pobjectdef(def)^.isclass) or
  178. ((def^.deftype=setdef) and (psetdef(def)^.settype=smallset)) or
  179. ((def^.deftype=floatdef) and (pfloatdef(def)^.typ=f32bit));
  180. end;
  181. { true if uses a parameter as return value }
  182. function ret_in_param(def : pdef) : boolean;
  183. begin
  184. ret_in_param:=(def^.deftype in [arraydef,recorddef]) or
  185. ((def^.deftype=stringdef) and (pstringdef(def)^.string_typ in [st_shortstring,st_longstring])) or
  186. ((def^.deftype=procvardef) and ((pprocvardef(def)^.options and pomethodpointer)<>0)) or
  187. ((def^.deftype=objectdef) and ((pobjectdef(def)^.options and oois_class)=0)) or
  188. ((def^.deftype=setdef) and (psetdef(def)^.settype<>smallset));
  189. end;
  190. { true if a const parameter is too large to copy }
  191. function dont_copy_const_param(def : pdef) : boolean;
  192. begin
  193. dont_copy_const_param:=(def^.deftype in [arraydef,objectdef,formaldef,recorddef]) or
  194. ((def^.deftype=stringdef) and (pstringdef(def)^.string_typ in [st_shortstring,st_longstring])) or
  195. ((def^.deftype=procvardef) and ((pprocvardef(def)^.options and pomethodpointer)<>0)) or
  196. ((def^.deftype=setdef) and (psetdef(def)^.settype<>smallset));
  197. end;
  198. procedure testrange(def : pdef;l : longint);
  199. var
  200. lv,hv: longint;
  201. begin
  202. getrange(def,lv,hv);
  203. if (def^.deftype=orddef) and
  204. (porddef(def)^.typ=u32bit) then
  205. begin
  206. if lv<=hv then
  207. begin
  208. if (l<lv) or (l>hv) then
  209. Message(parser_e_range_check_error);
  210. end
  211. else
  212. { this happens with the wrap around problem }
  213. { if lv is positive and hv is over $7ffffff }
  214. { so it seems negative }
  215. begin
  216. if ((l>=0) and (l<lv)) or
  217. ((l<0) and (l>hv)) then
  218. Message(parser_e_range_check_error);
  219. end;
  220. end
  221. else if (l<lv) or (l>hv) then
  222. Message(parser_e_range_check_error);
  223. end;
  224. procedure getrange(def : pdef;var l : longint;var h : longint);
  225. begin
  226. case def^.deftype of
  227. orddef : begin
  228. l:=porddef(def)^.low;
  229. h:=porddef(def)^.high;
  230. end;
  231. enumdef : begin
  232. l:=0;
  233. h:=penumdef(def)^.max;
  234. end;
  235. end;
  236. end;
  237. function mmx_type(p : pdef) : tmmxtype;
  238. begin
  239. mmx_type:=mmxno;
  240. if is_mmx_able_array(p) then
  241. begin
  242. if parraydef(p)^.definition^.deftype=floatdef then
  243. case pfloatdef(parraydef(p)^.definition)^.typ of
  244. s32real:
  245. mmx_type:=mmxsingle;
  246. f16bit:
  247. mmx_type:=mmxfixed16
  248. end
  249. else
  250. case porddef(parraydef(p)^.definition)^.typ of
  251. u8bit:
  252. mmx_type:=mmxu8bit;
  253. s8bit:
  254. mmx_type:=mmxs8bit;
  255. u16bit:
  256. mmx_type:=mmxu16bit;
  257. s16bit:
  258. mmx_type:=mmxs16bit;
  259. u32bit:
  260. mmx_type:=mmxu32bit;
  261. s32bit:
  262. mmx_type:=mmxs32bit;
  263. end;
  264. end;
  265. end;
  266. function is_mmx_able_array(p : pdef) : boolean;
  267. begin
  268. {$ifdef SUPPORT_MMX}
  269. if (cs_mmx_saturation in aktswitches) then
  270. begin
  271. is_mmx_able_array:=(p^.deftype=arraydef) and
  272. (
  273. ((parraydef(p)^.definition^.deftype=orddef) and
  274. (
  275. (parraydef(p)^.lowrange=0) and
  276. (parraydef(p)^.highrange=1) and
  277. (porddef(parraydef(p)^.definition)^.typ in [u32bit,s32bit])
  278. ) or
  279. (
  280. (parraydef(p)^.lowrange=0) and
  281. (parraydef(p)^.highrange=3) and
  282. (porddef(parraydef(p)^.definition)^.typ in [u16bit,s16bit])
  283. )
  284. )
  285. ) or
  286. (
  287. ((parraydef(p)^.definition^.deftype=floatdef) and
  288. (
  289. (parraydef(p)^.lowrange=0) and
  290. (parraydef(p)^.highrange=3) and
  291. (pfloatdef(parraydef(p)^.definition)^.typ=f16bit)
  292. ) or
  293. (
  294. (parraydef(p)^.lowrange=0) and
  295. (parraydef(p)^.highrange=1) and
  296. (pfloatdef(parraydef(p)^.definition)^.typ=s32real)
  297. )
  298. )
  299. );
  300. end
  301. else
  302. begin
  303. is_mmx_able_array:=(p^.deftype=arraydef) and
  304. (
  305. ((parraydef(p)^.definition^.deftype=orddef) and
  306. (
  307. (parraydef(p)^.lowrange=0) and
  308. (parraydef(p)^.highrange=1) and
  309. (porddef(parraydef(p)^.definition)^.typ in [u32bit,s32bit])
  310. ) or
  311. (
  312. (parraydef(p)^.lowrange=0) and
  313. (parraydef(p)^.highrange=3) and
  314. (porddef(parraydef(p)^.definition)^.typ in [u16bit,s16bit])
  315. ) or
  316. (
  317. (parraydef(p)^.lowrange=0) and
  318. (parraydef(p)^.highrange=7) and
  319. (porddef(parraydef(p)^.definition)^.typ in [u8bit,s8bit])
  320. )
  321. )
  322. ) or
  323. (
  324. ((parraydef(p)^.definition^.deftype=floatdef) and
  325. (
  326. (parraydef(p)^.lowrange=0) and
  327. (parraydef(p)^.highrange=3) and
  328. (pfloatdef(parraydef(p)^.definition)^.typ=f32bit)
  329. )
  330. or
  331. (
  332. (parraydef(p)^.lowrange=0) and
  333. (parraydef(p)^.highrange=1) and
  334. (pfloatdef(parraydef(p)^.definition)^.typ=s32real)
  335. )
  336. )
  337. );
  338. end;
  339. {$else SUPPORT_MMX}
  340. is_mmx_able_array:=false;
  341. {$endif SUPPORT_MMX}
  342. end;
  343. function is_equal(def1,def2 : pdef) : boolean;
  344. var
  345. b : boolean;
  346. hd : pdef;
  347. hp1,hp2 : pdefcoll;
  348. begin
  349. { both types must exists }
  350. if not (assigned(def1) and assigned(def2)) then
  351. begin
  352. is_equal:=false;
  353. exit;
  354. end;
  355. { be sure, that if there is a stringdef, that this is def1 }
  356. if def2^.deftype=stringdef then
  357. begin
  358. hd:=def1;
  359. def1:=def2;
  360. def2:=hd;
  361. end;
  362. b:=false;
  363. { wenn beide auf die gleiche Definition zeigen sind sie wohl gleich...}
  364. if def1=def2 then
  365. b:=true
  366. else
  367. { pointer with an equal definition are equal }
  368. if (def1^.deftype=pointerdef) and (def2^.deftype=pointerdef) then
  369. { here a problem detected in tabsolutesym }
  370. { the types can be forward type !! }
  371. begin
  372. if assigned(def1^.sym) and ((def1^.sym^.properties and sp_forwarddef)<>0) then
  373. b:=(def1^.sym=def2^.sym)
  374. else
  375. b:=is_equal(ppointerdef(def1)^.definition,ppointerdef(def2)^.definition);
  376. end
  377. else
  378. { ordinals are equal only when the ordinal type is equal }
  379. if (def1^.deftype=orddef) and (def2^.deftype=orddef) then
  380. begin
  381. case porddef(def1)^.typ of
  382. u8bit,u16bit,u32bit,
  383. s8bit,s16bit,s32bit:
  384. b:=((porddef(def1)^.typ=porddef(def2)^.typ) and
  385. (porddef(def1)^.low=porddef(def2)^.low) and
  386. (porddef(def1)^.high=porddef(def2)^.high));
  387. uvoid,uchar,
  388. bool8bit,bool16bit,bool32bit:
  389. b:=(porddef(def1)^.typ=porddef(def2)^.typ);
  390. end;
  391. end
  392. else
  393. if (def1^.deftype=floatdef) and (def2^.deftype=floatdef) then
  394. b:=pfloatdef(def1)^.typ=pfloatdef(def2)^.typ
  395. else
  396. { strings with the same length are equal }
  397. if (def1^.deftype=stringdef) and (def2^.deftype=stringdef) and
  398. (pstringdef(def1)^.len=pstringdef(def2)^.len) then
  399. b:=true
  400. { STRING[N] ist equivalent zu ARRAY[0..N] OF CHAR (N<256) }
  401. {
  402. else if ((def1^.deftype=stringdef) and (def2^.deftype=arraydef)) and
  403. (parraydef(def2)^.definition^.deftype=orddef) and
  404. (porddef(parraydef(def1)^.definition)^.typ=uchar) and
  405. (parraydef(def2)^.lowrange=0) and
  406. (parraydef(def2)^.highrange=pstringdef(def1)^.len) then
  407. b:=true }
  408. else
  409. if (def1^.deftype=formaldef) and (def2^.deftype=formaldef) then
  410. b:=true
  411. { file types with the same file element type are equal }
  412. { this is a problem for assign !! }
  413. { changed to allow if one is untyped }
  414. { all typed files are equal to the special }
  415. { typed file that has voiddef as elemnt type }
  416. { but must NOT match for text file !!! }
  417. else
  418. if (def1^.deftype=filedef) and (def2^.deftype=filedef) then
  419. b:=(pfiledef(def1)^.filetype=pfiledef(def2)^.filetype) and
  420. ((
  421. ((pfiledef(def1)^.typed_as=nil) and
  422. (pfiledef(def2)^.typed_as=nil)) or
  423. (
  424. (pfiledef(def1)^.typed_as<>nil) and
  425. (pfiledef(def2)^.typed_as<>nil) and
  426. is_equal(pfiledef(def1)^.typed_as,pfiledef(def2)^.typed_as)
  427. ) or
  428. ( (pfiledef(def1)^.typed_as=pdef(voiddef)) or
  429. (pfiledef(def2)^.typed_as=pdef(voiddef))
  430. )))
  431. { sets with the same element type are equal }
  432. else
  433. if (def1^.deftype=setdef) and (def2^.deftype=setdef) then
  434. begin
  435. if assigned(psetdef(def1)^.setof) and
  436. assigned(psetdef(def2)^.setof) then
  437. b:=is_equal(psetdef(def1)^.setof,psetdef(def2)^.setof)
  438. else b:=true;
  439. end
  440. else
  441. if (def1^.deftype=procvardef) and (def2^.deftype=procvardef) then
  442. begin
  443. { poassembler isn't important for compatibility }
  444. b:=((pprocvardef(def1)^.options and not(poassembler))=
  445. (pprocvardef(def2)^.options and not(poassembler))
  446. ) and
  447. is_equal(pprocvardef(def1)^.retdef,pprocvardef(def2)^.retdef);
  448. { now evalute the parameters }
  449. if b then
  450. begin
  451. hp1:=pprocvardef(def1)^.para1;
  452. hp2:=pprocvardef(def1)^.para1;
  453. while assigned(hp1) and assigned(hp2) do
  454. begin
  455. if not(is_equal(hp1^.data,hp2^.data)) or
  456. not(hp1^.paratyp=hp2^.paratyp) then
  457. begin
  458. b:=false;
  459. break;
  460. end;
  461. hp1:=hp1^.next;
  462. hp2:=hp2^.next;
  463. end;
  464. b:=(hp1=nil) and (hp2=nil);
  465. end;
  466. end
  467. else
  468. if (def1^.deftype=arraydef) and (def2^.deftype=arraydef) and
  469. (is_open_array(def1) or is_open_array(def2)) then
  470. begin
  471. b:=is_equal(parraydef(def1)^.definition,parraydef(def2)^.definition);
  472. end
  473. else
  474. if (def1^.deftype=classrefdef) and (def2^.deftype=classrefdef) then
  475. begin
  476. { similar to pointerdef: }
  477. if assigned(def1^.sym) and ((def1^.sym^.properties and sp_forwarddef)<>0) then
  478. b:=(def1^.sym=def2^.sym)
  479. else
  480. b:=is_equal(pclassrefdef(def1)^.definition,pclassrefdef(def2)^.definition);
  481. end;
  482. is_equal:=b;
  483. end;
  484. function is_subequal(def1, def2: pdef): boolean;
  485. Begin
  486. if assigned(def1) and assigned(def2) then
  487. Begin
  488. is_subequal := FALSE;
  489. if (def1^.deftype = orddef) and (def2^.deftype = orddef) then
  490. Begin
  491. { see p.47 of Turbo Pascal 7.01 manual for the separation of types }
  492. { range checking for case statements is done with testrange }
  493. case porddef(def1)^.typ of
  494. u8bit,u16bit,u32bit,
  495. s8bit,s16bit,s32bit : is_subequal:=(porddef(def2)^.typ in [s32bit,u32bit,u8bit,s8bit,s16bit,u16bit]);
  496. bool8bit,bool16bit,bool32bit : is_subequal:=(porddef(def2)^.typ in [bool8bit,bool16bit,bool32bit]);
  497. uchar : is_subequal:=(porddef(def2)^.typ=uchar);
  498. end;
  499. end
  500. else
  501. Begin
  502. { I assume that both enumerations are equal when the first }
  503. { pointers are equal. }
  504. if (def1^.deftype = enumdef) and (def2^.deftype =enumdef) then
  505. Begin
  506. if penumdef(def1)^.first = penumdef(def2)^.first then
  507. is_subequal := TRUE;
  508. end;
  509. end;
  510. end; { endif assigned ... }
  511. end;
  512. type
  513. pprocdefcoll = ^tprocdefcoll;
  514. tprocdefcoll = record
  515. next : pprocdefcoll;
  516. data : pprocdef;
  517. end;
  518. psymcoll = ^tsymcoll;
  519. tsymcoll = record
  520. next : psymcoll;
  521. name : pstring;
  522. data : pprocdefcoll;
  523. end;
  524. var
  525. wurzel : psymcoll;
  526. nextvirtnumber : longint;
  527. _c : pobjectdef;
  528. has_constructor,has_virtual_method : boolean;
  529. procedure eachsym(sym : psym);{$ifndef FPC}far;{$endif}
  530. var
  531. procdefcoll : pprocdefcoll;
  532. hp : pprocdef;
  533. symcoll : psymcoll;
  534. _name : string;
  535. stored : boolean;
  536. { creates a new entry in the procsym list }
  537. procedure newentry;
  538. begin
  539. { if not, generate a new symbol item }
  540. new(symcoll);
  541. symcoll^.name:=stringdup(sym^.name);
  542. symcoll^.next:=wurzel;
  543. symcoll^.data:=nil;
  544. wurzel:=symcoll;
  545. hp:=pprocsym(sym)^.definition;
  546. { inserts all definitions }
  547. while assigned(hp) do
  548. begin
  549. new(procdefcoll);
  550. procdefcoll^.data:=hp;
  551. procdefcoll^.next:=symcoll^.data;
  552. symcoll^.data:=procdefcoll;
  553. { if it's a virtual method }
  554. if (hp^.options and povirtualmethod)<>0 then
  555. begin
  556. { then it gets a number ... }
  557. hp^.extnumber:=nextvirtnumber;
  558. { and we inc the number }
  559. inc(nextvirtnumber);
  560. has_virtual_method:=true;
  561. end;
  562. if (hp^.options and poconstructor)<>0 then
  563. has_constructor:=true;
  564. { check, if a method should be overridden }
  565. if (hp^.options and pooverridingmethod)<>0 then
  566. Message1(parser_e_nothing_to_be_overridden,_c^.name^+'.'+_name);
  567. { next overloaded method }
  568. hp:=hp^.nextoverloaded;
  569. end;
  570. end;
  571. begin
  572. { put only sub routines into the VMT }
  573. if sym^.typ=procsym then
  574. begin
  575. _name:=sym^.name;
  576. symcoll:=wurzel;
  577. while assigned(symcoll) do
  578. begin
  579. { does the symbol already exist in the list ? }
  580. if _name=symcoll^.name^ then
  581. begin
  582. { walk through all defs of the symbol }
  583. hp:=pprocsym(sym)^.definition;
  584. while assigned(hp) do
  585. begin
  586. { compare with all stored definitions }
  587. procdefcoll:=symcoll^.data;
  588. stored:=false;
  589. while assigned(procdefcoll) do
  590. begin
  591. { compare parameters }
  592. if equal_paras(procdefcoll^.data^.para1,hp^.para1,false) and
  593. (
  594. ((procdefcoll^.data^.options and povirtualmethod)<>0) or
  595. ((hp^.options and povirtualmethod)<>0)
  596. ) then
  597. begin
  598. { wenn sie gleich sind }
  599. { und eine davon virtual deklariert ist }
  600. { Fehler falls nur eine VIRTUAL }
  601. if (procdefcoll^.data^.options and povirtualmethod)<>
  602. (hp^.options and povirtualmethod) then
  603. begin
  604. { in classes, we hide the old method }
  605. if _c^.isclass then
  606. begin
  607. { warn only if it is the first time,
  608. we hide the method }
  609. if _c=hp^._class then
  610. Message1(parser_w_should_use_override,_c^.name^+'.'+_name);
  611. newentry;
  612. exit;
  613. end
  614. else
  615. begin
  616. Message1(parser_e_overloaded_are_not_both_virtual,_c^.name^+'.'+_name);
  617. end;
  618. end;
  619. { check, if the overridden directive is set }
  620. { (povirtualmethod is set! }
  621. { class ? }
  622. if _c^.isclass and
  623. ((hp^.options and pooverridingmethod)=0) then
  624. begin
  625. { warn only if it is the first time,
  626. we hide the method }
  627. if _c=hp^._class then
  628. Message1(parser_w_should_use_override,_c^.name^+'.'+_name);
  629. newentry;
  630. exit;
  631. end;
  632. { error, if the return types aren't equal }
  633. if not(is_equal(procdefcoll^.data^.retdef,hp^.retdef)) then
  634. Message1(parser_e_overloaded_methodes_not_same_ret,_c^.name^+'.'+_name);
  635. { the flags have to match }
  636. { except abstract and override }
  637. if (procdefcoll^.data^.options and not(poabstractmethod or pooverridingmethod))<>
  638. (hp^.options and not(poabstractmethod or pooverridingmethod)) then
  639. Message1(parser_e_header_dont_match_forward,_c^.name^+'.'+_name);
  640. { now set the number }
  641. hp^.extnumber:=procdefcoll^.data^.extnumber;
  642. { and exchange }
  643. procdefcoll^.data:=hp;
  644. stored:=true;
  645. end;
  646. procdefcoll:=procdefcoll^.next;
  647. end;
  648. { if it isn't saved in the list }
  649. { we create a new entry }
  650. if not(stored) then
  651. begin
  652. new(procdefcoll);
  653. procdefcoll^.data:=hp;
  654. procdefcoll^.next:=symcoll^.data;
  655. symcoll^.data:=procdefcoll;
  656. { if the method is virtual ... }
  657. if (hp^.options and povirtualmethod)<>0 then
  658. begin
  659. { ... it will get a number }
  660. hp^.extnumber:=nextvirtnumber;
  661. inc(nextvirtnumber);
  662. end;
  663. { check, if a method should be overridden }
  664. if (hp^.options and pooverridingmethod)<>0 then
  665. Message1(parser_e_nothing_to_be_overridden,_c^.name^+'.'+_name);
  666. end;
  667. hp:=hp^.nextoverloaded;
  668. end;
  669. exit;
  670. end;
  671. symcoll:=symcoll^.next;
  672. end;
  673. newentry;
  674. end;
  675. end;
  676. procedure genvmt(_class : pobjectdef);
  677. procedure do_genvmt(p : pobjectdef);
  678. begin
  679. { start with the base class }
  680. if assigned(p^.childof) then
  681. do_genvmt(p^.childof);
  682. { walk through all public syms }
  683. _c:=_class;
  684. {$ifdef tp}
  685. p^.publicsyms^.foreach(eachsym);
  686. {$else}
  687. p^.publicsyms^.foreach(@eachsym);
  688. {$endif}
  689. end;
  690. var
  691. symcoll : psymcoll;
  692. procdefcoll : pprocdefcoll;
  693. i : longint;
  694. begin
  695. wurzel:=nil;
  696. nextvirtnumber:=0;
  697. has_constructor:=false;
  698. has_virtual_method:=false;
  699. { generates a tree of all used methods }
  700. do_genvmt(_class);
  701. if has_virtual_method and not(has_constructor) then
  702. Message1(parser_w_virtual_without_constructor,_class^.name^);
  703. { generates the VMT }
  704. { walk trough all numbers for virtual methods and search }
  705. { the method }
  706. for i:=0 to nextvirtnumber-1 do
  707. begin
  708. symcoll:=wurzel;
  709. { walk trough all symbols }
  710. while assigned(symcoll) do
  711. begin
  712. { walk trough all methods }
  713. procdefcoll:=symcoll^.data;
  714. while assigned(procdefcoll) do
  715. begin
  716. { writes the addresses to the VMT }
  717. { but only this which are declared as virtual }
  718. if procdefcoll^.data^.extnumber=i then
  719. begin
  720. if (procdefcoll^.data^.options and povirtualmethod)<>0 then
  721. begin
  722. { if a method is abstract, then is also the }
  723. { class abstract and it's not allow to }
  724. { generates an instance }
  725. if (procdefcoll^.data^.options and poabstractmethod)<>0 then
  726. begin
  727. _class^.options:=_class^.options or oois_abstract;
  728. datasegment^.concat(new(pai_const,init_symbol('ABSTRACTERROR')));
  729. end
  730. else
  731. begin
  732. datasegment^.concat(new(pai_const,init_symbol(
  733. strpnew(procdefcoll^.data^.mangledname))));
  734. maybe_concat_external(procdefcoll^.data^.owner,
  735. procdefcoll^.data^.mangledname);
  736. end;
  737. end;
  738. end;
  739. procdefcoll:=procdefcoll^.next;
  740. end;
  741. symcoll:=symcoll^.next;
  742. end;
  743. end;
  744. { disposes the above generated tree }
  745. symcoll:=wurzel;
  746. while assigned(symcoll) do
  747. begin
  748. wurzel:=symcoll^.next;
  749. stringdispose(symcoll^.name);
  750. procdefcoll:=symcoll^.data;
  751. while assigned(procdefcoll) do
  752. begin
  753. symcoll^.data:=procdefcoll^.next;
  754. dispose(procdefcoll);
  755. procdefcoll:=symcoll^.data;
  756. end;
  757. dispose(symcoll);
  758. symcoll:=wurzel;
  759. end;
  760. end;
  761. end.
  762. {
  763. $Log$
  764. Revision 1.15 1998-07-18 22:54:32 florian
  765. * some ansi/wide/longstring support fixed:
  766. o parameter passing
  767. o returning as result from functions
  768. Revision 1.14 1998/06/12 14:50:50 peter
  769. * removed the tree dependency to types.pas
  770. * long_fil.pas support (not fully tested yet)
  771. Revision 1.13 1998/06/03 22:49:07 peter
  772. + wordbool,longbool
  773. * rename bis,von -> high,low
  774. * moved some systemunit loading/creating to psystem.pas
  775. Revision 1.12 1998/05/12 10:47:00 peter
  776. * moved printstatus to verb_def
  777. + V_Normal which is between V_Error and V_Warning and doesn't have a
  778. prefix like error: warning: and is included in V_Default
  779. * fixed some messages
  780. * first time parameter scan is only for -v and -T
  781. - removed old style messages
  782. Revision 1.11 1998/05/01 16:38:46 florian
  783. * handling of private and protected fixed
  784. + change_keywords_to_tp implemented to remove
  785. keywords which aren't supported by tp
  786. * break and continue are now symbols of the system unit
  787. + widestring, longstring and ansistring type released
  788. Revision 1.10 1998/04/29 10:34:08 pierre
  789. + added some code for ansistring (not complete nor working yet)
  790. * corrected operator overloading
  791. * corrected nasm output
  792. + started inline procedures
  793. + added starstarn : use ** for exponentiation (^ gave problems)
  794. + started UseTokenInfo cond to get accurate positions
  795. Revision 1.9 1998/04/21 10:16:49 peter
  796. * patches from strasbourg
  797. * objects is not used anymore in the fpc compiled version
  798. Revision 1.8 1998/04/12 22:39:44 florian
  799. * problem with read access to properties solved
  800. * correct handling of hidding methods via virtual (COM)
  801. * correct result type of constructor calls (COM), the resulttype
  802. depends now on the type of the class reference
  803. Revision 1.7 1998/04/10 21:36:56 florian
  804. + some stuff to support method pointers (procedure of object) added
  805. (declaration, parameter handling)
  806. Revision 1.6 1998/04/10 15:39:49 florian
  807. * more fixes to get classes.pas compiled
  808. Revision 1.5 1998/04/09 23:02:16 florian
  809. * small problems solved to get remake3 work
  810. Revision 1.4 1998/04/08 16:58:09 pierre
  811. * several bugfixes
  812. ADD ADC and AND are also sign extended
  813. nasm output OK (program still crashes at end
  814. and creates wrong assembler files !!)
  815. procsym types sym in tdef removed !!
  816. Revision 1.3 1998/04/08 11:34:22 peter
  817. * nasm works (linux only tested)
  818. }