htypechk.pas 36 KB

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