htypechk.pas 38 KB

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