123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634 |
- {
- $Id$
- Copyright (c) 1998-2002 by Florian Klaempfl, Daniel Mantione
- Does the parsing of the procedures/functions
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- unit pdecsub;
- {$i fpcdefs.inc}
- interface
- uses
- tokens,symconst,symtype,symdef,symsym;
- type
- tpdflag=(
- pd_body, { directive needs a body }
- pd_implemen, { directive can be used implementation section }
- pd_interface, { directive can be used interface section }
- pd_object, { directive can be used object declaration }
- pd_procvar, { directive can be used procvar declaration }
- pd_notobject, { directive can not be used object declaration }
- pd_notobjintf, { directive can not be used interface declaration }
- pd_notprocvar { directive can not be used procvar declaration }
- );
- tpdflags=set of tpdflag;
- function check_proc_directive(isprocvar:boolean):boolean;
- procedure insert_funcret_local(pd:tprocdef);
- function proc_add_definition(var pd:tprocdef):boolean;
- function proc_get_importname(pd:tprocdef):string;
- procedure proc_set_mangledname(pd:tprocdef);
- procedure handle_calling_convention(pd:tabstractprocdef);
- procedure parse_parameter_dec(pd:tabstractprocdef);
- procedure parse_proc_directives(pd:tabstractprocdef;var pdflags:tpdflags);
- procedure parse_var_proc_directives(sym:tsym);
- procedure parse_object_proc_directives(pd:tabstractprocdef);
- function parse_proc_head(aclass:tobjectdef;potype:tproctypeoption;var pd:tprocdef):boolean;
- function parse_proc_dec(aclass:tobjectdef):tprocdef;
- implementation
- uses
- strings,
- { common }
- cutils,cclasses,
- { global }
- globtype,globals,verbose,
- systems,
- cpuinfo,
- { symtable }
- symbase,symtable,defutil,defcmp,paramgr,cpupara,
- { pass 1 }
- node,htypechk,
- nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
- { parser }
- scanner,
- pbase,pexpr,ptype,pdecl
- ;
- const
- { Please leave this here, this module should NOT use
- these variables.
- Declaring it as string here results in an error when compiling (PFV) }
- current_procinfo = 'error';
- procedure insert_funcret_para(pd:tabstractprocdef);
- var
- storepos : tfileposinfo;
- vs : tparavarsym;
- paranr : word;
- begin
- if not(pd.proctypeoption in [potype_constructor,potype_destructor]) and
- not is_void(pd.rettype.def) and
- paramanager.ret_in_param(pd.rettype.def,pd.proccalloption) then
- begin
- storepos:=akttokenpos;
- if pd.deftype=procdef then
- akttokenpos:=tprocdef(pd).fileinfo;
- { For left to right add it at the end to be delphi compatible }
- if pd.proccalloption in pushleftright_pocalls then
- paranr:=paranr_result_leftright
- else
- paranr:=paranr_result;
- { Generate result variable accessing function result }
- vs:=tparavarsym.create('$result',paranr,vs_var,pd.rettype,[vo_is_funcret,vo_is_hidden_para]);
- pd.parast.insert(vs);
- { Store the this symbol as funcretsym for procedures }
- if pd.deftype=procdef then
- tprocdef(pd).funcretsym:=vs;
- akttokenpos:=storepos;
- end;
- end;
- procedure insert_parentfp_para(pd:tabstractprocdef);
- var
- storepos : tfileposinfo;
- vs : tparavarsym;
- begin
- if pd.parast.symtablelevel>normal_function_level then
- begin
- storepos:=akttokenpos;
- if pd.deftype=procdef then
- akttokenpos:=tprocdef(pd).fileinfo;
- { Generate result variable accessing function result, it
- can't be put in a register since it must be accessable
- from the framepointer }
- vs:=tparavarsym.create('$parentfp',paranr_parentfp,vs_var,voidpointertype,[vo_is_parentfp,vo_is_hidden_para]);
- vs.varregable:=vr_none;
- pd.parast.insert(vs);
- akttokenpos:=storepos;
- end;
- end;
- procedure insert_self_and_vmt_para(pd:tabstractprocdef);
- var
- storepos : tfileposinfo;
- vs : tparavarsym;
- tt : ttype;
- vsp : tvarspez;
- begin
- if (pd.deftype=procvardef) and
- pd.is_methodpointer then
- begin
- { Generate self variable }
- tt:=voidpointertype;
- vs:=tparavarsym.create('$self',paranr_self,vs_value,tt,[vo_is_self,vo_is_hidden_para]);
- pd.parast.insert(vs);
- end
- else
- begin
- if (pd.deftype=procdef) and
- assigned(tprocdef(pd)._class) and
- (pd.parast.symtablelevel=normal_function_level) then
- begin
- storepos:=akttokenpos;
- akttokenpos:=tprocdef(pd).fileinfo;
- { Generate VMT variable for constructor/destructor }
- if pd.proctypeoption in [potype_constructor,potype_destructor] then
- begin
- { can't use classrefdef as type because inheriting
- will then always file because of a type mismatch }
- tt:=voidpointertype;
- vs:=tparavarsym.create('$vmt',paranr_vmt,vs_value,tt,[vo_is_vmt,vo_is_hidden_para]);
- pd.parast.insert(vs);
- end;
- { Generate self variable, for classes we need
- to use the generic voidpointer to be compatible with
- methodpointers }
- vsp:=vs_value;
- if (po_staticmethod in pd.procoptions) or
- (po_classmethod in pd.procoptions) then
- begin
- tt.setdef(tprocdef(pd)._class);
- tt.setdef(tclassrefdef.create(tt));
- end
- else
- begin
- if is_object(tprocdef(pd)._class) then
- vsp:=vs_var;
- tt.setdef(tprocdef(pd)._class);
- end;
- vs:=tparavarsym.create('$self',paranr_self,vsp,tt,[vo_is_self,vo_is_hidden_para]);
- pd.parast.insert(vs);
- akttokenpos:=storepos;
- end;
- end;
- end;
- procedure insert_funcret_local(pd:tprocdef);
- var
- storepos : tfileposinfo;
- vs : tlocalvarsym;
- aliasvs : tabsolutevarsym;
- sl : tsymlist;
- begin
- { The result from constructors and destructors can't be accessed directly }
- if not(pd.proctypeoption in [potype_constructor,potype_destructor]) and
- not is_void(pd.rettype.def) then
- begin
- storepos:=akttokenpos;
- akttokenpos:=pd.fileinfo;
- { We always need a localsymtable }
- if not assigned(pd.localst) then
- pd.insert_localst;
- { We need to insert a varsym for the result in the localst
- when it is returning in a register }
- if not paramanager.ret_in_param(pd.rettype.def,pd.proccalloption) then
- begin
- vs:=tlocalvarsym.create('$result',vs_value,pd.rettype,[vo_is_funcret]);
- pd.localst.insert(vs);
- pd.funcretsym:=vs;
- end;
- { insert the name of the procedure as alias for the function result,
- we can't use realname because that will not work for compilerprocs
- as the name is lowercase and unreachable from the code }
- if pd.resultname='' then
- pd.resultname:=pd.procsym.name;
- sl:=tsymlist.create;
- sl.addsym(sl_load,pd.funcretsym);
- aliasvs:=tabsolutevarsym.create_ref(pd.resultname,pd.rettype,sl);
- include(aliasvs.varoptions,vo_is_funcret);
- pd.localst.insert(aliasvs);
- { insert result also if support is on }
- if (m_result in aktmodeswitches) then
- begin
- sl:=tsymlist.create;
- sl.addsym(sl_load,pd.funcretsym);
- aliasvs:=tabsolutevarsym.create_ref('RESULT',pd.rettype,sl);
- include(aliasvs.varoptions,vo_is_funcret);
- include(aliasvs.varoptions,vo_is_result);
- pd.localst.insert(aliasvs);
- end;
- akttokenpos:=storepos;
- end;
- end;
- procedure insert_hidden_para(p:tnamedindexitem;arg:pointer);
- var
- hvs : tparavarsym;
- pd : tabstractprocdef absolute arg;
- begin
- if (tsym(p).typ<>paravarsym) then
- exit;
- with tparavarsym(p) do
- begin
- { We need a local copy for a value parameter when only the
- address is pushed. Open arrays and Array of Const are
- an exception because they are allocated at runtime and the
- address that is pushed is patched }
- if (varspez=vs_value) and
- paramanager.push_addr_param(varspez,vartype.def,pd.proccalloption) and
- not(is_open_array(vartype.def) or
- is_array_of_const(vartype.def)) then
- include(varoptions,vo_has_local_copy);
- { needs high parameter ? }
- if paramanager.push_high_param(varspez,vartype.def,pd.proccalloption) then
- begin
- hvs:=tparavarsym.create('$high'+name,paranr+1,vs_const,sinttype,[vo_is_high_para,vo_is_hidden_para]);
- owner.insert(hvs);
- end
- else
- begin
- { Give a warning that cdecl routines does not include high()
- support }
- if (pd.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
- paramanager.push_high_param(varspez,vartype.def,pocall_default) then
- begin
- if is_open_string(vartype.def) then
- Message(parser_w_cdecl_no_openstring);
- if not (po_external in pd.procoptions) then
- Message(parser_w_cdecl_has_no_high);
- end;
- end;
- end;
- end;
- procedure check_c_para(p:tnamedindexitem;arg:pointer);
- begin
- if (tsym(p).typ<>paravarsym) then
- exit;
- with tparavarsym(p) do
- begin
- case vartype.def.deftype of
- arraydef :
- begin
- if not is_variant_array(vartype.def) and
- not is_array_of_const(vartype.def) then
- begin
- if (varspez<>vs_var) then
- Message(parser_h_c_arrays_are_references);
- end;
- if is_array_of_const(vartype.def) and
- assigned(indexnext) and
- (tsym(indexnext).typ=paravarsym) and
- not(vo_is_high_para in tparavarsym(indexnext).varoptions) then
- Message(parser_e_C_array_of_const_must_be_last);
- end;
- end;
- end;
- end;
- procedure check_msg_para(p:tnamedindexitem;arg:pointer);
- begin
- if (tsym(p).typ<>paravarsym) then
- exit;
- with tparavarsym(p) do
- begin
- { Count parameters }
- if (paranr>=10) then
- inc(plongint(arg)^);
- { First parameter must be var }
- if (paranr=10) and
- (varspez<>vs_var) then
- Message(parser_e_ill_msg_param);
- end;
- end;
- procedure check_inline_para(p:tnamedindexitem;arg:pointer);
- var
- pd : tabstractprocdef absolute arg;
- begin
- if (pd.proccalloption<>pocall_inline) or
- (tsym(p).typ<>paravarsym) then
- exit;
- with tparavarsym(p) do
- begin
- case vartype.def.deftype of
- arraydef :
- begin
- with tarraydef(vartype.def) do
- if IsVariant or IsConstructor then
- begin
- Message1(parser_w_not_supported_for_inline,'array of const');
- Message(parser_w_inlining_disabled);
- pd.proccalloption:=pocall_default;
- end;
- end;
- end;
- end;
- end;
- procedure set_addr_param_regable(p:tnamedindexitem;arg:pointer);
- begin
- if (tsym(p).typ<>paravarsym) then
- exit;
- with tparavarsym(p) do
- begin
- if not vartype.def.needs_inittable and
- paramanager.push_addr_param(varspez,vartype.def,tprocdef(arg).proccalloption) then
- varregable:=vr_intreg;
- end;
- end;
- procedure parse_parameter_dec(pd:tabstractprocdef);
- {
- handle_procvar needs the same changes
- }
- type
- tppv = (pv_none,pv_proc,pv_func);
- var
- sc : tsinglelist;
- tt : ttype;
- arrayelementtype : ttype;
- vs : tparavarsym;
- srsym : tsym;
- pv : tprocvardef;
- varspez : Tvarspez;
- defaultvalue : tconstsym;
- defaultrequired : boolean;
- old_object_option : tsymoptions;
- currparast : tparasymtable;
- parseprocvar : tppv;
- explicit_paraloc : boolean;
- locationstr : string;
- paranr : integer;
- dummytype : ttypesym;
- begin
- explicit_paraloc:=false;
- consume(_LKLAMMER);
- { Delphi/Kylix supports nonsense like }
- { procedure p(); }
- if try_to_consume(_RKLAMMER) and
- not(m_tp7 in aktmodeswitches) then
- exit;
- { parsing a proc or procvar ? }
- currparast:=tparasymtable(pd.parast);
- { reset }
- sc:=tsinglelist.create;
- defaultrequired:=false;
- paranr:=0;
- { the variables are always public }
- old_object_option:=current_object_option;
- current_object_option:=[sp_public];
- inc(testcurobject);
- repeat
- parseprocvar:=pv_none;
- if try_to_consume(_VAR) then
- varspez:=vs_var
- else
- if try_to_consume(_CONST) then
- varspez:=vs_const
- else
- if (m_out in aktmodeswitches) and
- try_to_consume(_OUT) then
- varspez:=vs_out
- else
- if (m_mac in aktmodeswitches) and
- try_to_consume(_POINTPOINTPOINT) then
- begin
- include(pd.procoptions,po_varargs);
- break;
- end
- else
- if (m_mac in aktmodeswitches) and
- try_to_consume(_PROCEDURE) then
- begin
- parseprocvar:=pv_proc;
- varspez:=vs_const;
- end
- else
- if (m_mac in aktmodeswitches) and
- try_to_consume(_FUNCTION) then
- begin
- parseprocvar:=pv_func;
- varspez:=vs_const;
- end
- else
- varspez:=vs_value;
- defaultvalue:=nil;
- tt.reset;
- { read identifiers and insert with error type }
- sc.reset;
- repeat
- inc(paranr);
- vs:=tparavarsym.create(orgpattern,paranr*10,varspez,generrortype,[]);
- currparast.insert(vs);
- if assigned(vs.owner) then
- sc.insert(vs)
- else
- vs.free;
- consume(_ID);
- until not try_to_consume(_COMMA);
- locationstr:='';
- { macpas anonymous procvar }
- if parseprocvar<>pv_none then
- begin
- pv:=tprocvardef.create(normal_function_level);
- if token=_LKLAMMER then
- parse_parameter_dec(pv);
- if parseprocvar=pv_func then
- begin
- consume(_COLON);
- single_type(pv.rettype,false);
- end;
- tt.def:=pv;
- { possible proc directives }
- if check_proc_directive(true) then
- begin
- dummytype:=ttypesym.create('unnamed',tt);
- parse_var_proc_directives(tsym(dummytype));
- dummytype.restype.def:=nil;
- tt.def.typesym:=nil;
- dummytype.free;
- end;
- { Add implicit hidden parameters and function result }
- handle_calling_convention(pv);
- end
- else
- { read type declaration, force reading for value and const paras }
- if (token=_COLON) or (varspez=vs_value) then
- begin
- consume(_COLON);
- { check for an open array }
- if token=_ARRAY then
- begin
- consume(_ARRAY);
- consume(_OF);
- { define range and type of range }
- tt.setdef(tarraydef.create(0,-1,s32inttype));
- { array of const ? }
- if (token=_CONST) and (m_objpas in aktmodeswitches) then
- begin
- consume(_CONST);
- srsym:=searchsymonlyin(systemunit,'TVARREC');
- if not assigned(srsym) then
- InternalError(200404181);
- tarraydef(tt.def).setelementtype(ttypesym(srsym).restype);
- tarraydef(tt.def).IsArrayOfConst:=true;
- end
- else
- begin
- { define field type }
- single_type(arrayelementtype,false);
- tarraydef(tt.def).setelementtype(arrayelementtype);
- end;
- end
- else
- begin
- { open string ? }
- if (varspez=vs_var) and
- (
- (
- ((token=_STRING) or (idtoken=_SHORTSTRING)) and
- (cs_openstring in aktmoduleswitches) and
- not(cs_ansistrings in aktlocalswitches)
- ) or
- (idtoken=_OPENSTRING)) then
- begin
- consume(token);
- tt:=openshortstringtype;
- end
- else
- begin
- { everything else }
- if (m_mac in aktmodeswitches) then
- try_to_consume(_UNIV); {currently does nothing}
- single_type(tt,false);
- end;
- if (target_info.system in [system_powerpc_morphos,system_m68k_amiga]) then
- begin
- if (idtoken=_LOCATION) then
- begin
- consume(_LOCATION);
- locationstr:=pattern;
- consume(_CSTRING);
- end
- else
- begin
- if explicit_paraloc then
- Message(parser_e_paraloc_all_paras);
- locationstr:='';
- end;
- end
- else
- locationstr:='';
- { default parameter }
- if (m_default_para in aktmodeswitches) then
- begin
- if try_to_consume(_EQUAL) then
- begin
- vs:=tparavarsym(sc.first);
- if assigned(vs.listnext) then
- Message(parser_e_default_value_only_one_para);
- { prefix 'def' to the parameter name }
- defaultvalue:=ReadConstant('$def'+vs.name,vs.fileinfo);
- if assigned(defaultvalue) then
- begin
- include(defaultvalue.symoptions,sp_internal);
- pd.parast.insert(defaultvalue);
- end;
- defaultrequired:=true;
- end
- else
- begin
- if defaultrequired then
- Message1(parser_e_default_value_expected_for_para,vs.name);
- end;
- end;
- end;
- end
- else
- tt:=cformaltype;
- { File types are only allowed for var parameters }
- if (tt.def.deftype=filedef) and
- (varspez<>vs_var) then
- CGMessage(cg_e_file_must_call_by_reference);
- vs:=tparavarsym(sc.first);
- while assigned(vs) do
- begin
- { update varsym }
- vs.vartype:=tt;
- vs.defaultconstsym:=defaultvalue;
- if (target_info.system in [system_powerpc_morphos,system_m68k_amiga]) then
- begin
- if locationstr<>'' then
- begin
- if assigned(sc.first.listnext) then
- Message(parser_e_paraloc_only_one_para);
- if (paranr>1) and not(explicit_paraloc) then
- Message(parser_e_paraloc_all_paras);
- explicit_paraloc:=true;
- include(vs.varoptions,vo_has_explicit_paraloc);
- if not(paramanager.parseparaloc(vs,upper(locationstr))) then
- message(parser_e_illegal_explicit_paraloc);
- end
- else
- if explicit_paraloc then
- Message(parser_e_paraloc_all_paras);
- end;
- vs:=tparavarsym(vs.listnext);
- end;
- until not try_to_consume(_SEMICOLON);
- if explicit_paraloc then
- begin
- pd.has_paraloc_info:=true;
- include(pd.procoptions,po_explicitparaloc);
- end;
- { remove parasymtable from stack }
- sc.free;
- { reset object options }
- dec(testcurobject);
- current_object_option:=old_object_option;
- consume(_RKLAMMER);
- end;
- function parse_proc_head(aclass:tobjectdef;potype:tproctypeoption;var pd:tprocdef):boolean;
- var
- orgsp,sp : stringid;
- sym : tsym;
- srsym : tsym;
- srsymtable : tsymtable;
- storepos,
- procstartfilepos : tfileposinfo;
- searchagain : boolean;
- i : longint;
- st : tsymtable;
- aprocsym : tprocsym;
- begin
- { Save the position where this procedure really starts }
- procstartfilepos:=akttokenpos;
- result:=false;
- pd:=nil;
- aprocsym:=nil;
- if (potype=potype_operator) then
- begin
- sp:=overloaded_names[optoken];
- orgsp:=sp;
- end
- else
- begin
- sp:=pattern;
- orgsp:=orgpattern;
- consume(_ID);
- end;
- { examine interface map: function/procedure iname.functionname=locfuncname }
- if assigned(aclass) and
- assigned(aclass.implementedinterfaces) and
- (aclass.implementedinterfaces.count>0) and
- try_to_consume(_POINT) then
- begin
- storepos:=akttokenpos;
- akttokenpos:=procstartfilepos;
- { get interface syms}
- searchsym(sp,sym,srsymtable);
- if not assigned(sym) then
- begin
- identifier_not_found(orgsp);
- sym:=generrorsym;
- end;
- akttokenpos:=storepos;
- { qualifier is interface? }
- if (sym.typ=typesym) and
- (ttypesym(sym).restype.def.deftype=objectdef) then
- i:=aclass.implementedinterfaces.searchintf(ttypesym(sym).restype.def)
- else
- i:=-1;
- if (i=-1) then
- Message(parser_e_interface_id_expected);
- consume(_ID);
- consume(_EQUAL);
- if (token=_ID) then
- aclass.implementedinterfaces.addmappings(i,sp,pattern);
- consume(_ID);
- result:=true;
- exit;
- end;
- { method ? }
- if not assigned(aclass) and
- (potype<>potype_operator) and
- (symtablestack.symtablelevel=main_program_level) and
- try_to_consume(_POINT) then
- begin
- { search for object name }
- storepos:=akttokenpos;
- akttokenpos:=procstartfilepos;
- searchsym(sp,sym,srsymtable);
- if not assigned(sym) then
- begin
- identifier_not_found(orgsp);
- sym:=generrorsym;
- end;
- akttokenpos:=storepos;
- { consume proc name }
- sp:=pattern;
- orgsp:=orgpattern;
- procstartfilepos:=akttokenpos;
- consume(_ID);
- { qualifier is class name ? }
- if (sym.typ=typesym) and
- (ttypesym(sym).restype.def.deftype=objectdef) then
- begin
- aclass:=tobjectdef(ttypesym(sym).restype.def);
- aprocsym:=tprocsym(aclass.symtable.search(sp));
- { we solve this below }
- if assigned(aprocsym) then
- begin
- if aprocsym.typ<>procsym then
- begin
- { we use a different error message for tp7 so it looks more compatible }
- if (m_fpc in aktmodeswitches) then
- Message1(parser_e_overloaded_no_procedure,aprocsym.realname)
- else
- Message(parser_e_methode_id_expected);
- { rename the name to an unique name to avoid an
- error when inserting the symbol in the symtable }
- orgsp:=orgsp+'$'+tostr(aktfilepos.line);
- aprocsym:=nil;
- end;
- end
- else
- begin
- Message(parser_e_methode_id_expected);
- { recover by making it a normal procedure instead of method }
- aclass:=nil;
- end;
- end
- else
- Message(parser_e_class_id_expected);
- end
- else
- begin
- { check for constructor/destructor which is not allowed here }
- if (not parse_only) and
- (potype in [potype_constructor,potype_destructor]) then
- Message(parser_e_constructors_always_objects);
- repeat
- searchagain:=false;
- akttokenpos:=procstartfilepos;
- srsym:=tsym(symtablestack.search(sp));
- if not(parse_only) and
- not assigned(srsym) and
- (symtablestack.symtabletype=staticsymtable) and
- assigned(symtablestack.next) and
- (symtablestack.next.iscurrentunit) then
- begin
- { The procedure we prepare for is in the implementation
- part of the unit we compile. It is also possible that we
- are compiling a program, which is also some kind of
- implementaion part.
- We need to find out if the procedure is global. If it is
- global, it is in the global symtable.}
- srsym:=tsym(symtablestack.next.search(sp));
- end;
- { Check if overloaded is a procsym }
- if assigned(srsym) then
- begin
- if srsym.typ=procsym then
- aprocsym:=tprocsym(srsym)
- else
- begin
- { when the other symbol is a unit symbol then hide the unit
- symbol }
- if (srsym.typ=unitsym) then
- begin
- srsym.owner.rename(srsym.name,'hidden'+srsym.name);
- searchagain:=true;
- end
- else
- begin
- { we use a different error message for tp7 so it looks more compatible }
- if (m_fpc in aktmodeswitches) then
- Message1(parser_e_overloaded_no_procedure,srsym.realname)
- else
- tstoredsymtable(symtablestack).DuplicateSym(nil,srsym);
- { rename the name to an unique name to avoid an
- error when inserting the symbol in the symtable }
- orgsp:=orgsp+'$'+tostr(aktfilepos.line);
- end;
- end;
- end;
- until not searchagain;
- end;
- { test again if assigned, it can be reset to recover }
- if not assigned(aprocsym) then
- begin
- { create a new procsym and set the real filepos }
- akttokenpos:=procstartfilepos;
- { for operator we have only one procsym for each overloaded
- operation }
- if (potype=potype_operator) then
- begin
- Aprocsym:=Tprocsym(symtablestack.search(sp));
- if Aprocsym=nil then
- Aprocsym:=tprocsym.create('$'+sp);
- end
- else
- aprocsym:=tprocsym.create(orgsp);
- symtablestack.insert(aprocsym);
- end;
- { to get the correct symtablelevel we must ignore objectsymtables }
- st:=symtablestack;
- while not(st.symtabletype in [staticsymtable,globalsymtable,localsymtable]) do
- st:=st.next;
- pd:=tprocdef.create(st.symtablelevel+1);
- pd._class:=aclass;
- pd.procsym:=aprocsym;
- pd.proctypeoption:=potype;
- { methods need to be exported }
- if assigned(aclass) and
- (
- (symtablestack.symtabletype=objectsymtable) or
- (symtablestack.symtablelevel=main_program_level)
- ) then
- include(pd.procoptions,po_global);
- { symbol options that need to be kept per procdef }
- pd.fileinfo:=procstartfilepos;
- pd.symoptions:=current_object_option;
- { parse parameters }
- if token=_LKLAMMER then
- parse_parameter_dec(pd);
- result:=true;
- end;
- function parse_proc_dec(aclass:tobjectdef):tprocdef;
- var
- pd : tprocdef;
- isclassmethod : boolean;
- begin
- pd:=nil;
- isclassmethod:=false;
- { read class method }
- if try_to_consume(_CLASS) then
- begin
- { class method only allowed for procedures and functions }
- if not(token in [_FUNCTION,_PROCEDURE]) then
- Message(parser_e_procedure_or_function_expected);
- if is_interface(aclass) then
- Message(parser_e_no_static_method_in_interfaces)
- else
- isclassmethod:=true;
- end;
- case token of
- _FUNCTION :
- begin
- consume(_FUNCTION);
- if parse_proc_head(aclass,potype_none,pd) then
- begin
- { pd=nil when it is a interface mapping }
- if assigned(pd) then
- begin
- if try_to_consume(_COLON) then
- begin
- inc(testcurobject);
- single_type(pd.rettype,false);
- pd.test_if_fpu_result;
- dec(testcurobject);
- end
- else
- begin
- if (
- parse_only and
- not(is_interface(pd._class))
- ) or
- (m_repeat_forward in aktmodeswitches) then
- begin
- consume(_COLON);
- consume_all_until(_SEMICOLON);
- end;
- end;
- if isclassmethod then
- include(pd.procoptions,po_classmethod);
- end;
- end
- else
- begin
- { recover }
- consume(_COLON);
- consume_all_until(_SEMICOLON);
- end;
- end;
- _PROCEDURE :
- begin
- consume(_PROCEDURE);
- if parse_proc_head(aclass,potype_none,pd) then
- begin
- { pd=nil when it is a interface mapping }
- if assigned(pd) then
- begin
- pd.rettype:=voidtype;
- if isclassmethod then
- include(pd.procoptions,po_classmethod);
- end;
- end;
- end;
- _CONSTRUCTOR :
- begin
- consume(_CONSTRUCTOR);
- parse_proc_head(aclass,potype_constructor,pd);
- if assigned(pd) and
- assigned(pd._class) then
- begin
- { Set return type, class constructors return the
- created instance, object constructors return boolean }
- if is_class(pd._class) then
- pd.rettype.setdef(pd._class)
- else
- pd.rettype:=booltype;
- end;
- end;
- _DESTRUCTOR :
- begin
- consume(_DESTRUCTOR);
- parse_proc_head(aclass,potype_destructor,pd);
- if assigned(pd) then
- pd.rettype:=voidtype;
- end;
- _OPERATOR :
- begin
- consume(_OPERATOR);
- if (token in [first_overloaded..last_overloaded]) then
- begin
- optoken:=token;
- end
- else
- begin
- Message(parser_e_overload_operator_failed);
- { Use the dummy NOTOKEN that is also declared
- for the overloaded_operator[] }
- optoken:=NOTOKEN;
- end;
- consume(token);
- parse_proc_head(aclass,potype_operator,pd);
- if assigned(pd) then
- begin
- if pd.parast.symtablelevel>normal_function_level then
- Message(parser_e_no_local_operator);
- if token<>_ID then
- begin
- if not(m_result in aktmodeswitches) then
- consume(_ID);
- end
- else
- begin
- pd.resultname:=orgpattern;
- consume(_ID);
- end;
- if not try_to_consume(_COLON) then
- begin
- consume(_COLON);
- pd.rettype:=generrortype;
- consume_all_until(_SEMICOLON);
- end
- else
- begin
- single_type(pd.rettype,false);
- pd.test_if_fpu_result;
- if (optoken in [_EQUAL,_GT,_LT,_GTE,_LTE]) and
- ((pd.rettype.def.deftype<>orddef) or
- (torddef(pd.rettype.def).typ<>bool8bit)) then
- Message(parser_e_comparative_operator_return_boolean);
- if (optoken=_ASSIGNMENT) and
- equal_defs(pd.rettype.def,
- tparavarsym(pd.parast.symindex.first).vartype.def) then
- message(parser_e_no_such_assignment)
- else if not isoperatoracceptable(pd,optoken) then
- Message(parser_e_overload_impossible);
- end;
- end
- else
- begin
- { recover }
- try_to_consume(_ID);
- consume(_COLON);
- consume_all_until(_SEMICOLON);
- end;
- end;
- end;
- { support procedure proc stdcall export; }
- if not(check_proc_directive(false)) then
- consume(_SEMICOLON);
- result:=pd;
- end;
- {****************************************************************************
- Procedure directive handlers
- ****************************************************************************}
- procedure pd_far(pd:tabstractprocdef);
- begin
- Message1(parser_w_proc_directive_ignored,'FAR');
- end;
- procedure pd_near(pd:tabstractprocdef);
- begin
- Message1(parser_w_proc_directive_ignored,'NEAR');
- end;
- procedure pd_export(pd:tabstractprocdef);
- begin
- if pd.deftype<>procdef then
- internalerror(200304264);
- if assigned(tprocdef(pd)._class) then
- Message(parser_e_methods_dont_be_export);
- if pd.parast.symtablelevel>normal_function_level then
- Message(parser_e_dont_nest_export);
- end;
- procedure pd_forward(pd:tabstractprocdef);
- begin
- if pd.deftype<>procdef then
- internalerror(200304265);
- tprocdef(pd).forwarddef:=true;
- end;
- procedure pd_alias(pd:tabstractprocdef);
- begin
- if pd.deftype<>procdef then
- internalerror(200304266);
- consume(_COLON);
- tprocdef(pd).aliasnames.insert(get_stringconst);
- include(pd.procoptions,po_has_public_name);
- end;
- procedure pd_public(pd:tabstractprocdef);
- begin
- if pd.deftype<>procdef then
- internalerror(200304266);
- if try_to_consume(_NAME) then
- begin
- tprocdef(pd).aliasnames.insert(get_stringconst);
- include(pd.procoptions,po_has_public_name);
- end;
- end;
- procedure pd_asmname(pd:tabstractprocdef);
- begin
- if pd.deftype<>procdef then
- internalerror(200304267);
- tprocdef(pd).aliasnames.insert(target_info.Cprefix+pattern);
- if token=_CCHAR then
- consume(_CCHAR)
- else
- consume(_CSTRING);
- { we don't need anything else }
- tprocdef(pd).forwarddef:=false;
- end;
- procedure pd_inline(pd:tabstractprocdef);
- begin
- { Check if there are parameters that can't be inlined }
- pd.parast.foreach_static(@check_inline_para,pd);
- end;
- procedure pd_internconst(pd:tabstractprocdef);
- begin
- if pd.deftype<>procdef then
- internalerror(200304268);
- consume(_COLON);
- tprocdef(pd).extnumber:=get_intconst;
- end;
- procedure pd_internproc(pd:tabstractprocdef);
- begin
- if pd.deftype<>procdef then
- internalerror(200304268);
- consume(_COLON);
- tprocdef(pd).extnumber:=get_intconst;
- { the proc is defined }
- tprocdef(pd).forwarddef:=false;
- end;
- procedure pd_interrupt(pd:tabstractprocdef);
- begin
- if pd.parast.symtablelevel>normal_function_level then
- Message(parser_e_dont_nest_interrupt);
- end;
- procedure pd_abstract(pd:tabstractprocdef);
- begin
- if pd.deftype<>procdef then
- internalerror(200304269);
- if (po_virtualmethod in pd.procoptions) then
- include(pd.procoptions,po_abstractmethod)
- else
- Message(parser_e_only_virtual_methods_abstract);
- { the method is defined }
- tprocdef(pd).forwarddef:=false;
- end;
- procedure pd_virtual(pd:tabstractprocdef);
- {$ifdef WITHDMT}
- var
- pt : tnode;
- {$endif WITHDMT}
- begin
- if pd.deftype<>procdef then
- internalerror(2003042610);
- if (pd.proctypeoption=potype_constructor) and
- is_object(tprocdef(pd)._class) then
- Message(parser_e_constructor_cannot_be_not_virtual);
- {$ifdef WITHDMT}
- if is_object(tprocdef(pd)._class) and
- (token<>_SEMICOLON) then
- begin
- { any type of parameter is allowed here! }
- pt:=comp_expr(true);
- if is_constintnode(pt) then
- begin
- include(pd.procoptions,po_msgint);
- pd.messageinf.i:=pt^.value;
- end
- else
- Message(parser_e_ill_msg_expr);
- disposetree(pt);
- end;
- {$endif WITHDMT}
- end;
- procedure pd_static(pd:tabstractprocdef);
- begin
- if (cs_static_keyword in aktmoduleswitches) then
- begin
- if pd.deftype=procdef then
- include(tprocdef(pd).procsym.symoptions,sp_static);
- include(pd.procoptions,po_staticmethod);
- end;
- end;
- procedure pd_override(pd:tabstractprocdef);
- begin
- if pd.deftype<>procdef then
- internalerror(2003042611);
- if not(is_class_or_interface(tprocdef(pd)._class)) then
- Message(parser_e_no_object_override);
- end;
- procedure pd_overload(pd:tabstractprocdef);
- begin
- if pd.deftype<>procdef then
- internalerror(2003042612);
- include(tprocdef(pd).procsym.symoptions,sp_has_overloaded);
- end;
- procedure pd_message(pd:tabstractprocdef);
- var
- pt : tnode;
- paracnt : longint;
- begin
- if pd.deftype<>procdef then
- internalerror(2003042613);
- if not is_class(tprocdef(pd)._class) then
- Message(parser_e_msg_only_for_classes);
- { check parameter type }
- paracnt:=0;
- pd.parast.foreach_static(@check_msg_para,@paracnt);
- if paracnt<>1 then
- Message(parser_e_ill_msg_param);
- pt:=comp_expr(true);
- if pt.nodetype=stringconstn then
- begin
- include(pd.procoptions,po_msgstr);
- tprocdef(pd).messageinf.str:=strnew(tstringconstnode(pt).value_str);
- end
- else
- if is_constintnode(pt) then
- begin
- include(pd.procoptions,po_msgint);
- tprocdef(pd).messageinf.i:=tordconstnode(pt).value;
- end
- else
- Message(parser_e_ill_msg_expr);
- pt.free;
- end;
- procedure pd_reintroduce(pd:tabstractprocdef);
- begin
- if pd.deftype<>procdef then
- internalerror(200401211);
- if not(is_class_or_interface(tprocdef(pd)._class)) then
- Message(parser_e_no_object_reintroduce);
- end;
- procedure pd_syscall(pd:tabstractprocdef);
- {$ifdef powerpc}
- var
- vs : tparavarsym;
- sym : tsym;
- symtable : tsymtable;
- {$endif powerpc}
- begin
- if pd.deftype<>procdef then
- internalerror(2003042614);
- tprocdef(pd).forwarddef:=false;
- {$ifdef powerpc}
- if target_info.system in [system_powerpc_morphos] then
- begin
- if idtoken=_LEGACY then
- begin
- consume(_LEGACY);
- include(pd.procoptions,po_syscall_legacy);
- end
- else if idtoken=_SYSV then
- begin
- consume(_SYSV);
- include(pd.procoptions,po_syscall_sysv);
- end
- else if idtoken=_BASESYSV then
- begin
- consume(_BASESYSV);
- include(pd.procoptions,po_syscall_basesysv);
- end
- else if idtoken=_SYSVBASE then
- begin
- consume(_SYSVBASE);
- include(pd.procoptions,po_syscall_sysvbase);
- end
- else if idtoken=_R12BASE then
- begin
- consume(_R12BASE);
- include(pd.procoptions,po_syscall_r12base);
- end
- else
- if syscall_convention='LEGACY' then
- include(pd.procoptions,po_syscall_legacy)
- else if syscall_convention='SYSV' then
- include(pd.procoptions,po_syscall_sysv)
- else if syscall_convention='BASESYSV' then
- include(pd.procoptions,po_syscall_basesysv)
- else if syscall_convention='SYSVBASE' then
- include(pd.procoptions,po_syscall_sysvbase)
- else if syscall_convention='R12BASE' then
- include(pd.procoptions,po_syscall_r12base)
- else
- internalerror(2005010404);
- if consume_sym(sym,symtable) then
- begin
- if (sym.typ=globalvarsym) and
- (
- (tabstractvarsym(sym).vartype.def.deftype=pointerdef) or
- is_32bitint(tabstractvarsym(sym).vartype.def)
- ) then
- begin
- tprocdef(pd).libsym:=sym;
- if po_syscall_legacy in tprocdef(pd).procoptions then
- begin
- vs:=tparavarsym.create('$syscalllib',paranr_syscall_legacy,vs_value,tabstractvarsym(sym).vartype,[vo_is_syscall_lib,vo_is_hidden_para,vo_has_explicit_paraloc]);
- paramanager.parseparaloc(vs,'A6');
- pd.parast.insert(vs);
- end
- else if po_syscall_sysv in tprocdef(pd).procoptions then
- begin
- { Nothing to be done for sysv here for now, but this might change }
- end
- else if po_syscall_basesysv in tprocdef(pd).procoptions then
- begin
- vs:=tparavarsym.create('$syscalllib',paranr_syscall_basesysv,vs_value,tabstractvarsym(sym).vartype,[vo_is_syscall_lib,vo_is_hidden_para]);
- pd.parast.insert(vs);
- end
- else if po_syscall_sysvbase in tprocdef(pd).procoptions then
- begin
- vs:=tparavarsym.create('$syscalllib',paranr_syscall_sysvbase,vs_value,tabstractvarsym(sym).vartype,[vo_is_syscall_lib,vo_is_hidden_para]);
- pd.parast.insert(vs);
- end
- else if po_syscall_r12base in tprocdef(pd).procoptions then
- begin
- vs:=tparavarsym.create('$syscalllib',paranr_syscall_r12base,vs_value,tabstractvarsym(sym).vartype,[vo_is_syscall_lib,vo_is_hidden_para,vo_has_explicit_paraloc]);
- paramanager.parseparaloc(vs,'R12');
- pd.parast.insert(vs);
- end
- else
- internalerror(2005010501);
- end
- else
- Message(parser_e_32bitint_or_pointer_variable_expected);
- end;
- (paramanager as tppcparamanager).create_funcretloc_info(pd,calleeside);
- (paramanager as tppcparamanager).create_funcretloc_info(pd,callerside);
- end;
- {$endif powerpc}
- tprocdef(pd).extnumber:=get_intconst;
- end;
- procedure pd_external(pd:tabstractprocdef);
- {
- If import_dll=nil the procedure is assumed to be in another
- object file. In that object file it should have the name to
- which import_name is pointing to. Otherwise, the procedure is
- assumed to be in the DLL to which import_dll is pointing to. In
- that case either import_nr<>0 or import_name<>nil is true, so
- the procedure is either imported by number or by name. (DM)
- }
- begin
- if pd.deftype<>procdef then
- internalerror(2003042615);
- with tprocdef(pd) do
- begin
- forwarddef:=false;
- { forbid local external procedures }
- if parast.symtablelevel>normal_function_level then
- Message(parser_e_no_local_proc_external);
- { If the procedure should be imported from a DLL, a constant string follows.
- This isn't really correct, an contant string expression follows
- so we check if an semicolon follows, else a string constant have to
- follow (FK) }
- if not(token=_SEMICOLON) and not(idtoken=_NAME) then
- begin
- import_dll:=stringdup(get_stringconst);
- if (idtoken=_NAME) then
- begin
- consume(_NAME);
- import_name:=stringdup(get_stringconst);
- if import_name^='' then
- message(parser_e_empty_import_name);
- end;
- if (idtoken=_INDEX) then
- begin
- {After the word index follows the index number in the DLL.}
- consume(_INDEX);
- import_nr:=get_intconst;
- end;
- { default is to used the realname of the procedure }
- if (import_nr=0) and not assigned(import_name) then
- import_name:=stringdup(procsym.realname);
- end
- else
- begin
- if (idtoken=_NAME) then
- begin
- consume(_NAME);
- import_name:=stringdup(get_stringconst);
- if import_name^='' then
- message(parser_e_empty_import_name);
- end;
- end;
- end;
- end;
- type
- pd_handler=procedure(pd:tabstractprocdef);
- proc_dir_rec=record
- idtok : ttoken;
- pd_flags : tpdflags;
- handler : pd_handler;
- pocall : tproccalloption;
- pooption : tprocoptions;
- mutexclpocall : tproccalloptions;
- mutexclpotype : tproctypeoptions;
- mutexclpo : tprocoptions;
- end;
- const
- {Should contain the number of procedure directives we support.}
- num_proc_directives=36;
- proc_direcdata:array[1..num_proc_directives] of proc_dir_rec=
- (
- (
- idtok:_ABSTRACT;
- pd_flags : [pd_interface,pd_object,pd_notobjintf];
- handler : @pd_abstract;
- pocall : pocall_none;
- pooption : [po_abstractmethod];
- mutexclpocall : [pocall_internproc,pocall_inline];
- mutexclpotype : [];
- mutexclpo : [po_exports,po_interrupt,po_external]
- ),(
- idtok:_ALIAS;
- pd_flags : [pd_implemen,pd_body,pd_notobjintf];
- handler : @pd_alias;
- pocall : pocall_none;
- pooption : [];
- mutexclpocall : [pocall_inline];
- mutexclpotype : [];
- mutexclpo : [po_external]
- ),(
- idtok:_ASMNAME;
- pd_flags : [pd_interface,pd_implemen,pd_notobjintf];
- handler : @pd_asmname;
- pocall : pocall_cdecl;
- pooption : [po_external];
- mutexclpocall : [pocall_internproc,pocall_inline];
- mutexclpotype : [];
- mutexclpo : [po_external]
- ),(
- idtok:_ASSEMBLER;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
- handler : nil;
- pocall : pocall_none;
- pooption : [po_assembler];
- mutexclpocall : [];
- mutexclpotype : [];
- mutexclpo : [po_external]
- ),(
- idtok:_C; {same as cdecl for mode mac}
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_cdecl;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_assembler,po_external]
- ),(
- idtok:_CDECL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_cdecl;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_assembler,po_external]
- ),(
- idtok:_DYNAMIC;
- pd_flags : [pd_interface,pd_object,pd_notobjintf];
- handler : @pd_virtual;
- pocall : pocall_none;
- pooption : [po_virtualmethod];
- mutexclpocall : [pocall_internproc,pocall_inline];
- mutexclpotype : [];
- mutexclpo : [po_exports,po_interrupt,po_external,po_overridingmethod]
- ),(
- idtok:_EXPORT;
- pd_flags : [pd_body,pd_interface,pd_implemen,pd_notobjintf];
- handler : @pd_export;
- pocall : pocall_none;
- pooption : [po_exports,po_global];
- mutexclpocall : [pocall_internproc,pocall_inline];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_external,po_interrupt]
- ),(
- idtok:_EXTERNAL;
- pd_flags : [pd_implemen,pd_interface,pd_notobject,pd_notobjintf];
- handler : @pd_external;
- pocall : pocall_none;
- pooption : [po_external];
- mutexclpocall : [pocall_internproc,pocall_inline,pocall_syscall];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_public,po_exports,po_interrupt,po_assembler]
- ),(
- idtok:_FAR;
- pd_flags : [pd_implemen,pd_body,pd_interface,pd_procvar,pd_notobject,pd_notobjintf];
- handler : @pd_far;
- pocall : pocall_none;
- pooption : [];
- mutexclpocall : [pocall_internproc,pocall_inline];
- mutexclpotype : [];
- mutexclpo : []
- ),(
- idtok:_FAR16;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar,pd_notobject];
- handler : nil;
- pocall : pocall_far16;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [];
- mutexclpo : [po_external]
- ),(
- idtok:_FORWARD;
- pd_flags : [pd_implemen,pd_notobject,pd_notobjintf];
- handler : @pd_forward;
- pocall : pocall_none;
- pooption : [];
- mutexclpocall : [pocall_internproc,pocall_inline];
- mutexclpotype : [];
- mutexclpo : [po_external]
- ),(
- idtok:_OLDFPCCALL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_oldfpccall;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [];
- mutexclpo : []
- ),(
- idtok:_INLINE;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
- handler : @pd_inline;
- pocall : pocall_inline;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_exports,po_external,po_interrupt,po_virtualmethod]
- ),(
- idtok:_INTERNCONST;
- pd_flags : [pd_interface,pd_body,pd_notobject,pd_notobjintf];
- handler : @pd_internconst;
- pocall : pocall_none;
- pooption : [po_internconst];
- mutexclpocall : [];
- mutexclpotype : [potype_operator];
- mutexclpo : []
- ),(
- idtok:_INTERNPROC;
- pd_flags : [pd_interface,pd_notobject,pd_notobjintf];
- handler : @pd_internproc;
- pocall : pocall_internproc;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
- mutexclpo : [po_exports,po_external,po_interrupt,po_assembler,po_iocheck,po_virtualmethod]
- ),(
- idtok:_INTERRUPT;
- pd_flags : [pd_implemen,pd_body,pd_notobject,pd_notobjintf];
- handler : @pd_interrupt;
- pocall : pocall_none;
- pooption : [po_interrupt];
- mutexclpocall : [pocall_internproc,pocall_cdecl,pocall_cppdecl,pocall_stdcall,
- pocall_inline,pocall_pascal,pocall_far16,pocall_oldfpccall];
- mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
- mutexclpo : [po_external]
- ),(
- idtok:_IOCHECK;
- pd_flags : [pd_implemen,pd_body,pd_notobjintf];
- handler : nil;
- pocall : pocall_none;
- pooption : [po_iocheck];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_external]
- ),(
- idtok:_MESSAGE;
- pd_flags : [pd_interface,pd_object,pd_notobjintf];
- handler : @pd_message;
- pocall : pocall_none;
- pooption : []; { can be po_msgstr or po_msgint }
- mutexclpocall : [pocall_inline,pocall_internproc];
- mutexclpotype : [potype_constructor,potype_destructor,potype_operator];
- mutexclpo : [po_interrupt,po_external]
- ),(
- idtok:_NEAR;
- pd_flags : [pd_implemen,pd_body,pd_procvar,pd_notobjintf];
- handler : @pd_near;
- pocall : pocall_none;
- pooption : [];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : []
- ),(
- idtok:_NOSTACKFRAME;
- pd_flags : [pd_implemen,pd_body,pd_procvar,pd_notobjintf];
- handler : nil;
- pocall : pocall_none;
- pooption : [po_nostackframe];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : []
- ),(
- idtok:_OVERLOAD;
- pd_flags : [pd_implemen,pd_interface,pd_body];
- handler : @pd_overload;
- pocall : pocall_none;
- pooption : [po_overload];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : []
- ),(
- idtok:_OVERRIDE;
- pd_flags : [pd_interface,pd_object,pd_notobjintf];
- handler : @pd_override;
- pocall : pocall_none;
- pooption : [po_overridingmethod,po_virtualmethod];
- mutexclpocall : [pocall_inline,pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_exports,po_external,po_interrupt,po_virtualmethod]
- ),(
- idtok:_PASCAL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_pascal;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_external]
- ),(
- idtok:_PUBLIC;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobject,pd_notobjintf];
- handler : @pd_public;
- pocall : pocall_none;
- pooption : [po_public,po_global];
- mutexclpocall : [pocall_internproc,pocall_inline];
- mutexclpotype : [];
- mutexclpo : [po_external]
- ),(
- idtok:_REGISTER;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_register;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_external]
- ),(
- idtok:_REINTRODUCE;
- pd_flags : [pd_interface,pd_object,pd_notobjintf];
- handler : @pd_reintroduce;
- pocall : pocall_none;
- pooption : [po_reintroduce];
- mutexclpocall : [pocall_inline,pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_external,po_interrupt,po_exports,po_overridingmethod]
- ),(
- idtok:_SAFECALL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_safecall;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_external]
- ),(
- idtok:_SOFTFLOAT;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_softfloat;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor];
- { it's available with po_external because the libgcc floating point routines on the arm
- uses this calling convention }
- mutexclpo : []
- ),(
- idtok:_STATIC;
- pd_flags : [pd_interface,pd_object,pd_notobjintf];
- handler : @pd_static;
- pocall : pocall_none;
- pooption : [po_staticmethod];
- mutexclpocall : [pocall_inline,pocall_internproc];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_external,po_interrupt,po_exports]
- ),(
- idtok:_STDCALL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_stdcall;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_external]
- ),(
- idtok:_SYSCALL;
- pd_flags : [pd_interface,pd_implemen,pd_notobject,pd_notobjintf];
- handler : @pd_syscall;
- pocall : pocall_syscall;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_external,po_assembler,po_interrupt,po_exports]
- ),(
- idtok:_VIRTUAL;
- pd_flags : [pd_interface,pd_object,pd_notobjintf];
- handler : @pd_virtual;
- pocall : pocall_none;
- pooption : [po_virtualmethod];
- mutexclpocall : [pocall_inline,pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_external,po_interrupt,po_exports,po_overridingmethod]
- ),(
- idtok:_CPPDECL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_cppdecl;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_assembler,po_external,po_virtualmethod]
- ),(
- idtok:_VARARGS;
- pd_flags : [pd_interface,pd_implemen,pd_procvar];
- handler : nil;
- pocall : pocall_none;
- pooption : [po_varargs];
- mutexclpocall : [pocall_internproc,pocall_stdcall,pocall_register,
- pocall_inline,pocall_far16,pocall_oldfpccall];
- mutexclpotype : [];
- mutexclpo : [po_assembler,po_interrupt]
- ),(
- idtok:_COMPILERPROC;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
- handler : nil;
- pocall : pocall_compilerproc;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor];
- mutexclpo : [po_interrupt]
- )
- );
- function check_proc_directive(isprocvar:boolean):boolean;
- var
- i : longint;
- begin
- result:=false;
- for i:=1 to num_proc_directives do
- if proc_direcdata[i].idtok=idtoken then
- begin
- if ((not isprocvar) or
- (pd_procvar in proc_direcdata[i].pd_flags)) and
- { don't eat a public directive in classes }
- not((idtoken=_PUBLIC) and (symtablestack.symtabletype=objectsymtable)) then
- result:=true;
- exit;
- end;
- end;
- function parse_proc_direc(pd:tabstractprocdef;var pdflags:tpdflags):boolean;
- {
- Parse the procedure directive, returns true if a correct directive is found
- }
- var
- p : longint;
- found : boolean;
- name : stringid;
- begin
- parse_proc_direc:=false;
- name:=tokeninfo^[idtoken].str;
- found:=false;
- { Hint directive? Then exit immediatly }
- if (m_hintdirective in aktmodeswitches) then
- begin
- case idtoken of
- _LIBRARY,
- _PLATFORM,
- _UNIMPLEMENTED,
- _DEPRECATED :
- exit;
- end;
- end;
- { C directive is MAC only, because it breaks too much existing code
- on other platforms (PFV) }
- if (idtoken=_C) and
- not(m_mac in aktmodeswitches) then
- exit;
- { retrieve data for directive if found }
- for p:=1 to num_proc_directives do
- if proc_direcdata[p].idtok=idtoken then
- begin
- found:=true;
- break;
- end;
- { Check if the procedure directive is known }
- if not found then
- begin
- { parsing a procvar type the name can be any
- next variable !! }
- if ((pdflags * [pd_procvar,pd_object])=[]) and
- not(idtoken=_PROPERTY) then
- Message1(parser_w_unknown_proc_directive_ignored,name);
- exit;
- end;
- { static needs a special treatment }
- if (idtoken=_STATIC) and not (cs_static_keyword in aktmoduleswitches) then
- exit;
- { check if method and directive not for object, like public.
- This needs to be checked also for procvars }
- if (pd_notobject in proc_direcdata[p].pd_flags) and
- (symtablestack.symtabletype=objectsymtable) then
- exit;
- { Conflicts between directives ? }
- if (pd.proctypeoption in proc_direcdata[p].mutexclpotype) or
- (pd.proccalloption in proc_direcdata[p].mutexclpocall) or
- ((pd.procoptions*proc_direcdata[p].mutexclpo)<>[]) then
- begin
- Message1(parser_e_proc_dir_conflict,name);
- exit;
- end;
- { set calling convention }
- if proc_direcdata[p].pocall<>pocall_none then
- begin
- if (po_hascallingconvention in pd.procoptions) then
- begin
- Message2(parser_w_proc_overriding_calling,
- proccalloptionStr[pd.proccalloption],
- proccalloptionStr[proc_direcdata[p].pocall]);
- end;
- { check if the target processor supports this calling convention }
- if not(proc_direcdata[p].pocall in supported_calling_conventions) then
- begin
- Message1(parser_e_illegal_calling_convention,proccalloptionStr[proc_direcdata[p].pocall]);
- { recover }
- proc_direcdata[p].pocall:=pocall_stdcall;
- end;
- pd.proccalloption:=proc_direcdata[p].pocall;
- include(pd.procoptions,po_hascallingconvention);
- end;
- if pd.deftype=procdef then
- begin
- { Check if the directive is only for objects }
- if (pd_object in proc_direcdata[p].pd_flags) and
- not assigned(tprocdef(pd)._class) then
- exit;
- { check if method and directive not for interface }
- if (pd_notobjintf in proc_direcdata[p].pd_flags) and
- is_interface(tprocdef(pd)._class) then
- exit;
- end;
- { consume directive, and turn flag on }
- consume(token);
- parse_proc_direc:=true;
- { Check the pd_flags if the directive should be allowed }
- if (pd_interface in pdflags) and
- not(pd_interface in proc_direcdata[p].pd_flags) then
- begin
- Message1(parser_e_proc_dir_not_allowed_in_interface,name);
- exit;
- end;
- if (pd_implemen in pdflags) and
- not(pd_implemen in proc_direcdata[p].pd_flags) then
- begin
- Message1(parser_e_proc_dir_not_allowed_in_implementation,name);
- exit;
- end;
- if (pd_procvar in pdflags) and
- not(pd_procvar in proc_direcdata[p].pd_flags) then
- begin
- Message1(parser_e_proc_dir_not_allowed_in_procvar,name);
- exit;
- end;
- { Return the new pd_flags }
- if not(pd_body in proc_direcdata[p].pd_flags) then
- exclude(pdflags,pd_body);
- { Add the correct flag }
- pd.procoptions:=pd.procoptions+proc_direcdata[p].pooption;
- { Call the handler }
- if pointer(proc_direcdata[p].handler)<>nil then
- proc_direcdata[p].handler(pd);
- end;
- function proc_get_importname(pd:tprocdef):string;
- begin
- result:='';
- if not(po_external in pd.procoptions) then
- internalerror(200412151);
- { import by number? }
- if pd.import_nr<>0 then
- begin
- { Nothing to do }
- end
- else
- { external name specified }
- if assigned(pd.import_name) then
- begin
- { Win32 imports need to use the normal name since to functions
- can refer to the same DLL function. This is also needed for compatability
- with Delphi and TP7 }
- if not(
- assigned(pd.import_dll) and
- (target_info.system in [system_i386_win32,system_i386_wdosx,
- system_i386_emx,system_i386_os2])
- ) then
- begin
- if not(pd.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
- result:=pd.import_name^
- else
- result:=target_info.Cprefix+pd.import_name^;
- end;
- end
- else
- begin
- { Default names when importing variables }
- case pd.proccalloption of
- pocall_cdecl :
- begin
- if assigned(pd._class) then
- result:=target_info.Cprefix+pd._class.objrealname^+'_'+pd.procsym.realname
- else
- result:=target_info.Cprefix+pd.procsym.realname;
- end;
- pocall_cppdecl :
- begin
- result:=target_info.Cprefix+pd.cplusplusmangledname;
- end;
- else
- begin
- {In MacPas a single "external" has the same effect as "external name 'xxx'" }
- if (m_mac in aktmodeswitches) then
- result:=tprocdef(pd).procsym.realname;
- end;
- end;
- end;
- end;
- procedure proc_set_mangledname(pd:tprocdef);
- var
- s : string;
- begin
- { When the mangledname is already set we aren't allowed to change
- it because it can already be used somewhere (PFV) }
- if not(po_has_mangledname in pd.procoptions) then
- begin
- if (po_external in pd.procoptions) then
- begin
- { External Procedures are only allowed to change the mangledname
- in their first declaration }
- if (pd.forwarddef or (not pd.hasforward)) then
- begin
- s:=proc_get_importname(pd);
- if s<>'' then
- pd.setmangledname(s);
- end;
- end
- else
- { Normal procedures }
- begin
- case pd.proccalloption of
- pocall_compilerproc :
- begin
- pd.setmangledname(lower(pd.procsym.name));
- end;
- end;
- end;
- end;
- { Public/exported alias names }
- if (po_public in pd.procoptions) and
- not(po_has_public_name in pd.procoptions) then
- begin
- case pd.proccalloption of
- pocall_cdecl :
- begin
- if assigned(pd._class) then
- pd.aliasnames.insert(target_info.Cprefix+pd._class.objrealname^+'_'+pd.procsym.realname)
- else
- pd.aliasnames.insert(target_info.Cprefix+pd.procsym.realname);
- end;
- pocall_cppdecl :
- begin
- pd.aliasnames.insert(target_info.Cprefix+pd.cplusplusmangledname);
- end;
- end;
- { prevent adding the alias a second time }
- include(pd.procoptions,po_has_public_name);
- end;
- end;
- procedure handle_calling_convention(pd:tabstractprocdef);
- begin
- { set the default calling convention if none provided }
- if not(po_hascallingconvention in pd.procoptions) then
- pd.proccalloption:=aktdefproccall
- else
- begin
- if pd.proccalloption=pocall_none then
- internalerror(200309081);
- end;
- { handle proccall specific settings }
- case pd.proccalloption of
- pocall_cdecl,
- pocall_cppdecl :
- begin
- { check C cdecl para types }
- pd.parast.foreach_static(@check_c_para,nil);
- end;
- pocall_far16 :
- begin
- { Temporary stub, must be rewritten to support OS/2 far16 }
- Message1(parser_w_proc_directive_ignored,'FAR16');
- end;
- pocall_inline :
- begin
- if not(cs_support_inline in aktmoduleswitches) then
- begin
- Message(parser_e_proc_inline_not_supported);
- pd.proccalloption:=pocall_default;
- end;
- end;
- end;
- { For varargs directive also cdecl and external must be defined }
- if (po_varargs in pd.procoptions) then
- begin
- { check first for external in the interface, if available there
- then the cdecl must also be there since there is no implementation
- available to contain it }
- if parse_only then
- begin
- { if external is available, then cdecl must also be available,
- procvars don't need external }
- if not((po_external in pd.procoptions) or
- (pd.deftype=procvardef)) and
- not(pd.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
- Message(parser_e_varargs_need_cdecl_and_external);
- end
- else
- begin
- { both must be defined now }
- if not((po_external in pd.procoptions) or
- (pd.deftype=procvardef)) or
- not(pd.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
- Message(parser_e_varargs_need_cdecl_and_external);
- end;
- end;
- { Make var parameters regable, this must be done after the calling
- convention is set. }
- pd.parast.foreach_static(@set_addr_param_regable,pd);
- { insert hidden high parameters }
- pd.parast.foreach_static(@insert_hidden_para,pd);
- { insert hidden self parameter }
- insert_self_and_vmt_para(pd);
- { insert funcret parameter if required }
- insert_funcret_para(pd);
- { insert parentfp parameter if required }
- insert_parentfp_para(pd);
- { Calculate parameter tlist }
- pd.calcparas;
- end;
- procedure parse_proc_directives(pd:tabstractprocdef;var pdflags:tpdflags);
- {
- Parse the procedure directives. It does not matter if procedure directives
- are written using ;procdir; or ['procdir'] syntax.
- }
- var
- res : boolean;
- begin
- if (m_mac in aktmodeswitches) and (cs_externally_visible in aktlocalswitches) then
- begin
- tprocdef(pd).aliasnames.insert(tprocdef(pd).procsym.realname);
- include(pd.procoptions,po_public);
- include(pd.procoptions,po_has_public_name);
- include(pd.procoptions,po_global);
- end;
- while token in [_ID,_LECKKLAMMER] do
- begin
- if try_to_consume(_LECKKLAMMER) then
- begin
- repeat
- parse_proc_direc(pd,pdflags);
- until not try_to_consume(_COMMA);
- consume(_RECKKLAMMER);
- { we always expect at least '[];' }
- res:=true;
- end
- else
- begin
- res:=parse_proc_direc(pd,pdflags);
- end;
- { A procedure directive normally followed by a semicolon, but in
- a const section or reading a type we should stop when _EQUAL is found,
- because a constant/default value follows }
- if res then
- begin
- if (block_type in [bt_const,bt_type]) and
- (token=_EQUAL) then
- break;
- { support procedure proc;stdcall export; }
- if not(check_proc_directive((pd.deftype=procvardef))) then
- begin
- { support "record p : procedure stdcall end;" and
- "var p : procedure stdcall = nil;" }
- if (pd_procvar in pdflags) and
- (token in [_END,_RKLAMMER,_EQUAL]) then
- break
- else
- consume(_SEMICOLON);
- end;
- end
- else
- break;
- end;
- end;
- procedure parse_var_proc_directives(sym:tsym);
- var
- pdflags : tpdflags;
- pd : tabstractprocdef;
- begin
- pdflags:=[pd_procvar];
- pd:=nil;
- case sym.typ of
- fieldvarsym,
- globalvarsym,
- localvarsym,
- paravarsym :
- pd:=tabstractprocdef(tabstractvarsym(sym).vartype.def);
- typedconstsym :
- pd:=tabstractprocdef(ttypedconstsym(sym).typedconsttype.def);
- typesym :
- pd:=tabstractprocdef(ttypesym(sym).restype.def);
- else
- internalerror(2003042617);
- end;
- if pd.deftype<>procvardef then
- internalerror(2003042618);
- { names should never be used anyway }
- parse_proc_directives(pd,pdflags);
- end;
- procedure parse_object_proc_directives(pd:tabstractprocdef);
- var
- pdflags : tpdflags;
- begin
- pdflags:=[pd_object];
- parse_proc_directives(pd,pdflags);
- end;
- function proc_add_definition(var pd:tprocdef):boolean;
- {
- Add definition aprocdef to the overloaded definitions of aprocsym. If a
- forwarddef is found and reused it returns true
- }
- var
- hd : tprocdef;
- ad,fd : tsym;
- s1,s2 : stringid;
- i : cardinal;
- forwardfound : boolean;
- po_comp : tprocoptions;
- aprocsym : tprocsym;
- begin
- forwardfound:=false;
- aprocsym:=tprocsym(pd.procsym);
- { check overloaded functions if the same function already exists }
- for i:=1 to aprocsym.procdef_count do
- begin
- hd:=aprocsym.procdef[i];
- { Skip overloaded definitions that are declared in other
- units }
- if hd.procsym<>aprocsym then
- continue;
- { check the parameters, for delphi/tp it is possible to
- leave the parameters away in the implementation (forwarddef=false).
- But for an overload declared function this is not allowed }
- if { check if empty implementation arguments match is allowed }
- (
- not(m_repeat_forward in aktmodeswitches) and
- not(pd.forwarddef) and
- (pd.maxparacount=0) and
- not(po_overload in hd.procoptions)
- ) or
- { check arguments }
- (
- (compare_paras(pd.paras,hd.paras,cp_none,[cpo_comparedefaultvalue])>=te_equal) and
- { for operators equal_paras is not enough !! }
- ((pd.proctypeoption<>potype_operator) or (optoken<>_ASSIGNMENT) or
- equal_defs(hd.rettype.def,pd.rettype.def))
- ) then
- begin
- { Check if we've found the forwarddef, if found then
- we need to update the forward def with the current
- implementation settings }
- if hd.forwarddef then
- begin
- forwardfound:=true;
- { Check if the procedure type and return type are correct,
- also the parameters must match also with the type }
- if (hd.proctypeoption<>pd.proctypeoption) or
- (
- (m_repeat_forward in aktmodeswitches) and
- (not((pd.maxparacount=0) or
- (compare_paras(pd.paras,hd.paras,cp_all,[cpo_comparedefaultvalue])>=te_equal)))
- ) or
- (
- ((m_repeat_forward in aktmodeswitches) or
- not(is_void(pd.rettype.def))) and
- (not equal_defs(hd.rettype.def,pd.rettype.def))) then
- begin
- MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,
- pd.fullprocname(false));
- aprocsym.write_parameter_lists(pd);
- break;
- end;
- { Check if both are declared forward }
- if hd.forwarddef and pd.forwarddef then
- begin
- MessagePos1(pd.fileinfo,parser_e_function_already_declared_public_forward,
- pd.fullprocname(false));
- end;
- { internconst or internproc only need to be defined once }
- if (hd.proccalloption=pocall_internproc) then
- pd.proccalloption:=hd.proccalloption
- else
- if (pd.proccalloption=pocall_internproc) then
- hd.proccalloption:=pd.proccalloption;
- { Check calling convention }
- if (hd.proccalloption<>pd.proccalloption) then
- begin
- { In delphi it is possible to specify the calling
- convention in the interface or implementation if
- there was no convention specified in the other
- part }
- if (m_delphi in aktmodeswitches) then
- begin
- if not(po_hascallingconvention in pd.procoptions) then
- pd.proccalloption:=hd.proccalloption
- else
- if not(po_hascallingconvention in hd.procoptions) then
- hd.proccalloption:=pd.proccalloption
- else
- begin
- MessagePos(pd.fileinfo,parser_e_call_convention_dont_match_forward);
- aprocsym.write_parameter_lists(pd);
- { restore interface settings }
- pd.proccalloption:=hd.proccalloption;
- end;
- end
- else
- begin
- MessagePos(pd.fileinfo,parser_e_call_convention_dont_match_forward);
- aprocsym.write_parameter_lists(pd);
- { restore interface settings }
- pd.proccalloption:=hd.proccalloption;
- end;
- end;
- { Check procedure options, Delphi requires that class is
- repeated in the implementation for class methods }
- if (m_fpc in aktmodeswitches) then
- po_comp:=[po_varargs,po_methodpointer,po_interrupt]
- else
- po_comp:=[po_classmethod,po_methodpointer];
- if ((po_comp * hd.procoptions)<>(po_comp * pd.procoptions)) then
- begin
- MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,
- pd.fullprocname(false));
- aprocsym.write_parameter_lists(pd);
- { This error is non-fatal, we can recover }
- end;
- { Forward declaration is external? }
- if (po_external in hd.procoptions) then
- MessagePos(pd.fileinfo,parser_e_proc_already_external);
- { Check parameters }
- if (m_repeat_forward in aktmodeswitches) or
- (pd.minparacount>0) then
- begin
- { If mangled names are equal then they have the same amount of arguments }
- { We can check the names of the arguments }
- { both symtables are in the same order from left to right }
- ad:=tsym(hd.parast.symindex.first);
- fd:=tsym(pd.parast.symindex.first);
- repeat
- { skip default parameter constsyms }
- while assigned(ad) and (ad.typ<>paravarsym) do
- ad:=tsym(ad.indexnext);
- while assigned(fd) and (fd.typ<>paravarsym) do
- fd:=tsym(fd.indexnext);
- { stop when one of the two lists is at the end }
- if not assigned(ad) or not assigned(fd) then
- break;
- { retrieve names, remove reg for register parameters }
- s1:=ad.name;
- s2:=fd.name;
- { compare names }
- if (s1<>s2) then
- begin
- MessagePos3(pd.fileinfo,parser_e_header_different_var_names,
- aprocsym.name,s1,s2);
- break;
- end;
- ad:=tsym(ad.indexnext);
- fd:=tsym(fd.indexnext);
- until false;
- if assigned(ad) xor assigned(fd) then
- internalerror(200204178);
- end;
- { Everything is checked, now we can update the forward declaration
- with the new data from the implementation }
- hd.forwarddef:=pd.forwarddef;
- hd.hasforward:=true;
- hd.procoptions:=hd.procoptions+pd.procoptions;
- if hd.extnumber=65535 then
- hd.extnumber:=pd.extnumber;
- while not pd.aliasnames.empty do
- hd.aliasnames.insert(pd.aliasnames.getfirst);
- { update fileinfo so position references the implementation,
- also update funcretsym if it is already generated }
- hd.fileinfo:=pd.fileinfo;
- if assigned(hd.funcretsym) then
- hd.funcretsym.fileinfo:=pd.fileinfo;
- { import names }
- if assigned(pd.import_dll) then
- begin
- stringdispose(hd.import_dll);
- hd.import_dll:=stringdup(pd.import_dll^);
- end;
- if assigned(pd.import_name) then
- begin
- stringdispose(hd.import_name);
- hd.import_name:=stringdup(pd.import_name^);
- end;
- hd.import_nr:=pd.import_nr;
- { for compilerproc defines we need to rename and update the
- symbolname to lowercase }
- if (pd.proccalloption=pocall_compilerproc) then
- begin
- { rename to lowercase so users can't access it }
- aprocsym.owner.rename(aprocsym.name,lower(aprocsym.name));
- { also update the realname that is stored in the ppu }
- stringdispose(aprocsym._realname);
- aprocsym._realname:=stringdup('$'+aprocsym.name);
- { the mangeled name is already changed by the pd_compilerproc }
- { handler. It must be done immediately because if we have a }
- { call to a compilerproc before it's implementation is }
- { encountered, it must already use the new mangled name (JM) }
- end;
- { the procdef will be released by the symtable, we release
- at least the parast }
- pd.releasemem;
- pd:=hd;
- end
- else
- begin
- { abstract methods aren't forward defined, but this }
- { needs another error message }
- if (po_abstractmethod in hd.procoptions) then
- MessagePos(pd.fileinfo,parser_e_abstract_no_definition)
- else
- begin
- MessagePos(pd.fileinfo,parser_e_overloaded_have_same_parameters);
- aprocsym.write_parameter_lists(pd);
- end;
- end;
- { we found one proc with the same arguments, there are no others
- so we can stop }
- break;
- end;
- { check for allowing overload directive }
- if not(m_fpc in aktmodeswitches) then
- begin
- { overload directive turns on overloading }
- if ((po_overload in pd.procoptions) or
- (po_overload in hd.procoptions)) then
- begin
- { check if all procs have overloading, but not if the proc is a method or
- already declared forward, then the check is already done }
- if not(hd.hasforward or
- assigned(pd._class) or
- (pd.forwarddef<>hd.forwarddef) or
- ((po_overload in pd.procoptions) and
- (po_overload in hd.procoptions))) then
- begin
- MessagePos1(pd.fileinfo,parser_e_no_overload_for_all_procs,aprocsym.realname);
- break;
- end;
- end
- else
- begin
- if not(hd.forwarddef) then
- begin
- MessagePos(pd.fileinfo,parser_e_procedure_overloading_is_off);
- break;
- end;
- end;
- end; { equal arguments }
- end;
- { if we didn't reuse a forwarddef then we add the procdef to the overloaded
- list }
- if not forwardfound then
- aprocsym.addprocdef(pd);
- proc_add_definition:=forwardfound;
- end;
- end.
- {
- $Log$
- Revision 1.229 2005-02-03 17:11:40 peter
- * more procvar directive fixes
- Revision 1.228 2005/02/01 08:46:13 michael
- * Patch from peter: fix macpas anonymous function procvar
- Revision 1.227 2005/01/31 21:27:51 peter
- * macpas procvars in parameters
- Revision 1.226 2005/01/19 22:19:41 peter
- * unit mapping rewrite
- * new derefmap added
- Revision 1.225 2005/01/06 02:13:03 karoly
- * more SysV call support stuff for MorphOS
- Revision 1.224 2005/01/05 02:31:06 karoly
- * fixed SysV syscall support (MorphOS)
- Revision 1.223 2005/01/04 17:40:33 karoly
- + sysv style syscalls added for MorphOS
- Revision 1.222 2004/12/27 17:32:06 peter
- * don't parse public,private,protected as procdirectives, leave
- procdirective parsing before any other check is done
- Revision 1.221 2004/12/26 20:12:23 peter
- * don't allow class methods in interfaces
- Revision 1.220 2004/12/15 19:30:32 peter
- * syscall with sysv abi for morphos
- Revision 1.219 2004/12/15 16:00:16 peter
- * external is again allowed in implementation
- Revision 1.218 2004/12/07 16:11:52 peter
- * set vo_explicit_paraloc flag
- Revision 1.217 2004/12/05 12:28:11 peter
- * procvar handling for tp procvar mode fixed
- * proc to procvar moved from addrnode to typeconvnode
- * inlininginfo is now allocated only for inline routines that
- can be inlined, introduced a new flag po_has_inlining_info
- Revision 1.216 2004/12/05 00:32:56 olle
- + bugfix for $Z+ for mode macpas
- Revision 1.215 2004/11/29 21:50:08 peter
- * public is allowd in interface
- Revision 1.214 2004/11/29 17:48:34 peter
- * when importing by index don't change mangledname
- Revision 1.213 2004/11/22 12:22:25 jonas
- * fixed importing of cdecl routines for OS'es which have a cprefix
- Revision 1.212 2004/11/21 17:54:59 peter
- * ttempcreatenode.create_reg merged into .create with parameter
- whether a register is allowed
- * funcret_paraloc renamed to funcretloc
- Revision 1.211 2004/11/21 16:33:19 peter
- * fixed message methods
- * fixed typo with win32 dll import from implementation
- * released external check
- Revision 1.210 2004/11/19 08:17:01 michael
- * Split po_public into po_public and po_global (Peter)
- Revision 1.209 2004/11/17 22:41:41 peter
- * make some checks EXTDEBUG only for now so linux cycles again
- Revision 1.208 2004/11/17 22:21:35 peter
- mangledname setting moved to place after the complete proc declaration is read
- import generation moved to place where body is also parsed (still gives problems with win32)
- Revision 1.207 2004/11/16 22:09:57 peter
- * _mangledname for symbols moved only to symbols that really need it
- * overload number removed, add function result type to the mangledname fo
- procdefs
- Revision 1.206 2004/11/16 20:32:40 peter
- * fixes for win32 mangledname
- Revision 1.205 2004/11/15 23:35:31 peter
- * tparaitem removed, use tparavarsym instead
- * parameter order is now calculated from paranr value in tparavarsym
- Revision 1.204 2004/11/14 16:26:29 florian
- * fixed morphos syscall
- Revision 1.203 2004/11/11 19:31:33 peter
- * fixed compile of powerpc,sparc,arm
- Revision 1.202 2004/11/09 22:32:59 peter
- * small m68k updates to bring it up2date
- * give better error for external local variable
- Revision 1.201 2004/11/09 17:26:47 peter
- * fixed wrong typecasts
- Revision 1.200 2004/11/08 22:09:59 peter
- * tvarsym splitted
- Revision 1.199 2004/11/05 21:16:55 peter
- * rename duplicate symbols and insert with unique name in the
- symtable
- Revision 1.198 2004/10/31 18:54:24 peter
- * $fpctarget expands to <cpu>-<os>
- * allow * in middle of the path to support ../*/units/$fpctarget
- Revision 1.197 2004/10/24 20:01:08 peter
- * remove saveregister calling convention
- Revision 1.196 2004/10/24 13:48:50 peter
- * don't give warning for property as unknwon proc directive
- Revision 1.195 2004/10/24 11:44:28 peter
- * small regvar fixes
- * loadref parameter removed from concatcopy,incrrefcount,etc
- Revision 1.194 2004/10/15 09:14:17 mazen
- - remove $IFDEF DELPHI and related code
- - remove $IFDEF FPCPROCVAR and related code
- Revision 1.193 2004/10/11 15:45:35 peter
- * mark non-regable after calling convention is set
- Revision 1.192 2004/10/10 21:08:55 peter
- * parameter regvar fixes
- Revision 1.191 2004/10/08 17:09:43 peter
- * tvarsym.varregable added, split vo_regable from varoptions
- Revision 1.190 2004/08/29 11:28:41 peter
- fixed crash with error in default value
- allow assembler directive in interface
- Revision 1.189 2004/08/25 15:57:19 peter
- * fix for tw3261
- Revision 1.188 2004/08/22 20:11:38 florian
- * morphos now takes any pointer var. as libbase
- * alignment for sparc fixed
- * int -> double conversion on sparc fixed
- Revision 1.187 2004/08/22 11:24:27 peter
- * don't insert result variables for constructor/destructors
- Revision 1.186 2004/08/13 17:53:37 jonas
- * only set the mangled name immediately for external procedures in macpas
- mode if the procedure isn't cdecl (so that the c-prefix is taken into
- account, necessary for Mac OS X)
- Revision 1.185 2004/08/08 12:35:09 florian
- * proc. var declarations in a class doesn't eat a public anymore
- Revision 1.184 2004/07/17 13:51:57 florian
- * function result location for syscalls on MOS hopefully correctly set now
- Revision 1.183 2004/07/14 23:19:21 olle
- + added external facilities for macpas
- Revision 1.182 2004/06/20 08:55:30 florian
- * logs truncated
- Revision 1.181 2004/06/16 20:07:09 florian
- * dwarf branch merged
- Revision 1.180 2004/05/23 20:54:39 peter
- * fixed 3114
- Revision 1.179 2004/05/23 19:06:26 peter
- * expect : after function when it is a forwarddef
- Revision 1.178 2004/05/12 13:21:09 karoly
- * few small changes to add syscall support to M68k/Amiga target
- Revision 1.177 2004/05/11 22:52:48 olle
- * Moved import_implicit_external to symsym
- }
|