types.pas 37 KB

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