htypechk.pas 36 KB

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