types.pas 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  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)^.string_typ=pstringdef(def2)^.string_typ) then
  399. begin
  400. b:=not(is_shortstring(def1)) or
  401. (pstringdef(def1)^.len=pstringdef(def2)^.len);
  402. end
  403. { STRING[N] ist equivalent zu ARRAY[0..N] OF CHAR (N<256) }
  404. {
  405. else if ((def1^.deftype=stringdef) and (def2^.deftype=arraydef)) and
  406. (parraydef(def2)^.definition^.deftype=orddef) and
  407. (porddef(parraydef(def1)^.definition)^.typ=uchar) and
  408. (parraydef(def2)^.lowrange=0) and
  409. (parraydef(def2)^.highrange=pstringdef(def1)^.len) then
  410. b:=true }
  411. else
  412. if (def1^.deftype=formaldef) and (def2^.deftype=formaldef) then
  413. b:=true
  414. { file types with the same file element type are equal }
  415. { this is a problem for assign !! }
  416. { changed to allow if one is untyped }
  417. { all typed files are equal to the special }
  418. { typed file that has voiddef as elemnt type }
  419. { but must NOT match for text file !!! }
  420. else
  421. if (def1^.deftype=filedef) and (def2^.deftype=filedef) then
  422. b:=(pfiledef(def1)^.filetype=pfiledef(def2)^.filetype) and
  423. ((
  424. ((pfiledef(def1)^.typed_as=nil) and
  425. (pfiledef(def2)^.typed_as=nil)) or
  426. (
  427. (pfiledef(def1)^.typed_as<>nil) and
  428. (pfiledef(def2)^.typed_as<>nil) and
  429. is_equal(pfiledef(def1)^.typed_as,pfiledef(def2)^.typed_as)
  430. ) or
  431. ( (pfiledef(def1)^.typed_as=pdef(voiddef)) or
  432. (pfiledef(def2)^.typed_as=pdef(voiddef))
  433. )))
  434. { sets with the same element type are equal }
  435. else
  436. if (def1^.deftype=setdef) and (def2^.deftype=setdef) then
  437. begin
  438. if assigned(psetdef(def1)^.setof) and
  439. assigned(psetdef(def2)^.setof) then
  440. b:=is_equal(psetdef(def1)^.setof,psetdef(def2)^.setof)
  441. else b:=true;
  442. end
  443. else
  444. if (def1^.deftype=procvardef) and (def2^.deftype=procvardef) then
  445. begin
  446. { poassembler isn't important for compatibility }
  447. b:=((pprocvardef(def1)^.options and not(poassembler))=
  448. (pprocvardef(def2)^.options and not(poassembler))
  449. ) and
  450. is_equal(pprocvardef(def1)^.retdef,pprocvardef(def2)^.retdef);
  451. { now evalute the parameters }
  452. if b then
  453. begin
  454. hp1:=pprocvardef(def1)^.para1;
  455. hp2:=pprocvardef(def1)^.para1;
  456. while assigned(hp1) and assigned(hp2) do
  457. begin
  458. if not(is_equal(hp1^.data,hp2^.data)) or
  459. not(hp1^.paratyp=hp2^.paratyp) then
  460. begin
  461. b:=false;
  462. break;
  463. end;
  464. hp1:=hp1^.next;
  465. hp2:=hp2^.next;
  466. end;
  467. b:=(hp1=nil) and (hp2=nil);
  468. end;
  469. end
  470. else
  471. if (def1^.deftype=arraydef) and (def2^.deftype=arraydef) and
  472. (is_open_array(def1) or is_open_array(def2)) then
  473. begin
  474. b:=is_equal(parraydef(def1)^.definition,parraydef(def2)^.definition);
  475. end
  476. else
  477. if (def1^.deftype=classrefdef) and (def2^.deftype=classrefdef) then
  478. begin
  479. { similar to pointerdef: }
  480. if assigned(def1^.sym) and ((def1^.sym^.properties and sp_forwarddef)<>0) then
  481. b:=(def1^.sym=def2^.sym)
  482. else
  483. b:=is_equal(pclassrefdef(def1)^.definition,pclassrefdef(def2)^.definition);
  484. end;
  485. is_equal:=b;
  486. end;
  487. function is_subequal(def1, def2: pdef): boolean;
  488. Begin
  489. if assigned(def1) and assigned(def2) then
  490. Begin
  491. is_subequal := FALSE;
  492. if (def1^.deftype = orddef) and (def2^.deftype = orddef) then
  493. Begin
  494. { see p.47 of Turbo Pascal 7.01 manual for the separation of types }
  495. { range checking for case statements is done with testrange }
  496. case porddef(def1)^.typ of
  497. u8bit,u16bit,u32bit,
  498. s8bit,s16bit,s32bit : is_subequal:=(porddef(def2)^.typ in [s32bit,u32bit,u8bit,s8bit,s16bit,u16bit]);
  499. bool8bit,bool16bit,bool32bit : is_subequal:=(porddef(def2)^.typ in [bool8bit,bool16bit,bool32bit]);
  500. uchar : is_subequal:=(porddef(def2)^.typ=uchar);
  501. end;
  502. end
  503. else
  504. Begin
  505. { I assume that both enumerations are equal when the first }
  506. { pointers are equal. }
  507. if (def1^.deftype = enumdef) and (def2^.deftype =enumdef) then
  508. Begin
  509. if penumdef(def1)^.first = penumdef(def2)^.first then
  510. is_subequal := TRUE;
  511. end;
  512. end;
  513. end; { endif assigned ... }
  514. end;
  515. type
  516. pprocdefcoll = ^tprocdefcoll;
  517. tprocdefcoll = record
  518. next : pprocdefcoll;
  519. data : pprocdef;
  520. end;
  521. psymcoll = ^tsymcoll;
  522. tsymcoll = record
  523. next : psymcoll;
  524. name : pstring;
  525. data : pprocdefcoll;
  526. end;
  527. var
  528. wurzel : psymcoll;
  529. nextvirtnumber : longint;
  530. _c : pobjectdef;
  531. has_constructor,has_virtual_method : boolean;
  532. procedure eachsym(sym : psym);{$ifndef FPC}far;{$endif}
  533. var
  534. procdefcoll : pprocdefcoll;
  535. hp : pprocdef;
  536. symcoll : psymcoll;
  537. _name : string;
  538. stored : boolean;
  539. { creates a new entry in the procsym list }
  540. procedure newentry;
  541. begin
  542. { if not, generate a new symbol item }
  543. new(symcoll);
  544. symcoll^.name:=stringdup(sym^.name);
  545. symcoll^.next:=wurzel;
  546. symcoll^.data:=nil;
  547. wurzel:=symcoll;
  548. hp:=pprocsym(sym)^.definition;
  549. { inserts all definitions }
  550. while assigned(hp) do
  551. begin
  552. new(procdefcoll);
  553. procdefcoll^.data:=hp;
  554. procdefcoll^.next:=symcoll^.data;
  555. symcoll^.data:=procdefcoll;
  556. { if it's a virtual method }
  557. if (hp^.options and povirtualmethod)<>0 then
  558. begin
  559. { then it gets a number ... }
  560. hp^.extnumber:=nextvirtnumber;
  561. { and we inc the number }
  562. inc(nextvirtnumber);
  563. has_virtual_method:=true;
  564. end;
  565. if (hp^.options and poconstructor)<>0 then
  566. has_constructor:=true;
  567. { check, if a method should be overridden }
  568. if (hp^.options and pooverridingmethod)<>0 then
  569. Message1(parser_e_nothing_to_be_overridden,_c^.name^+'.'+_name);
  570. { next overloaded method }
  571. hp:=hp^.nextoverloaded;
  572. end;
  573. end;
  574. begin
  575. { put only sub routines into the VMT }
  576. if sym^.typ=procsym then
  577. begin
  578. _name:=sym^.name;
  579. symcoll:=wurzel;
  580. while assigned(symcoll) do
  581. begin
  582. { does the symbol already exist in the list ? }
  583. if _name=symcoll^.name^ then
  584. begin
  585. { walk through all defs of the symbol }
  586. hp:=pprocsym(sym)^.definition;
  587. while assigned(hp) do
  588. begin
  589. { compare with all stored definitions }
  590. procdefcoll:=symcoll^.data;
  591. stored:=false;
  592. while assigned(procdefcoll) do
  593. begin
  594. { compare parameters }
  595. if equal_paras(procdefcoll^.data^.para1,hp^.para1,false) and
  596. (
  597. ((procdefcoll^.data^.options and povirtualmethod)<>0) or
  598. ((hp^.options and povirtualmethod)<>0)
  599. ) then
  600. begin
  601. { wenn sie gleich sind }
  602. { und eine davon virtual deklariert ist }
  603. { Fehler falls nur eine VIRTUAL }
  604. if (procdefcoll^.data^.options and povirtualmethod)<>
  605. (hp^.options and povirtualmethod) then
  606. begin
  607. { in classes, we hide the old method }
  608. if _c^.isclass then
  609. begin
  610. { warn only if it is the first time,
  611. we hide the method }
  612. if _c=hp^._class then
  613. Message1(parser_w_should_use_override,_c^.name^+'.'+_name);
  614. newentry;
  615. exit;
  616. end
  617. else
  618. begin
  619. Message1(parser_e_overloaded_are_not_both_virtual,_c^.name^+'.'+_name);
  620. end;
  621. end;
  622. { check, if the overridden directive is set }
  623. { (povirtualmethod is set! }
  624. { class ? }
  625. if _c^.isclass and
  626. ((hp^.options and pooverridingmethod)=0) then
  627. begin
  628. { warn only if it is the first time,
  629. we hide the method }
  630. if _c=hp^._class then
  631. Message1(parser_w_should_use_override,_c^.name^+'.'+_name);
  632. newentry;
  633. exit;
  634. end;
  635. { error, if the return types aren't equal }
  636. if not(is_equal(procdefcoll^.data^.retdef,hp^.retdef)) then
  637. Message1(parser_e_overloaded_methodes_not_same_ret,_c^.name^+'.'+_name);
  638. { the flags have to match }
  639. { except abstract and override }
  640. if (procdefcoll^.data^.options and not(poabstractmethod or pooverridingmethod))<>
  641. (hp^.options and not(poabstractmethod or pooverridingmethod)) then
  642. Message1(parser_e_header_dont_match_forward,_c^.name^+'.'+_name);
  643. { now set the number }
  644. hp^.extnumber:=procdefcoll^.data^.extnumber;
  645. { and exchange }
  646. procdefcoll^.data:=hp;
  647. stored:=true;
  648. end;
  649. procdefcoll:=procdefcoll^.next;
  650. end;
  651. { if it isn't saved in the list }
  652. { we create a new entry }
  653. if not(stored) then
  654. begin
  655. new(procdefcoll);
  656. procdefcoll^.data:=hp;
  657. procdefcoll^.next:=symcoll^.data;
  658. symcoll^.data:=procdefcoll;
  659. { if the method is virtual ... }
  660. if (hp^.options and povirtualmethod)<>0 then
  661. begin
  662. { ... it will get a number }
  663. hp^.extnumber:=nextvirtnumber;
  664. inc(nextvirtnumber);
  665. end;
  666. { check, if a method should be overridden }
  667. if (hp^.options and pooverridingmethod)<>0 then
  668. Message1(parser_e_nothing_to_be_overridden,_c^.name^+'.'+_name);
  669. end;
  670. hp:=hp^.nextoverloaded;
  671. end;
  672. exit;
  673. end;
  674. symcoll:=symcoll^.next;
  675. end;
  676. newentry;
  677. end;
  678. end;
  679. procedure genvmt(_class : pobjectdef);
  680. procedure do_genvmt(p : pobjectdef);
  681. begin
  682. { start with the base class }
  683. if assigned(p^.childof) then
  684. do_genvmt(p^.childof);
  685. { walk through all public syms }
  686. _c:=_class;
  687. {$ifdef tp}
  688. p^.publicsyms^.foreach(eachsym);
  689. {$else}
  690. p^.publicsyms^.foreach(@eachsym);
  691. {$endif}
  692. end;
  693. var
  694. symcoll : psymcoll;
  695. procdefcoll : pprocdefcoll;
  696. i : longint;
  697. begin
  698. wurzel:=nil;
  699. nextvirtnumber:=0;
  700. has_constructor:=false;
  701. has_virtual_method:=false;
  702. { generates a tree of all used methods }
  703. do_genvmt(_class);
  704. if has_virtual_method and not(has_constructor) then
  705. Message1(parser_w_virtual_without_constructor,_class^.name^);
  706. { generates the VMT }
  707. { walk trough all numbers for virtual methods and search }
  708. { the method }
  709. for i:=0 to nextvirtnumber-1 do
  710. begin
  711. symcoll:=wurzel;
  712. { walk trough all symbols }
  713. while assigned(symcoll) do
  714. begin
  715. { walk trough all methods }
  716. procdefcoll:=symcoll^.data;
  717. while assigned(procdefcoll) do
  718. begin
  719. { writes the addresses to the VMT }
  720. { but only this which are declared as virtual }
  721. if procdefcoll^.data^.extnumber=i then
  722. begin
  723. if (procdefcoll^.data^.options and povirtualmethod)<>0 then
  724. begin
  725. { if a method is abstract, then is also the }
  726. { class abstract and it's not allow to }
  727. { generates an instance }
  728. if (procdefcoll^.data^.options and poabstractmethod)<>0 then
  729. begin
  730. _class^.options:=_class^.options or oois_abstract;
  731. datasegment^.concat(new(pai_const,init_symbol('ABSTRACTERROR')));
  732. end
  733. else
  734. begin
  735. datasegment^.concat(new(pai_const,init_symbol(
  736. strpnew(procdefcoll^.data^.mangledname))));
  737. maybe_concat_external(procdefcoll^.data^.owner,
  738. procdefcoll^.data^.mangledname);
  739. end;
  740. end;
  741. end;
  742. procdefcoll:=procdefcoll^.next;
  743. end;
  744. symcoll:=symcoll^.next;
  745. end;
  746. end;
  747. { disposes the above generated tree }
  748. symcoll:=wurzel;
  749. while assigned(symcoll) do
  750. begin
  751. wurzel:=symcoll^.next;
  752. stringdispose(symcoll^.name);
  753. procdefcoll:=symcoll^.data;
  754. while assigned(procdefcoll) do
  755. begin
  756. symcoll^.data:=procdefcoll^.next;
  757. dispose(procdefcoll);
  758. procdefcoll:=symcoll^.data;
  759. end;
  760. dispose(symcoll);
  761. symcoll:=wurzel;
  762. end;
  763. end;
  764. end.
  765. {
  766. $Log$
  767. Revision 1.17 1998-08-05 16:00:17 florian
  768. * some fixes for ansi strings
  769. * $log$ to $Log$ changed
  770. Revision 1.16 1998/07/20 23:35:50 michael
  771. Const ansistrings are not copied.
  772. Revision 1.15 1998/07/18 22:54:32 florian
  773. * some ansi/wide/longstring support fixed:
  774. o parameter passing
  775. o returning as result from functions
  776. Revision 1.14 1998/06/12 14:50:50 peter
  777. * removed the tree dependency to types.pas
  778. * long_fil.pas support (not fully tested yet)
  779. Revision 1.13 1998/06/03 22:49:07 peter
  780. + wordbool,longbool
  781. * rename bis,von -> high,low
  782. * moved some systemunit loading/creating to psystem.pas
  783. Revision 1.12 1998/05/12 10:47:00 peter
  784. * moved printstatus to verb_def
  785. + V_Normal which is between V_Error and V_Warning and doesn't have a
  786. prefix like error: warning: and is included in V_Default
  787. * fixed some messages
  788. * first time parameter scan is only for -v and -T
  789. - removed old style messages
  790. Revision 1.11 1998/05/01 16:38:46 florian
  791. * handling of private and protected fixed
  792. + change_keywords_to_tp implemented to remove
  793. keywords which aren't supported by tp
  794. * break and continue are now symbols of the system unit
  795. + widestring, longstring and ansistring type released
  796. Revision 1.10 1998/04/29 10:34:08 pierre
  797. + added some code for ansistring (not complete nor working yet)
  798. * corrected operator overloading
  799. * corrected nasm output
  800. + started inline procedures
  801. + added starstarn : use ** for exponentiation (^ gave problems)
  802. + started UseTokenInfo cond to get accurate positions
  803. Revision 1.9 1998/04/21 10:16:49 peter
  804. * patches from strasbourg
  805. * objects is not used anymore in the fpc compiled version
  806. Revision 1.8 1998/04/12 22:39:44 florian
  807. * problem with read access to properties solved
  808. * correct handling of hidding methods via virtual (COM)
  809. * correct result type of constructor calls (COM), the resulttype
  810. depends now on the type of the class reference
  811. Revision 1.7 1998/04/10 21:36:56 florian
  812. + some stuff to support method pointers (procedure of object) added
  813. (declaration, parameter handling)
  814. Revision 1.6 1998/04/10 15:39:49 florian
  815. * more fixes to get classes.pas compiled
  816. Revision 1.5 1998/04/09 23:02:16 florian
  817. * small problems solved to get remake3 work
  818. Revision 1.4 1998/04/08 16:58:09 pierre
  819. * several bugfixes
  820. ADD ADC and AND are also sign extended
  821. nasm output OK (program still crashes at end
  822. and creates wrong assembler files !!)
  823. procsym types sym in tdef removed !!
  824. Revision 1.3 1998/04/08 11:34:22 peter
  825. * nasm works (linux only tested)
  826. }