htypechk.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008
  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. (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. { the original t t will be released by firstpass! (JM) }
  332. t := t.getcopy;
  333. end
  334. else
  335. begin
  336. inc(tcallnode(ht).symtableprocentry.refs);
  337. { we need copies, because the originals will be destroyed when we give a }
  338. { changed node back to firstpass! (JM) }
  339. if assigned(tbinarynode(t).left) then
  340. if assigned(tbinarynode(t).right) then
  341. tcallnode(ht).left :=
  342. ccallparanode.create(tbinarynode(t).right.getcopy,
  343. ccallparanode.create(tbinarynode(t).left.getcopy,nil))
  344. else
  345. tcallnode(ht).left :=
  346. ccallparanode.create(nil,
  347. ccallparanode.create(tbinarynode(t).left.getcopy,nil))
  348. else if assigned(tbinarynode(t).right) then
  349. tcallnode(ht).left :=
  350. ccallparanode.create(tbinarynode(t).right.getcopy,
  351. ccallparanode.create(nil,nil));
  352. if t.nodetype=unequaln then
  353. ht:=cnotnode.create(ht);
  354. t:=ht;
  355. end;
  356. end;
  357. end;
  358. {****************************************************************************
  359. Register Calculation
  360. ****************************************************************************}
  361. { marks an lvalue as "unregable" }
  362. procedure make_not_regable(p : tnode);
  363. begin
  364. case p.nodetype of
  365. typeconvn :
  366. make_not_regable(ttypeconvnode(p).left);
  367. loadn :
  368. if tloadnode(p).symtableentry.typ=varsym then
  369. tvarsym(tloadnode(p).symtableentry).varoptions:=tvarsym(tloadnode(p).symtableentry).varoptions-[vo_regable,vo_fpuregable];
  370. end;
  371. end;
  372. { calculates the needed registers for a binary operator }
  373. procedure calcregisters(p : tbinarynode;r32,fpu,mmx : word);
  374. begin
  375. p.left_right_max;
  376. { Only when the difference between the left and right registers < the
  377. wanted registers allocate the amount of registers }
  378. if assigned(p.left) then
  379. begin
  380. if assigned(p.right) then
  381. begin
  382. if (abs(p.left.registers32-p.right.registers32)<r32) then
  383. inc(p.registers32,r32);
  384. if (abs(p.left.registersfpu-p.right.registersfpu)<fpu) then
  385. inc(p.registersfpu,fpu);
  386. {$ifdef SUPPORT_MMX}
  387. if (abs(p.left.registersmmx-p.right.registersmmx)<mmx) then
  388. inc(p.registersmmx,mmx);
  389. {$endif SUPPORT_MMX}
  390. { the following is a little bit guessing but I think }
  391. { it's the only way to solve same internalerrors: }
  392. { if the left and right node both uses registers }
  393. { and return a mem location, but the current node }
  394. { doesn't use an integer register we get probably }
  395. { trouble when restoring a node }
  396. if (p.left.registers32=p.right.registers32) and
  397. (p.registers32=p.left.registers32) and
  398. (p.registers32>0) and
  399. (p.left.location.loc in [LOC_REFERENCE,LOC_MEM]) and
  400. (p.right.location.loc in [LOC_REFERENCE,LOC_MEM]) then
  401. inc(p.registers32);
  402. end
  403. else
  404. begin
  405. if (p.left.registers32<r32) then
  406. inc(p.registers32,r32);
  407. if (p.left.registersfpu<fpu) then
  408. inc(p.registersfpu,fpu);
  409. {$ifdef SUPPORT_MMX}
  410. if (p.left.registersmmx<mmx) then
  411. inc(p.registersmmx,mmx);
  412. {$endif SUPPORT_MMX}
  413. end;
  414. end;
  415. { error CGMessage, if more than 8 floating point }
  416. { registers are needed }
  417. if p.registersfpu>8 then
  418. CGMessage(cg_e_too_complex_expr);
  419. end;
  420. {****************************************************************************
  421. Subroutine Handling
  422. ****************************************************************************}
  423. { protected field handling
  424. protected field can not appear in
  425. var parameters of function !!
  426. this can only be done after we have determined the
  427. overloaded function
  428. this is the reason why it is not in the parser, PM }
  429. procedure test_protected_sym(sym : tsym);
  430. begin
  431. if (sp_protected in sym.symoptions) and
  432. (
  433. (
  434. (sym.owner.symtabletype=globalsymtable) and
  435. (sym.owner.unitid<>0)
  436. ) or
  437. (
  438. (sym.owner.symtabletype=objectsymtable) and
  439. (tobjectdef(sym.owner.defowner).owner.symtabletype=globalsymtable) and
  440. (tobjectdef(sym.owner.defowner).owner.unitid<>0)
  441. )
  442. ) then
  443. CGMessage(parser_e_cant_access_protected_member);
  444. end;
  445. procedure test_protected(p : tnode);
  446. begin
  447. case p.nodetype of
  448. loadn : test_protected_sym(tloadnode(p).symtableentry);
  449. typeconvn : test_protected(ttypeconvnode(p).left);
  450. derefn : test_protected(tderefnode(p).left);
  451. subscriptn : begin
  452. { test_protected(p.left);
  453. Is a field of a protected var
  454. also protected ??? PM }
  455. test_protected_sym(tsubscriptnode(p).vs);
  456. end;
  457. end;
  458. end;
  459. function valid_for_formal_var(p : tnode) : boolean;
  460. var
  461. v : boolean;
  462. begin
  463. case p.nodetype of
  464. loadn :
  465. v:=(tloadnode(p).symtableentry.typ in [typedconstsym,varsym]);
  466. typeconvn :
  467. v:=valid_for_formal_var(ttypeconvnode(p).left);
  468. derefn,
  469. subscriptn,
  470. vecn,
  471. funcretn,
  472. selfn :
  473. v:=true;
  474. calln : { procvars are callnodes first }
  475. v:=assigned(tcallnode(p).right) and not assigned(tcallnode(p).left);
  476. addrn :
  477. begin
  478. { addrn is not allowed as this generate a constant value,
  479. but a tp procvar are allowed (PFV) }
  480. if nf_procvarload in p.flags then
  481. v:=true
  482. else
  483. v:=false;
  484. end;
  485. else
  486. v:=false;
  487. end;
  488. valid_for_formal_var:=v;
  489. end;
  490. function valid_for_formal_const(p : tnode) : boolean;
  491. var
  492. v : boolean;
  493. begin
  494. { p must have been firstpass'd before }
  495. { accept about anything but not a statement ! }
  496. case p.nodetype of
  497. calln,
  498. statementn,
  499. addrn :
  500. begin
  501. { addrn is not allowed as this generate a constant value,
  502. but a tp procvar are allowed (PFV) }
  503. if nf_procvarload in p.flags then
  504. v:=true
  505. else
  506. v:=false;
  507. end;
  508. else
  509. v:=true;
  510. end;
  511. valid_for_formal_const:=v;
  512. end;
  513. function is_procsym_load(p:tnode):boolean;
  514. begin
  515. is_procsym_load:=((p.nodetype=loadn) and (tloadnode(p).symtableentry.typ=procsym)) or
  516. ((p.nodetype=addrn) and (taddrnode(p).left.nodetype=loadn)
  517. and (tloadnode(taddrnode(p).left).symtableentry.typ=procsym)) ;
  518. end;
  519. { change a proc call to a procload for assignment to a procvar }
  520. { this can only happen for proc/function without arguments }
  521. function is_procsym_call(p:tnode):boolean;
  522. begin
  523. is_procsym_call:=(p.nodetype=calln) and (tcallnode(p).left=nil) and
  524. (((tcallnode(p).symtableprocentry.typ=procsym) and (tcallnode(p).right=nil)) or
  525. (assigned(tcallnode(p).right) and (tcallnode(tcallnode(p).right).symtableprocentry.typ=varsym)));
  526. end;
  527. { local routines can't be assigned to procvars }
  528. procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
  529. begin
  530. if (from_def.symtablelevel>1) and (to_def.deftype=procvardef) then
  531. CGMessage(type_e_cannot_local_proc_to_procvar);
  532. end;
  533. function valid_for_assign(p:tnode;allowprop:boolean):boolean;
  534. var
  535. hp : tnode;
  536. gotwith,
  537. gotsubscript,
  538. gotpointer,
  539. gotclass,
  540. gotderef : boolean;
  541. begin
  542. valid_for_assign:=false;
  543. gotsubscript:=false;
  544. gotderef:=false;
  545. gotclass:=false;
  546. gotpointer:=false;
  547. gotwith:=false;
  548. hp:=p;
  549. if is_void(hp.resulttype.def) then
  550. begin
  551. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  552. exit;
  553. end;
  554. while assigned(hp) do
  555. begin
  556. { property allowed? calln has a property check itself }
  557. if (not allowprop) and
  558. (nf_isproperty in hp.flags) and
  559. (hp.nodetype<>calln) then
  560. begin
  561. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  562. exit;
  563. end;
  564. case hp.nodetype of
  565. derefn :
  566. begin
  567. gotderef:=true;
  568. hp:=tderefnode(hp).left;
  569. end;
  570. typeconvn :
  571. begin
  572. case hp.resulttype.def.deftype of
  573. pointerdef :
  574. gotpointer:=true;
  575. objectdef :
  576. gotclass:=is_class_or_interface(hp.resulttype.def);
  577. classrefdef :
  578. gotclass:=true;
  579. arraydef :
  580. begin
  581. { pointer -> array conversion is done then we need to see it
  582. as a deref, because a ^ is then not required anymore }
  583. if (ttypeconvnode(hp).left.resulttype.def.deftype=pointerdef) then
  584. gotderef:=true;
  585. end;
  586. end;
  587. hp:=ttypeconvnode(hp).left;
  588. end;
  589. vecn,
  590. asn :
  591. hp:=tunarynode(hp).left;
  592. subscriptn :
  593. begin
  594. gotsubscript:=true;
  595. { a class/interface access is an implicit }
  596. { dereferencing }
  597. hp:=tsubscriptnode(hp).left;
  598. if is_class_or_interface(hp.resulttype.def) then
  599. gotderef:=true;
  600. end;
  601. subn,
  602. addn :
  603. begin
  604. { Allow add/sub operators on a pointer, or an integer
  605. and a pointer typecast and deref has been found }
  606. if (hp.resulttype.def.deftype=pointerdef) or
  607. (is_integer(hp.resulttype.def) and gotpointer and gotderef) then
  608. valid_for_assign:=true
  609. else
  610. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  611. exit;
  612. end;
  613. addrn :
  614. begin
  615. if not(gotderef) and
  616. not(nf_procvarload in hp.flags) then
  617. CGMessagePos(hp.fileinfo,type_e_no_assign_to_addr);
  618. exit;
  619. end;
  620. selfn,
  621. funcretn :
  622. begin
  623. valid_for_assign:=true;
  624. exit;
  625. end;
  626. calln :
  627. begin
  628. { check return type }
  629. case hp.resulttype.def.deftype of
  630. pointerdef :
  631. gotpointer:=true;
  632. objectdef :
  633. gotclass:=is_class_or_interface(hp.resulttype.def);
  634. recorddef, { handle record like class it needs a subscription }
  635. classrefdef :
  636. gotclass:=true;
  637. end;
  638. { 1. if it returns a pointer and we've found a deref,
  639. 2. if it returns a class or record and a subscription or with is found,
  640. 3. property is allowed }
  641. if (gotpointer and gotderef) or
  642. (gotclass and (gotsubscript or gotwith)) or
  643. ((nf_isproperty in hp.flags) and allowprop) then
  644. valid_for_assign:=true
  645. else
  646. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  647. exit;
  648. end;
  649. loadn :
  650. begin
  651. case tloadnode(hp).symtableentry.typ of
  652. absolutesym,
  653. varsym :
  654. begin
  655. if (tvarsym(tloadnode(hp).symtableentry).varspez=vs_const) then
  656. begin
  657. { allow p^:= constructions with p is const parameter }
  658. if gotderef then
  659. valid_for_assign:=true
  660. else
  661. CGMessagePos(tloadnode(hp).fileinfo,type_e_no_assign_to_const);
  662. exit;
  663. end;
  664. { Are we at a with symtable, then we need to process the
  665. withrefnode also to check for maybe a const load }
  666. if (tloadnode(hp).symtable.symtabletype=withsymtable) then
  667. begin
  668. { continue with processing the withref node }
  669. hp:=tnode(twithsymtable(tloadnode(hp).symtable).withrefnode);
  670. gotwith:=true;
  671. end
  672. else
  673. begin
  674. { set the assigned flag for varsyms }
  675. if (tvarsym(tloadnode(hp).symtableentry).varstate=vs_declared) then
  676. tvarsym(tloadnode(hp).symtableentry).varstate:=vs_assigned;
  677. valid_for_assign:=true;
  678. exit;
  679. end;
  680. end;
  681. funcretsym,
  682. typedconstsym :
  683. begin
  684. valid_for_assign:=true;
  685. exit;
  686. end;
  687. end;
  688. end;
  689. else
  690. begin
  691. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  692. exit;
  693. end;
  694. end;
  695. end;
  696. end;
  697. procedure set_varstate(p : tnode;must_be_valid : boolean);
  698. var
  699. hsym : tvarsym;
  700. begin
  701. while assigned(p) do
  702. begin
  703. if (nf_varstateset in p.flags) then
  704. exit;
  705. include(p.flags,nf_varstateset);
  706. case p.nodetype of
  707. typeconvn :
  708. begin
  709. case ttypeconvnode(p).convtype of
  710. tc_cchar_2_pchar,
  711. tc_cstring_2_pchar,
  712. tc_array_2_pointer :
  713. must_be_valid:=false;
  714. tc_pchar_2_string,
  715. tc_pointer_2_array :
  716. must_be_valid:=true;
  717. end;
  718. p:=tunarynode(p).left;
  719. end;
  720. subscriptn :
  721. p:=tunarynode(p).left;
  722. vecn:
  723. begin
  724. set_varstate(tbinarynode(p).right,true);
  725. if not(tunarynode(p).left.resulttype.def.deftype in [stringdef,arraydef]) then
  726. must_be_valid:=true;
  727. p:=tunarynode(p).left;
  728. end;
  729. { do not parse calln }
  730. calln :
  731. break;
  732. callparan :
  733. begin
  734. set_varstate(tbinarynode(p).right,must_be_valid);
  735. p:=tunarynode(p).left;
  736. end;
  737. loadn :
  738. begin
  739. if (tloadnode(p).symtableentry.typ=varsym) then
  740. begin
  741. hsym:=tvarsym(tloadnode(p).symtableentry);
  742. if must_be_valid and (nf_first in p.flags) then
  743. begin
  744. if (hsym.varstate=vs_declared_and_first_found) or
  745. (hsym.varstate=vs_set_but_first_not_passed) then
  746. begin
  747. if (assigned(hsym.owner) and
  748. assigned(aktprocsym) and
  749. (hsym.owner = aktprocsym.definition.localst)) then
  750. begin
  751. if tloadnode(p).symtable.symtabletype=localsymtable then
  752. CGMessage1(sym_n_uninitialized_local_variable,hsym.realname)
  753. else
  754. CGMessage1(sym_n_uninitialized_variable,hsym.realname);
  755. end;
  756. end;
  757. end;
  758. if (nf_first in p.flags) then
  759. begin
  760. if hsym.varstate=vs_declared_and_first_found then
  761. begin
  762. { this can only happen at left of an assignment, no ? PM }
  763. if (parsing_para_level=0) and not must_be_valid then
  764. hsym.varstate:=vs_assigned
  765. else
  766. hsym.varstate:=vs_used;
  767. end
  768. else
  769. if hsym.varstate=vs_set_but_first_not_passed then
  770. hsym.varstate:=vs_used;
  771. exclude(p.flags,nf_first);
  772. end
  773. else
  774. begin
  775. if (hsym.varstate=vs_assigned) and
  776. (must_be_valid or (parsing_para_level>0) or
  777. (p.resulttype.def.deftype=procvardef)) then
  778. hsym.varstate:=vs_used;
  779. if (hsym.varstate=vs_declared_and_first_found) and
  780. (must_be_valid or (parsing_para_level>0) or
  781. (p.resulttype.def.deftype=procvardef)) then
  782. hsym.varstate:=vs_set_but_first_not_passed;
  783. end;
  784. end;
  785. break;
  786. end;
  787. funcretn:
  788. begin
  789. { no claim if setting higher return value_str }
  790. if must_be_valid and
  791. (procinfo=pprocinfo(tfuncretnode(p).funcretprocinfo)) and
  792. ((procinfo^.funcret_state=vs_declared) or
  793. ((nf_is_first_funcret in p.flags) and
  794. (procinfo^.funcret_state=vs_declared_and_first_found))) then
  795. begin
  796. CGMessage(sym_w_function_result_not_set);
  797. { avoid multiple warnings }
  798. procinfo^.funcret_state:=vs_assigned;
  799. end;
  800. if (nf_is_first_funcret in p.flags) and not must_be_valid then
  801. pprocinfo(tfuncretnode(p).funcretprocinfo)^.funcret_state:=vs_assigned;
  802. break;
  803. end;
  804. else
  805. break;
  806. end;{case }
  807. end;
  808. end;
  809. procedure unset_varstate(p : tnode);
  810. begin
  811. while assigned(p) do
  812. begin
  813. exclude(p.flags,nf_varstateset);
  814. case p.nodetype of
  815. typeconvn,
  816. subscriptn,
  817. vecn :
  818. p:=tunarynode(p).left;
  819. else
  820. break;
  821. end;
  822. end;
  823. end;
  824. procedure set_unique(p : tnode);
  825. begin
  826. while assigned(p) do
  827. begin
  828. case p.nodetype of
  829. vecn:
  830. begin
  831. include(p.flags,nf_callunique);
  832. break;
  833. end;
  834. typeconvn,
  835. subscriptn,
  836. derefn:
  837. p:=tunarynode(p).left;
  838. else
  839. break;
  840. end;
  841. end;
  842. end;
  843. procedure set_funcret_is_valid(p:tnode);
  844. begin
  845. while assigned(p) do
  846. begin
  847. case p.nodetype of
  848. funcretn:
  849. begin
  850. if (nf_is_first_funcret in p.flags) then
  851. pprocinfo(tfuncretnode(p).funcretprocinfo)^.funcret_state:=vs_assigned;
  852. break;
  853. end;
  854. vecn,
  855. {derefn,}
  856. typeconvn,
  857. subscriptn:
  858. p:=tunarynode(p).left;
  859. else
  860. break;
  861. end;
  862. end;
  863. end;
  864. end.
  865. {
  866. $Log$
  867. Revision 1.25 2001-04-22 22:46:49 florian
  868. * more variant support
  869. Revision 1.24 2001/04/13 01:22:08 peter
  870. * symtable change to classes
  871. * range check generation and errors fixed, make cycle DEBUG=1 works
  872. * memory leaks fixed
  873. Revision 1.23 2001/04/02 21:20:29 peter
  874. * resulttype rewrite
  875. Revision 1.22 2001/02/20 21:46:26 peter
  876. * don't allow assign to void type (merged)
  877. Revision 1.21 2001/02/04 11:12:17 jonas
  878. * fixed web bug 1377 & const pointer arithmtic
  879. Revision 1.20 2000/12/09 13:04:05 florian
  880. * web bug 1207 fixed: field and properties of const classes can be
  881. changed
  882. Revision 1.19 2000/11/29 00:30:31 florian
  883. * unused units removed from uses clause
  884. * some changes for widestrings
  885. Revision 1.18 2000/11/28 17:14:33 jonas
  886. * fixed crash when trying to use an overloaded operator which is nowhere
  887. defined
  888. Revision 1.17 2000/11/28 14:04:03 jonas
  889. * fixed operator overloading problems
  890. Revision 1.16 2000/11/13 11:30:54 florian
  891. * some bugs with interfaces and NIL fixed
  892. Revision 1.15 2000/11/12 22:20:37 peter
  893. * create generic toutputsection for binary writers
  894. Revision 1.14 2000/11/04 14:25:19 florian
  895. + merged Attila's changes for interfaces, not tested yet
  896. Revision 1.13 2000/10/31 22:02:47 peter
  897. * symtable splitted, no real code changes
  898. Revision 1.12 2000/10/14 10:14:47 peter
  899. * moehrendorf oct 2000 rewrite
  900. Revision 1.11 2000/10/01 19:48:23 peter
  901. * lot of compile updates for cg11
  902. Revision 1.10 2000/09/29 15:45:23 florian
  903. * make cycle fixed
  904. Revision 1.9 2000/09/28 19:49:51 florian
  905. *** empty log message ***
  906. Revision 1.8 2000/09/27 18:14:31 florian
  907. * fixed a lot of syntax errors in the n*.pas stuff
  908. Revision 1.7 2000/09/26 20:06:13 florian
  909. * hmm, still a lot of work to get things compilable
  910. Revision 1.6 2000/09/24 15:06:17 peter
  911. * use defines.inc
  912. Revision 1.5 2000/08/27 16:11:51 peter
  913. * moved some util functions from globals,cobjects to cutils
  914. * splitted files into finput,fmodule
  915. Revision 1.4 2000/08/16 18:33:53 peter
  916. * splitted namedobjectitem.next into indexnext and listnext so it
  917. can be used in both lists
  918. * don't allow "word = word" type definitions (merged)
  919. Revision 1.3 2000/08/07 11:31:04 jonas
  920. * fixed bug in type conversions between enum subranges (it didn't take
  921. the packenum directive into account)
  922. + define PACKENUMFIXED symbol in options.pas
  923. (merged from fixes branch)
  924. Revision 1.2 2000/07/13 11:32:41 michael
  925. + removed logs
  926. }