pdecsub.pas 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203
  1. {
  2. $Id$
  3. Copyright (c) 1998-2001 by Florian Klaempfl, Daniel Mantione
  4. Does the parsing of the procedures/functions
  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 pdecsub;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. tokens,symconst,symtype,symdef,symsym;
  23. const
  24. pd_global = $1; { directive must be global }
  25. pd_body = $2; { directive needs a body }
  26. pd_implemen = $4; { directive can be used implementation section }
  27. pd_interface = $8; { directive can be used interface section }
  28. pd_object = $10; { directive can be used object declaration }
  29. pd_procvar = $20; { directive can be used procvar declaration }
  30. pd_notobject = $40; { directive can not be used object declaration }
  31. pd_notobjintf= $80; { directive can not be used interface declaration }
  32. function is_proc_directive(tok:ttoken):boolean;
  33. procedure parameter_dec(aktprocdef:tabstractprocdef);
  34. procedure parse_proc_directives(var pdflags:word);
  35. procedure handle_calling_convention(sym:tprocsym;def:tabstractprocdef);
  36. procedure parse_proc_head(options:tproctypeoption);
  37. procedure parse_proc_dec;
  38. procedure parse_var_proc_directives(var sym : tsym);
  39. procedure parse_object_proc_directives(var sym : tprocsym);
  40. function proc_add_definition(aprocsym:tprocsym;var aprocdef : tprocdef) : boolean;
  41. implementation
  42. uses
  43. {$ifdef delphi}
  44. sysutils,
  45. {$else delphi}
  46. strings,
  47. {$endif delphi}
  48. { common }
  49. cutils,cclasses,
  50. { global }
  51. globtype,globals,verbose,
  52. systems,
  53. { aasm }
  54. aasm,
  55. { symtable }
  56. symbase,symtable,types,
  57. { pass 1 }
  58. node,htypechk,
  59. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
  60. { parser }
  61. fmodule,scanner,
  62. pbase,pexpr,ptype,pdecl,
  63. { linking }
  64. import,gendef,
  65. { codegen }
  66. cgbase
  67. ;
  68. procedure resetvaluepara(p:tnamedindexitem);
  69. begin
  70. if tsym(p).typ=varsym then
  71. with tvarsym(p) do
  72. if copy(name,1,3)='val' then
  73. aktprocdef.parast.symsearch.rename(name,copy(name,4,length(name)));
  74. end;
  75. procedure parameter_dec(aktprocdef:tabstractprocdef);
  76. {
  77. handle_procvar needs the same changes
  78. }
  79. var
  80. is_procvar : boolean;
  81. sc : tidstringlist;
  82. s : string;
  83. hpos,
  84. storetokenpos : tfileposinfo;
  85. htype,
  86. tt : ttype;
  87. hvs,
  88. vs : tvarsym;
  89. srsym : tsym;
  90. hs1,hs2 : string;
  91. varspez : Tvarspez;
  92. inserthigh : boolean;
  93. tdefaultvalue : tconstsym;
  94. defaultrequired : boolean;
  95. begin
  96. { reset }
  97. defaultrequired:=false;
  98. { parsing a proc or procvar ? }
  99. is_procvar:=(aktprocdef.deftype=procvardef);
  100. if not is_procvar then
  101. hs2:=tprocdef(aktprocdef).mangledname;
  102. consume(_LKLAMMER);
  103. { Delphi/Kylix supports nonsense like }
  104. { procedure p(); }
  105. if try_to_consume(_RKLAMMER) and
  106. not(m_tp7 in aktmodeswitches) then
  107. exit;
  108. inc(testcurobject);
  109. repeat
  110. if try_to_consume(_VAR) then
  111. varspez:=vs_var
  112. else
  113. if try_to_consume(_CONST) then
  114. varspez:=vs_const
  115. else
  116. if (idtoken=_OUT) and (m_out in aktmodeswitches) then
  117. begin
  118. consume(_OUT);
  119. varspez:=vs_out
  120. end
  121. else
  122. varspez:=vs_value;
  123. inserthigh:=false;
  124. tdefaultvalue:=nil;
  125. tt.reset;
  126. { self is only allowed in procvars and class methods }
  127. if (idtoken=_SELF) and
  128. (is_procvar or
  129. (assigned(procinfo^._class) and is_class(procinfo^._class))) then
  130. begin
  131. if varspez <> vs_value then
  132. CGMessage(parser_e_self_call_by_value);
  133. if not is_procvar then
  134. begin
  135. {$ifndef UseNiceNames}
  136. hs2:=hs2+'$'+'self';
  137. {$else UseNiceNames}
  138. hs2:=hs2+tostr(length('self'))+'self';
  139. {$endif UseNiceNames}
  140. htype.setdef(procinfo^._class);
  141. vs:=tvarsym.create('@',htype);
  142. vs.varspez:=vs_var;
  143. { insert the sym in the parasymtable }
  144. tprocdef(aktprocdef).parast.insert(vs);
  145. inc(procinfo^.selfpointer_offset,vs.address);
  146. end
  147. else
  148. vs:=nil;
  149. { must also be included for procvars to allow the proc2procvar }
  150. { type conversions (po_containsself is in po_comp) (JM) }
  151. include(aktprocdef.procoptions,po_containsself);
  152. consume(idtoken);
  153. consume(_COLON);
  154. single_type(tt,hs1,false);
  155. { this must be call-by-value, but we generate already an }
  156. { an error above if that's not the case (JM) }
  157. aktprocdef.concatpara(tt,vs,varspez,nil);
  158. { check the types for procedures only }
  159. if not is_procvar then
  160. CheckTypes(tt.def,procinfo^._class);
  161. end
  162. else
  163. begin
  164. { read identifiers }
  165. sc:=consume_idlist;
  166. {$ifdef fixLeaksOnError}
  167. strContStack.push(sc);
  168. {$endif fixLeaksOnError}
  169. { read type declaration, force reading for value and const paras }
  170. if (token=_COLON) or (varspez=vs_value) then
  171. begin
  172. consume(_COLON);
  173. { check for an open array }
  174. if token=_ARRAY then
  175. begin
  176. consume(_ARRAY);
  177. consume(_OF);
  178. { define range and type of range }
  179. tt.setdef(tarraydef.create(0,-1,s32bittype));
  180. { array of const ? }
  181. if (token=_CONST) and (m_objpas in aktmodeswitches) then
  182. begin
  183. consume(_CONST);
  184. srsym:=searchsymonlyin(systemunit,'TVARREC');
  185. if not assigned(srsym) then
  186. InternalError(1234124);
  187. tarraydef(tt.def).elementtype:=ttypesym(srsym).restype;
  188. tarraydef(tt.def).IsArrayOfConst:=true;
  189. hs1:='array_of_const';
  190. end
  191. else
  192. begin
  193. { define field type }
  194. single_type(tarraydef(tt.def).elementtype,hs1,false);
  195. hs1:='array_of_'+hs1;
  196. end;
  197. inserthigh:=true;
  198. end
  199. else
  200. begin
  201. { open string ? }
  202. if (varspez=vs_var) and
  203. (
  204. (
  205. ((token=_STRING) or (idtoken=_SHORTSTRING)) and
  206. (cs_openstring in aktmoduleswitches) and
  207. not(cs_ansistrings in aktlocalswitches)
  208. ) or
  209. (idtoken=_OPENSTRING)) then
  210. begin
  211. consume(token);
  212. tt:=openshortstringtype;
  213. hs1:='openstring';
  214. inserthigh:=true;
  215. end
  216. else
  217. begin
  218. { everything else }
  219. single_type(tt,hs1,false);
  220. end;
  221. { default parameter }
  222. if (m_default_para in aktmodeswitches) then
  223. begin
  224. if try_to_consume(_EQUAL) then
  225. begin
  226. s:=sc.get(hpos);
  227. if not sc.empty then
  228. Comment(V_Error,'default value only allowed for one parameter');
  229. sc.add(s,hpos);
  230. { prefix 'def' to the parameter name }
  231. tdefaultvalue:=ReadConstant('$def'+Upper(s),hpos);
  232. if assigned(tdefaultvalue) then
  233. tprocdef(aktprocdef).parast.insert(tdefaultvalue);
  234. defaultrequired:=true;
  235. end
  236. else
  237. begin
  238. if defaultrequired then
  239. Comment(V_Error,'default parameter required');
  240. end;
  241. end;
  242. end;
  243. end
  244. else
  245. begin
  246. {$ifndef UseNiceNames}
  247. hs1:='$$$';
  248. {$else UseNiceNames}
  249. hs1:='var';
  250. {$endif UseNiceNames}
  251. tt:=cformaltype;
  252. end;
  253. storetokenpos:=akttokenpos;
  254. while not sc.empty do
  255. begin
  256. s:=sc.get(akttokenpos);
  257. { For proc vars we only need the definitions }
  258. if not is_procvar then
  259. begin
  260. {$ifndef UseNiceNames}
  261. hs2:=hs2+'$'+hs1;
  262. {$else UseNiceNames}
  263. hs2:=hs2+tostr(length(hs1))+hs1;
  264. {$endif UseNiceNames}
  265. vs:=tvarsym.create(s,tt);
  266. vs.varspez:=varspez;
  267. { we have to add this to avoid var param to be in registers !!!}
  268. { I don't understand the comment above, }
  269. { but I suppose the comment is wrong and }
  270. { it means that the address of var parameters can be placed }
  271. { in a register (FK) }
  272. if (varspez in [vs_var,vs_const,vs_out]) and push_addr_param(tt.def) then
  273. include(vs.varoptions,vo_regable);
  274. { insert the sym in the parasymtable }
  275. tprocdef(aktprocdef).parast.insert(vs);
  276. { do we need a local copy? Then rename the varsym, do this after the
  277. insert so the dup id checking is done correctly }
  278. if (varspez=vs_value) and
  279. push_addr_param(tt.def) and
  280. not(is_open_array(tt.def) or is_array_of_const(tt.def)) then
  281. tprocdef(aktprocdef).parast.rename(vs.name,'val'+vs.name);
  282. { also need to push a high value? }
  283. if inserthigh then
  284. begin
  285. hvs:=tvarsym.create('$high'+Upper(s),s32bittype);
  286. hvs.varspez:=vs_const;
  287. tprocdef(aktprocdef).parast.insert(hvs);
  288. end;
  289. end
  290. else
  291. vs:=nil;
  292. aktprocdef.concatpara(tt,vs,varspez,tdefaultvalue);
  293. end;
  294. {$ifdef fixLeaksOnError}
  295. if PStringContainer(strContStack.pop) <> sc then
  296. writeln('problem with strContStack in pdecl (1)');
  297. {$endif fixLeaksOnError}
  298. sc.free;
  299. akttokenpos:=storetokenpos;
  300. end;
  301. { set the new mangled name }
  302. until not try_to_consume(_SEMICOLON);
  303. if not is_procvar then
  304. tprocdef(aktprocdef).setmangledname(hs2);
  305. dec(testcurobject);
  306. consume(_RKLAMMER);
  307. end;
  308. procedure parse_proc_head(options:tproctypeoption);
  309. var
  310. orgsp,sp:stringid;
  311. paramoffset:longint;
  312. sym:tsym;
  313. hs:string;
  314. doinsert : boolean;
  315. st : tsymtable;
  316. srsymtable : tsymtable;
  317. pdl : pprocdeflist;
  318. overloaded_level:word;
  319. storepos,procstartfilepos : tfileposinfo;
  320. i: longint;
  321. procdefs : pprocdeflist;
  322. begin
  323. { Save the position where this procedure really starts }
  324. procstartfilepos:=akttokenpos;
  325. aktprocdef:=nil;
  326. if (options=potype_operator) then
  327. begin
  328. sp:=overloaded_names[optoken];
  329. orgsp:=sp;
  330. end
  331. else
  332. begin
  333. sp:=pattern;
  334. orgsp:=orgpattern;
  335. consume(_ID);
  336. end;
  337. { examine interface map: function/procedure iname.functionname=locfuncname }
  338. if parse_only and
  339. assigned(procinfo^._class) and
  340. assigned(procinfo^._class.implementedinterfaces) and
  341. (procinfo^._class.implementedinterfaces.count>0) and
  342. try_to_consume(_POINT) then
  343. begin
  344. storepos:=akttokenpos;
  345. akttokenpos:=procstartfilepos;
  346. { get interface syms}
  347. searchsym(sp,sym,srsymtable);
  348. if not assigned(sym) then
  349. begin
  350. identifier_not_found(orgsp);
  351. sym:=generrorsym;
  352. end;
  353. akttokenpos:=storepos;
  354. { load proc name }
  355. if sym.typ=typesym then
  356. i:=procinfo^._class.implementedinterfaces.searchintf(ttypesym(sym).restype.def);
  357. { qualifier is interface name? }
  358. if (sym.typ<>typesym) or (ttypesym(sym).restype.def.deftype<>objectdef) or
  359. (i=-1) then
  360. begin
  361. Message(parser_e_interface_id_expected);
  362. aktprocsym:=nil;
  363. end
  364. else
  365. begin
  366. aktprocsym:=tprocsym(procinfo^._class.implementedinterfaces.interfaces(i).symtable.search(sp));
  367. { the method can be declared after the mapping FK
  368. if not(assigned(aktprocsym)) then
  369. Message(parser_e_methode_id_expected);
  370. }
  371. end;
  372. consume(_ID);
  373. consume(_EQUAL);
  374. if (token=_ID) { and assigned(aktprocsym) } then
  375. procinfo^._class.implementedinterfaces.addmappings(i,sp,pattern);
  376. consume(_ID);
  377. exit;
  378. end;
  379. { method ? }
  380. if not(parse_only) and
  381. (lexlevel=normal_function_level) and
  382. try_to_consume(_POINT) then
  383. begin
  384. { search for object name }
  385. storepos:=akttokenpos;
  386. akttokenpos:=procstartfilepos;
  387. searchsym(sp,sym,srsymtable);
  388. if not assigned(sym) then
  389. begin
  390. identifier_not_found(orgsp);
  391. sym:=generrorsym;
  392. end;
  393. akttokenpos:=storepos;
  394. { consume proc name }
  395. sp:=pattern;
  396. orgsp:=orgpattern;
  397. procstartfilepos:=akttokenpos;
  398. consume(_ID);
  399. { qualifier is class name ? }
  400. if (sym.typ<>typesym) or
  401. (ttypesym(sym).restype.def.deftype<>objectdef) then
  402. begin
  403. Message(parser_e_class_id_expected);
  404. aktprocsym:=nil;
  405. aktprocdef:=nil;
  406. end
  407. else
  408. begin
  409. { used to allow private syms to be seen }
  410. aktobjectdef:=tobjectdef(ttypesym(sym).restype.def);
  411. procinfo^._class:=tobjectdef(ttypesym(sym).restype.def);
  412. aktprocsym:=tprocsym(procinfo^._class.symtable.search(sp));
  413. {The procedure has been found. So it is
  414. a global one. Set the flags to mark this.}
  415. procinfo^.flags:=procinfo^.flags or pi_is_global;
  416. aktobjectdef:=nil;
  417. { we solve this below }
  418. if not(assigned(aktprocsym)) then
  419. Message(parser_e_methode_id_expected);
  420. end;
  421. end
  422. else
  423. begin
  424. { check for constructor/destructor which is not allowed here }
  425. if (not parse_only) and
  426. (options in [potype_constructor,potype_destructor]) then
  427. Message(parser_e_constructors_always_objects);
  428. akttokenpos:=procstartfilepos;
  429. aktprocsym:=tprocsym(symtablestack.search(sp));
  430. if not(parse_only) then
  431. begin
  432. {The procedure we prepare for is in the implementation
  433. part of the unit we compile. It is also possible that we
  434. are compiling a program, which is also some kind of
  435. implementaion part.
  436. We need to find out if the procedure is global. If it is
  437. global, it is in the global symtable.}
  438. if not assigned(aktprocsym) and
  439. (symtablestack.symtabletype=staticsymtable) and
  440. assigned(symtablestack.next) and
  441. (symtablestack.next.unitid=0) then
  442. begin
  443. {Search the procedure in the global symtable.}
  444. aktprocsym:=tprocsym(symtablestack.next.search(sp));
  445. if assigned(aktprocsym) then
  446. begin
  447. {Check if it is a procedure.}
  448. if aktprocsym.typ<>procsym then
  449. DuplicateSym(aktprocsym);
  450. {The procedure has been found. So it is
  451. a global one. Set the flags to mark this.}
  452. procinfo^.flags:=procinfo^.flags or pi_is_global;
  453. end;
  454. end;
  455. end;
  456. end;
  457. { Create the mangledname }
  458. {$ifndef UseNiceNames}
  459. if assigned(procinfo^._class) then
  460. begin
  461. if (pos('_$$_',procprefix)=0) then
  462. hs:=procprefix+'_$$_'+upper(procinfo^._class.objname^)+'_$$_'+sp
  463. else
  464. hs:=procprefix+'_$'+sp;
  465. end
  466. else
  467. begin
  468. if lexlevel=normal_function_level then
  469. hs:=procprefix+'_'+sp
  470. else
  471. hs:=procprefix+'_$'+sp;
  472. end;
  473. {$else UseNiceNames}
  474. if assigned(procinfo^._class) then
  475. begin
  476. if (pos('_5Class_',procprefix)=0) then
  477. hs:=procprefix+'_5Class_'+procinfo^._class.name^+'_'+tostr(length(sp))+sp
  478. else
  479. hs:=procprefix+'_'+tostr(length(sp))+sp;
  480. end
  481. else
  482. begin
  483. if lexlevel=normal_function_level then
  484. hs:=procprefix+'_'+tostr(length(sp))+sp
  485. else
  486. hs:=lowercase(procprefix)+'_'+tostr(length(sp))+sp;
  487. end;
  488. {$endif UseNiceNames}
  489. doinsert:=true;
  490. if assigned(aktprocsym) then
  491. begin
  492. { Check if overloaded is a procsym }
  493. if aktprocsym.typ<>procsym then
  494. begin
  495. { when the other symbol is a unit symbol then hide the unit
  496. symbol. Only in tp mode because it's bad programming }
  497. if (m_tp in aktmodeswitches) and
  498. (aktprocsym.typ=unitsym) then
  499. begin
  500. aktprocsym.owner.rename(aktprocsym.name,'hidden'+aktprocsym.name);
  501. end
  502. else
  503. begin
  504. { we use a different error message for tp7 so it looks more compatible }
  505. if (m_fpc in aktmodeswitches) then
  506. Message1(parser_e_overloaded_no_procedure,aktprocsym.realname)
  507. else
  508. DuplicateSym(aktprocsym);
  509. { don't reinsert as that will generated another error }
  510. doinsert:=false;
  511. end;
  512. { generate a new aktprocsym }
  513. aktprocsym:=nil;
  514. end;
  515. end;
  516. { test again if assigned, it can be reset to recover }
  517. if not assigned(aktprocsym) then
  518. begin
  519. { create a new procsym and set the real filepos }
  520. akttokenpos:=procstartfilepos;
  521. { for operator we have only one procsym for each overloaded
  522. operation }
  523. if (options=potype_operator) then
  524. begin
  525. { is the current overload sym already in the current unit }
  526. if assigned(overloaded_operators[optoken]) and
  527. (overloaded_operators[optoken].owner=symtablestack) then
  528. aktprocsym:=overloaded_operators[optoken]
  529. else
  530. begin
  531. { create the procsym with saving the original case }
  532. aktprocsym:=tprocsym.create('$'+sp);
  533. { add already known overloaded defs }
  534. if assigned(overloaded_operators[optoken]) then
  535. begin
  536. pdl:=overloaded_operators[optoken].defs;
  537. while assigned(pdl) do
  538. begin
  539. aktprocsym.addprocdef(pdl^.def);
  540. pdl:=pdl^.next;
  541. end;
  542. end;
  543. end;
  544. end
  545. else
  546. aktprocsym:=tprocsym.create(orgsp);
  547. if doinsert then
  548. symtablestack.insert(aktprocsym);
  549. end;
  550. st:=symtablestack;
  551. aktprocdef:=tprocdef.create;
  552. aktprocdef.symtablelevel:=symtablestack.symtablelevel;
  553. if assigned(procinfo^._class) then
  554. aktprocdef._class := procinfo^._class;
  555. { set the options from the caller (podestructor or poconstructor) }
  556. aktprocdef.proctypeoption:=options;
  557. { calculate the offset of the parameters }
  558. paramoffset:=8;
  559. { calculate frame pointer offset }
  560. if lexlevel>normal_function_level then
  561. begin
  562. procinfo^.framepointer_offset:=paramoffset;
  563. inc(paramoffset,target_info.size_of_pointer);
  564. { this is needed to get correct framepointer push for local
  565. forward functions !! }
  566. aktprocdef.parast.symtablelevel:=lexlevel;
  567. end;
  568. if assigned (procinfo^._Class) and
  569. is_object(procinfo^._Class) and
  570. (aktprocdef.proctypeoption in [potype_constructor,potype_destructor]) then
  571. inc(paramoffset,target_info.size_of_pointer);
  572. { self pointer offset }
  573. { self isn't pushed in nested procedure of methods }
  574. if assigned(procinfo^._class) and (lexlevel=normal_function_level) then
  575. begin
  576. procinfo^.selfpointer_offset:=paramoffset;
  577. if assigned(aktprocdef) and
  578. not(po_containsself in aktprocdef.procoptions) then
  579. inc(paramoffset,target_info.size_of_pointer);
  580. end;
  581. { con/-destructor flag ? }
  582. if assigned (procinfo^._Class) and
  583. is_class(procinfo^._class) and
  584. (aktprocdef.proctypeoption in [potype_destructor,potype_constructor]) then
  585. inc(paramoffset,target_info.size_of_pointer);
  586. procinfo^.para_offset:=paramoffset;
  587. aktprocdef.parast.datasize:=0;
  588. { add procsym to the procdef }
  589. aktprocdef.procsym:=aktprocsym;
  590. { save file position }
  591. aktprocdef.fileinfo:=procstartfilepos;
  592. { store mangledname }
  593. aktprocdef.setmangledname(hs);
  594. if not parse_only then
  595. begin
  596. overloaded_level:=1;
  597. { we need another procprefix !!! }
  598. { count, but only those in the same unit !!}
  599. procdefs:=aktprocsym.defs;
  600. while assigned(procdefs) and
  601. (procdefs^.def.owner.symtabletype in [globalsymtable,staticsymtable]) do
  602. begin
  603. { only count already implemented functions }
  604. if not(procdefs^.def.forwarddef) then
  605. inc(overloaded_level);
  606. procdefs:=procdefs^.next;
  607. end;
  608. if overloaded_level>0 then
  609. procprefix:=hs+'$'+tostr(overloaded_level)+'$'
  610. else
  611. procprefix:=hs+'$';
  612. end;
  613. { this must also be inserted in the right symtable !! PM }
  614. { otherwise we get subbtle problems with
  615. definitions of args defs in staticsymtable for
  616. implementation of a global method }
  617. if token=_LKLAMMER then
  618. parameter_dec(aktprocdef);
  619. { so we only restore the symtable now }
  620. symtablestack:=st;
  621. if (options=potype_operator) then
  622. overloaded_operators[optoken]:=aktprocsym;
  623. end;
  624. procedure parse_proc_dec;
  625. var
  626. hs : string;
  627. isclassmethod : boolean;
  628. begin
  629. inc(lexlevel);
  630. { read class method }
  631. if token=_CLASS then
  632. begin
  633. consume(_CLASS);
  634. isclassmethod:=true;
  635. end
  636. else
  637. isclassmethod:=false;
  638. case token of
  639. _FUNCTION : begin
  640. consume(_FUNCTION);
  641. parse_proc_head(potype_none);
  642. if token<>_COLON then
  643. begin
  644. if assigned(aktprocsym) and
  645. not(is_interface(aktprocdef._class)) and
  646. not(aktprocdef.forwarddef) or
  647. (m_repeat_forward in aktmodeswitches) then
  648. begin
  649. consume(_COLON);
  650. consume_all_until(_SEMICOLON);
  651. end;
  652. end
  653. else
  654. begin
  655. consume(_COLON);
  656. inc(testcurobject);
  657. single_type(aktprocdef.rettype,hs,false);
  658. aktprocdef.test_if_fpu_result;
  659. dec(testcurobject);
  660. end;
  661. end;
  662. _PROCEDURE : begin
  663. consume(_PROCEDURE);
  664. parse_proc_head(potype_none);
  665. if assigned(aktprocsym) then
  666. aktprocdef.rettype:=voidtype;
  667. end;
  668. _CONSTRUCTOR : begin
  669. consume(_CONSTRUCTOR);
  670. parse_proc_head(potype_constructor);
  671. if assigned(procinfo^._class) and
  672. is_class(procinfo^._class) then
  673. begin
  674. { CLASS constructors return the created instance }
  675. aktprocdef.rettype.setdef(procinfo^._class);
  676. end
  677. else
  678. begin
  679. { OBJECT constructors return a boolean }
  680. aktprocdef.rettype:=booltype;
  681. end;
  682. end;
  683. _DESTRUCTOR : begin
  684. consume(_DESTRUCTOR);
  685. parse_proc_head(potype_destructor);
  686. aktprocdef.rettype:=voidtype;
  687. end;
  688. _OPERATOR : begin
  689. if lexlevel>normal_function_level then
  690. Message(parser_e_no_local_operator);
  691. consume(_OPERATOR);
  692. if (token in [first_overloaded..last_overloaded]) then
  693. begin
  694. procinfo^.flags:=procinfo^.flags or pi_operator;
  695. optoken:=token;
  696. end
  697. else
  698. begin
  699. Message(parser_e_overload_operator_failed);
  700. { Use the dummy NOTOKEN that is also declared
  701. for the overloaded_operator[] }
  702. optoken:=NOTOKEN;
  703. end;
  704. consume(Token);
  705. parse_proc_head(potype_operator);
  706. if token<>_ID then
  707. begin
  708. otsym:=nil;
  709. if not(m_result in aktmodeswitches) then
  710. consume(_ID);
  711. end
  712. else
  713. begin
  714. otsym:=tvarsym.create(pattern,voidtype);
  715. consume(_ID);
  716. end;
  717. if not try_to_consume(_COLON) then
  718. begin
  719. consume(_COLON);
  720. aktprocdef.rettype:=generrortype;
  721. consume_all_until(_SEMICOLON);
  722. end
  723. else
  724. begin
  725. single_type(aktprocdef.rettype,hs,false);
  726. aktprocdef.test_if_fpu_result;
  727. if (optoken in [_EQUAL,_GT,_LT,_GTE,_LTE]) and
  728. ((aktprocdef.rettype.def.deftype<>
  729. orddef) or (torddef(aktprocdef.
  730. rettype.def).typ<>bool8bit)) then
  731. Message(parser_e_comparative_operator_return_boolean);
  732. if assigned(otsym) then
  733. otsym.vartype.def:=aktprocdef.rettype.def;
  734. { We need to add the return type in the mangledname
  735. to allow overloading with just different results !! (PM) }
  736. aktprocdef.setmangledname(
  737. aktprocdef.mangledname+'$$'+hs);
  738. if (optoken=_ASSIGNMENT) and
  739. is_equal(aktprocdef.rettype.def,
  740. tvarsym(aktprocdef.parast.symindex.first).vartype.def) then
  741. message(parser_e_no_such_assignment)
  742. else if not isoperatoracceptable(aktprocdef,optoken) then
  743. Message(parser_e_overload_impossible);
  744. end;
  745. end;
  746. end;
  747. if isclassmethod and
  748. assigned(aktprocsym) then
  749. include(aktprocdef.procoptions,po_classmethod);
  750. { support procedure proc;stdcall export; in Delphi mode only }
  751. if not((m_delphi in aktmodeswitches) and
  752. is_proc_directive(token)) then
  753. consume(_SEMICOLON);
  754. dec(lexlevel);
  755. end;
  756. {****************************************************************************
  757. Procedure directive handlers
  758. ****************************************************************************}
  759. procedure pd_far;
  760. begin
  761. Message(parser_w_proc_far_ignored);
  762. end;
  763. procedure pd_near;
  764. begin
  765. Message(parser_w_proc_near_ignored);
  766. end;
  767. procedure pd_export;
  768. begin
  769. if assigned(procinfo^._class) then
  770. Message(parser_e_methods_dont_be_export);
  771. if lexlevel<>normal_function_level then
  772. Message(parser_e_dont_nest_export);
  773. { only os/2 needs this }
  774. if target_info.target=target_i386_os2 then
  775. begin
  776. aktprocdef.aliasnames.insert(aktprocsym.realname);
  777. procinfo^.exported:=true;
  778. if cs_link_deffile in aktglobalswitches then
  779. deffile.AddExport(aktprocdef.mangledname);
  780. end;
  781. end;
  782. procedure pd_forward;
  783. begin
  784. aktprocdef.forwarddef:=true;
  785. end;
  786. procedure pd_alias;
  787. begin
  788. consume(_COLON);
  789. aktprocdef.aliasnames.insert(get_stringconst);
  790. end;
  791. procedure pd_asmname;
  792. begin
  793. aktprocdef.setmangledname(target_info.Cprefix+pattern);
  794. aktprocdef.has_mangledname:=true;
  795. if token=_CCHAR then
  796. consume(_CCHAR)
  797. else
  798. consume(_CSTRING);
  799. { we don't need anything else }
  800. aktprocdef.forwarddef:=false;
  801. end;
  802. procedure pd_intern;
  803. begin
  804. consume(_COLON);
  805. aktprocdef.extnumber:=get_intconst;
  806. end;
  807. procedure pd_interrupt;
  808. begin
  809. {$ifndef i386}
  810. Message(parser_w_proc_interrupt_ignored);
  811. {$else i386}
  812. if lexlevel<>normal_function_level then
  813. Message(parser_e_dont_nest_interrupt);
  814. {$endif i386}
  815. end;
  816. procedure pd_abstract;
  817. begin
  818. if (po_virtualmethod in aktprocdef.procoptions) then
  819. include(aktprocdef.procoptions,po_abstractmethod)
  820. else
  821. Message(parser_e_only_virtual_methods_abstract);
  822. { the method is defined }
  823. aktprocdef.forwarddef:=false;
  824. end;
  825. procedure pd_virtual;
  826. {$ifdef WITHDMT}
  827. var
  828. pt : tnode;
  829. {$endif WITHDMT}
  830. begin
  831. if (aktprocdef.proctypeoption=potype_constructor) and
  832. is_object(aktprocdef._class) then
  833. Message(parser_e_constructor_cannot_be_not_virtual);
  834. {$ifdef WITHDMT}
  835. if is_object(aktprocdef._class) and
  836. (token<>_SEMICOLON) then
  837. begin
  838. { any type of parameter is allowed here! }
  839. pt:=comp_expr(true);
  840. if is_constintnode(pt) then
  841. begin
  842. include(aktprocdef.procoptions,po_msgint);
  843. aktprocdef.messageinf.i:=pt^.value;
  844. end
  845. else
  846. Message(parser_e_ill_msg_expr);
  847. disposetree(pt);
  848. end;
  849. {$endif WITHDMT}
  850. end;
  851. procedure pd_static;
  852. begin
  853. if (cs_static_keyword in aktmoduleswitches) then
  854. begin
  855. include(aktprocsym.symoptions,sp_static);
  856. include(aktprocdef.procoptions,po_staticmethod);
  857. end;
  858. end;
  859. procedure pd_override;
  860. begin
  861. if not(is_class_or_interface(aktprocdef._class)) then
  862. Message(parser_e_no_object_override);
  863. end;
  864. procedure pd_overload;
  865. begin
  866. include(aktprocsym.symoptions,sp_has_overloaded);
  867. end;
  868. procedure pd_message;
  869. var
  870. pt : tnode;
  871. begin
  872. { check parameter type }
  873. if not(po_containsself in aktprocdef.procoptions) and
  874. ((aktprocdef.minparacount<>1) or
  875. (aktprocdef.maxparacount<>1) or
  876. (TParaItem(aktprocdef.Para.first).paratyp<>vs_var)) then
  877. Message(parser_e_ill_msg_param);
  878. pt:=comp_expr(true);
  879. if pt.nodetype=stringconstn then
  880. begin
  881. include(aktprocdef.procoptions,po_msgstr);
  882. aktprocdef.messageinf.str:=strnew(tstringconstnode(pt).value_str);
  883. end
  884. else
  885. if is_constintnode(pt) then
  886. begin
  887. include(aktprocdef.procoptions,po_msgint);
  888. aktprocdef.messageinf.i:=tordconstnode(pt).value;
  889. end
  890. else
  891. Message(parser_e_ill_msg_expr);
  892. pt.free;
  893. end;
  894. procedure pd_reintroduce;
  895. begin
  896. Message1(parser_w_proc_directive_ignored,'REINTRODUCE');
  897. end;
  898. procedure pd_syscall;
  899. begin
  900. aktprocdef.forwarddef:=false;
  901. aktprocdef.extnumber:=get_intconst;
  902. end;
  903. procedure pd_external;
  904. {
  905. If import_dll=nil the procedure is assumed to be in another
  906. object file. In that object file it should have the name to
  907. which import_name is pointing to. Otherwise, the procedure is
  908. assumed to be in the DLL to which import_dll is pointing to. In
  909. that case either import_nr<>0 or import_name<>nil is true, so
  910. the procedure is either imported by number or by name. (DM)
  911. }
  912. var
  913. import_dll,
  914. import_name : string;
  915. import_nr : word;
  916. begin
  917. aktprocdef.forwarddef:=false;
  918. { forbid local external procedures }
  919. if lexlevel>normal_function_level then
  920. Message(parser_e_no_local_external);
  921. { If the procedure should be imported from a DLL, a constant string follows.
  922. This isn't really correct, an contant string expression follows
  923. so we check if an semicolon follows, else a string constant have to
  924. follow (FK) }
  925. import_nr:=0;
  926. import_name:='';
  927. if not(token=_SEMICOLON) and not(idtoken=_NAME) then
  928. begin
  929. import_dll:=get_stringconst;
  930. if (idtoken=_NAME) then
  931. begin
  932. consume(_NAME);
  933. import_name:=get_stringconst;
  934. end;
  935. if (idtoken=_INDEX) then
  936. begin
  937. {After the word index follows the index number in the DLL.}
  938. consume(_INDEX);
  939. import_nr:=get_intconst;
  940. end;
  941. { default is to used the realname of the procedure }
  942. if (import_nr=0) and (import_name='') then
  943. import_name:=aktprocsym.realname;
  944. { create importlib if not already done }
  945. if not(current_module.uses_imports) then
  946. begin
  947. current_module.uses_imports:=true;
  948. importlib.preparelib(current_module.modulename^);
  949. end;
  950. {$ifdef notused}
  951. if not(m_repeat_forward in aktmodeswitches) and
  952. { if the procedure is declared with the overload option }
  953. { it requires a full declaration in the implementation part }
  954. not(sp_has_overloaded in aktprocsym.symoptions) then
  955. begin
  956. { we can only have one overloaded here ! }
  957. if assigned(aktprocdef.defs.next) then
  958. importlib.importprocedure(aktprocdef.defs.next.mangledname,
  959. import_dll,import_nr,import_name)
  960. else
  961. importlib.importprocedure(aktprocdef.mangledname,import_dll,import_nr,import_name);
  962. end
  963. else
  964. {$endif notused}
  965. importlib.importprocedure(aktprocdef.mangledname,import_dll,import_nr,import_name);
  966. end
  967. else
  968. begin
  969. if (idtoken=_NAME) then
  970. begin
  971. consume(_NAME);
  972. import_name:=get_stringconst;
  973. aktprocdef.setmangledname(import_name);
  974. aktprocdef.has_mangledname:=true;
  975. end;
  976. end;
  977. end;
  978. type
  979. pd_handler=procedure;
  980. proc_dir_rec=record
  981. idtok : ttoken;
  982. pd_flags : longint;
  983. handler : pd_handler;
  984. pocall : tproccalloption;
  985. pooption : tprocoptions;
  986. mutexclpocall : tproccalloptions;
  987. mutexclpotype : tproctypeoptions;
  988. mutexclpo : tprocoptions;
  989. end;
  990. const
  991. {Should contain the number of procedure directives we support.}
  992. num_proc_directives=36;
  993. proc_direcdata:array[1..num_proc_directives] of proc_dir_rec=
  994. (
  995. (
  996. idtok:_ABSTRACT;
  997. pd_flags : pd_interface+pd_object+pd_notobjintf;
  998. handler : {$ifdef FPCPROCVAR}@{$endif}pd_abstract;
  999. pocall : pocall_none;
  1000. pooption : [po_abstractmethod];
  1001. mutexclpocall : [pocall_internproc,pocall_inline];
  1002. mutexclpotype : [potype_constructor,potype_destructor];
  1003. mutexclpo : [po_exports,po_interrupt,po_external]
  1004. ),(
  1005. idtok:_ALIAS;
  1006. pd_flags : pd_implemen+pd_body+pd_notobjintf;
  1007. handler : {$ifdef FPCPROCVAR}@{$endif}pd_alias;
  1008. pocall : pocall_none;
  1009. pooption : [];
  1010. mutexclpocall : [pocall_inline];
  1011. mutexclpotype : [];
  1012. mutexclpo : [po_external]
  1013. ),(
  1014. idtok:_ASMNAME;
  1015. pd_flags : pd_interface+pd_implemen+pd_notobjintf;
  1016. handler : {$ifdef FPCPROCVAR}@{$endif}pd_asmname;
  1017. pocall : pocall_cdecl;
  1018. pooption : [po_external];
  1019. mutexclpocall : [pocall_internproc,pocall_inline];
  1020. mutexclpotype : [];
  1021. mutexclpo : [po_external]
  1022. ),(
  1023. idtok:_ASSEMBLER;
  1024. pd_flags : pd_implemen+pd_body+pd_notobjintf;
  1025. handler : nil;
  1026. pocall : pocall_none;
  1027. pooption : [po_assembler];
  1028. mutexclpocall : [];
  1029. mutexclpotype : [];
  1030. mutexclpo : [po_external]
  1031. ),(
  1032. idtok:_CDECL;
  1033. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  1034. handler : nil;
  1035. pocall : pocall_cdecl;
  1036. pooption : [];
  1037. mutexclpocall : [];
  1038. mutexclpotype : [];
  1039. mutexclpo : [po_assembler,po_external]
  1040. ),(
  1041. idtok:_DYNAMIC;
  1042. pd_flags : pd_interface+pd_object+pd_notobjintf;
  1043. handler : {$ifdef FPCPROCVAR}@{$endif}pd_virtual;
  1044. pocall : pocall_none;
  1045. pooption : [po_virtualmethod];
  1046. mutexclpocall : [pocall_internproc,pocall_inline];
  1047. mutexclpotype : [];
  1048. mutexclpo : [po_exports,po_interrupt,po_external]
  1049. ),(
  1050. idtok:_EXPORT;
  1051. pd_flags : pd_body+pd_global+pd_interface+pd_implemen{??}+pd_notobjintf;
  1052. handler : {$ifdef FPCPROCVAR}@{$endif}pd_export;
  1053. pocall : pocall_none;
  1054. pooption : [po_exports];
  1055. mutexclpocall : [pocall_internproc,pocall_inline];
  1056. mutexclpotype : [];
  1057. mutexclpo : [po_external,po_interrupt]
  1058. ),(
  1059. idtok:_EXTERNAL;
  1060. pd_flags : pd_implemen+pd_interface+pd_notobjintf;
  1061. handler : {$ifdef FPCPROCVAR}@{$endif}pd_external;
  1062. pocall : pocall_none;
  1063. pooption : [po_external];
  1064. mutexclpocall : [pocall_internproc,pocall_inline,pocall_palmossyscall];
  1065. mutexclpotype : [];
  1066. mutexclpo : [po_exports,po_interrupt,po_assembler]
  1067. ),(
  1068. idtok:_FAR;
  1069. pd_flags : pd_implemen+pd_body+pd_interface+pd_procvar+pd_notobjintf;
  1070. handler : {$ifdef FPCPROCVAR}@{$endif}pd_far;
  1071. pocall : pocall_none;
  1072. pooption : [];
  1073. mutexclpocall : [pocall_internproc,pocall_inline];
  1074. mutexclpotype : [];
  1075. mutexclpo : []
  1076. ),(
  1077. idtok:_FAR16;
  1078. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  1079. handler : nil;
  1080. pocall : pocall_far16;
  1081. pooption : [];
  1082. mutexclpocall : [];
  1083. mutexclpotype : [];
  1084. mutexclpo : [po_external,po_leftright]
  1085. ),(
  1086. idtok:_FORWARD;
  1087. pd_flags : pd_implemen+pd_notobjintf;
  1088. handler : {$ifdef FPCPROCVAR}@{$endif}pd_forward;
  1089. pocall : pocall_none;
  1090. pooption : [];
  1091. mutexclpocall : [pocall_internproc,pocall_inline];
  1092. mutexclpotype : [];
  1093. mutexclpo : [po_external]
  1094. ),(
  1095. idtok:_FPCCALL;
  1096. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  1097. handler : nil;
  1098. pocall : pocall_fpccall;
  1099. pooption : [];
  1100. mutexclpocall : [];
  1101. mutexclpotype : [];
  1102. mutexclpo : [po_leftright]
  1103. ),(
  1104. idtok:_INLINE;
  1105. pd_flags : pd_implemen+pd_body+pd_notobjintf;
  1106. handler : nil;
  1107. pocall : pocall_inline;
  1108. pooption : [];
  1109. mutexclpocall : [];
  1110. mutexclpotype : [potype_constructor,potype_destructor];
  1111. mutexclpo : [po_exports,po_external,po_interrupt]
  1112. ),(
  1113. idtok:_INTERNCONST;
  1114. pd_flags : pd_implemen+pd_body+pd_notobjintf;
  1115. handler : {$ifdef FPCPROCVAR}@{$endif}pd_intern;
  1116. pocall : pocall_internconst;
  1117. pooption : [];
  1118. mutexclpocall : [];
  1119. mutexclpotype : [potype_operator];
  1120. mutexclpo : []
  1121. ),(
  1122. idtok:_INTERNPROC;
  1123. pd_flags : pd_implemen+pd_notobjintf;
  1124. handler : {$ifdef FPCPROCVAR}@{$endif}pd_intern;
  1125. pocall : pocall_internproc;
  1126. pooption : [];
  1127. mutexclpocall : [];
  1128. mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
  1129. mutexclpo : [po_exports,po_external,po_interrupt,po_assembler,po_iocheck,po_leftright]
  1130. ),(
  1131. idtok:_INTERRUPT;
  1132. pd_flags : pd_implemen+pd_body+pd_notobjintf;
  1133. handler : {$ifdef FPCPROCVAR}@{$endif}pd_interrupt;
  1134. pocall : pocall_none;
  1135. pooption : [po_interrupt];
  1136. mutexclpocall : [pocall_internproc,pocall_cdecl,pocall_cppdecl,
  1137. pocall_inline,pocall_pascal,pocall_system,pocall_far16,pocall_fpccall];
  1138. mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
  1139. mutexclpo : [po_external,po_leftright,po_clearstack]
  1140. ),(
  1141. idtok:_IOCHECK;
  1142. pd_flags : pd_implemen+pd_body+pd_notobjintf;
  1143. handler : nil;
  1144. pocall : pocall_none;
  1145. pooption : [po_iocheck];
  1146. mutexclpocall : [pocall_internproc];
  1147. mutexclpotype : [];
  1148. mutexclpo : [po_external]
  1149. ),(
  1150. idtok:_MESSAGE;
  1151. pd_flags : pd_interface+pd_object+pd_notobjintf;
  1152. handler : {$ifdef FPCPROCVAR}@{$endif}pd_message;
  1153. pocall : pocall_none;
  1154. pooption : []; { can be po_msgstr or po_msgint }
  1155. mutexclpocall : [pocall_inline,pocall_internproc];
  1156. mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
  1157. mutexclpo : [po_interrupt,po_external]
  1158. ),(
  1159. idtok:_NEAR;
  1160. pd_flags : pd_implemen+pd_body+pd_procvar+pd_notobjintf;
  1161. handler : {$ifdef FPCPROCVAR}@{$endif}pd_near;
  1162. pocall : pocall_none;
  1163. pooption : [];
  1164. mutexclpocall : [pocall_internproc];
  1165. mutexclpotype : [];
  1166. mutexclpo : []
  1167. ),(
  1168. idtok:_OVERLOAD;
  1169. pd_flags : pd_implemen+pd_interface+pd_body;
  1170. handler : {$ifdef FPCPROCVAR}@{$endif}pd_overload;
  1171. pocall : pocall_none;
  1172. pooption : [po_overload];
  1173. mutexclpocall : [pocall_internproc];
  1174. mutexclpotype : [];
  1175. mutexclpo : []
  1176. ),(
  1177. idtok:_OVERRIDE;
  1178. pd_flags : pd_interface+pd_object+pd_notobjintf;
  1179. handler : {$ifdef FPCPROCVAR}@{$endif}pd_override;
  1180. pocall : pocall_none;
  1181. pooption : [po_overridingmethod,po_virtualmethod];
  1182. mutexclpocall : [pocall_inline,pocall_internproc];
  1183. mutexclpotype : [];
  1184. mutexclpo : [po_exports,po_external,po_interrupt]
  1185. ),(
  1186. idtok:_PASCAL;
  1187. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  1188. handler : nil;
  1189. pocall : pocall_pascal;
  1190. pooption : [];
  1191. mutexclpocall : [];
  1192. mutexclpotype : [];
  1193. mutexclpo : [po_external]
  1194. ),(
  1195. idtok:_POPSTACK;
  1196. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  1197. handler : nil;
  1198. pocall : pocall_none;
  1199. pooption : [po_clearstack];
  1200. mutexclpocall : [pocall_inline,pocall_internproc,pocall_stdcall];
  1201. mutexclpotype : [];
  1202. mutexclpo : [po_assembler,po_external]
  1203. ),(
  1204. idtok:_PUBLIC;
  1205. pd_flags : pd_implemen+pd_body+pd_global+pd_notobject+pd_notobjintf;
  1206. handler : nil;
  1207. pocall : pocall_none;
  1208. pooption : [];
  1209. mutexclpocall : [pocall_internproc,pocall_inline];
  1210. mutexclpotype : [];
  1211. mutexclpo : [po_external]
  1212. ),(
  1213. idtok:_REGISTER;
  1214. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  1215. handler : nil;
  1216. pocall : pocall_register;
  1217. pooption : [];
  1218. mutexclpocall : [];
  1219. mutexclpotype : [];
  1220. mutexclpo : [po_external]
  1221. ),(
  1222. idtok:_REINTRODUCE;
  1223. pd_flags : pd_interface+pd_object;
  1224. handler : {$ifdef FPCPROCVAR}@{$endif}pd_reintroduce;
  1225. pocall : pocall_none;
  1226. pooption : [];
  1227. mutexclpocall : [];
  1228. mutexclpotype : [];
  1229. mutexclpo : []
  1230. ),(
  1231. idtok:_SAFECALL;
  1232. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  1233. handler : nil;
  1234. pocall : pocall_safecall;
  1235. pooption : [];
  1236. mutexclpocall : [];
  1237. mutexclpotype : [];
  1238. mutexclpo : [po_external]
  1239. ),(
  1240. idtok:_SAVEREGISTERS;
  1241. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar+pd_notobjintf;
  1242. handler : nil;
  1243. pocall : pocall_none;
  1244. pooption : [po_saveregisters];
  1245. mutexclpocall : [pocall_internproc];
  1246. mutexclpotype : [];
  1247. mutexclpo : [po_external]
  1248. ),(
  1249. idtok:_STATIC;
  1250. pd_flags : pd_interface+pd_object+pd_notobjintf;
  1251. handler : {$ifdef FPCPROCVAR}@{$endif}pd_static;
  1252. pocall : pocall_none;
  1253. pooption : [po_staticmethod];
  1254. mutexclpocall : [pocall_inline,pocall_internproc];
  1255. mutexclpotype : [potype_constructor,potype_destructor];
  1256. mutexclpo : [po_external,po_interrupt,po_exports]
  1257. ),(
  1258. idtok:_STDCALL;
  1259. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  1260. handler : nil;
  1261. pocall : pocall_stdcall;
  1262. pooption : [];
  1263. mutexclpocall : [];
  1264. mutexclpotype : [];
  1265. mutexclpo : [po_external]
  1266. ),(
  1267. idtok:_SYSCALL;
  1268. pd_flags : pd_interface+pd_implemen+pd_notobjintf;
  1269. handler : {$ifdef FPCPROCVAR}@{$endif}pd_syscall;
  1270. pocall : pocall_palmossyscall;
  1271. pooption : [];
  1272. mutexclpocall : [];
  1273. mutexclpotype : [];
  1274. mutexclpo : [po_external,po_assembler,po_interrupt,po_exports]
  1275. ),(
  1276. idtok:_SYSTEM;
  1277. pd_flags : pd_implemen+pd_notobjintf;
  1278. handler : nil;
  1279. pocall : pocall_system;
  1280. pooption : [];
  1281. mutexclpocall : [];
  1282. mutexclpotype : [];
  1283. mutexclpo : [po_external,po_assembler,po_interrupt]
  1284. ),(
  1285. idtok:_VIRTUAL;
  1286. pd_flags : pd_interface+pd_object+pd_notobjintf;
  1287. handler : {$ifdef FPCPROCVAR}@{$endif}pd_virtual;
  1288. pocall : pocall_none;
  1289. pooption : [po_virtualmethod];
  1290. mutexclpocall : [pocall_inline,pocall_internproc];
  1291. mutexclpotype : [];
  1292. mutexclpo : [po_external,po_interrupt,po_exports]
  1293. ),(
  1294. idtok:_CPPDECL;
  1295. pd_flags : pd_interface+pd_implemen+pd_body+pd_procvar;
  1296. handler : nil;
  1297. pocall : pocall_cppdecl;
  1298. pooption : [po_savestdregs];
  1299. mutexclpocall : [];
  1300. mutexclpotype : [];
  1301. mutexclpo : [po_assembler,po_external]
  1302. ),(
  1303. idtok:_VARARGS;
  1304. pd_flags : pd_interface+pd_implemen+pd_procvar;
  1305. handler : nil;
  1306. pocall : pocall_none;
  1307. pooption : [po_varargs];
  1308. mutexclpocall : [pocall_internproc,pocall_stdcall,pocall_register,
  1309. pocall_inline,pocall_far16,pocall_fpccall];
  1310. mutexclpotype : [];
  1311. mutexclpo : [po_assembler,po_interrupt,po_leftright]
  1312. ),(
  1313. idtok:_COMPILERPROC;
  1314. pd_flags : pd_interface+pd_implemen+pd_body+pd_notobjintf;
  1315. handler : nil;
  1316. pocall : pocall_compilerproc;
  1317. pooption : [];
  1318. mutexclpocall : [];
  1319. mutexclpotype : [];
  1320. mutexclpo : [po_interrupt]
  1321. )
  1322. );
  1323. function is_proc_directive(tok:ttoken):boolean;
  1324. var
  1325. i : longint;
  1326. begin
  1327. is_proc_directive:=false;
  1328. for i:=1 to num_proc_directives do
  1329. if proc_direcdata[i].idtok=idtoken then
  1330. begin
  1331. is_proc_directive:=true;
  1332. exit;
  1333. end;
  1334. end;
  1335. function parse_proc_direc(var pdflags:word):boolean;
  1336. {
  1337. Parse the procedure directive, returns true if a correct directive is found
  1338. }
  1339. var
  1340. p : longint;
  1341. found : boolean;
  1342. name : stringid;
  1343. begin
  1344. parse_proc_direc:=false;
  1345. name:=tokeninfo^[idtoken].str;
  1346. found:=false;
  1347. { Hint directive? Then exit immediatly }
  1348. if (m_hintdirective in aktmodeswitches) then
  1349. begin
  1350. case idtoken of
  1351. _LIBRARY,
  1352. _PLATFORM,
  1353. _DEPRECATED :
  1354. exit;
  1355. end;
  1356. end;
  1357. { retrieve data for directive if found }
  1358. for p:=1 to num_proc_directives do
  1359. if proc_direcdata[p].idtok=idtoken then
  1360. begin
  1361. found:=true;
  1362. break;
  1363. end;
  1364. { Check if the procedure directive is known }
  1365. if not found then
  1366. begin
  1367. { parsing a procvar type the name can be any
  1368. next variable !! }
  1369. if (pdflags and (pd_procvar or pd_object))=0 then
  1370. Message1(parser_w_unknown_proc_directive_ignored,name);
  1371. exit;
  1372. end;
  1373. { static needs a special treatment }
  1374. if (idtoken=_STATIC) and not (cs_static_keyword in aktmoduleswitches) then
  1375. exit;
  1376. { Conflicts between directives ? }
  1377. if (aktprocdef.proctypeoption in proc_direcdata[p].mutexclpotype) or
  1378. (aktprocdef.proccalloption in proc_direcdata[p].mutexclpocall) or
  1379. ((aktprocdef.procoptions*proc_direcdata[p].mutexclpo)<>[]) then
  1380. begin
  1381. Message1(parser_e_proc_dir_conflict,name);
  1382. exit;
  1383. end;
  1384. { set calling convention }
  1385. if proc_direcdata[p].pocall<>pocall_none then
  1386. begin
  1387. if aktprocdef.proccalloption<>pocall_none then
  1388. begin
  1389. Message2(parser_w_proc_overriding_calling,
  1390. proccalloptionStr[aktprocdef.proccalloption],
  1391. proccalloptionStr[proc_direcdata[p].pocall]);
  1392. end;
  1393. aktprocdef.proccalloption:=proc_direcdata[p].pocall;
  1394. end;
  1395. if aktprocdef.deftype=procdef then
  1396. begin
  1397. { Check if the directive is only for objects }
  1398. if ((proc_direcdata[p].pd_flags and pd_object)<>0) and
  1399. not assigned(aktprocdef._class) then
  1400. exit;
  1401. { check if method and directive not for object public }
  1402. if ((proc_direcdata[p].pd_flags and pd_notobject)<>0) and
  1403. assigned(aktprocdef._class) then
  1404. exit;
  1405. { check if method and directive not for interface }
  1406. if ((proc_direcdata[p].pd_flags and pd_notobjintf)<>0) and
  1407. is_interface(aktprocdef._class) then
  1408. exit;
  1409. end;
  1410. { consume directive, and turn flag on }
  1411. consume(token);
  1412. parse_proc_direc:=true;
  1413. { Check the pd_flags if the directive should be allowed }
  1414. if ((pdflags and pd_interface)<>0) and
  1415. ((proc_direcdata[p].pd_flags and pd_interface)=0) then
  1416. begin
  1417. Message1(parser_e_proc_dir_not_allowed_in_interface,name);
  1418. exit;
  1419. end;
  1420. if ((pdflags and pd_implemen)<>0) and
  1421. ((proc_direcdata[p].pd_flags and pd_implemen)=0) then
  1422. begin
  1423. Message1(parser_e_proc_dir_not_allowed_in_implementation,name);
  1424. exit;
  1425. end;
  1426. if ((pdflags and pd_procvar)<>0) and
  1427. ((proc_direcdata[p].pd_flags and pd_procvar)=0) then
  1428. begin
  1429. Message1(parser_e_proc_dir_not_allowed_in_procvar,name);
  1430. exit;
  1431. end;
  1432. { Return the new pd_flags }
  1433. if (proc_direcdata[p].pd_flags and pd_body)=0 then
  1434. pdflags:=pdflags and (not pd_body);
  1435. if (proc_direcdata[p].pd_flags and pd_global)<>0 then
  1436. pdflags:=pdflags or pd_global;
  1437. { Add the correct flag }
  1438. aktprocdef.procoptions:=aktprocdef.procoptions+proc_direcdata[p].pooption;
  1439. { Call the handler }
  1440. if pointer({$ifndef FPCPROCVAR}@{$endif}proc_direcdata[p].handler)<>nil then
  1441. proc_direcdata[p].handler{$ifdef FPCPROCVAR}(){$endif};
  1442. end;
  1443. procedure handle_calling_convention(sym:tprocsym;def:tabstractprocdef);
  1444. var
  1445. st,parast : tsymtable;
  1446. lastps,ps : tsym;
  1447. begin
  1448. { set the default calling convention }
  1449. if def.proccalloption=pocall_none then
  1450. def.proccalloption:=aktdefproccall;
  1451. case def.proccalloption of
  1452. pocall_cdecl :
  1453. begin
  1454. { use popstack and save std registers }
  1455. include(def.procoptions,po_clearstack);
  1456. include(def.procoptions,po_savestdregs);
  1457. { set mangledname }
  1458. if (def.deftype=procdef) then
  1459. begin
  1460. if not tprocdef(def).has_mangledname then
  1461. tprocdef(def).setmangledname(target_info.Cprefix+sym.realname);
  1462. if not assigned(tprocdef(def).parast) then
  1463. internalerror(200110234);
  1464. { do not copy on local !! }
  1465. tprocdef(def).parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}resetvaluepara);
  1466. { Adjust positions of args for cdecl or stdcall }
  1467. tparasymtable(tprocdef(def).parast).set_alignment(target_info.size_of_longint);
  1468. end;
  1469. end;
  1470. pocall_cppdecl :
  1471. begin
  1472. if not assigned(sym) then
  1473. internalerror(200110231);
  1474. { use popstack and save std registers }
  1475. include(def.procoptions,po_clearstack);
  1476. include(def.procoptions,po_savestdregs);
  1477. { set mangledname }
  1478. if (def.deftype=procdef) then
  1479. begin
  1480. if not tprocdef(def).has_mangledname then
  1481. tprocdef(def).setmangledname(target_info.Cprefix+tprocdef(def).cplusplusmangledname);
  1482. if not assigned(tprocdef(def).parast) then
  1483. internalerror(200110235);
  1484. { do not copy on local !! }
  1485. tprocdef(def).parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}resetvaluepara);
  1486. { Adjust positions of args for cdecl or stdcall }
  1487. tparasymtable(tprocdef(def).parast).set_alignment(target_info.size_of_longint);
  1488. end;
  1489. end;
  1490. pocall_stdcall :
  1491. begin
  1492. include(def.procoptions,po_savestdregs);
  1493. if (def.deftype=procdef) and
  1494. assigned(tprocdef(def).parast) then
  1495. begin
  1496. { Adjust positions of args for cdecl or stdcall }
  1497. tparasymtable(tprocdef(def).parast).set_alignment(target_info.size_of_longint);
  1498. end;
  1499. end;
  1500. pocall_safecall :
  1501. begin
  1502. include(def.procoptions,po_savestdregs);
  1503. end;
  1504. pocall_compilerproc :
  1505. begin
  1506. if (not assigned(sym)) or
  1507. (def.deftype<>procdef) then
  1508. internalerror(200110232);
  1509. tprocdef(def).setmangledname(lower(sym.name));
  1510. end;
  1511. pocall_pascal :
  1512. begin
  1513. include(def.procoptions,po_leftright);
  1514. st:=tparasymtable.create;
  1515. parast:=tprocdef(def).parast;
  1516. lastps:=nil;
  1517. while assigned(parast.symindex.first) and (lastps<>tsym(parast.symindex.first)) do
  1518. begin
  1519. ps:=tsym(parast.symindex.first);
  1520. while assigned(ps.indexnext) and (tsym(ps.indexnext)<>lastps) do
  1521. ps:=tsym(ps.indexnext);
  1522. ps.owner:=st;
  1523. { recalculate the corrected offset }
  1524. { the really_insert_in_data procedure
  1525. for parasymtable should only calculateoffset PM }
  1526. tstoredsym(ps).insert_in_data;
  1527. { reset the owner correctly }
  1528. ps.owner:=parast;
  1529. lastps:=ps;
  1530. end;
  1531. end;
  1532. pocall_register :
  1533. begin
  1534. Message1(parser_w_proc_directive_ignored,'REGISTER');
  1535. end;
  1536. pocall_far16 :
  1537. begin
  1538. { Temporary stub, must be rewritten to support OS/2 far16 }
  1539. Message1(parser_w_proc_directive_ignored,'FAR16');
  1540. end;
  1541. pocall_system :
  1542. begin
  1543. include(def.procoptions,po_clearstack);
  1544. if (not assigned(sym)) or
  1545. (def.deftype<>procdef) then
  1546. internalerror(200110233);
  1547. if not tprocdef(def).has_mangledname then
  1548. tprocdef(def).setmangledname(sym.realname);
  1549. end;
  1550. pocall_palmossyscall :
  1551. begin
  1552. { use popstack and save std registers }
  1553. include(def.procoptions,po_clearstack);
  1554. include(def.procoptions,po_savestdregs);
  1555. if (def.deftype=procdef) then
  1556. begin
  1557. if not assigned(tprocdef(def).parast) then
  1558. internalerror(200110236);
  1559. { do not copy on local !! }
  1560. tprocdef(def).parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}resetvaluepara);
  1561. { Adjust positions of args for cdecl or stdcall }
  1562. tparasymtable(tprocdef(def).parast).set_alignment(target_info.size_of_longint);
  1563. end;
  1564. end;
  1565. pocall_inline :
  1566. begin
  1567. if not(cs_support_inline in aktmoduleswitches) then
  1568. begin
  1569. Message(parser_e_proc_inline_not_supported);
  1570. def.proccalloption:=pocall_fpccall;
  1571. end;
  1572. end;
  1573. end;
  1574. { add mangledname to external list }
  1575. if (def.deftype=procdef) and
  1576. (po_external in def.procoptions) and
  1577. target_info.DllScanSupported then
  1578. current_module.externals.insert(tExternalsItem.create(tprocdef(def).mangledname));
  1579. end;
  1580. procedure parse_proc_directives(var pdflags:word);
  1581. {
  1582. Parse the procedure directives. It does not matter if procedure directives
  1583. are written using ;procdir; or ['procdir'] syntax.
  1584. }
  1585. var
  1586. res : boolean;
  1587. begin
  1588. while token in [_ID,_LECKKLAMMER] do
  1589. begin
  1590. if try_to_consume(_LECKKLAMMER) then
  1591. begin
  1592. repeat
  1593. parse_proc_direc(pdflags);
  1594. until not try_to_consume(_COMMA);
  1595. consume(_RECKKLAMMER);
  1596. { we always expect at least '[];' }
  1597. res:=true;
  1598. end
  1599. else
  1600. begin
  1601. res:=parse_proc_direc(pdflags);
  1602. end;
  1603. { A procedure directive normally followed by a semicolon, but in
  1604. a const section we should stop when _EQUAL is found }
  1605. if res then
  1606. begin
  1607. if (block_type=bt_const) and
  1608. (token=_EQUAL) then
  1609. break;
  1610. { support procedure proc;stdcall export; in Delphi mode only }
  1611. if not((m_delphi in aktmodeswitches) and
  1612. is_proc_directive(token)) then
  1613. consume(_SEMICOLON);
  1614. end
  1615. else
  1616. break;
  1617. end;
  1618. handle_calling_convention(aktprocsym,aktprocdef);
  1619. end;
  1620. procedure parse_var_proc_directives(var sym : tsym);
  1621. var
  1622. pdflags : word;
  1623. oldsym : tprocsym;
  1624. olddef : tprocdef;
  1625. pd : tabstractprocdef;
  1626. begin
  1627. oldsym:=aktprocsym;
  1628. olddef:=aktprocdef;
  1629. pdflags:=pd_procvar;
  1630. { we create a temporary aktprocsym to read the directives }
  1631. aktprocsym:=tprocsym.create(sym.name);
  1632. case sym.typ of
  1633. varsym :
  1634. pd:=tabstractprocdef(tvarsym(sym).vartype.def);
  1635. typedconstsym :
  1636. pd:=tabstractprocdef(ttypedconstsym(sym).typedconsttype.def);
  1637. typesym :
  1638. pd:=tabstractprocdef(ttypesym(sym).restype.def);
  1639. else
  1640. internalerror(994932432);
  1641. end;
  1642. if pd.deftype<>procvardef then
  1643. internalerror(994932433);
  1644. tabstractprocdef(aktprocdef):=pd;
  1645. { names should never be used anyway }
  1646. inc(lexlevel);
  1647. parse_proc_directives(pdflags);
  1648. dec(lexlevel);
  1649. aktprocsym.free;
  1650. aktprocsym:=oldsym;
  1651. aktprocdef:=olddef;
  1652. end;
  1653. procedure parse_object_proc_directives(var sym : tprocsym);
  1654. var
  1655. pdflags : word;
  1656. begin
  1657. pdflags:=pd_object;
  1658. inc(lexlevel);
  1659. parse_proc_directives(pdflags);
  1660. dec(lexlevel);
  1661. if (po_containsself in aktprocdef.procoptions) and
  1662. (([po_msgstr,po_msgint]*aktprocdef.procoptions)=[]) then
  1663. Message(parser_e_self_in_non_message_handler);
  1664. end;
  1665. function proc_add_definition(aprocsym:tprocsym;var aprocdef : tprocdef) : boolean;
  1666. {
  1667. Add definition aprocdef to the overloaded definitions of aprocsym. If a
  1668. forwarddef is found and reused it returns true
  1669. }
  1670. var
  1671. hd : tprocdef;
  1672. pdl : pprocdeflist;
  1673. ad,fd : tsym;
  1674. forwardfound : boolean;
  1675. begin
  1676. forwardfound:=false;
  1677. { check overloaded functions if the same function already exists }
  1678. pdl:=aprocsym.defs;
  1679. while assigned(pdl) do
  1680. begin
  1681. hd:=pdl^.def;
  1682. { check the parameters, for delphi/tp it is possible to
  1683. leave the parameters away in the implementation (forwarddef=false).
  1684. But for an overload declared function this is not allowed }
  1685. if { check if empty implementation arguments match is allowed }
  1686. (
  1687. not(m_repeat_forward in aktmodeswitches) and
  1688. not(aprocdef.forwarddef) and
  1689. (aprocdef.maxparacount=0) and
  1690. not(po_overload in hd.procoptions)
  1691. ) or
  1692. { check arguments }
  1693. (
  1694. equal_paras(aprocdef.para,hd.para,cp_none) and
  1695. { for operators equal_paras is not enough !! }
  1696. ((aprocdef.proctypeoption<>potype_operator) or (optoken<>_ASSIGNMENT) or
  1697. is_equal(hd.rettype.def,aprocdef.rettype.def))
  1698. ) then
  1699. begin
  1700. { Check if we've found the forwarddef, if found then
  1701. we need to update the forward def with the current
  1702. implementation settings }
  1703. if hd.forwarddef then
  1704. begin
  1705. { Check if the procedure type and return type are correct }
  1706. if (hd.proctypeoption<>aprocdef.proctypeoption) or
  1707. (not(is_equal(hd.rettype.def,aprocdef.rettype.def)) and
  1708. (m_repeat_forward in aktmodeswitches)) then
  1709. begin
  1710. MessagePos1(aprocdef.fileinfo,parser_e_header_dont_match_forward,
  1711. aprocdef.fullprocname);
  1712. break;
  1713. end;
  1714. { Check if both are declared forward }
  1715. if hd.forwarddef and aprocdef.forwarddef then
  1716. begin
  1717. MessagePos1(aprocdef.fileinfo,parser_e_function_already_declared_public_forward,
  1718. aprocdef.fullprocname);
  1719. end;
  1720. { internconst or internproc only need to be defined once }
  1721. if (hd.proccalloption in [pocall_internconst,pocall_internproc]) then
  1722. aprocdef.proccalloption:=hd.proccalloption
  1723. else
  1724. if (aprocdef.proccalloption in [pocall_internconst,pocall_internproc]) then
  1725. hd.proccalloption:=aprocdef.proccalloption;
  1726. { Check calling convention }
  1727. if (hd.proccalloption<>aprocdef.proccalloption) then
  1728. begin
  1729. { For delphi check if the current implementation has no proccalloption, then
  1730. take the options from the interface }
  1731. if (m_delphi in aktmodeswitches) then
  1732. begin
  1733. if (aprocdef.proccalloption=pocall_none) then
  1734. aprocdef.proccalloption:=hd.proccalloption
  1735. else
  1736. MessagePos(aprocdef.fileinfo,parser_e_call_convention_dont_match_forward);
  1737. end
  1738. else
  1739. MessagePos(aprocdef.fileinfo,parser_e_call_convention_dont_match_forward);
  1740. { restore interface settings for error recovery }
  1741. aprocdef.proccalloption:=hd.proccalloption;
  1742. aprocdef.setmangledname(hd.mangledname);
  1743. end;
  1744. { Check manglednames }
  1745. hd.count:=false;
  1746. if (m_repeat_forward in aktmodeswitches) or
  1747. aprocdef.haspara then
  1748. begin
  1749. if (hd.mangledname<>aprocdef.mangledname) then
  1750. begin
  1751. if not(po_external in aprocdef.procoptions) then
  1752. MessagePos2(aprocdef.fileinfo,parser_n_interface_name_diff_implementation_name,
  1753. hd.mangledname,aprocdef.mangledname);
  1754. { if the mangledname is already used, then rename it to the
  1755. new mangledname of the implementation }
  1756. if hd.is_used then
  1757. renameasmsymbol(hd.mangledname,aprocdef.mangledname);
  1758. { reset the mangledname of the interface }
  1759. hd.setmangledname(aprocdef.mangledname);
  1760. end
  1761. else
  1762. begin
  1763. { If mangled names are equal then they have the same amount of arguments }
  1764. { We can check the names of the arguments }
  1765. { both symtables are in the same order from left to right }
  1766. ad:=tsym(hd.parast.symindex.first);
  1767. fd:=tsym(aprocdef.parast.symindex.first);
  1768. while assigned(ad) and assigned(fd) do
  1769. begin
  1770. if ad.name<>fd.name then
  1771. begin
  1772. { don't give an error if the default parameter is not
  1773. specified in the implementation }
  1774. if ((copy(fd.name,1,3)='def') and
  1775. (copy(ad.name,1,3)<>'def')) then
  1776. MessagePos3(aprocdef.fileinfo,parser_e_header_different_var_names,
  1777. aprocsym.name,ad.name,fd.name);
  1778. break;
  1779. end;
  1780. ad:=tsym(ad.indexnext);
  1781. fd:=tsym(fd.indexnext);
  1782. end;
  1783. end;
  1784. end;
  1785. hd.count:=true;
  1786. { Everything is checked, now we can update the forward declaration
  1787. with the new data from the implementation }
  1788. hd.forwarddef:=aprocdef.forwarddef;
  1789. hd.hasforward:=true;
  1790. hd.parast.address_fixup:=aprocdef.parast.address_fixup;
  1791. hd.procoptions:=hd.procoptions+aprocdef.procoptions;
  1792. if hd.extnumber=-1 then
  1793. hd.extnumber:=aprocdef.extnumber;
  1794. while not aprocdef.aliasnames.empty do
  1795. hd.aliasnames.insert(aprocdef.aliasnames.getfirst);
  1796. { for compilerproc defines we need to rename and update the
  1797. symbolname to lowercase }
  1798. if (aprocdef.proccalloption=pocall_compilerproc) then
  1799. begin
  1800. { rename to lowercase so users can't access it }
  1801. aprocsym.owner.rename(aprocsym.name,lower(aprocsym.name));
  1802. { also update the realname that is stored in the ppu }
  1803. stringdispose(aprocsym._realname);
  1804. aprocsym._realname:=stringdup('$'+aprocsym.name);
  1805. { the mangeled name is already changed by the pd_compilerproc }
  1806. { handler. It must be done immediately because if we have a }
  1807. { call to a compilerproc before it's implementation is }
  1808. { encountered, it must already use the new mangled name (JM) }
  1809. end;
  1810. { return the forwarddef }
  1811. aprocdef:=hd;
  1812. forwardfound:=true;
  1813. end
  1814. else
  1815. begin
  1816. { abstract methods aren't forward defined, but this }
  1817. { needs another error message }
  1818. if (po_abstractmethod in hd.procoptions) then
  1819. MessagePos(aprocdef.fileinfo,parser_e_abstract_no_definition)
  1820. else
  1821. MessagePos(aprocdef.fileinfo,parser_e_overloaded_have_same_parameters);
  1822. end;
  1823. { we found one proc with the same arguments, there are no others
  1824. so we can stop }
  1825. break;
  1826. end;
  1827. { check for allowing overload directive }
  1828. if not(m_fpc in aktmodeswitches) then
  1829. begin
  1830. { overload directive turns on overloading }
  1831. if ((po_overload in aprocdef.procoptions) or
  1832. (po_overload in hd.procoptions)) then
  1833. begin
  1834. { check if all procs have overloading, but not if the proc was
  1835. already declared forward, then the check is already done }
  1836. if not(hd.hasforward or
  1837. (aprocdef.forwarddef<>hd.forwarddef) or
  1838. ((po_overload in aprocdef.procoptions) and
  1839. (po_overload in hd.procoptions))) then
  1840. begin
  1841. MessagePos1(aprocdef.fileinfo,parser_e_no_overload_for_all_procs,aprocsym.realname);
  1842. break;
  1843. end;
  1844. end
  1845. else
  1846. begin
  1847. if not(hd.forwarddef) then
  1848. begin
  1849. MessagePos(aprocdef.fileinfo,parser_e_procedure_overloading_is_off);
  1850. break;
  1851. end;
  1852. end;
  1853. end; { equal arguments }
  1854. { try next overloaded }
  1855. pdl:=pdl^.next;
  1856. end;
  1857. { if we didn't reuse a forwarddef then we add the procdef to the overloaded
  1858. list }
  1859. if not forwardfound then
  1860. aprocsym.addprocdef(aprocdef);
  1861. { insert otsym only in the right symtable }
  1862. if ((procinfo^.flags and pi_operator)<>0) and
  1863. assigned(otsym) and
  1864. not parse_only then
  1865. begin
  1866. if ret_in_param(aprocdef.rettype.def) then
  1867. begin
  1868. aprocdef.parast.insert(otsym);
  1869. { this increases the data size }
  1870. { correct this to get the right ret $value }
  1871. dec(aprocdef.parast.datasize,
  1872. align(otsym.getpushsize,aktprocdef.parast.dataalignment));
  1873. { this allows to read the funcretoffset }
  1874. otsym.address:=-4;
  1875. otsym.varspez:=vs_var;
  1876. end
  1877. else
  1878. aprocdef.localst.insert(otsym);
  1879. end;
  1880. proc_add_definition:=forwardfound;
  1881. end;
  1882. end.
  1883. {
  1884. $Log$
  1885. Revision 1.42 2001-12-06 17:57:36 florian
  1886. + parasym to tparaitem added
  1887. Revision 1.41 2001/11/02 22:58:03 peter
  1888. * procsym definition rewrite
  1889. Revision 1.40 2001/10/25 21:22:37 peter
  1890. * calling convention rewrite
  1891. Revision 1.39 2001/10/23 21:49:42 peter
  1892. * $calling directive and -Cc commandline patch added
  1893. from Pavel Ozerski
  1894. Revision 1.38 2001/10/01 13:38:44 jonas
  1895. * allow self parameter for normal procedures again (because Kylix allows
  1896. it too) ("merged")
  1897. Revision 1.37 2001/09/10 10:26:26 jonas
  1898. * fixed web bug 1593
  1899. * writing of procvar headers is more complete (mention var/const/out for
  1900. paras, add "of object" if applicable)
  1901. + error if declaring explicit self para as var/const
  1902. * fixed mangled name of procedures which contain an explicit self para
  1903. * parsing para's should be slightly faster because mangled name of
  1904. procedure is only updated once instead of after parsing each para
  1905. (all merged from fixes)
  1906. Revision 1.36 2001/08/26 13:36:45 florian
  1907. * some cg reorganisation
  1908. * some PPC updates
  1909. Revision 1.35 2001/08/23 14:28:36 jonas
  1910. + tempcreate/ref/delete nodes (allows the use of temps in the
  1911. resulttype and first pass)
  1912. * made handling of read(ln)/write(ln) processor independent
  1913. * moved processor independent handling for str and reset/rewrite-typed
  1914. from firstpass to resulttype pass
  1915. * changed names of helpers in text.inc to be generic for use as
  1916. compilerprocs + added "iocheck" directive for most of them
  1917. * reading of ordinals is done by procedures instead of functions
  1918. because otherwise FPC_IOCHECK overwrote the result before it could
  1919. be stored elsewhere (range checking still works)
  1920. * compilerprocs can now be used in the system unit before they are
  1921. implemented
  1922. * added note to errore.msg that booleans can't be read using read/readln
  1923. Revision 1.34 2001/08/22 21:16:21 florian
  1924. * some interfaces related problems regarding
  1925. mapping of interface implementions fixed
  1926. Revision 1.33 2001/08/19 21:11:20 florian
  1927. * some bugs fix:
  1928. - overload; with external procedures fixed
  1929. - better selection of routine to do an overloaded
  1930. type case
  1931. - ... some more
  1932. Revision 1.32 2001/08/19 11:22:23 peter
  1933. * palmos support from v10 merged
  1934. Revision 1.31 2001/08/05 13:18:50 peter
  1935. * turn pocall_inline off when inline is not supported
  1936. Revision 1.30 2001/08/01 15:07:29 jonas
  1937. + "compilerproc" directive support, which turns both the public and mangled
  1938. name to lowercase(declaration_name). This prevents a normal user from
  1939. accessing the routine, but they can still be easily looked up within
  1940. the compiler. This is used for helper procedures and should facilitate
  1941. the writing of more processor independent code in the code generator
  1942. itself (mostly written by Peter)
  1943. + new "createintern" constructor for tcal nodes to create a call to
  1944. helper exported using the "compilerproc" directive
  1945. + support for high(dynamic_array) using the the above new things
  1946. + definition of 'HASCOMPILERPROC' symbol (to be able to check in the
  1947. compiler and rtl whether the "compilerproc" directive is supported)
  1948. Revision 1.29 2001/07/09 21:11:14 peter
  1949. * fixed overload checking for delphi. Empty parameters are only
  1950. allowed in implementation and not when the forward declaration
  1951. contains overload directive
  1952. Revision 1.28 2001/07/01 20:16:16 peter
  1953. * alignmentinfo record added
  1954. * -Oa argument supports more alignment settings that can be specified
  1955. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  1956. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  1957. required alignment and the maximum usefull alignment. The final
  1958. alignment will be choosen per variable size dependent on these
  1959. settings
  1960. Revision 1.27 2001/06/04 18:12:26 peter
  1961. * fixed crash with procvar directive parsing. Be carefull as the procvar
  1962. directive parsing uses aktprocdef that is a tprocdef, but
  1963. for procvar the type is tprocvardef. So some fields are not available
  1964. Revision 1.26 2001/06/04 11:53:13 peter
  1965. + varargs directive
  1966. Revision 1.25 2001/06/03 21:57:36 peter
  1967. + hint directive parsing support
  1968. Revision 1.24 2001/05/08 21:06:31 florian
  1969. * some more support for widechars commited especially
  1970. regarding type casting and constants
  1971. Revision 1.23 2001/05/08 14:32:58 jonas
  1972. * fixed bug for overloaded operators with a return type that has a size
  1973. which isn't a multiple of the target_os.stackalignment (main branch
  1974. patch from Peter)
  1975. Revision 1.22 2001/05/04 15:52:03 florian
  1976. * some Delphi incompatibilities fixed:
  1977. - out, dispose and new can be used as idenfiers now
  1978. - const p = apointerype(nil); is supported now
  1979. + support for const p = apointertype(pointer(1234)); added
  1980. Revision 1.21 2001/04/18 22:01:57 peter
  1981. * registration of targets and assemblers
  1982. Revision 1.20 2001/04/13 20:05:16 peter
  1983. * better check for globalsymtable
  1984. Revision 1.19 2001/04/13 18:03:16 peter
  1985. * give error with local external procedure
  1986. Revision 1.18 2001/04/13 01:22:11 peter
  1987. * symtable change to classes
  1988. * range check generation and errors fixed, make cycle DEBUG=1 works
  1989. * memory leaks fixed
  1990. Revision 1.17 2001/04/04 22:43:52 peter
  1991. * remove unnecessary calls to firstpass
  1992. Revision 1.16 2001/04/02 21:20:33 peter
  1993. * resulttype rewrite
  1994. Revision 1.15 2001/03/24 12:18:11 florian
  1995. * procedure p(); is now allowed in all modes except TP
  1996. Revision 1.14 2001/03/22 22:35:42 florian
  1997. + support for type a = (a=1); in Delphi mode added
  1998. + procedure p(); in Delphi mode supported
  1999. + on isn't keyword anymore, it can be used as
  2000. id etc. now
  2001. Revision 1.13 2001/03/11 22:58:50 peter
  2002. * getsym redesign, removed the globals srsym,srsymtable
  2003. Revision 1.12 2001/03/06 18:28:02 peter
  2004. * patch from Pavel with a new and much faster DLL Scanner for
  2005. automatic importing so $linklib works for DLLs. Thanks Pavel!
  2006. Revision 1.11 2001/01/08 21:40:26 peter
  2007. * fixed crash with unsupported token overloading
  2008. Revision 1.10 2000/12/25 00:07:27 peter
  2009. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  2010. tlinkedlist objects)
  2011. Revision 1.9 2000/11/29 00:30:35 florian
  2012. * unused units removed from uses clause
  2013. * some changes for widestrings
  2014. Revision 1.8 2000/11/26 23:45:34 florian
  2015. * pascal modifier in interfaces of units works now
  2016. Revision 1.7 2000/11/06 20:30:55 peter
  2017. * more fixes to get make cycle working
  2018. Revision 1.6 2000/11/04 14:25:20 florian
  2019. + merged Attila's changes for interfaces, not tested yet
  2020. Revision 1.5 2000/11/01 23:04:37 peter
  2021. * tprocdef.fullprocname added for better casesensitve writing of
  2022. procedures
  2023. Revision 1.4 2000/10/31 22:02:49 peter
  2024. * symtable splitted, no real code changes
  2025. Revision 1.3 2000/10/21 18:16:11 florian
  2026. * a lot of changes:
  2027. - basic dyn. array support
  2028. - basic C++ support
  2029. - some work for interfaces done
  2030. ....
  2031. Revision 1.2 2000/10/15 07:47:51 peter
  2032. * unit names and procedure names are stored mixed case
  2033. Revision 1.1 2000/10/14 10:14:51 peter
  2034. * moehrendorf oct 2000 rewrite
  2035. }