htypechk.pas 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  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 : tdef;
  70. treetyp : tnodetype) : boolean;
  71. { is overloading of this operator allowed for this
  72. unary operator }
  73. function isunaryoperatoroverloadable(rd,dd : tdef;
  74. treetyp : tnodetype) : boolean;
  75. { check operator args and result type }
  76. function isoperatoracceptable(pf : tprocdef; 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 : tsym);
  83. procedure test_protected(p : tnode);
  84. function is_procsym_load(p:tnode):boolean;
  85. function is_procsym_call(p:tnode):boolean;
  86. procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
  87. {
  88. type
  89. tvarstaterequire = (vsr_can_be_undefined,vsr_must_be_valid,
  90. vsr_is_used_after,vsr_must_be_valid_and_is_used_after); }
  91. { sets varsym varstate field correctly }
  92. procedure unset_varstate(p : tnode);
  93. procedure set_varstate(p : tnode;must_be_valid : boolean);
  94. { sets the callunique flag, if the node is a vecn, }
  95. { takes care of type casts etc. }
  96. procedure set_unique(p : tnode);
  97. { sets funcret_is_valid to true, if p contains a funcref node }
  98. procedure set_funcret_is_valid(p : tnode);
  99. function valid_for_formal_var(p : tnode) : boolean;
  100. function valid_for_formal_const(p : tnode) : boolean;
  101. function valid_for_var(p:tnode):boolean;
  102. function valid_for_assignment(p:tnode):boolean;
  103. implementation
  104. uses
  105. globtype,systems,
  106. cutils,verbose,globals,
  107. symconst,symsym,symtable,
  108. types,cpubase,
  109. ncnv,nld,
  110. nmem,ncal,nmat,
  111. cgbase
  112. ;
  113. type
  114. TValidAssign=(Valid_Property,Valid_Void);
  115. TValidAssigns=set of TValidAssign;
  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 : tdef;
  120. treetyp : tnodetype) : boolean;
  121. begin
  122. isbinaryoperatoroverloadable:=
  123. (treetyp=starstarn) or
  124. (ld.deftype=recorddef) or
  125. (rd.deftype=recorddef) or
  126. (ld.deftype=variantdef) or
  127. (rd.deftype=variantdef) or
  128. ((rd.deftype=pointerdef) and
  129. not(is_pchar(rd) and
  130. (is_chararray(ld) or
  131. (ld.deftype=stringdef) or
  132. (treetyp=addn))) and
  133. (not(ld.deftype in [pointerdef,objectdef,classrefdef,procvardef]) or
  134. not (treetyp in [equaln,unequaln,gtn,gten,ltn,lten,subn])
  135. ) and
  136. (not is_integer(ld) or not (treetyp in [addn,subn]))
  137. ) or
  138. ((ld.deftype=pointerdef) and
  139. not(is_pchar(ld) and
  140. (is_chararray(rd) or
  141. (rd.deftype=stringdef) or
  142. (treetyp=addn))) and
  143. (not(rd.deftype in [stringdef,pointerdef,objectdef,classrefdef,procvardef]) and
  144. ((not is_integer(rd) and (rd.deftype<>objectdef)
  145. and (rd.deftype<>classrefdef)) or
  146. not (treetyp in [equaln,unequaln,gtn,gten,ltn,lten,addn,subn])
  147. )
  148. )
  149. ) or
  150. { array def, but not mmx or chararray+[char,string,chararray] }
  151. ((ld.deftype=arraydef) and
  152. not((cs_mmx in aktlocalswitches) and
  153. is_mmx_able_array(ld)) and
  154. not(is_chararray(ld) and
  155. (is_char(rd) or
  156. is_pchar(rd) or
  157. { char array + int = pchar + int, fix for web bug 1377 (JM) }
  158. is_integer(rd) or
  159. (rd.deftype=stringdef) or
  160. is_chararray(rd)))
  161. ) or
  162. ((rd.deftype=arraydef) and
  163. not((cs_mmx in aktlocalswitches) and
  164. is_mmx_able_array(rd)) and
  165. not(is_chararray(rd) and
  166. (is_char(ld) or
  167. is_pchar(ld) or
  168. (ld.deftype=stringdef) or
  169. is_chararray(ld)))
  170. ) or
  171. { <> and = are defined for classes }
  172. (
  173. (ld.deftype=objectdef) and
  174. not((treetyp in [equaln,unequaln]) and is_class_or_interface(ld))
  175. ) or
  176. (
  177. (rd.deftype=objectdef) and
  178. not((treetyp in [equaln,unequaln]) and is_class_or_interface(rd))
  179. )
  180. or
  181. { allow other operators that + on strings }
  182. (
  183. (is_char(rd) or
  184. is_pchar(rd) or
  185. (rd.deftype=stringdef) or
  186. is_chararray(rd) or
  187. is_char(ld) or
  188. is_pchar(ld) or
  189. (ld.deftype=stringdef) or
  190. is_chararray(ld)
  191. ) and
  192. not(treetyp in [addn,equaln,unequaln,gtn,gten,ltn,lten]) and
  193. not(is_pchar(ld) and
  194. (is_integer(rd) or (rd.deftype=pointerdef)) and
  195. (treetyp=subn)
  196. )
  197. );
  198. end;
  199. function isunaryoperatoroverloadable(rd,dd : tdef;
  200. treetyp : tnodetype) : boolean;
  201. begin
  202. isunaryoperatoroverloadable:=false;
  203. { what assignment overloading should be allowed ?? }
  204. if (treetyp=assignn) then
  205. begin
  206. isunaryoperatoroverloadable:=true;
  207. { this already get tbs0261 to fail
  208. isunaryoperatoroverloadable:=not is_equal(rd,dd); PM }
  209. end
  210. { should we force that rd and dd are equal ?? }
  211. else if (treetyp=subn { unaryminusn }) then
  212. begin
  213. isunaryoperatoroverloadable:=
  214. not is_integer(rd) and not (rd.deftype=floatdef)
  215. {$ifdef SUPPORT_MMX}
  216. and not ((cs_mmx in aktlocalswitches) and
  217. is_mmx_able_array(rd))
  218. {$endif SUPPORT_MMX}
  219. ;
  220. end
  221. else if (treetyp=notn) then
  222. begin
  223. isunaryoperatoroverloadable:=not is_integer(rd) and not is_boolean(rd)
  224. {$ifdef SUPPORT_MMX}
  225. and not ((cs_mmx in aktlocalswitches) and
  226. is_mmx_able_array(rd))
  227. {$endif SUPPORT_MMX}
  228. ;
  229. end;
  230. end;
  231. function isoperatoracceptable(pf : tprocdef; optoken : ttoken) : boolean;
  232. var
  233. ld,rd,dd : tdef;
  234. i : longint;
  235. begin
  236. case pf.parast.symindex.count of
  237. 2 : begin
  238. isoperatoracceptable:=false;
  239. for i:=1 to tok2nodes do
  240. if tok2node[i].tok=optoken then
  241. begin
  242. ld:=tvarsym(pf.parast.symindex.first).vartype.def;
  243. rd:=tvarsym(pf.parast.symindex.first.indexnext).vartype.def;
  244. dd:=pf.rettype.def;
  245. isoperatoracceptable:=
  246. tok2node[i].op_overloading_supported and
  247. isbinaryoperatoroverloadable(ld,rd,dd,tok2node[i].nod);
  248. break;
  249. end;
  250. end;
  251. 1 : begin
  252. rd:=tvarsym(pf.parast.symindex.first).vartype.def;
  253. dd:=pf.rettype.def;
  254. for i:=1 to tok2nodes do
  255. if tok2node[i].tok=optoken then
  256. begin
  257. isoperatoracceptable:=
  258. tok2node[i].op_overloading_supported and
  259. isunaryoperatoroverloadable(rd,dd,tok2node[i].nod);
  260. break;
  261. end;
  262. end;
  263. else
  264. isoperatoracceptable:=false;
  265. end;
  266. end;
  267. function isbinaryoverloaded(var t : tnode) : boolean;
  268. var
  269. rd,ld : tdef;
  270. optoken : ttoken;
  271. ht : tnode;
  272. begin
  273. isbinaryoverloaded:=false;
  274. { overloaded operator ? }
  275. { load easier access variables }
  276. rd:=tbinarynode(t).right.resulttype.def;
  277. ld:=tbinarynode(t).left.resulttype.def;
  278. if isbinaryoperatoroverloadable(ld,rd,voidtype.def,t.nodetype) then
  279. begin
  280. isbinaryoverloaded:=true;
  281. {!!!!!!!!! handle paras }
  282. case t.nodetype of
  283. addn:
  284. optoken:=_PLUS;
  285. subn:
  286. optoken:=_MINUS;
  287. muln:
  288. optoken:=_STAR;
  289. starstarn:
  290. optoken:=_STARSTAR;
  291. slashn:
  292. optoken:=_SLASH;
  293. ltn:
  294. optoken:=tokens._lt;
  295. gtn:
  296. optoken:=tokens._gt;
  297. lten:
  298. optoken:=_lte;
  299. gten:
  300. optoken:=_gte;
  301. equaln,unequaln :
  302. optoken:=_EQUAL;
  303. symdifn :
  304. optoken:=_SYMDIF;
  305. modn :
  306. optoken:=_OP_MOD;
  307. orn :
  308. optoken:=_OP_OR;
  309. xorn :
  310. optoken:=_OP_XOR;
  311. andn :
  312. optoken:=_OP_AND;
  313. divn :
  314. optoken:=_OP_DIV;
  315. shln :
  316. optoken:=_OP_SHL;
  317. shrn :
  318. optoken:=_OP_SHR;
  319. else
  320. exit;
  321. end;
  322. { the nil as symtable signs firstcalln that this is
  323. an overloaded operator }
  324. ht:=ccallnode.create(nil,overloaded_operators[optoken],nil,nil);
  325. { we have to convert p^.left and p^.right into
  326. callparanodes }
  327. if tcallnode(ht).symtableprocentry=nil then
  328. begin
  329. CGMessage(parser_e_operator_not_overloaded);
  330. ht.free;
  331. isbinaryoverloaded:=false;
  332. exit;
  333. end;
  334. inc(tcallnode(ht).symtableprocentry.refs);
  335. { we need copies, because the originals will be destroyed when we give a }
  336. { changed node back to firstpass! (JM) }
  337. if assigned(tbinarynode(t).left) then
  338. if assigned(tbinarynode(t).right) then
  339. tcallnode(ht).left :=
  340. ccallparanode.create(tbinarynode(t).right.getcopy,
  341. ccallparanode.create(tbinarynode(t).left.getcopy,nil))
  342. else
  343. tcallnode(ht).left :=
  344. ccallparanode.create(nil,
  345. ccallparanode.create(tbinarynode(t).left.getcopy,nil))
  346. else if assigned(tbinarynode(t).right) then
  347. tcallnode(ht).left :=
  348. ccallparanode.create(tbinarynode(t).right.getcopy,
  349. ccallparanode.create(nil,nil));
  350. if t.nodetype=unequaln then
  351. ht:=cnotnode.create(ht);
  352. t:=ht;
  353. end;
  354. end;
  355. {****************************************************************************
  356. Register Calculation
  357. ****************************************************************************}
  358. { marks an lvalue as "unregable" }
  359. procedure make_not_regable(p : tnode);
  360. begin
  361. case p.nodetype of
  362. typeconvn :
  363. make_not_regable(ttypeconvnode(p).left);
  364. loadn :
  365. if tloadnode(p).symtableentry.typ=varsym then
  366. tvarsym(tloadnode(p).symtableentry).varoptions:=tvarsym(tloadnode(p).symtableentry).varoptions-[vo_regable,vo_fpuregable];
  367. end;
  368. end;
  369. { calculates the needed registers for a binary operator }
  370. procedure calcregisters(p : tbinarynode;r32,fpu,mmx : word);
  371. begin
  372. p.left_right_max;
  373. { Only when the difference between the left and right registers < the
  374. wanted registers allocate the amount of registers }
  375. if assigned(p.left) then
  376. begin
  377. if assigned(p.right) then
  378. begin
  379. { the location must be already filled in because we need it to }
  380. { calculate the necessary number of registers (JM) }
  381. if p.location.loc = LOC_INVALID then
  382. internalerror(200110101);
  383. if (abs(p.left.registers32-p.right.registers32)<r32) or
  384. ((p.location.loc = LOC_FPU) and
  385. (p.right.registersfpu <= p.left.registersfpu) and
  386. ((p.right.registersfpu <> 0) or (p.left.registersfpu <> 0)) and
  387. (p.left.registers32 < p.right.registers32)) then
  388. inc(p.registers32,r32);
  389. if (abs(p.left.registersfpu-p.right.registersfpu)<fpu) then
  390. inc(p.registersfpu,fpu);
  391. {$ifdef SUPPORT_MMX}
  392. if (abs(p.left.registersmmx-p.right.registersmmx)<mmx) then
  393. inc(p.registersmmx,mmx);
  394. {$endif SUPPORT_MMX}
  395. { the following is a little bit guessing but I think }
  396. { it's the only way to solve same internalerrors: }
  397. { if the left and right node both uses registers }
  398. { and return a mem location, but the current node }
  399. { doesn't use an integer register we get probably }
  400. { trouble when restoring a node }
  401. if (p.left.registers32=p.right.registers32) and
  402. (p.registers32=p.left.registers32) and
  403. (p.registers32>0) and
  404. (p.left.location.loc in [LOC_REFERENCE,LOC_MEM]) and
  405. (p.right.location.loc in [LOC_REFERENCE,LOC_MEM]) then
  406. inc(p.registers32);
  407. end
  408. else
  409. begin
  410. if (p.left.registers32<r32) then
  411. inc(p.registers32,r32);
  412. if (p.left.registersfpu<fpu) then
  413. inc(p.registersfpu,fpu);
  414. {$ifdef SUPPORT_MMX}
  415. if (p.left.registersmmx<mmx) then
  416. inc(p.registersmmx,mmx);
  417. {$endif SUPPORT_MMX}
  418. end;
  419. end;
  420. { error CGMessage, if more than 8 floating point }
  421. { registers are needed }
  422. { if p.registersfpu>maxfpuregs then
  423. CGMessage(cg_e_too_complex_expr); now pushed if needed PM }
  424. end;
  425. {****************************************************************************
  426. Subroutine Handling
  427. ****************************************************************************}
  428. { protected field handling
  429. protected field can not appear in
  430. var parameters of function !!
  431. this can only be done after we have determined the
  432. overloaded function
  433. this is the reason why it is not in the parser, PM }
  434. procedure test_protected_sym(sym : tsym);
  435. begin
  436. if (sp_protected in sym.symoptions) and
  437. (
  438. (
  439. (sym.owner.symtabletype=globalsymtable) and
  440. (sym.owner.unitid<>0)
  441. ) or
  442. (
  443. (sym.owner.symtabletype=objectsymtable) and
  444. (tobjectdef(sym.owner.defowner).owner.symtabletype=globalsymtable) and
  445. (tobjectdef(sym.owner.defowner).owner.unitid<>0)
  446. )
  447. ) then
  448. CGMessage(parser_e_cant_access_protected_member);
  449. end;
  450. procedure test_protected(p : tnode);
  451. begin
  452. case p.nodetype of
  453. loadn : test_protected_sym(tloadnode(p).symtableentry);
  454. typeconvn : test_protected(ttypeconvnode(p).left);
  455. derefn : test_protected(tderefnode(p).left);
  456. subscriptn : begin
  457. { test_protected(p.left);
  458. Is a field of a protected var
  459. also protected ??? PM }
  460. test_protected_sym(tsubscriptnode(p).vs);
  461. end;
  462. end;
  463. end;
  464. function is_procsym_load(p:tnode):boolean;
  465. begin
  466. is_procsym_load:=((p.nodetype=loadn) and (tloadnode(p).symtableentry.typ=procsym)) or
  467. ((p.nodetype=addrn) and (taddrnode(p).left.nodetype=loadn)
  468. and (tloadnode(taddrnode(p).left).symtableentry.typ=procsym)) ;
  469. end;
  470. { change a proc call to a procload for assignment to a procvar }
  471. { this can only happen for proc/function without arguments }
  472. function is_procsym_call(p:tnode):boolean;
  473. begin
  474. is_procsym_call:=(p.nodetype=calln) and (tcallnode(p).left=nil) and
  475. (((tcallnode(p).symtableprocentry.typ=procsym) and (tcallnode(p).right=nil)) or
  476. (assigned(tcallnode(p).right) and (tcallnode(tcallnode(p).right).symtableprocentry.typ=varsym)));
  477. end;
  478. { local routines can't be assigned to procvars }
  479. procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
  480. begin
  481. if (from_def.symtablelevel>1) and (to_def.deftype=procvardef) then
  482. CGMessage(type_e_cannot_local_proc_to_procvar);
  483. end;
  484. procedure set_varstate(p : tnode;must_be_valid : boolean);
  485. var
  486. hsym : tvarsym;
  487. begin
  488. while assigned(p) do
  489. begin
  490. if (nf_varstateset in p.flags) then
  491. exit;
  492. include(p.flags,nf_varstateset);
  493. case p.nodetype of
  494. typeconvn :
  495. begin
  496. case ttypeconvnode(p).convtype of
  497. tc_cchar_2_pchar,
  498. tc_cstring_2_pchar,
  499. tc_array_2_pointer :
  500. must_be_valid:=false;
  501. tc_pchar_2_string,
  502. tc_pointer_2_array :
  503. must_be_valid:=true;
  504. end;
  505. p:=tunarynode(p).left;
  506. end;
  507. subscriptn :
  508. p:=tunarynode(p).left;
  509. vecn:
  510. begin
  511. set_varstate(tbinarynode(p).right,true);
  512. if not(tunarynode(p).left.resulttype.def.deftype in [stringdef,arraydef]) then
  513. must_be_valid:=true;
  514. p:=tunarynode(p).left;
  515. end;
  516. { do not parse calln }
  517. calln :
  518. break;
  519. callparan :
  520. begin
  521. set_varstate(tbinarynode(p).right,must_be_valid);
  522. p:=tunarynode(p).left;
  523. end;
  524. loadn :
  525. begin
  526. if (tloadnode(p).symtableentry.typ=varsym) then
  527. begin
  528. hsym:=tvarsym(tloadnode(p).symtableentry);
  529. if must_be_valid and (nf_first in p.flags) then
  530. begin
  531. if (hsym.varstate=vs_declared_and_first_found) or
  532. (hsym.varstate=vs_set_but_first_not_passed) then
  533. begin
  534. if (assigned(hsym.owner) and
  535. assigned(aktprocsym) and
  536. (hsym.owner = aktprocdef.localst)) then
  537. begin
  538. if tloadnode(p).symtable.symtabletype=localsymtable then
  539. CGMessage1(sym_n_uninitialized_local_variable,hsym.realname)
  540. else
  541. CGMessage1(sym_n_uninitialized_variable,hsym.realname);
  542. end;
  543. end;
  544. end;
  545. if (nf_first in p.flags) then
  546. begin
  547. if hsym.varstate=vs_declared_and_first_found then
  548. begin
  549. { this can only happen at left of an assignment, no ? PM }
  550. if (parsing_para_level=0) and not must_be_valid then
  551. hsym.varstate:=vs_assigned
  552. else
  553. hsym.varstate:=vs_used;
  554. end
  555. else
  556. if hsym.varstate=vs_set_but_first_not_passed then
  557. hsym.varstate:=vs_used;
  558. exclude(p.flags,nf_first);
  559. end
  560. else
  561. begin
  562. if (hsym.varstate=vs_assigned) and
  563. (must_be_valid or (parsing_para_level>0) or
  564. (p.resulttype.def.deftype=procvardef)) then
  565. hsym.varstate:=vs_used;
  566. if (hsym.varstate=vs_declared_and_first_found) and
  567. (must_be_valid or (parsing_para_level>0) or
  568. (p.resulttype.def.deftype=procvardef)) then
  569. hsym.varstate:=vs_set_but_first_not_passed;
  570. end;
  571. end;
  572. break;
  573. end;
  574. funcretn:
  575. begin
  576. { no claim if setting higher return value_str }
  577. if must_be_valid and
  578. (lexlevel=tfuncretnode(p).funcretsym.owner.symtablelevel) and
  579. ((tfuncretnode(p).funcretsym.funcretstate=vs_declared) or
  580. ((nf_is_first_funcret in p.flags) and
  581. (tfuncretnode(p).funcretsym.funcretstate=vs_declared_and_first_found))) then
  582. begin
  583. CGMessage(sym_w_function_result_not_set);
  584. { avoid multiple warnings }
  585. tfuncretnode(p).funcretsym.funcretstate:=vs_assigned;
  586. end;
  587. if (nf_is_first_funcret in p.flags) and not must_be_valid then
  588. tfuncretnode(p).funcretsym.funcretstate:=vs_assigned;
  589. break;
  590. end;
  591. else
  592. break;
  593. end;{case }
  594. end;
  595. end;
  596. procedure unset_varstate(p : tnode);
  597. begin
  598. while assigned(p) do
  599. begin
  600. exclude(p.flags,nf_varstateset);
  601. case p.nodetype of
  602. typeconvn,
  603. subscriptn,
  604. vecn :
  605. p:=tunarynode(p).left;
  606. else
  607. break;
  608. end;
  609. end;
  610. end;
  611. procedure set_unique(p : tnode);
  612. begin
  613. while assigned(p) do
  614. begin
  615. case p.nodetype of
  616. vecn:
  617. begin
  618. include(p.flags,nf_callunique);
  619. break;
  620. end;
  621. typeconvn,
  622. subscriptn,
  623. derefn:
  624. p:=tunarynode(p).left;
  625. else
  626. break;
  627. end;
  628. end;
  629. end;
  630. procedure set_funcret_is_valid(p:tnode);
  631. begin
  632. while assigned(p) do
  633. begin
  634. case p.nodetype of
  635. funcretn:
  636. begin
  637. if (nf_is_first_funcret in p.flags) then
  638. tfuncretnode(p).funcretsym.funcretstate:=vs_assigned;
  639. break;
  640. end;
  641. vecn,
  642. {derefn,}
  643. typeconvn,
  644. subscriptn:
  645. p:=tunarynode(p).left;
  646. else
  647. break;
  648. end;
  649. end;
  650. end;
  651. function valid_for_assign(p:tnode;opts:TValidAssigns):boolean;
  652. var
  653. hp : tnode;
  654. gotwith,
  655. gotsubscript,
  656. gotpointer,
  657. gotclass,
  658. gotderef : boolean;
  659. fromdef,
  660. todef : tdef;
  661. begin
  662. valid_for_assign:=false;
  663. gotsubscript:=false;
  664. gotderef:=false;
  665. gotclass:=false;
  666. gotpointer:=false;
  667. gotwith:=false;
  668. hp:=p;
  669. if not(valid_void in opts) and
  670. is_void(hp.resulttype.def) then
  671. begin
  672. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  673. exit;
  674. end;
  675. while assigned(hp) do
  676. begin
  677. { property allowed? calln has a property check itself }
  678. if (nf_isproperty in hp.flags) then
  679. begin
  680. if (valid_property in opts) then
  681. valid_for_assign:=true
  682. else
  683. begin
  684. { check return type }
  685. case hp.resulttype.def.deftype of
  686. pointerdef :
  687. gotpointer:=true;
  688. objectdef :
  689. gotclass:=is_class_or_interface(hp.resulttype.def);
  690. recorddef, { handle record like class it needs a subscription }
  691. classrefdef :
  692. gotclass:=true;
  693. end;
  694. { 1. if it returns a pointer and we've found a deref,
  695. 2. if it returns a class or record and a subscription or with is found }
  696. if (gotpointer and gotderef) or
  697. (gotclass and (gotsubscript or gotwith)) then
  698. valid_for_assign:=true
  699. else
  700. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  701. end;
  702. exit;
  703. end;
  704. case hp.nodetype of
  705. temprefn :
  706. begin
  707. valid_for_assign := true;
  708. exit;
  709. end;
  710. derefn :
  711. begin
  712. gotderef:=true;
  713. hp:=tderefnode(hp).left;
  714. end;
  715. typeconvn :
  716. begin
  717. { typecast sizes must match, exceptions:
  718. - from formaldef
  719. - from void
  720. - typecast from pointer to array }
  721. fromdef:=ttypeconvnode(hp).left.resulttype.def;
  722. todef:=hp.resulttype.def;
  723. if not((fromdef.deftype=formaldef) or
  724. is_void(fromdef) or
  725. ((fromdef.deftype=pointerdef) and (todef.deftype=arraydef)) or
  726. ((fromdef.deftype = objectdef) and (todef.deftype = objectdef) and
  727. (tobjectdef(fromdef).is_related(tobjectdef(todef))))) and
  728. (fromdef.size<>todef.size) then
  729. begin
  730. { in TP it is allowed to typecast to smaller types }
  731. if not(m_tp7 in aktmodeswitches) or
  732. (todef.size>fromdef.size) then
  733. CGMessagePos2(hp.fileinfo,type_e_typecast_wrong_size_for_assignment,tostr(fromdef.size),tostr(todef.size));
  734. end;
  735. case hp.resulttype.def.deftype of
  736. pointerdef :
  737. gotpointer:=true;
  738. objectdef :
  739. gotclass:=is_class_or_interface(hp.resulttype.def);
  740. classrefdef :
  741. gotclass:=true;
  742. arraydef :
  743. begin
  744. { pointer -> array conversion is done then we need to see it
  745. as a deref, because a ^ is then not required anymore }
  746. if (ttypeconvnode(hp).left.resulttype.def.deftype=pointerdef) then
  747. gotderef:=true;
  748. end;
  749. end;
  750. hp:=ttypeconvnode(hp).left;
  751. end;
  752. vecn,
  753. asn :
  754. hp:=tunarynode(hp).left;
  755. subscriptn :
  756. begin
  757. gotsubscript:=true;
  758. { a class/interface access is an implicit }
  759. { dereferencing }
  760. hp:=tsubscriptnode(hp).left;
  761. if is_class_or_interface(hp.resulttype.def) then
  762. gotderef:=true;
  763. end;
  764. subn,
  765. addn :
  766. begin
  767. { Allow add/sub operators on a pointer, or an integer
  768. and a pointer typecast and deref has been found }
  769. if (hp.resulttype.def.deftype=pointerdef) or
  770. (is_integer(hp.resulttype.def) and gotpointer and gotderef) then
  771. valid_for_assign:=true
  772. else
  773. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  774. exit;
  775. end;
  776. addrn :
  777. begin
  778. if gotderef or
  779. (nf_procvarload in hp.flags) then
  780. valid_for_assign:=true
  781. else
  782. CGMessagePos(hp.fileinfo,type_e_no_assign_to_addr);
  783. exit;
  784. end;
  785. selfn,
  786. funcretn :
  787. begin
  788. valid_for_assign:=true;
  789. exit;
  790. end;
  791. calln :
  792. begin
  793. { check return type }
  794. case hp.resulttype.def.deftype of
  795. pointerdef :
  796. gotpointer:=true;
  797. objectdef :
  798. gotclass:=is_class_or_interface(hp.resulttype.def);
  799. recorddef, { handle record like class it needs a subscription }
  800. classrefdef :
  801. gotclass:=true;
  802. end;
  803. { 1. if it returns a pointer and we've found a deref,
  804. 2. if it returns a class or record and a subscription or with is found }
  805. if (gotpointer and gotderef) or
  806. (gotclass and (gotsubscript or gotwith)) then
  807. valid_for_assign:=true
  808. else
  809. CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
  810. exit;
  811. end;
  812. loadn :
  813. begin
  814. case tloadnode(hp).symtableentry.typ of
  815. absolutesym,
  816. varsym :
  817. begin
  818. if (tvarsym(tloadnode(hp).symtableentry).varspez=vs_const) then
  819. begin
  820. { allow p^:= constructions with p is const parameter }
  821. if gotderef then
  822. valid_for_assign:=true
  823. else
  824. CGMessagePos(tloadnode(hp).fileinfo,type_e_no_assign_to_const);
  825. exit;
  826. end;
  827. { Are we at a with symtable, then we need to process the
  828. withrefnode also to check for maybe a const load }
  829. if (tloadnode(hp).symtable.symtabletype=withsymtable) then
  830. begin
  831. { continue with processing the withref node }
  832. hp:=tnode(twithsymtable(tloadnode(hp).symtable).withrefnode);
  833. gotwith:=true;
  834. end
  835. else
  836. begin
  837. { set the assigned flag for varsyms }
  838. if (tvarsym(tloadnode(hp).symtableentry).varstate=vs_declared) then
  839. tvarsym(tloadnode(hp).symtableentry).varstate:=vs_assigned;
  840. valid_for_assign:=true;
  841. exit;
  842. end;
  843. end;
  844. funcretsym :
  845. begin
  846. valid_for_assign:=true;
  847. exit;
  848. end;
  849. typedconstsym :
  850. begin
  851. if ttypedconstsym(tloadnode(hp).symtableentry).is_writable then
  852. valid_for_assign:=true
  853. else
  854. CGMessagePos(hp.fileinfo,type_e_no_assign_to_const);
  855. exit;
  856. end;
  857. else
  858. begin
  859. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  860. exit;
  861. end;
  862. end;
  863. end;
  864. else
  865. begin
  866. CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
  867. exit;
  868. end;
  869. end;
  870. end;
  871. end;
  872. function valid_for_var(p:tnode):boolean;
  873. begin
  874. valid_for_var:=valid_for_assign(p,[]);
  875. end;
  876. function valid_for_formal_var(p : tnode) : boolean;
  877. begin
  878. valid_for_formal_var:=valid_for_assign(p,[valid_void]);
  879. end;
  880. function valid_for_formal_const(p : tnode) : boolean;
  881. var
  882. v : boolean;
  883. begin
  884. { p must have been firstpass'd before }
  885. { accept about anything but not a statement ! }
  886. case p.nodetype of
  887. calln,
  888. statementn,
  889. addrn :
  890. begin
  891. { addrn is not allowed as this generate a constant value,
  892. but a tp procvar are allowed (PFV) }
  893. if nf_procvarload in p.flags then
  894. v:=true
  895. else
  896. v:=false;
  897. end;
  898. else
  899. v:=true;
  900. end;
  901. valid_for_formal_const:=v;
  902. end;
  903. function valid_for_assignment(p:tnode):boolean;
  904. begin
  905. valid_for_assignment:=valid_for_assign(p,[valid_property]);
  906. end;
  907. end.
  908. {
  909. $Log$
  910. Revision 1.39 2001-11-08 21:55:36 marco
  911. * Fix from Peter. Fixes a hang when ptop's upperstr procedure is converted
  912. to ansistrings
  913. Revision 1.38 2001/11/02 22:58:01 peter
  914. * procsym definition rewrite
  915. Revision 1.37 2001/10/20 20:30:21 peter
  916. * read only typed const support, switch $J-
  917. Revision 1.36 2001/10/12 13:51:51 jonas
  918. * fixed internalerror(10) due to previous fpu overflow fixes ("merged")
  919. * fixed bug in n386add (introduced after compilerproc changes for string
  920. operations) where calcregisters wasn't called for shortstring addnodes
  921. * NOTE: from now on, the location of a binary node must now always be set
  922. before you call calcregisters() for it
  923. Revision 1.35 2001/09/17 21:29:11 peter
  924. * merged netbsd, fpu-overflow from fixes branch
  925. Revision 1.34 2001/09/07 07:46:17 jonas
  926. * allow typecasting from child object types to parent object types (with
  927. different sizes)
  928. Revision 1.33 2001/09/02 21:13:31 peter
  929. * check for size differences in typecasts when assigning
  930. Revision 1.32 2001/08/26 13:36:37 florian
  931. * some cg reorganisation
  932. * some PPC updates
  933. Revision 1.31 2001/08/23 14:28:35 jonas
  934. + tempcreate/ref/delete nodes (allows the use of temps in the
  935. resulttype and first pass)
  936. * made handling of read(ln)/write(ln) processor independent
  937. * moved processor independent handling for str and reset/rewrite-typed
  938. from firstpass to resulttype pass
  939. * changed names of helpers in text.inc to be generic for use as
  940. compilerprocs + added "iocheck" directive for most of them
  941. * reading of ordinals is done by procedures instead of functions
  942. because otherwise FPC_IOCHECK overwrote the result before it could
  943. be stored elsewhere (range checking still works)
  944. * compilerprocs can now be used in the system unit before they are
  945. implemented
  946. * added note to errore.msg that booleans can't be read using read/readln
  947. Revision 1.30 2001/08/06 21:40:46 peter
  948. * funcret moved from tprocinfo to tprocdef
  949. Revision 1.29 2001/06/04 18:04:36 peter
  950. * fixes to valid_for_assign for properties
  951. Revision 1.28 2001/06/04 11:48:02 peter
  952. * better const to var checking
  953. Revision 1.27 2001/05/18 22:57:08 peter
  954. * replace constant by cpu dependent value (merged)
  955. Revision 1.26 2001/05/08 08:52:05 jonas
  956. * fix from Peter to avoid excessive number of warnings
  957. Revision 1.25 2001/04/22 22:46:49 florian
  958. * more variant support
  959. Revision 1.24 2001/04/13 01:22:08 peter
  960. * symtable change to classes
  961. * range check generation and errors fixed, make cycle DEBUG=1 works
  962. * memory leaks fixed
  963. Revision 1.23 2001/04/02 21:20:29 peter
  964. * resulttype rewrite
  965. Revision 1.22 2001/02/20 21:46:26 peter
  966. * don't allow assign to void type (merged)
  967. Revision 1.21 2001/02/04 11:12:17 jonas
  968. * fixed web bug 1377 & const pointer arithmtic
  969. Revision 1.20 2000/12/09 13:04:05 florian
  970. * web bug 1207 fixed: field and properties of const classes can be
  971. changed
  972. Revision 1.19 2000/11/29 00:30:31 florian
  973. * unused units removed from uses clause
  974. * some changes for widestrings
  975. Revision 1.18 2000/11/28 17:14:33 jonas
  976. * fixed crash when trying to use an overloaded operator which is nowhere
  977. defined
  978. Revision 1.17 2000/11/28 14:04:03 jonas
  979. * fixed operator overloading problems
  980. Revision 1.16 2000/11/13 11:30:54 florian
  981. * some bugs with interfaces and NIL fixed
  982. Revision 1.15 2000/11/12 22:20:37 peter
  983. * create generic toutputsection for binary writers
  984. Revision 1.14 2000/11/04 14:25:19 florian
  985. + merged Attila's changes for interfaces, not tested yet
  986. Revision 1.13 2000/10/31 22:02:47 peter
  987. * symtable splitted, no real code changes
  988. Revision 1.12 2000/10/14 10:14:47 peter
  989. * moehrendorf oct 2000 rewrite
  990. Revision 1.11 2000/10/01 19:48:23 peter
  991. * lot of compile updates for cg11
  992. Revision 1.10 2000/09/29 15:45:23 florian
  993. * make cycle fixed
  994. Revision 1.9 2000/09/28 19:49:51 florian
  995. *** empty log message ***
  996. Revision 1.8 2000/09/27 18:14:31 florian
  997. * fixed a lot of syntax errors in the n*.pas stuff
  998. Revision 1.7 2000/09/26 20:06:13 florian
  999. * hmm, still a lot of work to get things compilable
  1000. Revision 1.6 2000/09/24 15:06:17 peter
  1001. * use defines.inc
  1002. Revision 1.5 2000/08/27 16:11:51 peter
  1003. * moved some util functions from globals,cobjects to cutils
  1004. * splitted files into finput,fmodule
  1005. Revision 1.4 2000/08/16 18:33:53 peter
  1006. * splitted namedobjectitem.next into indexnext and listnext so it
  1007. can be used in both lists
  1008. * don't allow "word = word" type definitions (merged)
  1009. Revision 1.3 2000/08/07 11:31:04 jonas
  1010. * fixed bug in type conversions between enum subranges (it didn't take
  1011. the packenum directive into account)
  1012. + define PACKENUMFIXED symbol in options.pas
  1013. (merged from fixes branch)
  1014. Revision 1.2 2000/07/13 11:32:41 michael
  1015. + removed logs
  1016. }