htypechk.pas 34 KB

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