types.pas 34 KB

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