htypechk.pas 34 KB

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