htypechk.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. This unit exports some help routines for the type checking
  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 htypechk;
  19. {The isconvertable can better be handled inside the symtable, this
  20. would result is much better maintenance possibilities.}
  21. interface
  22. uses
  23. tree,symtable,defs,symbols;
  24. const
  25. { firstcallparan without varspez we don't count the ref }
  26. {$ifdef extdebug}
  27. count_ref : boolean = true;
  28. {$endif def extdebug}
  29. get_para_resulttype : boolean = false;
  30. allow_array_constructor : boolean = false;
  31. { Conversion }
  32. function isconvertable(def_from,def_to : pdef;
  33. var doconv : tconverttype;fromtreetype : ttreetyp;
  34. explicit : boolean) : byte;
  35. { Register Allocation }
  36. procedure make_not_regable(p : ptree);
  37. procedure left_right_max(p : ptree);
  38. procedure calcregisters(p : ptree;r32,fpu,mmx : word);
  39. { subroutine handling }
  40. (* procedure test_protected_sym(sym : psym);
  41. procedure test_protected(p : ptree);*)
  42. function valid_for_formal_var(p : ptree) : boolean;
  43. function valid_for_formal_const(p : ptree) : boolean;
  44. function is_procsym_load(p:Ptree):boolean;
  45. function is_procsym_call(p:Ptree):boolean;
  46. function assignment_overloaded(from_def,to_def : pdef) : pprocdef;
  47. procedure test_local_to_procvar(from_def:pprocvardef;to_def:pdef);
  48. function valid_for_assign(p:ptree;allowprop:boolean):boolean;
  49. implementation
  50. uses
  51. globtype,systems,tokens,
  52. cobjects,verbose,globals,
  53. types,pass_1,cpubase,symtablt,
  54. {$ifdef newcg}
  55. cgbase
  56. {$else}
  57. hcodegen
  58. {$endif}
  59. ;
  60. {****************************************************************************
  61. Convert
  62. ****************************************************************************}
  63. { Returns:
  64. 0 - Not convertable
  65. 1 - Convertable
  66. 2 - Convertable, but not first choice }
  67. function isconvertable(def_from,def_to : pdef;
  68. var doconv : tconverttype;fromtreetype : ttreetyp;
  69. explicit : boolean) : byte;
  70. { Tbasetype: uauto,uvoid,uchar,
  71. u8bit,u16bit,u32bit,
  72. s8bit,s16bit,s32,
  73. bool8bit,bool16bit,bool32bit,
  74. u64bit,s64bitint }
  75. type
  76. tbasedef=(bvoid,bchar,bint,bbool);
  77. const
  78. basedeftbl:array[tbasetype] of tbasedef =
  79. (bvoid,bvoid,bchar,
  80. bint,bint,bint,
  81. bint,bint,bint,
  82. bbool,bbool,bbool,bint,bint,bint,bchar);
  83. basedefconverts : array[tbasedef,tbasedef] of tconverttype =
  84. ((tc_not_possible,tc_not_possible,tc_not_possible,tc_not_possible),
  85. (tc_not_possible,tc_equal,tc_not_possible,tc_not_possible),
  86. (tc_not_possible,tc_not_possible,tc_int_2_int,tc_int_2_bool),
  87. (tc_not_possible,tc_not_possible,tc_bool_2_int,tc_bool_2_bool));
  88. var
  89. b : byte;
  90. hd1,hd2 : pdef;
  91. hct : tconverttype;
  92. begin
  93. {!!!! This code should never be called with nil parameters. If you really
  94. want to check this, make it an internalerror instead of an exit!! (DM)
  95. if not(assigned(def_from) and assigned(def_to)) then
  96. begin
  97. isconvertable:=0;
  98. exit;
  99. end;}
  100. { tp7 procvar def support, in tp7 a procvar is always called, if the
  101. procvar is passed explicit a addrn would be there }
  102. if (m_tp_procvar in aktmodeswitches) and
  103. (def_from^.is_object(typeof(Tprocvardef))) and
  104. (fromtreetype=loadn) then
  105. begin
  106. def_from:=pprocvardef(def_from)^.retdef;
  107. end;
  108. { we walk the wanted (def_to) types and check then the def_from
  109. types if there is a conversion possible }
  110. b:=0;
  111. if def_to^.is_object(typeof(Torddef)) then
  112. begin
  113. if def_from^.is_object(typeof(Torddef)) then
  114. begin
  115. doconv:=basedefconverts[basedeftbl[Tbasetype(porddef(def_from)^.typ)],basedeftbl[porddef(def_to)^.typ]];
  116. b:=1;
  117. if (doconv=tc_not_possible) or
  118. ((doconv=tc_int_2_bool) and
  119. (not explicit) and
  120. (not is_boolean(def_from))) or
  121. ((doconv=tc_bool_2_int) and
  122. (not explicit) and
  123. (not is_boolean(def_to))) then
  124. b:=0;
  125. end
  126. else if def_from^.is_object(typeof(Tenumdef)) then
  127. begin
  128. { needed for char(enum) }
  129. if explicit then
  130. begin
  131. doconv:=tc_int_2_int;
  132. b:=1;
  133. end;
  134. end;
  135. end
  136. else if def_to^.is_object(typeof(Tstringdef)) then
  137. begin
  138. if def_from^.is_object(typeof(Tstringdef)) then
  139. begin
  140. doconv:=tc_string_2_string;
  141. b:=1;
  142. end
  143. else if def_from^.is_object(typeof(Torddef)) then
  144. begin
  145. { char to string}
  146. if is_char(def_from) then
  147. begin
  148. doconv:=tc_char_2_string;
  149. b:=1;
  150. end;
  151. end
  152. else if def_from^.is_object(typeof(Tarraydef)) then
  153. begin
  154. { array of char to string, the length check is done by the firstpass of this node }
  155. if is_chararray(def_from) then
  156. begin
  157. doconv:=tc_chararray_2_string;
  158. if (not(cs_ansistrings in aktlocalswitches) and
  159. is_shortstring(def_to)) or
  160. ((cs_ansistrings in aktlocalswitches) and
  161. is_ansistring(def_to)) then
  162. b:=1
  163. else
  164. b:=2;
  165. end;
  166. end
  167. else if def_from^.is_object(typeof(Tpointerdef)) then
  168. begin
  169. { pchar can be assigned to short/ansistrings }
  170. if is_pchar(def_from) and not(m_tp in aktmodeswitches) then
  171. begin
  172. doconv:=tc_pchar_2_string;
  173. b:=1;
  174. end;
  175. end;
  176. end
  177. else if def_to^.is_object(typeof(Tfloatdef)) then
  178. begin
  179. if def_from^.is_object(typeof(Torddef)) then
  180. begin { ordinal to real }
  181. if is_integer(def_from) then
  182. begin
  183. if pfloatdef(def_to)^.typ=f32bit then
  184. doconv:=tc_int_2_fix
  185. else
  186. doconv:=tc_int_2_real;
  187. b:=1;
  188. end;
  189. end
  190. else if def_from^.is_object(typeof(Tfloatdef)) then
  191. begin { 2 float types ? }
  192. if pfloatdef(def_from)^.typ=pfloatdef(def_to)^.typ then
  193. doconv:=tc_equal
  194. else
  195. begin
  196. if pfloatdef(def_from)^.typ=f32bit then
  197. doconv:=tc_fix_2_real
  198. else
  199. if pfloatdef(def_to)^.typ=f32bit then
  200. doconv:=tc_real_2_fix
  201. else
  202. doconv:=tc_real_2_real;
  203. end;
  204. b:=1;
  205. end;
  206. end
  207. else if def_to^.is_object(typeof(Tenumdef)) then
  208. begin
  209. if def_from^.is_object(typeof(Tenumdef)) then
  210. begin
  211. if assigned(penumdef(def_from)^.basedef) then
  212. hd1:=penumdef(def_from)^.basedef
  213. else
  214. hd1:=def_from;
  215. if assigned(penumdef(def_to)^.basedef) then
  216. hd2:=penumdef(def_to)^.basedef
  217. else
  218. hd2:=def_to;
  219. if (hd1=hd2) then
  220. b:=1;
  221. end;
  222. end
  223. else if def_to^.is_object(typeof(Tarraydef)) then
  224. begin
  225. { open array is also compatible with a single element of its base type }
  226. if is_open_array(def_to) and
  227. is_equal(parraydef(def_to)^.definition,def_from) then
  228. begin
  229. doconv:=tc_equal;
  230. b:=1;
  231. end
  232. else
  233. begin
  234. if def_from^.is_object(typeof(Tarraydef)) then
  235. begin
  236. { array constructor -> open array }
  237. if is_open_array(def_to) and
  238. is_array_constructor(def_from) then
  239. begin
  240. if is_void(parraydef(def_from)^.definition) or
  241. is_equal(parraydef(def_to)^.definition,parraydef(def_from)^.definition) then
  242. begin
  243. doconv:=tc_equal;
  244. b:=1;
  245. end
  246. else
  247. if isconvertable(parraydef(def_to)^.definition,
  248. parraydef(def_from)^.definition,hct,nothingn,false)<>0 then
  249. begin
  250. doconv:=hct;
  251. b:=2;
  252. end;
  253. end;
  254. end
  255. else if def_from^.is_object(typeof(Tpointerdef)) then
  256. begin
  257. if is_zero_based_array(def_to) and
  258. is_equal(ppointerdef(def_from)^.definition,parraydef(def_to)^.definition) then
  259. begin
  260. doconv:=tc_pointer_2_array;
  261. b:=1;
  262. end;
  263. end
  264. else if def_from^.is_object(typeof(Tstringdef)) then
  265. begin
  266. { string to array of char}
  267. if (not(is_special_array(def_to)) or is_open_array(def_to)) and
  268. is_equal(parraydef(def_to)^.definition,cchardef) then
  269. begin
  270. doconv:=tc_string_2_chararray;
  271. b:=1;
  272. end;
  273. end;
  274. end;
  275. end
  276. else if def_to^.is_object(typeof(Tpointerdef)) then
  277. begin
  278. if def_from^.is_object(typeof(Tstringdef)) then
  279. begin
  280. { string constant to zero terminated string constant }
  281. if (fromtreetype=stringconstn) and
  282. is_pchar(def_to) then
  283. begin
  284. doconv:=tc_cstring_2_pchar;
  285. b:=1;
  286. end;
  287. end
  288. else if def_from^.is_object(typeof(Torddef)) then
  289. begin
  290. { char constant to zero terminated string constant }
  291. if (fromtreetype=ordconstn) then
  292. begin
  293. if is_equal(def_from,cchardef) and
  294. is_pchar(def_to) then
  295. begin
  296. doconv:=tc_cchar_2_pchar;
  297. b:=1;
  298. end
  299. else
  300. if is_integer(def_from) then
  301. begin
  302. doconv:=tc_cord_2_pointer;
  303. b:=1;
  304. end;
  305. end;
  306. end
  307. else if def_from^.is_object(typeof(Tarraydef)) then
  308. begin
  309. { chararray to pointer }
  310. if is_zero_based_array(def_from) and
  311. is_equal(parraydef(def_from)^.definition,ppointerdef(def_to)^.definition) then
  312. begin
  313. doconv:=tc_array_2_pointer;
  314. b:=1;
  315. end;
  316. end
  317. else if def_from^.is_object(typeof(Tpointerdef)) then
  318. begin
  319. { child class pointer can be assigned to anchestor pointers }
  320. if (
  321. (Ppointerdef(def_from)^.definition^.is_object(typeof(Tobjectdef))) and
  322. (Ppointerdef(def_to)^.definition^.is_object(typeof(Tobjectdef))) and
  323. pobjectdef(ppointerdef(def_from)^.definition)^.is_related(
  324. pobjectdef(ppointerdef(def_to)^.definition))
  325. ) or
  326. { all pointers can be assigned to void-pointer }
  327. is_equal(ppointerdef(def_to)^.definition,voiddef) or
  328. { in my opnion, is this not clean pascal }
  329. { well, but it's handy to use, it isn't ? (FK) }
  330. is_equal(ppointerdef(def_from)^.definition,voiddef) then
  331. begin
  332. doconv:=tc_equal;
  333. b:=1;
  334. end;
  335. end
  336. else if def_from^.is_object(typeof(Tprocvardef)) then
  337. begin
  338. { procedure variable can be assigned to an void pointer }
  339. { Not anymore. Use the @ operator now.}
  340. if not(m_tp_procvar in aktmodeswitches) and
  341. (typeof((Ppointerdef(def_to)^.definition^))=typeof(Torddef)) and
  342. (porddef(ppointerdef(def_to)^.definition)^.typ=uvoid) then
  343. begin
  344. doconv:=tc_equal;
  345. b:=1;
  346. end;
  347. end
  348. else if def_from^.is_object(typeof(Tclassrefdef)) or
  349. def_from^.is_object(typeof(Tobjectdef)) then
  350. begin
  351. { class types and class reference type
  352. can be assigned to void pointers }
  353. if (
  354. (def_from^.is_object(typeof(Tobjectdef)) and
  355. (oo_is_class in pobjectdef(def_from)^.options))) or
  356. (def_from^.is_object(typeof(Tclassrefdef))
  357. ) and
  358. ppointerdef(def_to)^.definition^.is_object(typeof(Torddef)) and
  359. (porddef(ppointerdef(def_to)^.definition)^.typ=uvoid) then
  360. begin
  361. doconv:=tc_equal;
  362. b:=1;
  363. end;
  364. end;
  365. end
  366. else if def_to^.is_object(typeof(Tsetdef)) then
  367. begin
  368. { automatic arrayconstructor -> set conversion }
  369. if is_array_constructor(def_from) then
  370. begin
  371. doconv:=tc_arrayconstructor_2_set;
  372. b:=1;
  373. end;
  374. end
  375. else if def_to^.is_object(typeof(Tprocvardef)) then
  376. begin
  377. { proc -> procvar }
  378. if def_from^.is_object(typeof(Tprocdef)) then
  379. begin
  380. doconv:=tc_proc_2_procvar;
  381. if proc_to_procvar_equal(pprocdef(def_from),pprocvardef(def_to)) then
  382. b:=1;
  383. end
  384. else
  385. { for example delphi allows the assignement from pointers }
  386. { to procedure variables }
  387. if (m_pointer_2_procedure in aktmodeswitches) and
  388. def_from^.is_object(typeof(Tpointerdef)) and
  389. ppointerdef(def_from)^.definition^.is_object(typeof(Torddef)) and
  390. (porddef(ppointerdef(def_from)^.definition)^.typ=uvoid) then
  391. begin
  392. doconv:=tc_equal;
  393. b:=1;
  394. end
  395. else
  396. { nil is compatible with procvars }
  397. if (fromtreetype=niln) then
  398. begin
  399. doconv:=tc_equal;
  400. b:=1;
  401. end;
  402. end
  403. else if def_to^.is_object(typeof(Tobjectdef)) then
  404. begin
  405. { object pascal objects }
  406. if def_from^.is_object(typeof(Tobjectdef)) then
  407. begin
  408. doconv:=tc_equal;
  409. if pobjectdef(def_from)^.is_related(pobjectdef(def_to)) then
  410. b:=1;
  411. end
  412. else
  413. { Class specific }
  414. if (oo_is_class in pobjectdef(def_to)^.options) then
  415. begin
  416. { void pointer also for delphi mode }
  417. if (m_delphi in aktmodeswitches) and
  418. is_voidpointer(def_from) then
  419. begin
  420. doconv:=tc_equal;
  421. b:=1;
  422. end
  423. else
  424. { nil is compatible with class instances }
  425. if (fromtreetype=niln) and (oo_is_class in pobjectdef(def_to)^.options) then
  426. begin
  427. doconv:=tc_equal;
  428. b:=1;
  429. end;
  430. end;
  431. end
  432. else if def_to^.is_object(typeof(Tclassrefdef)) then
  433. begin
  434. { class reference types }
  435. if def_from^.is_object(typeof(Tclassrefdef)) then
  436. begin
  437. doconv:=tc_equal;
  438. if pobjectdef(pclassrefdef(def_from)^.definition)^.is_related(
  439. pobjectdef(pclassrefdef(def_to)^.definition)) then
  440. b:=1;
  441. end
  442. else
  443. { nil is compatible with class references }
  444. if (fromtreetype=niln) then
  445. begin
  446. doconv:=tc_equal;
  447. b:=1;
  448. end;
  449. end
  450. else if def_to^.is_object(typeof(Tfiledef)) then
  451. begin
  452. { typed files are all equal to the abstract file type
  453. name TYPEDFILE in system.pp in is_equal in types.pas
  454. the problem is that it sholud be also compatible to FILE
  455. but this would leed to a problem for ASSIGN RESET and REWRITE
  456. when trying to find the good overloaded function !!
  457. so all file function are doubled in system.pp
  458. this is not very beautiful !!}
  459. if (typeof(def_from^)=typeof(Tfiledef)) and
  460. (
  461. (
  462. (pfiledef(def_from)^.filetype = ft_typed) and
  463. (pfiledef(def_to)^.filetype = ft_typed) and
  464. (
  465. (pfiledef(def_from)^.definition=pdef(voiddef)) or
  466. (pfiledef(def_to)^.definition=pdef(voiddef))
  467. )
  468. ) or
  469. (
  470. (
  471. (pfiledef(def_from)^.filetype = ft_untyped) and
  472. (pfiledef(def_to)^.filetype = ft_typed)
  473. ) or
  474. (
  475. (pfiledef(def_from)^.filetype = ft_typed) and
  476. (pfiledef(def_to)^.filetype = ft_untyped)
  477. )
  478. )
  479. ) then
  480. begin
  481. doconv:=tc_equal;
  482. b:=1;
  483. end
  484. end
  485. else
  486. begin
  487. { assignment overwritten ?? }
  488. if assignment_overloaded(def_from,def_to)<>nil then
  489. b:=2;
  490. end;
  491. isconvertable:=b;
  492. end;
  493. {****************************************************************************
  494. Register Calculation
  495. ****************************************************************************}
  496. { marks an lvalue as "unregable" }
  497. procedure make_not_regable(p : ptree);
  498. begin
  499. case p^.treetype of
  500. typeconvn :
  501. make_not_regable(p^.left);
  502. loadn :
  503. if typeof(p^.symtableentry^)=typeof(Tvarsym) then
  504. pvarsym(p^.symtableentry)^.properties:=
  505. pvarsym(p^.symtableentry)^.properties-[vo_regable,vo_fpuregable];
  506. end;
  507. end;
  508. procedure left_right_max(p : ptree);
  509. begin
  510. if assigned(p^.left) then
  511. begin
  512. if assigned(p^.right) then
  513. begin
  514. p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
  515. p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
  516. {$ifdef SUPPORT_MMX}
  517. p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
  518. {$endif SUPPORT_MMX}
  519. end
  520. else
  521. begin
  522. p^.registers32:=p^.left^.registers32;
  523. p^.registersfpu:=p^.left^.registersfpu;
  524. {$ifdef SUPPORT_MMX}
  525. p^.registersmmx:=p^.left^.registersmmx;
  526. {$endif SUPPORT_MMX}
  527. end;
  528. end;
  529. end;
  530. { calculates the needed registers for a binary operator }
  531. procedure calcregisters(p : ptree;r32,fpu,mmx : word);
  532. begin
  533. left_right_max(p);
  534. { Only when the difference between the left and right registers < the
  535. wanted registers allocate the amount of registers }
  536. if assigned(p^.left) then
  537. begin
  538. if assigned(p^.right) then
  539. begin
  540. if (abs(p^.left^.registers32-p^.right^.registers32)<r32) then
  541. inc(p^.registers32,r32);
  542. if (abs(p^.left^.registersfpu-p^.right^.registersfpu)<fpu) then
  543. inc(p^.registersfpu,fpu);
  544. {$ifdef SUPPORT_MMX}
  545. if (abs(p^.left^.registersmmx-p^.right^.registersmmx)<mmx) then
  546. inc(p^.registersmmx,mmx);
  547. {$endif SUPPORT_MMX}
  548. { the following is a little bit guessing but I think }
  549. { it's the only way to solve same internalerrors: }
  550. { if the left and right node both uses registers }
  551. { and return a mem location, but the current node }
  552. { doesn't use an integer register we get probably }
  553. { trouble when restoring a node }
  554. if (p^.left^.registers32=p^.right^.registers32) and
  555. (p^.registers32=p^.left^.registers32) and
  556. (p^.registers32>0) and
  557. (p^.left^.location.loc in [LOC_REFERENCE,LOC_MEM]) and
  558. (p^.right^.location.loc in [LOC_REFERENCE,LOC_MEM]) then
  559. inc(p^.registers32);
  560. end
  561. else
  562. begin
  563. if (p^.left^.registers32<r32) then
  564. inc(p^.registers32,r32);
  565. if (p^.left^.registersfpu<fpu) then
  566. inc(p^.registersfpu,fpu);
  567. {$ifdef SUPPORT_MMX}
  568. if (p^.left^.registersmmx<mmx) then
  569. inc(p^.registersmmx,mmx);
  570. {$endif SUPPORT_MMX}
  571. end;
  572. end;
  573. { error CGMessage, if more than 8 floating point }
  574. { registers are needed }
  575. if p^.registersfpu>8 then
  576. CGMessage(cg_e_too_complex_expr);
  577. end;
  578. {****************************************************************************
  579. Subroutine Handling
  580. ****************************************************************************}
  581. { protected field handling
  582. protected field can not appear in
  583. var parameters of function !!
  584. this can only be done after we have determined the
  585. overloaded function
  586. this is the reason why it is not in the parser, PM }
  587. (* procedure test_protected_sym(sym : Pprocsym);
  588. begin
  589. if (sp_protected in sym^.symoptions) and
  590. ((sym^.owner^.symtabletype=unitsymtable) or
  591. ((sym^.owner^.symtabletype=objectsymtable) and
  592. (pobjectdef(sym^.owner^.defowner)^.owner^.symtabletype=unitsymtable))
  593. ) then
  594. CGMessage(parser_e_cant_access_protected_member);
  595. end;
  596. procedure test_protected(p : ptree);
  597. begin
  598. case p^.treetype of
  599. loadn : test_protected_sym(p^.symtableentry);
  600. typeconvn : test_protected(p^.left);
  601. derefn : test_protected(p^.left);
  602. subscriptn : begin
  603. { test_protected(p^.left);
  604. Is a field of a protected var
  605. also protected ??? PM }
  606. test_protected_sym(p^.vs);
  607. end;
  608. end;
  609. end;*)
  610. function valid_for_formal_var(p : ptree) : boolean;
  611. var
  612. v : boolean;
  613. begin
  614. case p^.treetype of
  615. loadn : v:=(typeof(p^.symtableentry^)=typeof(Ttypedconstsym)) or
  616. (typeof(p^.symtableentry^)=typeof(Tvarsym));
  617. typeconvn : v:=valid_for_formal_var(p^.left);
  618. typen : v:=false;
  619. derefn,subscriptn,vecn,
  620. funcretn,selfn : v:=true;
  621. { procvars are callnodes first }
  622. calln : v:=assigned(p^.right) and not assigned(p^.left);
  623. { should this depend on mode ? }
  624. addrn : v:=true;
  625. { no other node accepted (PM) }
  626. else v:=false;
  627. end;
  628. valid_for_formal_var:=v;
  629. end;
  630. function valid_for_formal_const(p : ptree) : boolean;
  631. var
  632. v : boolean;
  633. begin
  634. { p must have been firstpass'd before }
  635. { accept about anything but not a statement ! }
  636. v:=true;
  637. if (p^.treetype in [calln,statementn]) then
  638. { if not assigned(p^.resulttype) or (p^.resulttype=pdef(voiddef)) then }
  639. v:=false;
  640. valid_for_formal_const:=v;
  641. end;
  642. function is_procsym_load(p:Ptree):boolean;
  643. begin
  644. is_procsym_load:=((p^.treetype=loadn) and (typeof(p^.symtableentry^)=typeof(Tprocsym)) or
  645. ((p^.treetype=addrn) and (p^.left^.treetype=loadn)
  646. and (typeof(p^.left^.symtableentry^)=typeof(Tprocsym))));
  647. end;
  648. { change a proc call to a procload for assignment to a procvar }
  649. { this can only happen for proc/function without arguments }
  650. function is_procsym_call(p:Ptree):boolean;
  651. begin
  652. is_procsym_call:=(p^.treetype=calln) and (p^.left=nil) and
  653. (((typeof(p^.symtableprocentry^)=typeof(Tprocsym)) and (p^.right=nil)) or
  654. ((p^.right<>nil) and (typeof(p^.right^.symtableprocentry^)=typeof(Tvarsym))));
  655. end;
  656. function assignment_overloaded(from_def,to_def : pdef) : pprocdef;
  657. function matches(item:pointer):boolean;{$IFDEF TP}far;{$ENDIF TP}
  658. var first_param_def:Pdef;
  659. convtyp:Tconverttype;
  660. begin
  661. {The right assignment overload had been found when:
  662. - The retdef of item equals the to_def.
  663. - The definition of the first parameter equals the from_def
  664. or it can be converted to from_def.}
  665. first_param_def:=Pparamsym(Pparameter(Pprocdef(item)^.
  666. parameters^.at(0))^.data)^.definition;
  667. if is_equal(Pprocdef(item)^.retdef,to_def) and
  668. (is_equal(first_param_def,from_def) or
  669. (isconvertable(from_def,first_param_def,
  670. convtyp,ordconstn,false)=1)) then
  671. matches:=true;
  672. end;
  673. var passproc:Pprocdef;
  674. begin
  675. assignment_overloaded:=nil;
  676. if overloaded_operators[_assignment]<>nil then
  677. assignment_overloaded:=overloaded_operators[_assignment]^.
  678. firstthat(@matches);
  679. end;
  680. { local routines can't be assigned to procvars }
  681. procedure test_local_to_procvar(from_def:pprocvardef;to_def:pdef);
  682. begin
  683. if (typeof(from_def^.owner^)=typeof(Tprocsymtable)) and
  684. (typeof(to_def^)=typeof(Tprocvardef)) then
  685. CGMessage(type_e_cannot_local_proc_to_procvar);
  686. end;
  687. function valid_for_assign(p:ptree;allowprop:boolean):boolean;
  688. var
  689. hp : ptree;
  690. gotsubscript,
  691. gotpointer,
  692. gotclass,
  693. gotderef : boolean;
  694. begin
  695. valid_for_assign:=false;
  696. gotsubscript:=false;
  697. gotderef:=false;
  698. gotclass:=false;
  699. gotpointer:=false;
  700. hp:=p;
  701. while assigned(hp) do
  702. begin
  703. { property allowed? calln has a property check itself }
  704. if (not allowprop) and
  705. (hp^.isproperty) and
  706. (hp^.treetype<>calln) then
  707. begin
  708. CGMessagePos(hp^.fileinfo,type_e_argument_cant_be_assigned);
  709. exit;
  710. end;
  711. case hp^.treetype of
  712. derefn :
  713. begin
  714. gotderef:=true;
  715. hp:=hp^.left;
  716. end;
  717. typeconvn :
  718. begin
  719. if typeof(hp^.resulttype^)=typeof(Tpointerdef) then
  720. gotpointer:=true
  721. else if typeof(hp^.resulttype^)=typeof(Tobjectdef) then
  722. gotclass:=oo_is_class in Pobjectdef(hp^.resulttype)^.options
  723. else if typeof(hp^.resulttype^)=typeof(Tclassrefdef) then
  724. gotclass:=true
  725. else if (typeof(hp^.resulttype^)=typeof(Tarraydef)) and
  726. (typeof(hp^.left^.resulttype^)=typeof(Tpointerdef)) then
  727. gotderef:=true;
  728. hp:=hp^.left;
  729. end;
  730. vecn,
  731. asn :
  732. hp:=hp^.left;
  733. subscriptn :
  734. begin
  735. gotsubscript:=true;
  736. hp:=hp^.left;
  737. end;
  738. subn,
  739. addn :
  740. begin
  741. { Allow add/sub operators on a pointer, or an integer
  742. and a pointer typecast and deref has been found }
  743. if (typeof(hp^.resulttype^)=typeof(Tpointerdef)) or
  744. (is_integer(hp^.resulttype) and gotpointer and gotderef) then
  745. valid_for_assign:=true
  746. else
  747. CGMessagePos(hp^.fileinfo,type_e_variable_id_expected);
  748. exit;
  749. end;
  750. addrn :
  751. begin
  752. if not(gotderef) and
  753. not(hp^.procvarload) then
  754. CGMessagePos(hp^.fileinfo,type_e_no_assign_to_addr);
  755. exit;
  756. end;
  757. selfn,
  758. funcretn :
  759. begin
  760. valid_for_assign:=true;
  761. exit;
  762. end;
  763. calln :
  764. begin
  765. { check return type }
  766. if typeof(hp^.resulttype^)=typeof(Tpointerdef) then
  767. gotpointer:=true
  768. else if typeof(hp^.resulttype^)=typeof(Tobjectdef) then
  769. gotclass:=oo_is_class in Pobjectdef(hp^.resulttype)^.options
  770. else if typeof(hp^.resulttype^)=typeof(Tclassrefdef) then
  771. gotclass:=true;
  772. { 1. if it returns a pointer and we've found a deref,
  773. 2. if it returns a class and a subscription is found,
  774. 3. property is allowed }
  775. if (gotpointer and gotderef) or
  776. (gotclass and gotsubscript) or
  777. (hp^.isproperty and allowprop) then
  778. valid_for_assign:=true
  779. else
  780. CGMessagePos(hp^.fileinfo,type_e_argument_cant_be_assigned);
  781. exit;
  782. end;
  783. loadn :
  784. begin
  785. if (typeof(hp^.symtableentry^)=typeof(Tabsolutesym)) or
  786. (typeof(hp^.symtableentry^)=typeof(Tparamsym)) or
  787. (typeof(hp^.symtableentry^)=typeof(Tvarsym)) then
  788. begin
  789. if (typeof(hp^.symtableentry^)=typeof(Tparamsym)) and
  790. (Pparamsym(hp^.symtableentry)^.varspez=vs_const) then
  791. begin
  792. { allow p^:= constructions with p is const parameter }
  793. if gotderef then
  794. valid_for_assign:=true
  795. else
  796. CGMessagePos(hp^.fileinfo,type_e_no_assign_to_const);
  797. exit;
  798. end;
  799. { Are we at a with symtable, then we need to process the
  800. withrefnode also to check for maybe a const load }
  801. if typeof(hp^.symtable^)=typeof(Twithsymtable) then
  802. begin
  803. { continue with processing the withref node }
  804. hp:=ptree(pwithsymtable(hp^.symtable)^.withrefnode);
  805. end
  806. else
  807. begin
  808. { set the assigned flag for varsyms }
  809. if (pvarsym(hp^.symtableentry)^.state=vs_declared) then
  810. pvarsym(hp^.symtableentry)^.state:=vs_assigned;
  811. valid_for_assign:=true;
  812. exit;
  813. end;
  814. end;
  815. if (typeof(hp^.symtableentry^)=typeof(Tfuncretsym)) or
  816. (typeof(hp^.symtableentry^)=typeof(Ttypedconstsym)) then
  817. begin
  818. valid_for_assign:=true;
  819. exit;
  820. end;
  821. end;
  822. else
  823. CGMessagePos(hp^.fileinfo,type_e_variable_id_expected);
  824. exit;
  825. end;
  826. end;
  827. end;
  828. end.
  829. {
  830. $Log$
  831. Revision 1.1 2000-07-13 06:30:13 michael
  832. + Initial import
  833. Revision 1.2 2000/03/11 21:11:25 daniel
  834. * Ported hcgdata to new symtable.
  835. * Alignment code changed as suggested by Peter
  836. + Usage of my is operator replacement, is_object
  837. Revision 1.1 2000/02/28 17:23:58 daniel
  838. * Current work of symtable integration committed. The symtable can be
  839. activated by defining 'newst', but doesn't compile yet. Changes in type
  840. checking and oop are completed. What is left is to write a new
  841. symtablestack and adapt the parser to use it.
  842. Revision 1.59 2000/02/18 16:13:29 florian
  843. * optimized ansistring compare with ''
  844. * fixed 852
  845. Revision 1.58 2000/02/09 13:22:53 peter
  846. * log truncated
  847. Revision 1.57 2000/02/05 12:11:50 peter
  848. * property check for assigning fixed for calln
  849. Revision 1.56 2000/02/01 09:41:27 peter
  850. * allow class -> voidpointer for delphi mode
  851. Revision 1.55 2000/01/07 01:14:27 peter
  852. * updated copyright to 2000
  853. Revision 1.54 1999/12/31 14:26:27 peter
  854. * fixed crash with empty array constructors
  855. Revision 1.53 1999/12/18 14:55:21 florian
  856. * very basic widestring support
  857. Revision 1.52 1999/12/16 19:12:04 peter
  858. * allow constant pointer^ also for assignment
  859. Revision 1.51 1999/12/09 09:35:54 peter
  860. * allow assigning to self
  861. Revision 1.50 1999/11/30 10:40:43 peter
  862. + ttype, tsymlist
  863. Revision 1.49 1999/11/18 15:34:45 pierre
  864. * Notes/Hints for local syms changed to
  865. Set_varstate function
  866. Revision 1.48 1999/11/09 14:47:03 peter
  867. * pointer->array is allowed for all pointer types in FPC, fixed assign
  868. check for it.
  869. Revision 1.47 1999/11/09 13:29:33 peter
  870. * valid_for_assign allow properties with calln
  871. Revision 1.46 1999/11/08 22:45:33 peter
  872. * allow typecasting to integer within pointer typecast+deref
  873. Revision 1.45 1999/11/06 14:34:21 peter
  874. * truncated log to 20 revs
  875. Revision 1.44 1999/11/04 23:11:21 peter
  876. * fixed pchar and deref detection for assigning
  877. Revision 1.43 1999/10/27 16:04:45 peter
  878. * valid_for_assign support for calln,asn
  879. Revision 1.42 1999/10/26 12:30:41 peter
  880. * const parameter is now checked
  881. * better and generic check if a node can be used for assigning
  882. * export fixes
  883. * procvar equal works now (it never had worked at least from 0.99.8)
  884. * defcoll changed to linkedlist with pparaitem so it can easily be
  885. walked both directions
  886. Revision 1.41 1999/10/14 14:57:52 florian
  887. - removed the hcodegen use in the new cg, use cgbase instead
  888. Revision 1.40 1999/09/26 21:30:15 peter
  889. + constant pointer support which can happend with typecasting like
  890. const p=pointer(1)
  891. * better procvar parsing in typed consts
  892. Revision 1.39 1999/09/17 17:14:04 peter
  893. * @procvar fixes for tp mode
  894. * @<id>:= gives now an error
  895. Revision 1.38 1999/08/17 13:26:07 peter
  896. * arrayconstructor -> arrayofconst fixed when arraycosntructor was not
  897. variant.
  898. }