htypechk.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  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. (typeof(def_from^)=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 typeof(def_to^)=typeof(Torddef) then
  112. begin
  113. if typeof(def_from^)=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 typeof(def_from^)=typeof(Torddef) 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 typeof(def_to^)=typeof(Tstringdef) then
  137. begin
  138. if typeof(def_from^)=typeof(Tstringdef) then
  139. begin
  140. doconv:=tc_string_2_string;
  141. b:=1;
  142. end
  143. else if typeof(def_from^)=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 typeof(def_from^)=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 typeof(def_from^)=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 typeof(def_to^)=typeof(Tfloatdef) then
  178. begin
  179. if typeof(def_from^)=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 typeof(def_from^)=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 typeof(def_to^)=typeof(Tenumdef) then
  208. begin
  209. if typeof(def_from^)=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 typeof(def_to^)=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 typeof(def_from^)=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 typeof(def_from^)=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 typeof(def_from^)=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 typeof(def_to^)=typeof(Tpointerdef) then
  277. begin
  278. if typeof(def_from^)=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 typeof(def_from^)=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 typeof(def_from^)=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 typeof(def_from^)=typeof(Tpointerdef) then
  318. begin
  319. { child class pointer can be assigned to anchestor pointers }
  320. if (
  321. {Bug in TP: typeof(( )) required when typecasting.}
  322. (typeof((Ppointerdef(def_from)^.definition^))=typeof(Tobjectdef)) and
  323. (typeof((Ppointerdef(def_to)^.definition^))=typeof(Tobjectdef)) and
  324. pobjectdef(ppointerdef(def_from)^.definition)^.is_related(
  325. pobjectdef(ppointerdef(def_to)^.definition))
  326. ) or
  327. { all pointers can be assigned to void-pointer }
  328. is_equal(ppointerdef(def_to)^.definition,voiddef) or
  329. { in my opnion, is this not clean pascal }
  330. { well, but it's handy to use, it isn't ? (FK) }
  331. is_equal(ppointerdef(def_from)^.definition,voiddef) then
  332. begin
  333. doconv:=tc_equal;
  334. b:=1;
  335. end;
  336. end
  337. else if typeof(def_from^)=typeof(Tprocvardef) then
  338. begin
  339. { procedure variable can be assigned to an void pointer }
  340. { Not anymore. Use the @ operator now.}
  341. if not(m_tp_procvar in aktmodeswitches) and
  342. (typeof((Ppointerdef(def_to)^.definition^))=typeof(Torddef)) and
  343. (porddef(ppointerdef(def_to)^.definition)^.typ=uvoid) then
  344. begin
  345. doconv:=tc_equal;
  346. b:=1;
  347. end;
  348. end
  349. else if (typeof(def_from^)=typeof(Tclassrefdef)) or
  350. (typeof(def_from^)=typeof(Tobjectdef)) then
  351. begin
  352. { class types and class reference type
  353. can be assigned to void pointers }
  354. if (
  355. ((typeof(def_from^)=typeof(Tobjectdef)) and
  356. (oo_is_class in pobjectdef(def_from)^.options)) or
  357. (typeof(def_from^)=typeof(Tclassrefdef))
  358. ) and
  359. (typeof((ppointerdef(def_to)^.definition^))=typeof(Torddef)) and
  360. (porddef(ppointerdef(def_to)^.definition)^.typ=uvoid) then
  361. begin
  362. doconv:=tc_equal;
  363. b:=1;
  364. end;
  365. end;
  366. end
  367. else if typeof(def_to^)=typeof(Tsetdef) then
  368. begin
  369. { automatic arrayconstructor -> set conversion }
  370. if is_array_constructor(def_from) then
  371. begin
  372. doconv:=tc_arrayconstructor_2_set;
  373. b:=1;
  374. end;
  375. end
  376. else if typeof(def_to^)=typeof(Tprocvardef) then
  377. begin
  378. { proc -> procvar }
  379. if (typeof(def_from^)=typeof(Tprocdef)) then
  380. begin
  381. doconv:=tc_proc_2_procvar;
  382. if proc_to_procvar_equal(pprocdef(def_from),pprocvardef(def_to)) then
  383. b:=1;
  384. end
  385. else
  386. { for example delphi allows the assignement from pointers }
  387. { to procedure variables }
  388. if (m_pointer_2_procedure in aktmodeswitches) and
  389. (typeof(def_from^)=typeof(Tpointerdef)) and
  390. (typeof((ppointerdef(def_from)^.definition^))=typeof(Torddef)) and
  391. (porddef(ppointerdef(def_from)^.definition)^.typ=uvoid) then
  392. begin
  393. doconv:=tc_equal;
  394. b:=1;
  395. end
  396. else
  397. { nil is compatible with procvars }
  398. if (fromtreetype=niln) then
  399. begin
  400. doconv:=tc_equal;
  401. b:=1;
  402. end;
  403. end
  404. else if typeof(def_to^)=typeof(Tobjectdef) then
  405. begin
  406. { object pascal objects }
  407. if typeof(def_from^)=typeof(Tobjectdef) then
  408. begin
  409. doconv:=tc_equal;
  410. if pobjectdef(def_from)^.is_related(pobjectdef(def_to)) then
  411. b:=1;
  412. end
  413. else
  414. { Class specific }
  415. if (oo_is_class in pobjectdef(def_to)^.options) then
  416. begin
  417. { void pointer also for delphi mode }
  418. if (m_delphi in aktmodeswitches) and
  419. is_voidpointer(def_from) then
  420. begin
  421. doconv:=tc_equal;
  422. b:=1;
  423. end
  424. else
  425. { nil is compatible with class instances }
  426. if (fromtreetype=niln) and (oo_is_class in pobjectdef(def_to)^.options) then
  427. begin
  428. doconv:=tc_equal;
  429. b:=1;
  430. end;
  431. end;
  432. end
  433. else if typeof(def_to^)=typeof(Tclassrefdef) then
  434. begin
  435. { class reference types }
  436. if typeof(def_from^)=typeof(Tclassrefdef) then
  437. begin
  438. doconv:=tc_equal;
  439. if pobjectdef(pclassrefdef(def_from)^.definition)^.is_related(
  440. pobjectdef(pclassrefdef(def_to)^.definition)) then
  441. b:=1;
  442. end
  443. else
  444. { nil is compatible with class references }
  445. if (fromtreetype=niln) then
  446. begin
  447. doconv:=tc_equal;
  448. b:=1;
  449. end;
  450. end
  451. else if typeof(def_to^)=typeof(Tfiledef) then
  452. begin
  453. { typed files are all equal to the abstract file type
  454. name TYPEDFILE in system.pp in is_equal in types.pas
  455. the problem is that it sholud be also compatible to FILE
  456. but this would leed to a problem for ASSIGN RESET and REWRITE
  457. when trying to find the good overloaded function !!
  458. so all file function are doubled in system.pp
  459. this is not very beautiful !!}
  460. if (typeof(def_from^)=typeof(Tfiledef)) and
  461. (
  462. (
  463. (pfiledef(def_from)^.filetype = ft_typed) and
  464. (pfiledef(def_to)^.filetype = ft_typed) and
  465. (
  466. (pfiledef(def_from)^.definition=pdef(voiddef)) or
  467. (pfiledef(def_to)^.definition=pdef(voiddef))
  468. )
  469. ) or
  470. (
  471. (
  472. (pfiledef(def_from)^.filetype = ft_untyped) and
  473. (pfiledef(def_to)^.filetype = ft_typed)
  474. ) or
  475. (
  476. (pfiledef(def_from)^.filetype = ft_typed) and
  477. (pfiledef(def_to)^.filetype = ft_untyped)
  478. )
  479. )
  480. ) then
  481. begin
  482. doconv:=tc_equal;
  483. b:=1;
  484. end
  485. end
  486. else
  487. begin
  488. { assignment overwritten ?? }
  489. if assignment_overloaded(def_from,def_to)<>nil then
  490. b:=2;
  491. end;
  492. isconvertable:=b;
  493. end;
  494. {****************************************************************************
  495. Register Calculation
  496. ****************************************************************************}
  497. { marks an lvalue as "unregable" }
  498. procedure make_not_regable(p : ptree);
  499. begin
  500. case p^.treetype of
  501. typeconvn :
  502. make_not_regable(p^.left);
  503. loadn :
  504. if typeof(p^.symtableentry^)=typeof(Tvarsym) then
  505. pvarsym(p^.symtableentry)^.properties:=
  506. pvarsym(p^.symtableentry)^.properties-[vo_regable,vo_fpuregable];
  507. end;
  508. end;
  509. procedure left_right_max(p : ptree);
  510. begin
  511. if assigned(p^.left) then
  512. begin
  513. if assigned(p^.right) then
  514. begin
  515. p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
  516. p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
  517. {$ifdef SUPPORT_MMX}
  518. p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
  519. {$endif SUPPORT_MMX}
  520. end
  521. else
  522. begin
  523. p^.registers32:=p^.left^.registers32;
  524. p^.registersfpu:=p^.left^.registersfpu;
  525. {$ifdef SUPPORT_MMX}
  526. p^.registersmmx:=p^.left^.registersmmx;
  527. {$endif SUPPORT_MMX}
  528. end;
  529. end;
  530. end;
  531. { calculates the needed registers for a binary operator }
  532. procedure calcregisters(p : ptree;r32,fpu,mmx : word);
  533. begin
  534. left_right_max(p);
  535. { Only when the difference between the left and right registers < the
  536. wanted registers allocate the amount of registers }
  537. if assigned(p^.left) then
  538. begin
  539. if assigned(p^.right) then
  540. begin
  541. if (abs(p^.left^.registers32-p^.right^.registers32)<r32) then
  542. inc(p^.registers32,r32);
  543. if (abs(p^.left^.registersfpu-p^.right^.registersfpu)<fpu) then
  544. inc(p^.registersfpu,fpu);
  545. {$ifdef SUPPORT_MMX}
  546. if (abs(p^.left^.registersmmx-p^.right^.registersmmx)<mmx) then
  547. inc(p^.registersmmx,mmx);
  548. {$endif SUPPORT_MMX}
  549. { the following is a little bit guessing but I think }
  550. { it's the only way to solve same internalerrors: }
  551. { if the left and right node both uses registers }
  552. { and return a mem location, but the current node }
  553. { doesn't use an integer register we get probably }
  554. { trouble when restoring a node }
  555. if (p^.left^.registers32=p^.right^.registers32) and
  556. (p^.registers32=p^.left^.registers32) and
  557. (p^.registers32>0) and
  558. (p^.left^.location.loc in [LOC_REFERENCE,LOC_MEM]) and
  559. (p^.right^.location.loc in [LOC_REFERENCE,LOC_MEM]) then
  560. inc(p^.registers32);
  561. end
  562. else
  563. begin
  564. if (p^.left^.registers32<r32) then
  565. inc(p^.registers32,r32);
  566. if (p^.left^.registersfpu<fpu) then
  567. inc(p^.registersfpu,fpu);
  568. {$ifdef SUPPORT_MMX}
  569. if (p^.left^.registersmmx<mmx) then
  570. inc(p^.registersmmx,mmx);
  571. {$endif SUPPORT_MMX}
  572. end;
  573. end;
  574. { error CGMessage, if more than 8 floating point }
  575. { registers are needed }
  576. if p^.registersfpu>8 then
  577. CGMessage(cg_e_too_complex_expr);
  578. end;
  579. {****************************************************************************
  580. Subroutine Handling
  581. ****************************************************************************}
  582. { protected field handling
  583. protected field can not appear in
  584. var parameters of function !!
  585. this can only be done after we have determined the
  586. overloaded function
  587. this is the reason why it is not in the parser, PM }
  588. (* procedure test_protected_sym(sym : Pprocsym);
  589. begin
  590. if (sp_protected in sym^.symoptions) and
  591. ((sym^.owner^.symtabletype=unitsymtable) or
  592. ((sym^.owner^.symtabletype=objectsymtable) and
  593. (pobjectdef(sym^.owner^.defowner)^.owner^.symtabletype=unitsymtable))
  594. ) then
  595. CGMessage(parser_e_cant_access_protected_member);
  596. end;
  597. procedure test_protected(p : ptree);
  598. begin
  599. case p^.treetype of
  600. loadn : test_protected_sym(p^.symtableentry);
  601. typeconvn : test_protected(p^.left);
  602. derefn : test_protected(p^.left);
  603. subscriptn : begin
  604. { test_protected(p^.left);
  605. Is a field of a protected var
  606. also protected ??? PM }
  607. test_protected_sym(p^.vs);
  608. end;
  609. end;
  610. end;*)
  611. function valid_for_formal_var(p : ptree) : boolean;
  612. var
  613. v : boolean;
  614. begin
  615. case p^.treetype of
  616. loadn : v:=(typeof(p^.symtableentry^)=typeof(Ttypedconstsym)) or
  617. (typeof(p^.symtableentry^)=typeof(Tvarsym));
  618. typeconvn : v:=valid_for_formal_var(p^.left);
  619. typen : v:=false;
  620. derefn,subscriptn,vecn,
  621. funcretn,selfn : v:=true;
  622. { procvars are callnodes first }
  623. calln : v:=assigned(p^.right) and not assigned(p^.left);
  624. { should this depend on mode ? }
  625. addrn : v:=true;
  626. { no other node accepted (PM) }
  627. else v:=false;
  628. end;
  629. valid_for_formal_var:=v;
  630. end;
  631. function valid_for_formal_const(p : ptree) : boolean;
  632. var
  633. v : boolean;
  634. begin
  635. { p must have been firstpass'd before }
  636. { accept about anything but not a statement ! }
  637. v:=true;
  638. if (p^.treetype in [calln,statementn]) then
  639. { if not assigned(p^.resulttype) or (p^.resulttype=pdef(voiddef)) then }
  640. v:=false;
  641. valid_for_formal_const:=v;
  642. end;
  643. function is_procsym_load(p:Ptree):boolean;
  644. begin
  645. is_procsym_load:=((p^.treetype=loadn) and (typeof(p^.symtableentry^)=typeof(Tprocsym)) or
  646. ((p^.treetype=addrn) and (p^.left^.treetype=loadn)
  647. and (typeof(p^.left^.symtableentry^)=typeof(Tprocsym))));
  648. end;
  649. { change a proc call to a procload for assignment to a procvar }
  650. { this can only happen for proc/function without arguments }
  651. function is_procsym_call(p:Ptree):boolean;
  652. begin
  653. is_procsym_call:=(p^.treetype=calln) and (p^.left=nil) and
  654. (((typeof(p^.symtableprocentry^)=typeof(Tprocsym)) and (p^.right=nil)) or
  655. ((p^.right<>nil) and (typeof(p^.right^.symtableprocentry^)=typeof(Tvarsym))));
  656. end;
  657. function assignment_overloaded(from_def,to_def : pdef) : pprocdef;
  658. function matches(item:pointer):boolean;{$IFDEF TP}far;{$ENDIF TP}
  659. var first_param_def:Pdef;
  660. convtyp:Tconverttype;
  661. begin
  662. {The right assignment overload had been found when:
  663. - The retdef of item equals the to_def.
  664. - The definition of the first parameter equals the from_def
  665. or it can be converted to from_def.}
  666. first_param_def:=Pparamsym(Pparameter(Pprocdef(item)^.
  667. parameters^.at(0))^.data)^.definition;
  668. if is_equal(Pprocdef(item)^.retdef,to_def) and
  669. (is_equal(first_param_def,from_def) or
  670. (isconvertable(from_def,first_param_def,
  671. convtyp,ordconstn,false)=1)) then
  672. matches:=true;
  673. end;
  674. var passproc:Pprocdef;
  675. begin
  676. assignment_overloaded:=nil;
  677. if overloaded_operators[_assignment]<>nil then
  678. assignment_overloaded:=overloaded_operators[_assignment]^.
  679. firstthat(@matches);
  680. end;
  681. { local routines can't be assigned to procvars }
  682. procedure test_local_to_procvar(from_def:pprocvardef;to_def:pdef);
  683. begin
  684. if (typeof(from_def^.owner^)=typeof(Tprocsymtable)) and
  685. (typeof(to_def^)=typeof(Tprocvardef)) then
  686. CGMessage(type_e_cannot_local_proc_to_procvar);
  687. end;
  688. function valid_for_assign(p:ptree;allowprop:boolean):boolean;
  689. var
  690. hp : ptree;
  691. gotsubscript,
  692. gotpointer,
  693. gotclass,
  694. gotderef : boolean;
  695. begin
  696. valid_for_assign:=false;
  697. gotsubscript:=false;
  698. gotderef:=false;
  699. gotclass:=false;
  700. gotpointer:=false;
  701. hp:=p;
  702. while assigned(hp) do
  703. begin
  704. { property allowed? calln has a property check itself }
  705. if (not allowprop) and
  706. (hp^.isproperty) and
  707. (hp^.treetype<>calln) then
  708. begin
  709. CGMessagePos(hp^.fileinfo,type_e_argument_cant_be_assigned);
  710. exit;
  711. end;
  712. case hp^.treetype of
  713. derefn :
  714. begin
  715. gotderef:=true;
  716. hp:=hp^.left;
  717. end;
  718. typeconvn :
  719. begin
  720. if typeof(hp^.resulttype^)=typeof(Tpointerdef) then
  721. gotpointer:=true
  722. else if typeof(hp^.resulttype^)=typeof(Tobjectdef) then
  723. gotclass:=oo_is_class in Pobjectdef(hp^.resulttype)^.options
  724. else if typeof(hp^.resulttype^)=typeof(Tclassrefdef) then
  725. gotclass:=true
  726. else if (typeof(hp^.resulttype^)=typeof(Tarraydef)) and
  727. (typeof(hp^.left^.resulttype^)=typeof(Tpointerdef)) then
  728. gotderef:=true;
  729. hp:=hp^.left;
  730. end;
  731. vecn,
  732. asn :
  733. hp:=hp^.left;
  734. subscriptn :
  735. begin
  736. gotsubscript:=true;
  737. hp:=hp^.left;
  738. end;
  739. subn,
  740. addn :
  741. begin
  742. { Allow add/sub operators on a pointer, or an integer
  743. and a pointer typecast and deref has been found }
  744. if (typeof(hp^.resulttype^)=typeof(Tpointerdef)) or
  745. (is_integer(hp^.resulttype) and gotpointer and gotderef) then
  746. valid_for_assign:=true
  747. else
  748. CGMessagePos(hp^.fileinfo,type_e_variable_id_expected);
  749. exit;
  750. end;
  751. addrn :
  752. begin
  753. if not(gotderef) and
  754. not(hp^.procvarload) then
  755. CGMessagePos(hp^.fileinfo,type_e_no_assign_to_addr);
  756. exit;
  757. end;
  758. selfn,
  759. funcretn :
  760. begin
  761. valid_for_assign:=true;
  762. exit;
  763. end;
  764. calln :
  765. begin
  766. { check return type }
  767. if typeof(hp^.resulttype^)=typeof(Tpointerdef) then
  768. gotpointer:=true
  769. else if typeof(hp^.resulttype^)=typeof(Tobjectdef) then
  770. gotclass:=oo_is_class in Pobjectdef(hp^.resulttype)^.options
  771. else if typeof(hp^.resulttype^)=typeof(Tclassrefdef) then
  772. gotclass:=true;
  773. { 1. if it returns a pointer and we've found a deref,
  774. 2. if it returns a class and a subscription is found,
  775. 3. property is allowed }
  776. if (gotpointer and gotderef) or
  777. (gotclass and gotsubscript) or
  778. (hp^.isproperty and allowprop) then
  779. valid_for_assign:=true
  780. else
  781. CGMessagePos(hp^.fileinfo,type_e_argument_cant_be_assigned);
  782. exit;
  783. end;
  784. loadn :
  785. begin
  786. if (typeof(hp^.symtableentry^)=typeof(Tabsolutesym)) or
  787. (typeof(hp^.symtableentry^)=typeof(Tparamsym)) or
  788. (typeof(hp^.symtableentry^)=typeof(Tvarsym)) then
  789. begin
  790. if (typeof(hp^.symtableentry^)=typeof(Tparamsym)) and
  791. (Pparamsym(hp^.symtableentry)^.varspez=vs_const) then
  792. begin
  793. { allow p^:= constructions with p is const parameter }
  794. if gotderef then
  795. valid_for_assign:=true
  796. else
  797. CGMessagePos(hp^.fileinfo,type_e_no_assign_to_const);
  798. exit;
  799. end;
  800. { Are we at a with symtable, then we need to process the
  801. withrefnode also to check for maybe a const load }
  802. if typeof(hp^.symtable^)=typeof(Twithsymtable) then
  803. begin
  804. { continue with processing the withref node }
  805. hp:=ptree(pwithsymtable(hp^.symtable)^.withrefnode);
  806. end
  807. else
  808. begin
  809. { set the assigned flag for varsyms }
  810. if (pvarsym(hp^.symtableentry)^.state=vs_declared) then
  811. pvarsym(hp^.symtableentry)^.state:=vs_assigned;
  812. valid_for_assign:=true;
  813. exit;
  814. end;
  815. end;
  816. if (typeof(hp^.symtableentry^)=typeof(Tfuncretsym)) or
  817. (typeof(hp^.symtableentry^)=typeof(Ttypedconstsym)) then
  818. begin
  819. valid_for_assign:=true;
  820. exit;
  821. end;
  822. end;
  823. else
  824. CGMessagePos(hp^.fileinfo,type_e_variable_id_expected);
  825. exit;
  826. end;
  827. end;
  828. end;
  829. end.
  830. {
  831. $Log$
  832. Revision 1.1 2000-02-28 17:23:58 daniel
  833. * Current work of symtable integration committed. The symtable can be
  834. activated by defining 'newst', but doesn't compile yet. Changes in type
  835. checking and oop are completed. What is left is to write a new
  836. symtablestack and adapt the parser to use it.
  837. Revision 1.59 2000/02/18 16:13:29 florian
  838. * optimized ansistring compare with ''
  839. * fixed 852
  840. Revision 1.58 2000/02/09 13:22:53 peter
  841. * log truncated
  842. Revision 1.57 2000/02/05 12:11:50 peter
  843. * property check for assigning fixed for calln
  844. Revision 1.56 2000/02/01 09:41:27 peter
  845. * allow class -> voidpointer for delphi mode
  846. Revision 1.55 2000/01/07 01:14:27 peter
  847. * updated copyright to 2000
  848. Revision 1.54 1999/12/31 14:26:27 peter
  849. * fixed crash with empty array constructors
  850. Revision 1.53 1999/12/18 14:55:21 florian
  851. * very basic widestring support
  852. Revision 1.52 1999/12/16 19:12:04 peter
  853. * allow constant pointer^ also for assignment
  854. Revision 1.51 1999/12/09 09:35:54 peter
  855. * allow assigning to self
  856. Revision 1.50 1999/11/30 10:40:43 peter
  857. + ttype, tsymlist
  858. Revision 1.49 1999/11/18 15:34:45 pierre
  859. * Notes/Hints for local syms changed to
  860. Set_varstate function
  861. Revision 1.48 1999/11/09 14:47:03 peter
  862. * pointer->array is allowed for all pointer types in FPC, fixed assign
  863. check for it.
  864. Revision 1.47 1999/11/09 13:29:33 peter
  865. * valid_for_assign allow properties with calln
  866. Revision 1.46 1999/11/08 22:45:33 peter
  867. * allow typecasting to integer within pointer typecast+deref
  868. Revision 1.45 1999/11/06 14:34:21 peter
  869. * truncated log to 20 revs
  870. Revision 1.44 1999/11/04 23:11:21 peter
  871. * fixed pchar and deref detection for assigning
  872. Revision 1.43 1999/10/27 16:04:45 peter
  873. * valid_for_assign support for calln,asn
  874. Revision 1.42 1999/10/26 12:30:41 peter
  875. * const parameter is now checked
  876. * better and generic check if a node can be used for assigning
  877. * export fixes
  878. * procvar equal works now (it never had worked at least from 0.99.8)
  879. * defcoll changed to linkedlist with pparaitem so it can easily be
  880. walked both directions
  881. Revision 1.41 1999/10/14 14:57:52 florian
  882. - removed the hcodegen use in the new cg, use cgbase instead
  883. Revision 1.40 1999/09/26 21:30:15 peter
  884. + constant pointer support which can happend with typecasting like
  885. const p=pointer(1)
  886. * better procvar parsing in typed consts
  887. Revision 1.39 1999/09/17 17:14:04 peter
  888. * @procvar fixes for tp mode
  889. * @<id>:= gives now an error
  890. Revision 1.38 1999/08/17 13:26:07 peter
  891. * arrayconstructor -> arrayofconst fixed when arraycosntructor was not
  892. variant.
  893. }