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