htypechk.pas 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  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. while assigned(hp) do
  540. begin
  541. { property allowed? calln has a property check itself }
  542. if (not allowprop) and
  543. (nf_isproperty in hp.flags) and
  544. (hp.nodetype<>calln) then
  545. begin
  546. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  547. exit;
  548. end;
  549. case hp.nodetype of
  550. derefn :
  551. begin
  552. gotderef:=true;
  553. hp:=tderefnode(hp).left;
  554. end;
  555. typeconvn :
  556. begin
  557. case hp.resulttype^.deftype of
  558. pointerdef :
  559. gotpointer:=true;
  560. objectdef :
  561. gotclass:=is_class_or_interface(hp.resulttype);
  562. classrefdef :
  563. gotclass:=true;
  564. arraydef :
  565. begin
  566. { pointer -> array conversion is done then we need to see it
  567. as a deref, because a ^ is then not required anymore }
  568. if (ttypeconvnode(hp).left.resulttype^.deftype=pointerdef) then
  569. gotderef:=true;
  570. end;
  571. end;
  572. hp:=ttypeconvnode(hp).left;
  573. end;
  574. vecn,
  575. asn :
  576. hp:=tunarynode(hp).left;
  577. subscriptn :
  578. begin
  579. gotsubscript:=true;
  580. { a class/interface access is an implicit }
  581. { dereferencing }
  582. hp:=tsubscriptnode(hp).left;
  583. if is_class_or_interface(hp.resulttype) then
  584. gotderef:=true;
  585. end;
  586. subn,
  587. addn :
  588. begin
  589. { Allow add/sub operators on a pointer, or an integer
  590. and a pointer typecast and deref has been found }
  591. if (hp.resulttype^.deftype=pointerdef) or
  592. (is_integer(hp.resulttype) and gotpointer and gotderef) then
  593. valid_for_assign:=true
  594. else
  595. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  596. exit;
  597. end;
  598. addrn :
  599. begin
  600. if not(gotderef) and
  601. not(nf_procvarload in hp.flags) then
  602. CGMessagePos(hp.fileinfo,type_e_no_assign_to_addr);
  603. exit;
  604. end;
  605. selfn,
  606. funcretn :
  607. begin
  608. valid_for_assign:=true;
  609. exit;
  610. end;
  611. calln :
  612. begin
  613. { check return type }
  614. case hp.resulttype^.deftype of
  615. pointerdef :
  616. gotpointer:=true;
  617. objectdef :
  618. gotclass:=is_class_or_interface(hp.resulttype);
  619. recorddef, { handle record like class it needs a subscription }
  620. classrefdef :
  621. gotclass:=true;
  622. end;
  623. { 1. if it returns a pointer and we've found a deref,
  624. 2. if it returns a class or record and a subscription or with is found,
  625. 3. property is allowed }
  626. if (gotpointer and gotderef) or
  627. (gotclass and (gotsubscript or gotwith)) or
  628. ((nf_isproperty in hp.flags) and allowprop) then
  629. valid_for_assign:=true
  630. else
  631. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  632. exit;
  633. end;
  634. loadn :
  635. begin
  636. case tloadnode(hp).symtableentry^.typ of
  637. absolutesym,
  638. varsym :
  639. begin
  640. if (pvarsym(tloadnode(hp).symtableentry)^.varspez=vs_const) then
  641. begin
  642. { allow p^:= constructions with p is const parameter }
  643. if gotderef then
  644. valid_for_assign:=true
  645. else
  646. CGMessagePos(tloadnode(hp).fileinfo,type_e_no_assign_to_const);
  647. exit;
  648. end;
  649. { Are we at a with symtable, then we need to process the
  650. withrefnode also to check for maybe a const load }
  651. if (tloadnode(hp).symtable^.symtabletype=withsymtable) then
  652. begin
  653. { continue with processing the withref node }
  654. hp:=tnode(pwithsymtable(tloadnode(hp).symtable)^.withrefnode);
  655. gotwith:=true;
  656. end
  657. else
  658. begin
  659. { set the assigned flag for varsyms }
  660. if (pvarsym(tloadnode(hp).symtableentry)^.varstate=vs_declared) then
  661. pvarsym(tloadnode(hp).symtableentry)^.varstate:=vs_assigned;
  662. valid_for_assign:=true;
  663. exit;
  664. end;
  665. end;
  666. funcretsym,
  667. typedconstsym :
  668. begin
  669. valid_for_assign:=true;
  670. exit;
  671. end;
  672. end;
  673. end;
  674. else
  675. begin
  676. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  677. exit;
  678. end;
  679. end;
  680. end;
  681. end;
  682. procedure set_varstate(p : tnode;must_be_valid : boolean);
  683. var
  684. hsym : pvarsym;
  685. begin
  686. while assigned(p) do
  687. begin
  688. if (nf_varstateset in p.flags) then
  689. exit;
  690. include(p.flags,nf_varstateset);
  691. case p.nodetype of
  692. typeconvn :
  693. begin
  694. case ttypeconvnode(p).convtype of
  695. tc_cchar_2_pchar,
  696. tc_cstring_2_pchar,
  697. tc_array_2_pointer :
  698. must_be_valid:=false;
  699. tc_pchar_2_string,
  700. tc_pointer_2_array :
  701. must_be_valid:=true;
  702. end;
  703. p:=tunarynode(p).left;
  704. end;
  705. subscriptn :
  706. p:=tunarynode(p).left;
  707. vecn:
  708. begin
  709. set_varstate(tbinarynode(p).right,true);
  710. if not(tunarynode(p).left.resulttype^.deftype in [stringdef,arraydef]) then
  711. must_be_valid:=true;
  712. p:=tunarynode(p).left;
  713. end;
  714. { do not parse calln }
  715. calln :
  716. break;
  717. callparan :
  718. begin
  719. set_varstate(tbinarynode(p).right,must_be_valid);
  720. p:=tunarynode(p).left;
  721. end;
  722. loadn :
  723. begin
  724. if (tloadnode(p).symtableentry^.typ=varsym) then
  725. begin
  726. hsym:=pvarsym(tloadnode(p).symtableentry);
  727. if must_be_valid and (nf_first in p.flags) then
  728. begin
  729. if (hsym^.varstate=vs_declared_and_first_found) or
  730. (hsym^.varstate=vs_set_but_first_not_passed) then
  731. begin
  732. if (assigned(hsym^.owner) and
  733. assigned(aktprocsym) and
  734. (hsym^.owner = aktprocsym^.definition^.localst)) then
  735. begin
  736. if tloadnode(p).symtable^.symtabletype=localsymtable then
  737. CGMessage1(sym_n_uninitialized_local_variable,hsym^.realname)
  738. else
  739. CGMessage1(sym_n_uninitialized_variable,hsym^.realname);
  740. end;
  741. end;
  742. end;
  743. if (nf_first in p.flags) then
  744. begin
  745. if hsym^.varstate=vs_declared_and_first_found then
  746. begin
  747. { this can only happen at left of an assignment, no ? PM }
  748. if (parsing_para_level=0) and not must_be_valid then
  749. hsym^.varstate:=vs_assigned
  750. else
  751. hsym^.varstate:=vs_used;
  752. end
  753. else
  754. if hsym^.varstate=vs_set_but_first_not_passed then
  755. hsym^.varstate:=vs_used;
  756. exclude(p.flags,nf_first);
  757. end
  758. else
  759. begin
  760. if (hsym^.varstate=vs_assigned) and
  761. (must_be_valid or (parsing_para_level>0) or
  762. (p.resulttype^.deftype=procvardef)) then
  763. hsym^.varstate:=vs_used;
  764. if (hsym^.varstate=vs_declared_and_first_found) and
  765. (must_be_valid or (parsing_para_level>0) or
  766. (p.resulttype^.deftype=procvardef)) then
  767. hsym^.varstate:=vs_set_but_first_not_passed;
  768. end;
  769. end;
  770. break;
  771. end;
  772. funcretn:
  773. begin
  774. { no claim if setting higher return value_str }
  775. if must_be_valid and
  776. (procinfo=pprocinfo(tfuncretnode(p).funcretprocinfo)) and
  777. ((procinfo^.funcret_state=vs_declared) or
  778. ((nf_is_first_funcret in p.flags) and
  779. (procinfo^.funcret_state=vs_declared_and_first_found))) then
  780. begin
  781. CGMessage(sym_w_function_result_not_set);
  782. { avoid multiple warnings }
  783. procinfo^.funcret_state:=vs_assigned;
  784. end;
  785. if (nf_is_first_funcret in p.flags) and not must_be_valid then
  786. pprocinfo(tfuncretnode(p).funcretprocinfo)^.funcret_state:=vs_assigned;
  787. break;
  788. end;
  789. else
  790. break;
  791. end;{case }
  792. end;
  793. end;
  794. procedure unset_varstate(p : tnode);
  795. begin
  796. while assigned(p) do
  797. begin
  798. exclude(p.flags,nf_varstateset);
  799. case p.nodetype of
  800. typeconvn,
  801. subscriptn,
  802. vecn :
  803. p:=tunarynode(p).left;
  804. else
  805. break;
  806. end;
  807. end;
  808. end;
  809. procedure set_unique(p : tnode);
  810. begin
  811. while assigned(p) do
  812. begin
  813. case p.nodetype of
  814. vecn:
  815. begin
  816. include(p.flags,nf_callunique);
  817. break;
  818. end;
  819. typeconvn,
  820. subscriptn,
  821. derefn:
  822. p:=tunarynode(p).left;
  823. else
  824. break;
  825. end;
  826. end;
  827. end;
  828. procedure set_funcret_is_valid(p:tnode);
  829. begin
  830. while assigned(p) do
  831. begin
  832. case p.nodetype of
  833. funcretn:
  834. begin
  835. if (nf_is_first_funcret in p.flags) then
  836. pprocinfo(tfuncretnode(p).funcretprocinfo)^.funcret_state:=vs_assigned;
  837. break;
  838. end;
  839. vecn,
  840. {derefn,}
  841. typeconvn,
  842. subscriptn:
  843. p:=tunarynode(p).left;
  844. else
  845. break;
  846. end;
  847. end;
  848. end;
  849. end.
  850. {
  851. $Log$
  852. Revision 1.21 2001-02-04 11:12:17 jonas
  853. * fixed web bug 1377 & const pointer arithmtic
  854. Revision 1.20 2000/12/09 13:04:05 florian
  855. * web bug 1207 fixed: field and properties of const classes can be
  856. changed
  857. Revision 1.19 2000/11/29 00:30:31 florian
  858. * unused units removed from uses clause
  859. * some changes for widestrings
  860. Revision 1.18 2000/11/28 17:14:33 jonas
  861. * fixed crash when trying to use an overloaded operator which is nowhere
  862. defined
  863. Revision 1.17 2000/11/28 14:04:03 jonas
  864. * fixed operator overloading problems
  865. Revision 1.16 2000/11/13 11:30:54 florian
  866. * some bugs with interfaces and NIL fixed
  867. Revision 1.15 2000/11/12 22:20:37 peter
  868. * create generic toutputsection for binary writers
  869. Revision 1.14 2000/11/04 14:25:19 florian
  870. + merged Attila's changes for interfaces, not tested yet
  871. Revision 1.13 2000/10/31 22:02:47 peter
  872. * symtable splitted, no real code changes
  873. Revision 1.12 2000/10/14 10:14:47 peter
  874. * moehrendorf oct 2000 rewrite
  875. Revision 1.11 2000/10/01 19:48:23 peter
  876. * lot of compile updates for cg11
  877. Revision 1.10 2000/09/29 15:45:23 florian
  878. * make cycle fixed
  879. Revision 1.9 2000/09/28 19:49:51 florian
  880. *** empty log message ***
  881. Revision 1.8 2000/09/27 18:14:31 florian
  882. * fixed a lot of syntax errors in the n*.pas stuff
  883. Revision 1.7 2000/09/26 20:06:13 florian
  884. * hmm, still a lot of work to get things compilable
  885. Revision 1.6 2000/09/24 15:06:17 peter
  886. * use defines.inc
  887. Revision 1.5 2000/08/27 16:11:51 peter
  888. * moved some util functions from globals,cobjects to cutils
  889. * splitted files into finput,fmodule
  890. Revision 1.4 2000/08/16 18:33:53 peter
  891. * splitted namedobjectitem.next into indexnext and listnext so it
  892. can be used in both lists
  893. * don't allow "word = word" type definitions (merged)
  894. Revision 1.3 2000/08/07 11:31:04 jonas
  895. * fixed bug in type conversions between enum subranges (it didn't take
  896. the packenum directive into account)
  897. + define PACKENUMFIXED symbol in options.pas
  898. (merged from fixes branch)
  899. Revision 1.2 2000/07/13 11:32:41 michael
  900. + removed logs
  901. }