htypechk.pas 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  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. {$i defines.inc}
  20. interface
  21. uses
  22. tokens,
  23. node,
  24. symtype,symdef;
  25. type
  26. Ttok2nodeRec=record
  27. tok : ttoken;
  28. nod : tnodetype;
  29. op_overloading_supported : boolean;
  30. end;
  31. const
  32. tok2nodes=25;
  33. tok2node:array[1..tok2nodes] of ttok2noderec=(
  34. (tok:_PLUS ;nod:addn;op_overloading_supported:true), { binary overloading supported }
  35. (tok:_MINUS ;nod:subn;op_overloading_supported:true), { binary and unary overloading supported }
  36. (tok:_STAR ;nod:muln;op_overloading_supported:true), { binary overloading supported }
  37. (tok:_SLASH ;nod:slashn;op_overloading_supported:true), { binary overloading supported }
  38. (tok:_EQUAL ;nod:equaln;op_overloading_supported:true), { binary overloading supported }
  39. (tok:_GT ;nod:gtn;op_overloading_supported:true), { binary overloading supported }
  40. (tok:_LT ;nod:ltn;op_overloading_supported:true), { binary overloading supported }
  41. (tok:_GTE ;nod:gten;op_overloading_supported:true), { binary overloading supported }
  42. (tok:_LTE ;nod:lten;op_overloading_supported:true), { binary overloading supported }
  43. (tok:_SYMDIF ;nod:symdifn;op_overloading_supported:true), { binary overloading supported }
  44. (tok:_STARSTAR;nod:starstarn;op_overloading_supported:true), { binary overloading supported }
  45. (tok:_OP_AS ;nod:asn;op_overloading_supported:false), { binary overloading NOT supported }
  46. (tok:_OP_IN ;nod:inn;op_overloading_supported:false), { binary overloading NOT supported }
  47. (tok:_OP_IS ;nod:isn;op_overloading_supported:false), { binary overloading NOT supported }
  48. (tok:_OP_OR ;nod:orn;op_overloading_supported:true), { binary overloading supported }
  49. (tok:_OP_AND ;nod:andn;op_overloading_supported:true), { binary overloading supported }
  50. (tok:_OP_DIV ;nod:divn;op_overloading_supported:true), { binary overloading supported }
  51. (tok:_OP_NOT ;nod:notn;op_overloading_supported:true), { unary overloading supported }
  52. (tok:_OP_MOD ;nod:modn;op_overloading_supported:true), { binary overloading supported }
  53. (tok:_OP_SHL ;nod:shln;op_overloading_supported:true), { binary overloading supported }
  54. (tok:_OP_SHR ;nod:shrn;op_overloading_supported:true), { binary overloading supported }
  55. (tok:_OP_XOR ;nod:xorn;op_overloading_supported:true), { binary overloading supported }
  56. (tok:_ASSIGNMENT;nod:assignn;op_overloading_supported:true), { unary overloading supported }
  57. (tok:_CARET ;nod:caretn;op_overloading_supported:false), { binary overloading NOT supported }
  58. (tok:_UNEQUAL ;nod:unequaln;op_overloading_supported:false) { binary overloading NOT supported overload = instead }
  59. );
  60. const
  61. { firstcallparan without varspez we don't count the ref }
  62. {$ifdef extdebug}
  63. count_ref : boolean = true;
  64. {$endif def extdebug}
  65. get_para_resulttype : boolean = false;
  66. allow_array_constructor : boolean = false;
  67. { is overloading of this operator allowed for this
  68. binary operator }
  69. function isbinaryoperatoroverloadable(ld, rd,dd : tdef;
  70. treetyp : tnodetype) : boolean;
  71. { is overloading of this operator allowed for this
  72. unary operator }
  73. function isunaryoperatoroverloadable(rd,dd : tdef;
  74. treetyp : tnodetype) : boolean;
  75. { check operator args and result type }
  76. function isoperatoracceptable(pf : tprocdef; optoken : ttoken) : boolean;
  77. function isbinaryoverloaded(var t : tnode) : boolean;
  78. { Register Allocation }
  79. procedure make_not_regable(p : tnode);
  80. procedure calcregisters(p : tbinarynode;r32,fpu,mmx : word);
  81. { subroutine handling }
  82. procedure test_protected_sym(sym : tsym);
  83. procedure test_protected(p : tnode);
  84. function valid_for_formal_var(p : tnode) : boolean;
  85. function valid_for_formal_const(p : tnode) : boolean;
  86. function is_procsym_load(p:tnode):boolean;
  87. function is_procsym_call(p:tnode):boolean;
  88. procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
  89. function valid_for_assign(p:tnode;allowprop:boolean):boolean;
  90. { sets the callunique flag, if the node is a vecn, }
  91. { takes care of type casts etc. }
  92. procedure set_unique(p : tnode);
  93. { sets funcret_is_valid to true, if p contains a funcref node }
  94. procedure set_funcret_is_valid(p : tnode);
  95. {
  96. type
  97. tvarstaterequire = (vsr_can_be_undefined,vsr_must_be_valid,
  98. vsr_is_used_after,vsr_must_be_valid_and_is_used_after); }
  99. { sets varsym varstate field correctly }
  100. procedure unset_varstate(p : tnode);
  101. procedure set_varstate(p : tnode;must_be_valid : boolean);
  102. implementation
  103. uses
  104. globtype,systems,
  105. cutils,verbose,globals,
  106. symconst,symsym,symtable,
  107. types,cpubase,
  108. ncnv,nld,
  109. nmem,ncal,nmat,
  110. {$ifdef newcg}
  111. cgbase
  112. {$else}
  113. hcodegen
  114. {$endif}
  115. ;
  116. { ld is the left type definition
  117. rd the right type definition
  118. dd the result type definition or voiddef if unkown }
  119. function isbinaryoperatoroverloadable(ld, rd, dd : tdef;
  120. treetyp : tnodetype) : boolean;
  121. begin
  122. isbinaryoperatoroverloadable:=
  123. (treetyp=starstarn) or
  124. (ld.deftype=recorddef) or
  125. (rd.deftype=recorddef) or
  126. ((rd.deftype=pointerdef) and
  127. not(is_pchar(rd) and
  128. (is_chararray(ld) or
  129. (ld.deftype=stringdef) or
  130. (treetyp=addn))) and
  131. (not(ld.deftype in [pointerdef,objectdef,classrefdef,procvardef]) or
  132. not (treetyp in [equaln,unequaln,gtn,gten,ltn,lten,subn])
  133. ) and
  134. (not is_integer(ld) or not (treetyp in [addn,subn]))
  135. ) or
  136. ((ld.deftype=pointerdef) and
  137. not(is_pchar(ld) and
  138. (is_chararray(rd) or
  139. (rd.deftype=stringdef) or
  140. (treetyp=addn))) and
  141. (not(rd.deftype in [stringdef,pointerdef,objectdef,classrefdef,procvardef]) and
  142. ((not is_integer(rd) and (rd.deftype<>objectdef)
  143. and (rd.deftype<>classrefdef)) or
  144. not (treetyp in [equaln,unequaln,gtn,gten,ltn,lten,addn,subn])
  145. )
  146. )
  147. ) or
  148. { array def, but not mmx or chararray+[char,string,chararray] }
  149. ((ld.deftype=arraydef) and
  150. not((cs_mmx in aktlocalswitches) and
  151. is_mmx_able_array(ld)) and
  152. not(is_chararray(ld) and
  153. (is_char(rd) or
  154. is_pchar(rd) or
  155. { char array + int = pchar + int, fix for web bug 1377 (JM) }
  156. is_integer(rd) or
  157. (rd.deftype=stringdef) or
  158. is_chararray(rd)))
  159. ) or
  160. ((rd.deftype=arraydef) and
  161. not((cs_mmx in aktlocalswitches) and
  162. is_mmx_able_array(rd)) and
  163. not(is_chararray(rd) and
  164. (is_char(ld) or
  165. is_pchar(ld) or
  166. (ld.deftype=stringdef) or
  167. is_chararray(ld)))
  168. ) or
  169. { <> and = are defined for classes }
  170. (
  171. (ld.deftype=objectdef) and
  172. not((treetyp in [equaln,unequaln]) and is_class_or_interface(ld))
  173. ) or
  174. (
  175. (rd.deftype=objectdef) and
  176. not((treetyp in [equaln,unequaln]) and is_class_or_interface(rd))
  177. )
  178. or
  179. { allow other operators that + on strings }
  180. (
  181. (is_char(rd) or
  182. is_pchar(rd) or
  183. (rd.deftype=stringdef) or
  184. is_chararray(rd) or
  185. is_char(ld) or
  186. is_pchar(ld) or
  187. (ld.deftype=stringdef) or
  188. is_chararray(ld)
  189. ) and
  190. not(treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) and
  191. not(is_pchar(ld) and
  192. (is_integer(rd) or (rd.deftype=pointerdef)) and
  193. (treetyp=subn)
  194. )
  195. );
  196. end;
  197. function isunaryoperatoroverloadable(rd,dd : tdef;
  198. treetyp : tnodetype) : boolean;
  199. begin
  200. isunaryoperatoroverloadable:=false;
  201. { what assignment overloading should be allowed ?? }
  202. if (treetyp=assignn) then
  203. begin
  204. isunaryoperatoroverloadable:=true;
  205. { this already get tbs0261 to fail
  206. isunaryoperatoroverloadable:=not is_equal(rd,dd); PM }
  207. end
  208. { should we force that rd and dd are equal ?? }
  209. else if (treetyp=subn { unaryminusn }) then
  210. begin
  211. isunaryoperatoroverloadable:=
  212. not is_integer(rd) and not (rd.deftype=floatdef)
  213. {$ifdef SUPPORT_MMX}
  214. and not ((cs_mmx in aktlocalswitches) and
  215. is_mmx_able_array(rd))
  216. {$endif SUPPORT_MMX}
  217. ;
  218. end
  219. else if (treetyp=notn) then
  220. begin
  221. isunaryoperatoroverloadable:=not is_integer(rd) and not is_boolean(rd)
  222. {$ifdef SUPPORT_MMX}
  223. and not ((cs_mmx in aktlocalswitches) and
  224. is_mmx_able_array(rd))
  225. {$endif SUPPORT_MMX}
  226. ;
  227. end;
  228. end;
  229. function isoperatoracceptable(pf : tprocdef; optoken : ttoken) : boolean;
  230. var
  231. ld,rd,dd : tdef;
  232. i : longint;
  233. begin
  234. case pf.parast.symindex.count of
  235. 2 : begin
  236. isoperatoracceptable:=false;
  237. for i:=1 to tok2nodes do
  238. if tok2node[i].tok=optoken then
  239. begin
  240. ld:=tvarsym(pf.parast.symindex.first).vartype.def;
  241. rd:=tvarsym(pf.parast.symindex.first.indexnext).vartype.def;
  242. dd:=pf.rettype.def;
  243. isoperatoracceptable:=
  244. tok2node[i].op_overloading_supported and
  245. isbinaryoperatoroverloadable(ld,rd,dd,tok2node[i].nod);
  246. break;
  247. end;
  248. end;
  249. 1 : begin
  250. rd:=tvarsym(pf.parast.symindex.first).vartype.def;
  251. dd:=pf.rettype.def;
  252. for i:=1 to tok2nodes do
  253. if tok2node[i].tok=optoken then
  254. begin
  255. isoperatoracceptable:=
  256. tok2node[i].op_overloading_supported and
  257. isunaryoperatoroverloadable(rd,dd,tok2node[i].nod);
  258. break;
  259. end;
  260. end;
  261. else
  262. isoperatoracceptable:=false;
  263. end;
  264. end;
  265. function isbinaryoverloaded(var t : tnode) : boolean;
  266. var
  267. rd,ld : tdef;
  268. optoken : ttoken;
  269. ht : tnode;
  270. begin
  271. isbinaryoverloaded:=false;
  272. { overloaded operator ? }
  273. { load easier access variables }
  274. rd:=tbinarynode(t).right.resulttype.def;
  275. ld:=tbinarynode(t).left.resulttype.def;
  276. if isbinaryoperatoroverloadable(ld,rd,voidtype.def,t.nodetype) then
  277. begin
  278. isbinaryoverloaded:=true;
  279. {!!!!!!!!! handle paras }
  280. case t.nodetype of
  281. addn:
  282. optoken:=_PLUS;
  283. subn:
  284. optoken:=_MINUS;
  285. muln:
  286. optoken:=_STAR;
  287. starstarn:
  288. optoken:=_STARSTAR;
  289. slashn:
  290. optoken:=_SLASH;
  291. ltn:
  292. optoken:=tokens._lt;
  293. gtn:
  294. optoken:=tokens._gt;
  295. lten:
  296. optoken:=_lte;
  297. gten:
  298. optoken:=_gte;
  299. equaln,unequaln :
  300. optoken:=_EQUAL;
  301. symdifn :
  302. optoken:=_SYMDIF;
  303. modn :
  304. optoken:=_OP_MOD;
  305. orn :
  306. optoken:=_OP_OR;
  307. xorn :
  308. optoken:=_OP_XOR;
  309. andn :
  310. optoken:=_OP_AND;
  311. divn :
  312. optoken:=_OP_DIV;
  313. shln :
  314. optoken:=_OP_SHL;
  315. shrn :
  316. optoken:=_OP_SHR;
  317. else
  318. exit;
  319. end;
  320. { the nil as symtable signs firstcalln that this is
  321. an overloaded operator }
  322. ht:=ccallnode.create(nil,overloaded_operators[optoken],nil,nil);
  323. { we have to convert p^.left and p^.right into
  324. callparanodes }
  325. if tcallnode(ht).symtableprocentry=nil then
  326. begin
  327. CGMessage(parser_e_operator_not_overloaded);
  328. ht.free;
  329. { the original t t will be released by firstpass! (JM) }
  330. t := t.getcopy;
  331. end
  332. else
  333. begin
  334. inc(tcallnode(ht).symtableprocentry.refs);
  335. { we need copies, because the originals will be destroyed when we give a }
  336. { changed node back to firstpass! (JM) }
  337. if assigned(tbinarynode(t).left) then
  338. if assigned(tbinarynode(t).right) then
  339. tcallnode(ht).left :=
  340. ccallparanode.create(tbinarynode(t).right.getcopy,
  341. ccallparanode.create(tbinarynode(t).left.getcopy,nil))
  342. else
  343. tcallnode(ht).left :=
  344. ccallparanode.create(nil,
  345. ccallparanode.create(tbinarynode(t).left.getcopy,nil))
  346. else if assigned(tbinarynode(t).right) then
  347. tcallnode(ht).left :=
  348. ccallparanode.create(tbinarynode(t).right.getcopy,
  349. ccallparanode.create(nil,nil));
  350. if t.nodetype=unequaln then
  351. ht:=cnotnode.create(ht);
  352. t:=ht;
  353. end;
  354. end;
  355. end;
  356. {****************************************************************************
  357. Register Calculation
  358. ****************************************************************************}
  359. { marks an lvalue as "unregable" }
  360. procedure make_not_regable(p : tnode);
  361. begin
  362. case p.nodetype of
  363. typeconvn :
  364. make_not_regable(ttypeconvnode(p).left);
  365. loadn :
  366. if tloadnode(p).symtableentry.typ=varsym then
  367. tvarsym(tloadnode(p).symtableentry).varoptions:=tvarsym(tloadnode(p).symtableentry).varoptions-[vo_regable,vo_fpuregable];
  368. end;
  369. end;
  370. { calculates the needed registers for a binary operator }
  371. procedure calcregisters(p : tbinarynode;r32,fpu,mmx : word);
  372. begin
  373. p.left_right_max;
  374. { Only when the difference between the left and right registers < the
  375. wanted registers allocate the amount of registers }
  376. if assigned(p.left) then
  377. begin
  378. if assigned(p.right) then
  379. begin
  380. if (abs(p.left.registers32-p.right.registers32)<r32) then
  381. inc(p.registers32,r32);
  382. if (abs(p.left.registersfpu-p.right.registersfpu)<fpu) then
  383. inc(p.registersfpu,fpu);
  384. {$ifdef SUPPORT_MMX}
  385. if (abs(p.left.registersmmx-p.right.registersmmx)<mmx) then
  386. inc(p.registersmmx,mmx);
  387. {$endif SUPPORT_MMX}
  388. { the following is a little bit guessing but I think }
  389. { it's the only way to solve same internalerrors: }
  390. { if the left and right node both uses registers }
  391. { and return a mem location, but the current node }
  392. { doesn't use an integer register we get probably }
  393. { trouble when restoring a node }
  394. if (p.left.registers32=p.right.registers32) and
  395. (p.registers32=p.left.registers32) and
  396. (p.registers32>0) and
  397. (p.left.location.loc in [LOC_REFERENCE,LOC_MEM]) and
  398. (p.right.location.loc in [LOC_REFERENCE,LOC_MEM]) then
  399. inc(p.registers32);
  400. end
  401. else
  402. begin
  403. if (p.left.registers32<r32) then
  404. inc(p.registers32,r32);
  405. if (p.left.registersfpu<fpu) then
  406. inc(p.registersfpu,fpu);
  407. {$ifdef SUPPORT_MMX}
  408. if (p.left.registersmmx<mmx) then
  409. inc(p.registersmmx,mmx);
  410. {$endif SUPPORT_MMX}
  411. end;
  412. end;
  413. { error CGMessage, if more than 8 floating point }
  414. { registers are needed }
  415. if p.registersfpu>8 then
  416. CGMessage(cg_e_too_complex_expr);
  417. end;
  418. {****************************************************************************
  419. Subroutine Handling
  420. ****************************************************************************}
  421. { protected field handling
  422. protected field can not appear in
  423. var parameters of function !!
  424. this can only be done after we have determined the
  425. overloaded function
  426. this is the reason why it is not in the parser, PM }
  427. procedure test_protected_sym(sym : tsym);
  428. begin
  429. if (sp_protected in sym.symoptions) and
  430. (
  431. (
  432. (sym.owner.symtabletype=globalsymtable) and
  433. (sym.owner.unitid<>0)
  434. ) or
  435. (
  436. (sym.owner.symtabletype=objectsymtable) and
  437. (tobjectdef(sym.owner.defowner).owner.symtabletype=globalsymtable) and
  438. (tobjectdef(sym.owner.defowner).owner.unitid<>0)
  439. )
  440. ) then
  441. CGMessage(parser_e_cant_access_protected_member);
  442. end;
  443. procedure test_protected(p : tnode);
  444. begin
  445. case p.nodetype of
  446. loadn : test_protected_sym(tloadnode(p).symtableentry);
  447. typeconvn : test_protected(ttypeconvnode(p).left);
  448. derefn : test_protected(tderefnode(p).left);
  449. subscriptn : begin
  450. { test_protected(p.left);
  451. Is a field of a protected var
  452. also protected ??? PM }
  453. test_protected_sym(tsubscriptnode(p).vs);
  454. end;
  455. end;
  456. end;
  457. function valid_for_formal_var(p : tnode) : boolean;
  458. var
  459. v : boolean;
  460. begin
  461. case p.nodetype of
  462. loadn :
  463. v:=(tloadnode(p).symtableentry.typ in [typedconstsym,varsym]);
  464. typeconvn :
  465. v:=valid_for_formal_var(ttypeconvnode(p).left);
  466. derefn,
  467. subscriptn,
  468. vecn,
  469. funcretn,
  470. selfn :
  471. v:=true;
  472. calln : { procvars are callnodes first }
  473. v:=assigned(tcallnode(p).right) and not assigned(tcallnode(p).left);
  474. addrn :
  475. begin
  476. { addrn is not allowed as this generate a constant value,
  477. but a tp procvar are allowed (PFV) }
  478. if nf_procvarload in p.flags then
  479. v:=true
  480. else
  481. v:=false;
  482. end;
  483. else
  484. v:=false;
  485. end;
  486. valid_for_formal_var:=v;
  487. end;
  488. function valid_for_formal_const(p : tnode) : boolean;
  489. var
  490. v : boolean;
  491. begin
  492. { p must have been firstpass'd before }
  493. { accept about anything but not a statement ! }
  494. case p.nodetype of
  495. calln,
  496. statementn,
  497. addrn :
  498. begin
  499. { addrn is not allowed as this generate a constant value,
  500. but a tp procvar are allowed (PFV) }
  501. if nf_procvarload in p.flags then
  502. v:=true
  503. else
  504. v:=false;
  505. end;
  506. else
  507. v:=true;
  508. end;
  509. valid_for_formal_const:=v;
  510. end;
  511. function is_procsym_load(p:tnode):boolean;
  512. begin
  513. is_procsym_load:=((p.nodetype=loadn) and (tloadnode(p).symtableentry.typ=procsym)) or
  514. ((p.nodetype=addrn) and (taddrnode(p).left.nodetype=loadn)
  515. and (tloadnode(taddrnode(p).left).symtableentry.typ=procsym)) ;
  516. end;
  517. { change a proc call to a procload for assignment to a procvar }
  518. { this can only happen for proc/function without arguments }
  519. function is_procsym_call(p:tnode):boolean;
  520. begin
  521. is_procsym_call:=(p.nodetype=calln) and (tcallnode(p).left=nil) and
  522. (((tcallnode(p).symtableprocentry.typ=procsym) and (tcallnode(p).right=nil)) or
  523. (assigned(tcallnode(p).right) and (tcallnode(tcallnode(p).right).symtableprocentry.typ=varsym)));
  524. end;
  525. { local routines can't be assigned to procvars }
  526. procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
  527. begin
  528. if (from_def.symtablelevel>1) and (to_def.deftype=procvardef) then
  529. CGMessage(type_e_cannot_local_proc_to_procvar);
  530. end;
  531. function valid_for_assign(p:tnode;allowprop:boolean):boolean;
  532. var
  533. hp : tnode;
  534. gotwith,
  535. gotsubscript,
  536. gotpointer,
  537. gotclass,
  538. gotderef : boolean;
  539. begin
  540. valid_for_assign:=false;
  541. gotsubscript:=false;
  542. gotderef:=false;
  543. gotclass:=false;
  544. gotpointer:=false;
  545. gotwith:=false;
  546. hp:=p;
  547. if is_void(hp.resulttype.def) then
  548. begin
  549. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  550. exit;
  551. end;
  552. while assigned(hp) do
  553. begin
  554. { property allowed? calln has a property check itself }
  555. if (not allowprop) and
  556. (nf_isproperty in hp.flags) and
  557. (hp.nodetype<>calln) then
  558. begin
  559. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  560. exit;
  561. end;
  562. case hp.nodetype of
  563. derefn :
  564. begin
  565. gotderef:=true;
  566. hp:=tderefnode(hp).left;
  567. end;
  568. typeconvn :
  569. begin
  570. case hp.resulttype.def.deftype of
  571. pointerdef :
  572. gotpointer:=true;
  573. objectdef :
  574. gotclass:=is_class_or_interface(hp.resulttype.def);
  575. classrefdef :
  576. gotclass:=true;
  577. arraydef :
  578. begin
  579. { pointer -> array conversion is done then we need to see it
  580. as a deref, because a ^ is then not required anymore }
  581. if (ttypeconvnode(hp).left.resulttype.def.deftype=pointerdef) then
  582. gotderef:=true;
  583. end;
  584. end;
  585. hp:=ttypeconvnode(hp).left;
  586. end;
  587. vecn,
  588. asn :
  589. hp:=tunarynode(hp).left;
  590. subscriptn :
  591. begin
  592. gotsubscript:=true;
  593. { a class/interface access is an implicit }
  594. { dereferencing }
  595. hp:=tsubscriptnode(hp).left;
  596. if is_class_or_interface(hp.resulttype.def) then
  597. gotderef:=true;
  598. end;
  599. subn,
  600. addn :
  601. begin
  602. { Allow add/sub operators on a pointer, or an integer
  603. and a pointer typecast and deref has been found }
  604. if (hp.resulttype.def.deftype=pointerdef) or
  605. (is_integer(hp.resulttype.def) and gotpointer and gotderef) then
  606. valid_for_assign:=true
  607. else
  608. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  609. exit;
  610. end;
  611. addrn :
  612. begin
  613. if not(gotderef) and
  614. not(nf_procvarload in hp.flags) then
  615. CGMessagePos(hp.fileinfo,type_e_no_assign_to_addr);
  616. exit;
  617. end;
  618. selfn,
  619. funcretn :
  620. begin
  621. valid_for_assign:=true;
  622. exit;
  623. end;
  624. calln :
  625. begin
  626. { check return type }
  627. case hp.resulttype.def.deftype of
  628. pointerdef :
  629. gotpointer:=true;
  630. objectdef :
  631. gotclass:=is_class_or_interface(hp.resulttype.def);
  632. recorddef, { handle record like class it needs a subscription }
  633. classrefdef :
  634. gotclass:=true;
  635. end;
  636. { 1. if it returns a pointer and we've found a deref,
  637. 2. if it returns a class or record and a subscription or with is found,
  638. 3. property is allowed }
  639. if (gotpointer and gotderef) or
  640. (gotclass and (gotsubscript or gotwith)) or
  641. ((nf_isproperty in hp.flags) and allowprop) then
  642. valid_for_assign:=true
  643. else
  644. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  645. exit;
  646. end;
  647. loadn :
  648. begin
  649. case tloadnode(hp).symtableentry.typ of
  650. absolutesym,
  651. varsym :
  652. begin
  653. if (tvarsym(tloadnode(hp).symtableentry).varspez=vs_const) then
  654. begin
  655. { allow p^:= constructions with p is const parameter }
  656. if gotderef then
  657. valid_for_assign:=true
  658. else
  659. CGMessagePos(tloadnode(hp).fileinfo,type_e_no_assign_to_const);
  660. exit;
  661. end;
  662. { Are we at a with symtable, then we need to process the
  663. withrefnode also to check for maybe a const load }
  664. if (tloadnode(hp).symtable.symtabletype=withsymtable) then
  665. begin
  666. { continue with processing the withref node }
  667. hp:=tnode(twithsymtable(tloadnode(hp).symtable).withrefnode);
  668. gotwith:=true;
  669. end
  670. else
  671. begin
  672. { set the assigned flag for varsyms }
  673. if (tvarsym(tloadnode(hp).symtableentry).varstate=vs_declared) then
  674. tvarsym(tloadnode(hp).symtableentry).varstate:=vs_assigned;
  675. valid_for_assign:=true;
  676. exit;
  677. end;
  678. end;
  679. funcretsym,
  680. typedconstsym :
  681. begin
  682. valid_for_assign:=true;
  683. exit;
  684. end;
  685. end;
  686. end;
  687. else
  688. begin
  689. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  690. exit;
  691. end;
  692. end;
  693. end;
  694. end;
  695. procedure set_varstate(p : tnode;must_be_valid : boolean);
  696. var
  697. hsym : tvarsym;
  698. begin
  699. while assigned(p) do
  700. begin
  701. if (nf_varstateset in p.flags) then
  702. exit;
  703. include(p.flags,nf_varstateset);
  704. case p.nodetype of
  705. typeconvn :
  706. begin
  707. case ttypeconvnode(p).convtype of
  708. tc_cchar_2_pchar,
  709. tc_cstring_2_pchar,
  710. tc_array_2_pointer :
  711. must_be_valid:=false;
  712. tc_pchar_2_string,
  713. tc_pointer_2_array :
  714. must_be_valid:=true;
  715. end;
  716. p:=tunarynode(p).left;
  717. end;
  718. subscriptn :
  719. p:=tunarynode(p).left;
  720. vecn:
  721. begin
  722. set_varstate(tbinarynode(p).right,true);
  723. if not(tunarynode(p).left.resulttype.def.deftype in [stringdef,arraydef]) then
  724. must_be_valid:=true;
  725. p:=tunarynode(p).left;
  726. end;
  727. { do not parse calln }
  728. calln :
  729. break;
  730. callparan :
  731. begin
  732. set_varstate(tbinarynode(p).right,must_be_valid);
  733. p:=tunarynode(p).left;
  734. end;
  735. loadn :
  736. begin
  737. if (tloadnode(p).symtableentry.typ=varsym) then
  738. begin
  739. hsym:=tvarsym(tloadnode(p).symtableentry);
  740. if must_be_valid and (nf_first in p.flags) then
  741. begin
  742. if (hsym.varstate=vs_declared_and_first_found) or
  743. (hsym.varstate=vs_set_but_first_not_passed) then
  744. begin
  745. if (assigned(hsym.owner) and
  746. assigned(aktprocsym) and
  747. (hsym.owner = aktprocsym.definition.localst)) then
  748. begin
  749. if tloadnode(p).symtable.symtabletype=localsymtable then
  750. CGMessage1(sym_n_uninitialized_local_variable,hsym.realname)
  751. else
  752. CGMessage1(sym_n_uninitialized_variable,hsym.realname);
  753. end;
  754. end;
  755. end;
  756. if (nf_first in p.flags) then
  757. begin
  758. if hsym.varstate=vs_declared_and_first_found then
  759. begin
  760. { this can only happen at left of an assignment, no ? PM }
  761. if (parsing_para_level=0) and not must_be_valid then
  762. hsym.varstate:=vs_assigned
  763. else
  764. hsym.varstate:=vs_used;
  765. end
  766. else
  767. if hsym.varstate=vs_set_but_first_not_passed then
  768. hsym.varstate:=vs_used;
  769. exclude(p.flags,nf_first);
  770. end
  771. else
  772. begin
  773. if (hsym.varstate=vs_assigned) and
  774. (must_be_valid or (parsing_para_level>0) or
  775. (p.resulttype.def.deftype=procvardef)) then
  776. hsym.varstate:=vs_used;
  777. if (hsym.varstate=vs_declared_and_first_found) and
  778. (must_be_valid or (parsing_para_level>0) or
  779. (p.resulttype.def.deftype=procvardef)) then
  780. hsym.varstate:=vs_set_but_first_not_passed;
  781. end;
  782. end;
  783. break;
  784. end;
  785. funcretn:
  786. begin
  787. { no claim if setting higher return value_str }
  788. if must_be_valid and
  789. (procinfo=pprocinfo(tfuncretnode(p).funcretprocinfo)) and
  790. ((procinfo^.funcret_state=vs_declared) or
  791. ((nf_is_first_funcret in p.flags) and
  792. (procinfo^.funcret_state=vs_declared_and_first_found))) then
  793. begin
  794. CGMessage(sym_w_function_result_not_set);
  795. { avoid multiple warnings }
  796. procinfo^.funcret_state:=vs_assigned;
  797. end;
  798. if (nf_is_first_funcret in p.flags) and not must_be_valid then
  799. pprocinfo(tfuncretnode(p).funcretprocinfo)^.funcret_state:=vs_assigned;
  800. break;
  801. end;
  802. else
  803. break;
  804. end;{case }
  805. end;
  806. end;
  807. procedure unset_varstate(p : tnode);
  808. begin
  809. while assigned(p) do
  810. begin
  811. exclude(p.flags,nf_varstateset);
  812. case p.nodetype of
  813. typeconvn,
  814. subscriptn,
  815. vecn :
  816. p:=tunarynode(p).left;
  817. else
  818. break;
  819. end;
  820. end;
  821. end;
  822. procedure set_unique(p : tnode);
  823. begin
  824. while assigned(p) do
  825. begin
  826. case p.nodetype of
  827. vecn:
  828. begin
  829. include(p.flags,nf_callunique);
  830. break;
  831. end;
  832. typeconvn,
  833. subscriptn,
  834. derefn:
  835. p:=tunarynode(p).left;
  836. else
  837. break;
  838. end;
  839. end;
  840. end;
  841. procedure set_funcret_is_valid(p:tnode);
  842. begin
  843. while assigned(p) do
  844. begin
  845. case p.nodetype of
  846. funcretn:
  847. begin
  848. if (nf_is_first_funcret in p.flags) then
  849. pprocinfo(tfuncretnode(p).funcretprocinfo)^.funcret_state:=vs_assigned;
  850. break;
  851. end;
  852. vecn,
  853. {derefn,}
  854. typeconvn,
  855. subscriptn:
  856. p:=tunarynode(p).left;
  857. else
  858. break;
  859. end;
  860. end;
  861. end;
  862. end.
  863. {
  864. $Log$
  865. Revision 1.24 2001-04-13 01:22:08 peter
  866. * symtable change to classes
  867. * range check generation and errors fixed, make cycle DEBUG=1 works
  868. * memory leaks fixed
  869. Revision 1.23 2001/04/02 21:20:29 peter
  870. * resulttype rewrite
  871. Revision 1.22 2001/02/20 21:46:26 peter
  872. * don't allow assign to void type (merged)
  873. Revision 1.21 2001/02/04 11:12:17 jonas
  874. * fixed web bug 1377 & const pointer arithmtic
  875. Revision 1.20 2000/12/09 13:04:05 florian
  876. * web bug 1207 fixed: field and properties of const classes can be
  877. changed
  878. Revision 1.19 2000/11/29 00:30:31 florian
  879. * unused units removed from uses clause
  880. * some changes for widestrings
  881. Revision 1.18 2000/11/28 17:14:33 jonas
  882. * fixed crash when trying to use an overloaded operator which is nowhere
  883. defined
  884. Revision 1.17 2000/11/28 14:04:03 jonas
  885. * fixed operator overloading problems
  886. Revision 1.16 2000/11/13 11:30:54 florian
  887. * some bugs with interfaces and NIL fixed
  888. Revision 1.15 2000/11/12 22:20:37 peter
  889. * create generic toutputsection for binary writers
  890. Revision 1.14 2000/11/04 14:25:19 florian
  891. + merged Attila's changes for interfaces, not tested yet
  892. Revision 1.13 2000/10/31 22:02:47 peter
  893. * symtable splitted, no real code changes
  894. Revision 1.12 2000/10/14 10:14:47 peter
  895. * moehrendorf oct 2000 rewrite
  896. Revision 1.11 2000/10/01 19:48:23 peter
  897. * lot of compile updates for cg11
  898. Revision 1.10 2000/09/29 15:45:23 florian
  899. * make cycle fixed
  900. Revision 1.9 2000/09/28 19:49:51 florian
  901. *** empty log message ***
  902. Revision 1.8 2000/09/27 18:14:31 florian
  903. * fixed a lot of syntax errors in the n*.pas stuff
  904. Revision 1.7 2000/09/26 20:06:13 florian
  905. * hmm, still a lot of work to get things compilable
  906. Revision 1.6 2000/09/24 15:06:17 peter
  907. * use defines.inc
  908. Revision 1.5 2000/08/27 16:11:51 peter
  909. * moved some util functions from globals,cobjects to cutils
  910. * splitted files into finput,fmodule
  911. Revision 1.4 2000/08/16 18:33:53 peter
  912. * splitted namedobjectitem.next into indexnext and listnext so it
  913. can be used in both lists
  914. * don't allow "word = word" type definitions (merged)
  915. Revision 1.3 2000/08/07 11:31:04 jonas
  916. * fixed bug in type conversions between enum subranges (it didn't take
  917. the packenum directive into account)
  918. + define PACKENUMFIXED symbol in options.pas
  919. (merged from fixes branch)
  920. Revision 1.2 2000/07/13 11:32:41 michael
  921. + removed logs
  922. }