htypechk.pas 36 KB

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