pdecsub.pas 76 KB

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