1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448 |
- {
- 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
- { common }
- cclasses,
- { scanner }
- tokens,
- { symtable }
- symconst,symtype,symdef,symsym;
- type
- tpdflag=(
- pd_body, { directive needs a body }
- pd_implemen, { directive can be used in implementation section }
- pd_interface, { directive can be used in interface section }
- pd_object, { directive can be used with object declaration }
- pd_record, { directive can be used with record declaration }
- pd_procvar, { directive can be used with procvar declaration }
- pd_notobject, { directive can not be used with object declaration }
- pd_notrecord, { directive can not be used with record declaration }
- pd_notobjintf, { directive can not be used with interface declaration }
- pd_notprocvar, { directive can not be used with procvar declaration }
- pd_dispinterface,{ directive can be used with dispinterface methods }
- pd_cppobject, { directive can be used with cppclass }
- pd_objcclass, { directive can be used with objcclass }
- pd_objcprot, { directive can be used with objcprotocol }
- pd_nothelper, { directive can not be used with record/class helper declaration }
- pd_javaclass, { directive can be used with Java class }
- pd_intfjava { directive can be used with Java interface }
- );
- tpdflags=set of tpdflag;
- function check_proc_directive(isprocvar:boolean):boolean;
- function proc_get_importname(pd:tprocdef):string;
- procedure proc_set_mangledname(pd:tprocdef);
- 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);
- procedure parse_record_proc_directives(pd:tabstractprocdef);
- function parse_proc_head(astruct:tabstractrecorddef;potype:tproctypeoption;isgeneric:boolean;genericdef:tdef;generictypelist:tfphashobjectlist;out pd:tprocdef):boolean;
- function parse_proc_dec(isclassmethod:boolean;astruct:tabstractrecorddef;isgeneric:boolean):tprocdef;
- procedure parse_proc_dec_finish(pd:tprocdef;isclassmethod:boolean;astruct:tabstractrecorddef);
- { parse a record method declaration (not a (class) constructor/destructor) }
- function parse_record_method_dec(astruct: tabstractrecorddef; is_classdef: boolean;hadgeneric:boolean): tprocdef;
- { helper functions - they insert nested objects hierarchy to the symtablestack
- with object hierarchy
- }
- function push_child_hierarchy(obj:tabstractrecorddef):integer;
- function pop_child_hierarchy(obj:tabstractrecorddef):integer;
- function push_nested_hierarchy(obj:tabstractrecorddef):integer;
- function pop_nested_hierarchy(obj:tabstractrecorddef):integer;
- implementation
- uses
- SysUtils,
- { common }
- cutils,
- { global }
- globtype,globals,verbose,constexp,
- systems,
- cpuinfo,
- { assembler }
- aasmbase,
- { symtable }
- symbase,symcpu,symtable,symutil,defutil,defcmp,
- { parameter handling }
- paramgr,cpupara,
- { pass 1 }
- fmodule,node,htypechk,ncon,nld,
- objcutil,
- { parser }
- scanner,
- syscinfo,
- pbase,pexpr,ptype,pdecl,pparautl,pgenutil
- {$ifdef jvm}
- ,pjvm
- {$endif}
- ;
- 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';
- function push_child_hierarchy(obj:tabstractrecorddef):integer;
- var
- _class,hp : tobjectdef;
- begin
- if obj.typ=recorddef then
- begin
- symtablestack.push(obj.symtable);
- result:=1;
- exit;
- end;
- result:=0;
- { insert class hierarchy in the reverse order }
- hp:=nil;
- repeat
- _class:=tobjectdef(obj);
- while _class.childof<>hp do
- _class:=_class.childof;
- hp:=_class;
- symtablestack.push(_class.symtable);
- inc(result);
- until hp=obj;
- end;
- function push_nested_hierarchy(obj:tabstractrecorddef):integer;
- begin
- result:=0;
- if obj.owner.symtabletype in [ObjectSymtable,recordsymtable] then
- inc(result,push_nested_hierarchy(tabstractrecorddef(obj.owner.defowner)));
- inc(result,push_child_hierarchy(obj));
- end;
- function pop_child_hierarchy(obj:tabstractrecorddef):integer;
- var
- _class : tobjectdef;
- begin
- if obj.typ=recorddef then
- begin
- symtablestack.pop(obj.symtable);
- result:=1;
- exit;
- end;
- result:=0;
- _class:=tobjectdef(obj);
- while assigned(_class) do
- begin
- symtablestack.pop(_class.symtable);
- _class:=_class.childof;
- inc(result);
- end;
- end;
- function pop_nested_hierarchy(obj:tabstractrecorddef):integer;
- begin
- result:=pop_child_hierarchy(obj);
- if obj.owner.symtabletype in [ObjectSymtable,recordsymtable] then
- inc(result,pop_nested_hierarchy(tabstractrecorddef(obj.owner.defowner)));
- end;
- procedure check_msg_para(p:TObject;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
- MessagePos(fileinfo,parser_e_ill_msg_param);
- end;
- end;
- procedure parse_parameter_dec(pd:tabstractprocdef);
- {
- handle_procvar needs the same changes
- }
- type
- tppv = (pv_none,pv_proc,pv_func);
- var
- sc : TFPObjectList;
- hdef : tdef;
- arrayelementdef : tdef;
- vs : tparavarsym;
- i : longint;
- srsym : tsym;
- pv : tprocvardef;
- varspez : Tvarspez;
- defaultvalue : tconstsym;
- defaultrequired : boolean;
- old_block_type : tblock_type;
- currparast : tparasymtable;
- parseprocvar : tppv;
- locationstr : string;
- paranr : integer;
- dummytype : ttypesym;
- explicit_paraloc,
- need_array,
- is_univ: boolean;
- stoptions : TSingleTypeOptions;
- procedure handle_default_para_value;
- var
- convpd : tprocdef;
- doconv : tconverttype;
- nodetype : tnodetype;
- bt : tblock_type;
- begin
- { only allowed for types that can be represented by a
- constant expression }
- if try_to_consume(_EQ) then
- begin
- if (hdef.typ in [recorddef,variantdef,filedef,formaldef]) or
- is_object(hdef) or
- ((hdef.typ=arraydef) and
- not is_dynamic_array(hdef)) then
- Message1(type_e_invalid_default_value,FullTypeName(hdef,nil));
- vs:=tparavarsym(sc[0]);
- if sc.count>1 then
- Message(parser_e_default_value_only_one_para);
- if not(vs.varspez in [vs_value,vs_const,vs_constref]) then
- Message(parser_e_default_value_val_const);
- bt:=block_type;
- block_type:=bt_const;
- { prefix 'def' to the parameter name }
- defaultvalue:=ReadConstant('$def'+vs.name,vs.fileinfo,nodetype);
- block_type:=bt;
- if assigned(defaultvalue) then
- begin
- include(defaultvalue.symoptions,sp_internal);
- pd.parast.insert(defaultvalue);
- { check whether the default value is of the correct
- type }
- if compare_defs_ext(defaultvalue.constdef,hdef,nodetype,doconv,convpd,[])<=te_convert_operator then
- MessagePos2(defaultvalue.fileinfo,type_e_incompatible_types,FullTypeName(defaultvalue.constdef,hdef),FullTypeName(hdef,defaultvalue.constdef));
- end;
- defaultrequired:=true;
- end
- else
- begin
- if defaultrequired then
- Message1(parser_e_default_value_expected_for_para,vs.name);
- end;
- end;
- begin
- old_block_type:=block_type;
- explicit_paraloc:=false;
- consume(_LKLAMMER);
- { Delphi/Kylix supports nonsense like }
- { procedure p(); }
- if try_to_consume(_RKLAMMER) and
- not(m_tp7 in current_settings.modeswitches) then
- exit;
- { parsing a proc or procvar ? }
- currparast:=tparasymtable(pd.parast);
- { reset }
- sc:=TFPObjectList.create(false);
- defaultrequired:=false;
- paranr:=0;
- block_type:=bt_var;
- is_univ:=false;
- 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 current_settings.modeswitches) and
- try_to_consume(_OUT) then
- varspez:=vs_out
- else
- if try_to_consume(_CONSTREF) then
- varspez:=vs_constref
- else
- if (m_mac in current_settings.modeswitches) and
- try_to_consume(_POINTPOINTPOINT) then
- begin
- include(pd.procoptions,po_varargs);
- break;
- end
- else
- if (m_nested_procvars in current_settings.modeswitches) and
- try_to_consume(_PROCEDURE) then
- begin
- parseprocvar:=pv_proc;
- varspez:=vs_const;
- end
- else
- if (m_nested_procvars in current_settings.modeswitches) and
- try_to_consume(_FUNCTION) then
- begin
- parseprocvar:=pv_func;
- varspez:=vs_const;
- end
- else
- varspez:=vs_value;
- defaultvalue:=nil;
- hdef:=nil;
- { read identifiers and insert with error type }
- sc.clear;
- repeat
- inc(paranr);
- vs:=cparavarsym.create(orgpattern,paranr*10,varspez,generrordef,[]);
- currparast.insert(vs);
- if assigned(vs.owner) then
- sc.add(vs)
- else
- vs.free;
- consume(_ID);
- until not try_to_consume(_COMMA);
- locationstr:='';
- { macpas anonymous procvar }
- if parseprocvar<>pv_none then
- begin
- { inline procvar definitions are always nested procvars }
- pv:=cprocvardef.create(normal_function_level+1);
- if token=_LKLAMMER then
- parse_parameter_dec(pv);
- if parseprocvar=pv_func then
- begin
- block_type:=bt_var_type;
- consume(_COLON);
- single_type(pv.returndef,[]);
- block_type:=bt_var;
- end;
- hdef:=pv;
- { possible proc directives }
- if check_proc_directive(true) then
- begin
- dummytype:=ctypesym.create('unnamed',hdef);
- parse_var_proc_directives(tsym(dummytype));
- dummytype.typedef:=nil;
- hdef.typesym:=nil;
- dummytype.free;
- end;
- { Add implicit hidden parameters and function result }
- handle_calling_convention(pv,hcc_default_actions_intf);
- {$ifdef jvm}
- { anonymous -> no name }
- jvm_create_procvar_class('',pv);
- {$endif}
- end
- else
- { read type declaration, force reading for value paras }
- if (token=_COLON) or (varspez=vs_value) then
- begin
- consume(_COLON);
- { check for an open array }
- need_array:=false;
- { bitpacked open array are not yet supported }
- if (token=_PACKED) and
- not(cs_bitpacking in current_settings.localswitches) then
- begin
- consume(_PACKED);
- need_array:=true;
- end;
- if (token=_ARRAY) or
- need_array then
- begin
- consume(_ARRAY);
- consume(_OF);
- { define range and type of range }
- hdef:=carraydef.create_openarray;
- { array of const ? }
- if (token=_CONST) and (m_objpas in current_settings.modeswitches) then
- begin
- consume(_CONST);
- srsym:=search_system_type('TVARREC');
- tarraydef(hdef).elementdef:=ttypesym(srsym).typedef;
- include(tarraydef(hdef).arrayoptions,ado_IsArrayOfConst);
- end
- else
- begin
- { define field type }
- if m_delphi in current_settings.modeswitches then
- stoptions:=[stoAllowSpecialization]
- else
- stoptions:=[];
- single_type(arrayelementdef,stoptions);
- tarraydef(hdef).elementdef:=arrayelementdef;
- end;
- end
- else
- begin
- if (m_mac in current_settings.modeswitches) then
- is_univ:=try_to_consume(_UNIV);
- if try_to_consume(_TYPE) then
- hdef:=ctypedformaltype
- else
- begin
- block_type:=bt_var_type;
- single_type(hdef,[stoAllowSpecialization]);
- block_type:=bt_var;
- end;
- { open string ? }
- if is_shortstring(hdef) then
- begin
- case varspez of
- vs_var,vs_out:
- begin
- { not 100% Delphi-compatible: type xstr=string[255] cannot
- become an openstring there, while here it can }
- if (cs_openstring in current_settings.moduleswitches) and
- (tstringdef(hdef).len=255) then
- hdef:=openshortstringtype
- end;
- vs_value:
- begin
- { value "openstring" parameters don't make sense (the
- original string can never be modified, so there's no
- use in passing its original length), so change these
- into regular shortstring parameters (seems to be what
- Delphi also does) }
- if is_open_string(hdef) then
- hdef:=cshortstringtype;
- end;
- else
- ;
- end;
- end;
- if (target_info.system in [system_powerpc_morphos,system_m68k_amiga]) then
- begin
- if (idtoken=_LOCATION) then
- begin
- consume(_LOCATION);
- locationstr:=cstringpattern;
- 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 current_settings.modeswitches) then
- handle_default_para_value;
- end;
- end
- else
- hdef:=cformaltype;
- { File types are only allowed for var and out parameters }
- if (hdef.typ=filedef) and
- not(varspez in [vs_out,vs_var]) then
- CGMessage(cg_e_file_must_call_by_reference);
- { Dispinterfaces are restricted to using only automatable types }
- if (pd.typ=procdef) and is_dispinterface(tprocdef(pd).struct) and
- not is_automatable(hdef) then
- Message1(type_e_not_automatable,hdef.typename);
- { univ cannot be used with types whose size is not known at compile
- time }
- if is_univ and
- not is_valid_univ_para_type(hdef) then
- Message1(parser_e_invalid_univ_para,hdef.typename);
- for i:=0 to sc.count-1 do
- begin
- vs:=tparavarsym(sc[i]);
- vs.univpara:=is_univ;
- { update varsym }
- vs.vardef:=hdef;
- vs.defaultconstsym:=defaultvalue;
- if (target_info.system in [system_powerpc_morphos,system_m68k_amiga]) then
- begin
- if locationstr<>'' then
- begin
- if sc.count>1 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,locationstr)) then
- message(parser_e_illegal_explicit_paraloc);
- end
- else
- if explicit_paraloc then
- Message(parser_e_paraloc_all_paras);
- end;
- end;
- until not try_to_consume(_SEMICOLON);
- if explicit_paraloc then
- include(pd.procoptions,po_explicitparaloc);
- { remove parasymtable from stack }
- sc.free;
- { reset object options }
- block_type:=old_block_type;
- consume(_RKLAMMER);
- end;
- function parse_proc_head(astruct:tabstractrecorddef;potype:tproctypeoption;isgeneric:boolean;genericdef:tdef;generictypelist:tfphashobjectlist;out pd:tprocdef):boolean;
- var
- hs : string;
- orgsp,sp,orgspnongen,spnongen : TIDString;
- dummysym,srsym : tsym;
- checkstack : psymtablestackitem;
- oldfilepos,
- classstartfilepos,
- procstartfilepos : tfileposinfo;
- i,
- index : longint;
- addgendummy,
- hadspecialize,
- firstpart,
- found,
- searchagain : boolean;
- st,
- genericst: TSymtable;
- aprocsym : tprocsym;
- popclass : integer;
- ImplIntf : TImplementedInterface;
- old_parse_generic : boolean;
- old_current_structdef: tabstractrecorddef;
- old_current_genericdef,
- old_current_specializedef: tstoreddef;
- lasttoken,lastidtoken: ttoken;
- genericparams : tfphashobjectlist;
- procedure parse_operator_name;
- begin
- if (lasttoken in [first_overloaded..last_overloaded]) then
- begin
- optoken:=token;
- end
- else
- begin
- case lasttoken of
- _CARET:
- Message1(parser_e_overload_operator_failed,'**');
- _ID:
- case lastidtoken of
- _ENUMERATOR:optoken:=_OP_ENUMERATOR;
- _EXPLICIT:optoken:=_OP_EXPLICIT;
- _INC:optoken:=_OP_INC;
- _DEC:optoken:=_OP_DEC;
- _INITIALIZE:optoken:=_OP_INITIALIZE;
- _FINALIZE:optoken:=_OP_FINALIZE;
- _ADDREF:optoken:=_OP_ADDREF;
- _COPY:optoken:=_OP_COPY;
- else
- if (m_delphi in current_settings.modeswitches) then
- case lastidtoken of
- _IMPLICIT:optoken:=_ASSIGNMENT;
- _NEGATIVE:optoken:=_MINUS;
- _POSITIVE:optoken:=_PLUS;
- _LOGICALNOT:optoken:=_OP_NOT;
- _IN:optoken:=_OP_IN;
- _EQUAL:optoken:=_EQ;
- _NOTEQUAL:optoken:=_NE;
- _GREATERTHAN:optoken:=_GT;
- _GREATERTHANOREQUAL:optoken:=_GTE;
- _LESSTHAN:optoken:=_LT;
- _LESSTHANOREQUAL:optoken:=_LTE;
- _ADD:optoken:=_PLUS;
- _SUBTRACT:optoken:=_MINUS;
- _MULTIPLY:optoken:=_STAR;
- _DIVIDE:optoken:=_SLASH;
- _INTDIVIDE:optoken:=_OP_DIV;
- _MODULUS:optoken:=_OP_MOD;
- _LEFTSHIFT:optoken:=_OP_SHL;
- _RIGHTSHIFT:optoken:=_OP_SHR;
- _LOGICALAND:optoken:=_OP_AND;
- _LOGICALOR:optoken:=_OP_OR;
- _LOGICALXOR:optoken:=_OP_XOR;
- _BITWISEAND:optoken:=_OP_AND;
- _BITWISEOR:optoken:=_OP_OR;
- _BITWISEXOR:optoken:=_OP_XOR;
- else
- Message1(parser_e_overload_operator_failed,'');
- end
- else
- Message1(parser_e_overload_operator_failed,'');
- end
- else
- Message1(parser_e_overload_operator_failed,'');
- end;
- end;
- sp:=overloaded_names[optoken];
- orgsp:=sp;
- spnongen:=sp;
- orgspnongen:=orgsp;
- end;
- procedure consume_proc_name;
- var
- s : string;
- i : longint;
- sym : ttypesym;
- begin
- lasttoken:=token;
- lastidtoken:=idtoken;
- if assigned(genericparams) then
- for i:=0 to genericparams.count-1 do
- begin
- sym:=ttypesym(genericparams[i]);
- if (sym.typ<>constsym) and tstoreddef(sym.typedef).is_registered then
- begin
- sym.typedef.free;
- sym.typedef:=nil;
- end;
- sym.free;
- end;
- genericparams.free;
- genericparams:=nil;
- hadspecialize:=false;
- if potype=potype_operator then
- optoken:=NOTOKEN;
- if (potype=potype_operator) and (token<>_ID) then
- begin
- parse_operator_name;
- consume(token);
- end
- else
- begin
- sp:=pattern;
- orgsp:=orgpattern;
- spnongen:=sp;
- orgspnongen:=orgsp;
- if firstpart and
- not (m_delphi in current_settings.modeswitches) and
- (idtoken=_SPECIALIZE) then
- hadspecialize:=true;
- consume(_ID);
- if (isgeneric or (m_delphi in current_settings.modeswitches)) and
- (token in [_LT,_LSHARPBRACKET]) then
- begin
- consume(token);
- if token in [_GT,_RSHARPBRACKET] then
- message(type_e_type_id_expected)
- else
- begin
- genericparams:=parse_generic_parameters(true);
- if not assigned(genericparams) then
- internalerror(2015061201);
- if genericparams.count=0 then
- internalerror(2015061202);
- s:='';
- str(genericparams.count,s);
- spnongen:=sp;
- orgspnongen:=orgsp;
- sp:=sp+'$'+s;
- orgsp:=orgsp+'$'+s;
- end;
- if not try_to_consume(_GT) then
- consume(_RSHARPBRACKET);
- end;
- end;
- firstpart:=false;
- end;
- function search_object_name(const sp:TIDString;gen_error:boolean):tsym;
- var
- storepos:tfileposinfo;
- srsymtable:TSymtable;
- begin
- storepos:=current_tokenpos;
- current_tokenpos:=procstartfilepos;
- searchsym(sp,result,srsymtable);
- if not assigned(result) then
- begin
- if gen_error then
- identifier_not_found(orgsp);
- result:=generrorsym;
- end;
- current_tokenpos:=storepos;
- end;
- procedure consume_generic_interface;
- var
- genparalist : tfpobjectlist;
- prettyname,
- specializename : ansistring;
- genname,
- ugenname : tidstring;
- gencount : string;
- begin
- consume(_LSHARPBRACKET);
- genparalist:=tfpobjectlist.create(false);
- if not parse_generic_specialization_types(genparalist,nil,prettyname,specializename) then
- srsym:=generrorsym
- else
- begin
- str(genparalist.count,gencount);
- genname:=sp+'$'+gencount;
- { ToDo: handle nested interfaces }
- genname:=generate_generic_name(genname,specializename,'');
- ugenname:=upper(genname);
- srsym:=search_object_name(ugenname,false);
- if not assigned(srsym) then
- begin
- Message1(type_e_generic_declaration_does_not_match,sp+'<'+prettyname+'>');
- srsym:=nil;
- exit;
- end;
- end;
- genparalist.free;
- consume(_RSHARPBRACKET);
- end;
- function handle_generic_interface:boolean;
- var
- i : longint;
- sym : ttypesym;
- typesrsym : tsym;
- typesrsymtable : tsymtable;
- specializename,
- prettyname: ansistring;
- error : boolean;
- genname,
- ugenname : tidstring;
- module : tmodule;
- begin
- result:=false;
- if not assigned(genericparams) then
- exit;
- specializename:='$';
- prettyname:='';
- error:=false;
- for i:=0 to genericparams.count-1 do
- begin
- sym:=ttypesym(genericparams[i]);
- { ToDo: position }
- if not searchsym(upper(sym.RealName),typesrsym,typesrsymtable) then
- begin
- message1(sym_e_id_not_found,sym.name);
- error:=true;
- continue;
- end;
- if typesrsym.typ<>typesym then
- begin
- message(type_e_type_id_expected);
- error:=true;
- continue;
- end;
- module:=find_module_from_symtable(ttypesym(typesrsym).typedef.owner);
- if not assigned(module) then
- internalerror(2016112803);
- specializename:=specializename+'_$'+hexstr(module.moduleid,8)+'$$'+ttypesym(typesrsym).typedef.unique_id_str;
- if i>0 then
- prettyname:=prettyname+',';
- prettyname:=prettyname+ttypesym(typesrsym).prettyname;
- end;
- result:=true;
- if error then
- begin
- srsym:=generrorsym;
- exit;
- end;
- { ToDo: handle nested interfaces }
- genname:=generate_generic_name(sp,specializename,'');
- ugenname:=upper(genname);
- srsym:=search_object_name(ugenname,false);
- if not assigned(srsym) then
- begin
- Message1(type_e_generic_declaration_does_not_match,sp+'<'+prettyname+'>');
- srsym:=generrorsym;
- end;
- end;
- procedure specialize_generic_interface;
- var
- node : tnode;
- begin
- node:=factor(false,[ef_type_only,ef_had_specialize]);
- if node.nodetype=typen then
- begin
- sp:=ttypenode(node).typedef.typesym.name;
- end
- else
- sp:='';
- end;
- function check_generic_parameters(def:tstoreddef):boolean;
- var
- i : longint;
- declsym,
- implsym : tsym;
- impltype : ttypesym absolute implsym;
- implname : tsymstr;
- fileinfo : tfileposinfo;
- begin
- result:=true;
- if not assigned(def.genericparas) then
- internalerror(2018090102);
- if not assigned(genericparams) then
- internalerror(2018090103);
- if def.genericparas.count<>genericparams.count then
- internalerror(2018090104);
- for i:=0 to def.genericparas.count-1 do
- begin
- declsym:=tsym(def.genericparas[i]);
- implsym:=tsym(genericparams[i]);
- implname:=upper(genericparams.nameofindex(i));
- if declsym.name<>implname then
- begin
- messagepos1(implsym.fileinfo,sym_e_generic_type_param_mismatch,implsym.realname);
- messagepos1(declsym.fileinfo,sym_e_generic_type_param_decl,declsym.realname);
- result:=false;
- end;
- if ((implsym.typ=typesym) and (df_genconstraint in impltype.typedef.defoptions)) or
- (implsym.typ=constsym) then
- begin
- if implsym.typ=constsym then
- fileinfo:=impltype.fileinfo
- else
- fileinfo:=tstoreddef(impltype.typedef).genconstraintdata.fileinfo;
- messagepos(fileinfo,parser_e_generic_constraints_not_allowed_here);
- result:=false;
- end;
- end;
- end;
- begin
- sp:='';
- orgsp:='';
- spnongen:='';
- orgspnongen:='';
- { Save the position where this procedure really starts }
- procstartfilepos:=current_tokenpos;
- old_parse_generic:=parse_generic;
- firstpart:=true;
- result:=false;
- pd:=nil;
- aprocsym:=nil;
- srsym:=nil;
- genericparams:=nil;
- hadspecialize:=false;
- addgendummy:=false;
- if not assigned(genericdef) then
- begin
- consume_proc_name;
- { examine interface map: function/procedure iname.functionname=locfuncname }
- if assigned(astruct) and
- (astruct.typ=objectdef) and
- assigned(tobjectdef(astruct).ImplementedInterfaces) and
- (tobjectdef(astruct).ImplementedInterfaces.count>0) and
- (
- (token=_POINT) or
- (
- hadspecialize and
- (token=_ID)
- )
- ) then
- begin
- if hadspecialize and (token=_ID) then
- specialize_generic_interface;
- consume(_POINT);
- if hadspecialize or not handle_generic_interface then
- srsym:=search_object_name(sp,true);
- { qualifier is interface? }
- ImplIntf:=nil;
- if assigned(srsym) and
- (srsym.typ=typesym) and
- (ttypesym(srsym).typedef.typ=objectdef) then
- ImplIntf:=find_implemented_interface(tobjectdef(astruct),tobjectdef(ttypesym(srsym).typedef));
- if ImplIntf=nil then
- begin
- Message(parser_e_interface_id_expected);
- { error recovery }
- consume(_ID);
- if try_to_consume(_EQ) then
- consume(_ID);
- exit;
- end
- else
- { in case of a generic or specialized interface we need to use the
- name of the def instead of the symbol, so that always the correct
- name is used }
- if [df_generic,df_specialization]*ttypesym(srsym).typedef.defoptions<>[] then
- sp:=tobjectdef(ttypesym(srsym).typedef).objname^;
- { must be a directly implemented interface }
- if Assigned(ImplIntf.ImplementsGetter) then
- Message2(parser_e_implements_no_mapping,ImplIntf.IntfDef.typename,astruct.objrealname^);
- consume(_ID);
- { Create unique name <interface>.<method> }
- hs:=sp+'.'+pattern;
- consume(_EQ);
- if assigned(ImplIntf) and
- (token=_ID) then
- ImplIntf.AddMapping(hs,pattern);
- consume(_ID);
- result:=true;
- exit;
- end;
- if assigned(genericparams) and assigned(current_genericdef) then
- Message(parser_f_no_generic_inside_generic);
- { method ? }
- srsym:=nil;
- if not assigned(astruct) and
- (symtablestack.top.symtablelevel=main_program_level) and
- try_to_consume(_POINT) then
- begin
- repeat
- classstartfilepos:=procstartfilepos;
- searchagain:=false;
- { throw the error at the right location }
- oldfilepos:=current_filepos;
- current_filepos:=procstartfilepos;
- if not assigned(astruct) and not assigned(srsym) then
- srsym:=search_object_name(sp,true);
- current_filepos:=oldfilepos;
- { we need to check whether the names of the generic parameter
- types match with the one in the declaration of a class/record,
- but we need to do this before consume_proc_name frees the
- type parameters of the class part }
- if (srsym.typ=typesym) and
- (ttypesym(srsym).typedef.typ in [objectdef,recorddef]) and
- tstoreddef(ttypesym(srsym).typedef).is_generic and
- assigned(genericparams) then
- { this is recoverable, so no further action necessary }
- check_generic_parameters(tstoreddef(ttypesym(srsym).typedef));
- { consume proc name }
- procstartfilepos:=current_tokenpos;
- consume_proc_name;
- { qualifier is class name ? }
- if (srsym.typ=typesym) and
- (ttypesym(srsym).typedef.typ in [objectdef,recorddef]) then
- begin
- astruct:=tabstractrecorddef(ttypesym(srsym).typedef);
- if (token<>_POINT) then
- if (potype in [potype_class_constructor,potype_class_destructor]) then
- sp:=lower(sp)
- else
- if (potype=potype_operator) and (optoken=NOTOKEN) then
- parse_operator_name;
- srsym:=tsym(astruct.symtable.Find(sp));
- if assigned(srsym) then
- begin
- if srsym.typ=procsym then
- aprocsym:=tprocsym(srsym)
- else
- if (srsym.typ=typesym) and
- (ttypesym(srsym).typedef.typ in [objectdef,recorddef]) then
- begin
- searchagain:=true;
- consume(_POINT);
- end
- else
- begin
- { we use a different error message for tp7 so it looks more compatible }
- if (m_fpc in current_settings.modeswitches) then
- Message1(parser_e_overloaded_no_procedure,srsym.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(current_filepos.line);
- end;
- end
- else
- begin
- MessagePos(procstartfilepos,parser_e_methode_id_expected);
- { recover by making it a normal procedure instead of method }
- astruct:=nil;
- end;
- end
- else
- MessagePos(classstartfilepos,parser_e_class_id_expected);
- until not searchagain;
- end
- else
- begin
- { check for constructor/destructor/class operators which are not allowed here }
- if (not parse_only) and
- ((potype in [potype_constructor,potype_destructor,
- potype_class_constructor,potype_class_destructor]) or
- ((potype=potype_operator) and (m_delphi in current_settings.modeswitches))) then
- Message(parser_e_only_methods_allowed);
- repeat
- { only 1 class constructor and destructor is allowed in the class and
- the check was already done with oo_has_class_constructor or
- oo_has_class_destructor -> skip searching
- (bug #28801) }
- if (potype in [potype_class_constructor,potype_class_destructor]) then
- break;
- searchagain:=false;
- current_tokenpos:=procstartfilepos;
- if (potype=potype_operator)and(optoken=NOTOKEN) then
- parse_operator_name;
- srsym:=tsym(symtablestack.top.Find(sp));
- { Also look in the globalsymtable if we didn't found
- the symbol in the localsymtable }
- if not assigned(srsym) and
- not(parse_only) and
- (symtablestack.top=current_module.localsymtable) and
- assigned(current_module.globalsymtable) then
- srsym:=tsym(current_module.globalsymtable.Find(sp));
- { 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, this is not supported in tp7 }
- if not(m_tp7 in current_settings.modeswitches) and
- (srsym.typ=unitsym) then
- begin
- HideSym(srsym);
- searchagain:=true;
- end
- else
- if (m_delphi in current_settings.modeswitches) and
- (srsym.typ=absolutevarsym) and
- ([vo_is_funcret,vo_is_result]*tabstractvarsym(srsym).varoptions=[vo_is_funcret]) then
- begin
- HideSym(srsym);
- searchagain:=true;
- end
- else if (srsym.typ=typesym) and
- (sp_generic_dummy in srsym.symoptions) and
- (ttypesym(srsym).typedef.typ=undefineddef) and
- not assigned(genericparams) then
- begin
- { this is a generic dummy symbol that has not yet
- been used; so we rename the dummy symbol and continue
- as if nothing happened }
- hidesym(srsym);
- searchagain:=true;
- addgendummy:=true;
- end
- else
- begin
- { we use a different error message for tp7 so it looks more compatible }
- if (m_fpc in current_settings.modeswitches) then
- Message1(parser_e_overloaded_no_procedure,srsym.realname)
- else
- Message1(sym_e_duplicate_id,srsym.realname);
- { rename the name to an unique name to avoid an
- error when inserting the symbol in the symtable }
- orgsp:=orgsp+'$'+tostr(current_filepos.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 }
- current_tokenpos:=procstartfilepos;
- { for operator we have only one procsym for each overloaded
- operation }
- if (potype=potype_operator) then
- begin
- aprocsym:=Tprocsym(symtablestack.top.Find(sp));
- if aprocsym=nil then
- aprocsym:=cprocsym.create('$'+sp);
- end
- else
- if (potype in [potype_class_constructor,potype_class_destructor]) then
- aprocsym:=cprocsym.create('$'+lower(sp))
- else
- aprocsym:=cprocsym.create(orgsp);
- if addgendummy then
- include(aprocsym.symoptions,sp_generic_dummy);
- symtablestack.top.insert(aprocsym);
- end;
- end;
- { to get the correct symtablelevel we must ignore ObjectSymtables }
- st:=nil;
- checkstack:=symtablestack.stack;
- while assigned(checkstack) do
- begin
- st:=checkstack^.symtable;
- if st.symtabletype in [staticsymtable,globalsymtable,localsymtable] then
- break;
- checkstack:=checkstack^.next;
- end;
- pd:=cprocdef.create(st.symtablelevel+1,not assigned(genericdef));
- pd.struct:=astruct;
- pd.procsym:=aprocsym;
- pd.proctypeoption:=potype;
- if assigned(genericparams) then
- begin
- if potype=potype_constructor then
- begin
- Message(parser_e_constructurs_cannot_take_type_parameters);
- genericparams.free;
- genericparams:=nil;
- end
- else
- begin
- include(pd.defoptions,df_generic);
- { push the parameter symtable so that constraint definitions are added
- there and not in the owner symtable }
- symtablestack.push(pd.parast);
- { register the parameters }
- for i:=0 to genericparams.count-1 do
- begin
- tsym(genericparams[i]).register_sym;
- if tsym(genericparams[i]).typ=typesym then
- tstoreddef(ttypesym(genericparams[i]).typedef).register_def;
- end;
- insert_generic_parameter_types(pd,nil,genericparams);
- { the list is no longer required }
- genericparams.free;
- genericparams:=nil;
- symtablestack.pop(pd.parast);
- parse_generic:=true;
- { also generate a dummy symbol if none exists already }
- if assigned(astruct) then
- dummysym:=tsym(astruct.symtable.find(spnongen))
- else
- begin
- dummysym:=tsym(symtablestack.top.find(spnongen));
- if not assigned(dummysym) and
- (symtablestack.top=current_module.localsymtable) and
- assigned(current_module.globalsymtable) then
- dummysym:=tsym(current_module.globalsymtable.find(spnongen));
- end;
- if not assigned(dummysym) then
- begin
- { overloading generic routines with non-generic types is not
- allowed, so we create a procsym as dummy }
- dummysym:=cprocsym.create(orgspnongen);
- if assigned(astruct) then
- astruct.symtable.insert(dummysym)
- else
- symtablestack.top.insert(dummysym);
- end
- else if (dummysym.typ<>procsym) and
- (
- { show error only for the declaration, not also the implementation }
- not assigned(astruct) or
- (symtablestack.top.symtablelevel<>main_program_level)
- ) then
- Message1(sym_e_duplicate_id,dummysym.realname);
- if not (sp_generic_dummy in dummysym.symoptions) then
- begin
- include(dummysym.symoptions,sp_generic_dummy);
- add_generic_dummysym(dummysym);
- end;
- if dummysym.typ=procsym then
- tprocsym(dummysym).add_generic_overload(aprocsym);
- { start token recorder for the declaration }
- pd.init_genericdecl;
- current_scanner.startrecordtokens(pd.genericdecltokenbuf);
- end;
- end
- else if assigned(genericdef) then
- insert_generic_parameter_types(pd,tstoreddef(genericdef),generictypelist);
- { methods inherit df_generic or df_specialization from the objectdef }
- if assigned(pd.struct) and
- (pd.parast.symtablelevel=normal_function_level) then
- begin
- if (df_generic in pd.struct.defoptions) then
- begin
- include(pd.defoptions,df_generic);
- parse_generic:=true;
- end;
- if (df_specialization in pd.struct.defoptions) then
- begin
- if assigned(current_specializedef) then
- begin
- include(pd.defoptions,df_specialization);
- { Find corresponding genericdef, we need it later to
- replay the tokens to generate the body }
- if not assigned(pd.struct.genericdef) then
- internalerror(200512113);
- genericst:=pd.struct.genericdef.GetSymtable(gs_record);
- if not assigned(genericst) then
- internalerror(200512114);
- { when searching for the correct procdef to use as genericdef we need to ignore
- everything except procdefs so that we can find the correct indices }
- index:=0;
- found:=false;
- for i:=0 to pd.owner.deflist.count-1 do
- begin
- if tdef(pd.owner.deflist[i]).typ<>procdef then
- continue;
- if pd.owner.deflist[i]=pd then
- begin
- found:=true;
- break;
- end;
- inc(index);
- end;
- if not found then
- internalerror(2014052301);
- for i:=0 to genericst.deflist.count-1 do
- begin
- if tdef(genericst.deflist[i]).typ<>procdef then
- continue;
- if index=0 then
- pd.genericdef:=tstoreddef(genericst.deflist[i]);
- dec(index);
- end;
- if not assigned(pd.genericdef) or
- (pd.genericdef.typ<>procdef) then
- internalerror(200512115);
- end
- else
- Message(parser_e_explicit_method_implementation_for_specializations_not_allowed);
- end;
- end;
- { methods need to be exported }
- if assigned(astruct) and
- (
- (symtablestack.top.symtabletype in [ObjectSymtable,recordsymtable]) or
- (symtablestack.top.symtablelevel=main_program_level)
- ) then
- include(pd.procoptions,po_global);
- { symbol options that need to be kept per procdef }
- pd.fileinfo:=procstartfilepos;
- pd.visibility:=symtablestack.top.currentvisibility;
- if symtablestack.top.currentlyoptional then
- include(pd.procoptions,po_optional);
- { parse parameters }
- if token=_LKLAMMER then
- begin
- old_current_structdef:=nil;
- old_current_genericdef:=current_genericdef;
- old_current_specializedef:=nil;
- { Add ObjectSymtable to be able to find nested type definitions }
- popclass:=0;
- if assigned(pd.struct) and
- (pd.parast.symtablelevel>=normal_function_level) and
- not(symtablestack.top.symtabletype in [ObjectSymtable,recordsymtable]) then
- begin
- popclass:=push_nested_hierarchy(pd.struct);
- old_current_structdef:=current_structdef;
- old_current_specializedef:=current_specializedef;
- current_structdef:=pd.struct;
- if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then
- current_genericdef:=current_structdef;
- if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
- current_specializedef:=current_structdef;
- end;
- if pd.is_generic then
- current_genericdef:=pd;
- { Add parameter symtable }
- if pd.parast.symtabletype<>staticsymtable then
- symtablestack.push(pd.parast);
- parse_parameter_dec(pd);
- if pd.parast.symtabletype<>staticsymtable then
- symtablestack.pop(pd.parast);
- current_genericdef:=old_current_genericdef;
- if popclass>0 then
- begin
- current_structdef:=old_current_structdef;
- current_specializedef:=old_current_specializedef;
- dec(popclass,pop_nested_hierarchy(pd.struct));
- if popclass<>0 then
- internalerror(201011260); // 11 nov 2010 index 0
- end;
- end;
- parse_generic:=old_parse_generic;
- result:=true;
- end;
- procedure parse_proc_dec_finish(pd:tprocdef;isclassmethod:boolean;astruct:tabstractrecorddef);
- var
- locationstr: string;
- i: integer;
- found: boolean;
- procedure read_returndef(pd: tprocdef);
- var
- popclass: integer;
- old_parse_generic: boolean;
- old_current_structdef: tabstractrecorddef;
- old_current_genericdef,
- old_current_specializedef: tstoreddef;
- begin
- old_parse_generic:=parse_generic;
- { Add ObjectSymtable to be able to find generic type definitions }
- popclass:=0;
- old_current_structdef:=nil;
- old_current_genericdef:=current_genericdef;
- old_current_specializedef:=current_specializedef;
- current_genericdef:=nil;
- current_specializedef:=nil;
- if assigned(pd.struct) and
- (pd.parast.symtablelevel>=normal_function_level) and
- not (symtablestack.top.symtabletype in [ObjectSymtable,recordsymtable]) then
- begin
- popclass:=push_nested_hierarchy(pd.struct);
- old_current_structdef:=current_structdef;
- current_structdef:=pd.struct;
- end;
- if df_generic in pd.defoptions then
- begin
- if pd.is_generic then
- current_genericdef:=pd
- else if assigned(pd.struct) then
- current_genericdef:=pd.struct
- else
- internalerror(2016090202);
- end;
- if df_specialization in pd.defoptions then
- begin
- if pd.is_specialization then
- current_specializedef:=pd
- else if assigned(pd.struct) then
- current_specializedef:=pd.struct
- else
- internalerror(2016090203);
- end;
- parse_generic:=(df_generic in pd.defoptions);
- if pd.is_generic or pd.is_specialization then
- symtablestack.push(pd.parast);
- pd.returndef:=result_type([stoAllowSpecialization]);
- // Issue #24863, enabled only for the main progra commented out for now because it breaks building of RTL and needs extensive
- // testing and/or RTL patching.
- {
- if ((pd.returndef=cvarianttype) or (pd.returndef=colevarianttype)) and
- not(cs_compilesystem in current_settings.moduleswitches) then
- include(current_module.moduleflags,mf_uses_variants);
- }
- if is_dispinterface(pd.struct) and not is_automatable(pd.returndef) then
- Message1(type_e_not_automatable,pd.returndef.typename);
- if pd.is_generic or pd.is_specialization then
- symtablestack.pop(pd.parast);
- if popclass>0 then
- begin
- current_structdef:=old_current_structdef;
- dec(popclass,pop_nested_hierarchy(pd.struct));
- if popclass<>0 then
- internalerror(201012020);
- end;
- current_genericdef:=old_current_genericdef;
- current_specializedef:=old_current_specializedef;
- parse_generic:=old_parse_generic;
- end;
- begin
- locationstr:='';
- case pd.proctypeoption of
- potype_procedure:
- begin
- pd.returndef:=voidtype;
- if isclassmethod then
- include(pd.procoptions,po_classmethod);
- end;
- potype_function:
- begin
- if try_to_consume(_COLON) then
- begin
- read_returndef(pd);
- if (target_info.system in [system_m68k_amiga]) then
- begin
- if (idtoken=_LOCATION) then
- begin
- if po_explicitparaloc in pd.procoptions then
- begin
- consume(_LOCATION);
- locationstr:=cstringpattern;
- consume(_CSTRING);
- end
- else
- { I guess this needs a new message... (KB) }
- Message(parser_e_paraloc_all_paras);
- end
- else
- begin
- if po_explicitparaloc in pd.procoptions then
- { assign default locationstr, if none specified }
- { and we've arguments with explicit paraloc }
- locationstr:='D0';
- end;
- end;
- end
- else
- begin
- if (
- parse_only and
- not(is_interface(pd.struct))
- ) or
- (m_repeat_forward in current_settings.modeswitches) then
- begin
- consume(_COLON);
- consume_all_until(_SEMICOLON);
- end;
- end;
- if isclassmethod then
- include(pd.procoptions,po_classmethod);
- end;
- potype_constructor,
- potype_class_constructor:
- begin
- if not isclassmethod and
- assigned(pd) and
- assigned(pd.struct) then
- begin
- { Set return type, class constructors return the
- created instance, object constructors return boolean }
- if is_class(pd.struct) or
- is_record(pd.struct) or
- is_javaclass(pd.struct) then
- pd.returndef:=pd.struct
- else
- if is_objectpascal_helper(pd.struct) then
- pd.returndef:=tobjectdef(pd.struct).extendeddef
- else
- {$ifdef CPU64bitaddr}
- pd.returndef:=bool64type;
- {$else CPU64bitaddr}
- pd.returndef:=bool32type;
- {$endif CPU64bitaddr}
- end
- else
- pd.returndef:=voidtype;
- end;
- potype_class_destructor,
- potype_destructor:
- begin
- if assigned(pd) then
- pd.returndef:=voidtype;
- end;
- potype_operator:
- begin
- { operators always need to be searched in all units (that
- contain operators) }
- include(pd.procoptions,po_overload);
- pd.procsym.owner.includeoption(sto_has_operator);
- if pd.parast.symtablelevel>normal_function_level then
- Message(parser_e_no_local_operator);
- if isclassmethod then
- begin
- include(pd.procoptions,po_classmethod);
- { any class operator is also static }
- include(pd.procoptions,po_staticmethod);
- end;
- if token<>_ID then
- begin
- if not(m_result in current_settings.modeswitches) then
- consume(_ID);
- end
- else
- begin
- pd.resultname:=stringdup(orgpattern);
- consume(_ID);
- end;
- { operators without result (management operators) }
- if optoken in [_OP_INITIALIZE, _OP_FINALIZE, _OP_ADDREF, _OP_COPY] then
- begin
- { single var parameter to point the record }
- if (optoken in [_OP_INITIALIZE, _OP_FINALIZE, _OP_ADDREF]) and
- (
- (pd.parast.SymList.Count<>1) or
- (tparavarsym(pd.parast.SymList[0]).vardef<>pd.struct) or
- (tparavarsym(pd.parast.SymList[0]).varspez<>vs_var)
- ) then
- Message(parser_e_overload_impossible)
- { constref (source) and var (dest) parameter to point the records }
- else if (optoken=_OP_COPY) and
- (
- (pd.parast.SymList.Count<>2) or
- (tparavarsym(pd.parast.SymList[0]).vardef<>pd.struct) or
- (tparavarsym(pd.parast.SymList[0]).varspez<>vs_constref) or
- (tparavarsym(pd.parast.SymList[1]).vardef<>pd.struct) or
- (tparavarsym(pd.parast.SymList[1]).varspez<>vs_var)
- ) then
- Message(parser_e_overload_impossible);
- trecordsymtable(pd.procsym.Owner).includemanagementoperator(
- token2managementoperator(optoken));
- pd.returndef:=voidtype
- end
- else
- if not try_to_consume(_COLON) then
- begin
- consume(_COLON);
- pd.returndef:=generrordef;
- consume_all_until(_SEMICOLON);
- end
- else
- begin
- read_returndef(pd);
- { check that class operators have either return type of structure or }
- { at least one argument of that type }
- if (po_classmethod in pd.procoptions) and
- (pd.returndef <> pd.struct) then
- begin
- found:=false;
- for i := 0 to pd.parast.SymList.Count - 1 do
- if tparavarsym(pd.parast.SymList[i]).vardef=pd.struct then
- begin
- found:=true;
- break;
- end;
- if not found then
- if assigned(pd.struct) then
- Message1(parser_e_at_least_one_argument_must_be_of_type,pd.struct.RttiName)
- else
- MessagePos(pd.fileinfo,type_e_type_id_expected);
- end;
- if not assigned(pd.struct) or assigned(astruct) then
- begin
- if (optoken in [_ASSIGNMENT,_OP_EXPLICIT]) and
- equal_defs(pd.returndef,tparavarsym(pd.parast.SymList[0]).vardef) and
- (pd.returndef.typ<>undefineddef) and (tparavarsym(pd.parast.SymList[0]).vardef.typ<>undefineddef) then
- message(parser_e_no_such_assignment)
- else if not isoperatoracceptable(pd,optoken) then
- Message(parser_e_overload_impossible);
- end;
- end;
- end;
- else
- internalerror(2015052202);
- end;
- if (pd.proccalloption in cdecl_pocalls) and
- (pd.paras.count>0) and
- is_array_of_const(tparavarsym(pd.paras[pd.paras.count-1]).vardef) then
- begin
- include(pd.procoptions,po_variadic);
- end;
- { support procedure proc stdcall export; }
- if not(check_proc_directive(false)) then
- begin
- if (token=_COLON) and not(Assigned(pd) and is_void(pd.returndef)) then
- begin
- message(parser_e_field_not_allowed_here);
- consume_all_until(_SEMICOLON);
- end;
- consume(_SEMICOLON);
- end;
- if locationstr<>'' then
- begin
- if not(paramanager.parsefuncretloc(pd,upper(locationstr))) then
- { I guess this needs a new message... (KB) }
- message(parser_e_illegal_explicit_paraloc);
- end;
- end;
- function parse_proc_dec(isclassmethod:boolean;astruct:tabstractrecorddef;isgeneric:boolean):tprocdef;
- var
- pd : tprocdef;
- old_block_type : tblock_type;
- recover : boolean;
- procedure finish_intf_mapping;
- begin
- if token=_COLON then
- begin
- message(parser_e_field_not_allowed_here);
- consume_all_until(_SEMICOLON);
- end;
- consume(_SEMICOLON);
- end;
- begin
- pd:=nil;
- recover:=false;
- case token of
- _FUNCTION :
- begin
- consume(_FUNCTION);
- if parse_proc_head(astruct,potype_function,isgeneric,nil,nil,pd) then
- begin
- { pd=nil when it is a interface mapping }
- if assigned(pd) then
- parse_proc_dec_finish(pd,isclassmethod,astruct)
- else
- finish_intf_mapping;
- end
- else
- begin
- { recover }
- consume(_COLON);
- consume_all_until(_SEMICOLON);
- recover:=true;
- end;
- end;
- _PROCEDURE :
- begin
- consume(_PROCEDURE);
- if parse_proc_head(astruct,potype_procedure,isgeneric,nil,nil,pd) then
- begin
- { pd=nil when it is an interface mapping }
- if assigned(pd) then
- parse_proc_dec_finish(pd,isclassmethod,astruct)
- else
- finish_intf_mapping;
- end
- else
- recover:=true;
- end;
- _CONSTRUCTOR :
- begin
- consume(_CONSTRUCTOR);
- if isclassmethod then
- recover:=not parse_proc_head(astruct,potype_class_constructor,false,nil,nil,pd)
- else
- recover:=not parse_proc_head(astruct,potype_constructor,false,nil,nil,pd);
- if not recover then
- parse_proc_dec_finish(pd,isclassmethod,astruct);
- end;
- _DESTRUCTOR :
- begin
- consume(_DESTRUCTOR);
- if isclassmethod then
- recover:=not parse_proc_head(astruct,potype_class_destructor,false,nil,nil,pd)
- else
- recover:=not parse_proc_head(astruct,potype_destructor,false,nil,nil,pd);
- if not recover then
- parse_proc_dec_finish(pd,isclassmethod,astruct);
- end;
- else
- if (token=_OPERATOR) or
- (isclassmethod and (idtoken=_OPERATOR)) then
- begin
- { we need to set the block type to bt_body, so that operator names
- like ">", "=>" or "<>" are parsed correctly instead of e.g.
- _LSHARPBRACKET and _RSHARPBRACKET for "<>" }
- old_block_type:=block_type;
- block_type:=bt_body;
- consume(_OPERATOR);
- parse_proc_head(astruct,potype_operator,false,nil,nil,pd);
- block_type:=old_block_type;
- if assigned(pd) then
- parse_proc_dec_finish(pd,isclassmethod,astruct)
- else
- begin
- { recover }
- try_to_consume(_ID);
- consume(_COLON);
- consume_all_until(_SEMICOLON);
- recover:=true;
- end;
- end;
- end;
- if recover and not(check_proc_directive(false)) then
- begin
- if (token=_COLON) and not(Assigned(pd) and is_void(pd.returndef)) then
- begin
- message(parser_e_field_not_allowed_here);
- consume_all_until(_SEMICOLON);
- end;
- consume(_SEMICOLON);
- end;
- { we've parsed the final semicolon, so stop recording tokens }
- if assigned(pd) and
- (df_generic in pd.defoptions) and
- assigned(pd.genericdecltokenbuf) then
- current_scanner.stoprecordtokens;
- result:=pd;
- end;
- function parse_record_method_dec(astruct: tabstractrecorddef; is_classdef: boolean;hadgeneric:boolean): tprocdef;
- var
- oldparse_only: boolean;
- begin
- oldparse_only:=parse_only;
- parse_only:=true;
- result:=parse_proc_dec(is_classdef,astruct,hadgeneric);
- { this is for error recovery as well as forward }
- { interface mappings, i.e. mapping to a method }
- { which isn't declared yet }
- if assigned(result) then
- begin
- parse_record_proc_directives(result);
- { since records have no inheritance, don't allow non-static
- class methods. Delphi does the same. }
- if (result.proctypeoption<>potype_operator) and
- is_classdef and
- not (po_staticmethod in result.procoptions) then
- MessagePos(result.fileinfo, parser_e_class_methods_only_static_in_records);
- // we can't add hidden params here because record is not yet defined
- // and therefore record size which has influence on paramter passing rules may change too
- // look at record_dec to see where calling conventions are applied (issue #0021044)
- handle_calling_convention(result,hcc_default_actions_intf_struct);
- { add definition to procsym }
- proc_add_definition(result);
- if result.is_generic then
- astruct.symtable.includeoption(sto_has_generic);
- end;
- maybe_parse_hint_directives(result);
- parse_only:=oldparse_only;
- end;
- {****************************************************************************
- Procedure directive handlers
- ****************************************************************************}
- procedure pd_compilerproc(pd:tabstractprocdef);
- var
- v : Tconstexprint;
- begin
- { check for optional syssym index }
- if try_to_consume(_COLON) then
- begin
- v:=get_intconst;
- if (v<int64(low(longint))) or (v>int64(high(longint))) then
- message3(type_e_range_check_error_bounds,tostr(v),tostr(low(longint)),tostr(high(longint)))
- else if not assigned(tsyssym.find_by_number(longint(v.svalue))) then
- message1(parser_e_invalid_internal_function_index,tostr(v))
- else
- tprocdef(pd).extnumber:=longint(v.svalue);
- end;
- end;
- procedure pd_far(pd:tabstractprocdef);
- begin
- pd.declared_far;
- end;
- procedure pd_near(pd:tabstractprocdef);
- begin
- pd.declared_near;
- end;
- procedure pd_export(pd:tabstractprocdef);
- begin
- if pd.typ<>procdef then
- internalerror(200304264);
- if assigned(tprocdef(pd).struct) 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.typ<>procdef then
- internalerror(200304265);
- tprocdef(pd).forwarddef:=true;
- end;
- procedure pd_alias(pd:tabstractprocdef);
- begin
- if pd.typ<>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.typ<>procdef then
- internalerror(2003042601);
- 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.typ<>procdef then
- internalerror(200304267);
- if token=_CCHAR then
- begin
- tprocdef(pd).aliasnames.insert(target_info.Cprefix+pattern);
- consume(_CCHAR)
- end
- else
- begin
- tprocdef(pd).aliasnames.insert(target_info.Cprefix+cstringpattern);
- consume(_CSTRING);
- end;
- { we don't need anything else }
- tprocdef(pd).forwarddef:=false;
- end;
- procedure pd_internconst(pd:tabstractprocdef);
- var v:Tconstexprint;
- begin
- if pd.typ<>procdef then
- internalerror(200304268);
- consume(_COLON);
- v:=get_intconst;
- if (v<int64(low(longint))) or (v>int64(high(longint))) then
- message3(type_e_range_check_error_bounds,tostr(v),tostr(low(longint)),tostr(high(longint)))
- else
- Tprocdef(pd).extnumber:=longint(v.svalue);
- end;
- procedure pd_internproc(pd:tabstractprocdef);
- var v:Tconstexprint;
- begin
- if pd.typ<>procdef then
- internalerror(2003042602);
- consume(_COLON);
- v:=get_intconst;
- if (v<int64(low(longint))) or (v>int64(high(longint))) then
- message3(type_e_range_check_error_bounds,tostr(v),tostr(low(longint)),tostr(high(longint)))
- else
- Tprocdef(pd).extnumber:=longint(v.svalue);
- { 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.typ<>procdef then
- internalerror(200304269);
- if is_objectpascal_helper(tprocdef(pd).struct) then
- Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_ABSTRACT].str);
- if assigned(tprocdef(pd).struct) and
- (oo_is_sealed in tprocdef(pd).struct.objectoptions) then
- Message(parser_e_sealed_class_cannot_have_abstract_methods)
- else if (po_virtualmethod in pd.procoptions) then
- begin
- include(pd.procoptions,po_abstractmethod);
- { one more abstract method }
- inc(tobjectdef(pd.owner.defowner).abstractcnt);
- end
- else
- Message(parser_e_only_virtual_methods_abstract);
- { the method is defined }
- tprocdef(pd).forwarddef:=false;
- end;
- procedure pd_final(pd:tabstractprocdef);
- begin
- if pd.typ<>procdef then
- internalerror(200910170);
- if is_objectpascal_helper(tprocdef(pd).struct) and
- (m_objfpc in current_settings.modeswitches) then
- Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_FINAL].str);
- if (po_virtualmethod in pd.procoptions) or
- (is_javaclass(tprocdef(pd).struct) and
- (po_classmethod in pd.procoptions)) then
- include(pd.procoptions,po_finalmethod)
- else
- Message(parser_e_only_virtual_methods_final);
- end;
- procedure pd_enumerator(pd:tabstractprocdef);
- begin
- if pd.typ<>procdef then
- internalerror(200910250);
- if (token = _ID) then
- begin
- if pattern='MOVENEXT' then
- begin
- if oo_has_enumerator_movenext in tprocdef(pd).struct.objectoptions then
- message(parser_e_only_one_enumerator_movenext);
- pd.calcparas;
- if (pd.proctypeoption = potype_function) and is_boolean(pd.returndef) and
- (pd.minparacount = 0) then
- begin
- include(tprocdef(pd).struct.objectoptions, oo_has_enumerator_movenext);
- include(pd.procoptions,po_enumerator_movenext);
- end
- else
- Message(parser_e_enumerator_movenext_is_not_valid)
- end
- else
- Message1(parser_e_invalid_enumerator_identifier, pattern);
- consume(token);
- end
- else
- Message(parser_e_enumerator_identifier_required);
- end;
- procedure pd_virtual(pd:tabstractprocdef);
- {$ifdef WITHDMT}
- var
- pt : tnode;
- {$endif WITHDMT}
- begin
- if assigned(pd.owner) and
- (not assigned(pd.owner.defowner) or
- not is_java_class_or_interface(tdef(pd.owner.defowner))) and
- (po_external in pd.procoptions) then
- Message2(parser_e_proc_dir_conflict,'EXTERNAL','"VIRTUAL"');
- if pd.typ<>procdef then
- internalerror(2003042610);
- if (pd.proctypeoption=potype_constructor) and
- is_object(tprocdef(pd).struct) then
- Message(parser_e_constructor_cannot_be_not_virtual);
- if pd.is_generic then
- message(parser_e_genfuncs_cannot_be_virtual);
- if is_objectpascal_helper(tprocdef(pd).struct) and
- (m_objfpc in current_settings.modeswitches) then
- Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_VIRTUAL].str);
- {$ifdef WITHDMT}
- if is_object(tprocdef(pd).struct) 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_dispid(pd:tabstractprocdef);
- var pt:Tnode;
- begin
- if pd.typ<>procdef then
- internalerror(200604301);
- pt:=comp_expr([ef_accept_equal]);
- if is_constintnode(pt) then
- if (Tordconstnode(pt).value<int64(low(longint))) or (Tordconstnode(pt).value>int64(high(longint))) then
- message3(type_e_range_check_error_bounds,tostr(Tordconstnode(pt).value),tostr(low(longint)),tostr(high(longint)))
- else
- Tprocdef(pd).dispid:=Tordconstnode(pt).value.svalue
- else
- message(parser_e_dispid_must_be_ord_const);
- pt.free;
- end;
- procedure pd_static(pd:tabstractprocdef);
- begin
- if pd.typ<>procdef then
- internalerror(2013032001);
- if not assigned(tprocdef(pd).struct) then
- internalerror(2013032002);
- include(tprocdef(pd).procsym.symoptions,sp_static);
- { "static" is not allowed for operators or normal methods (except in objects) }
- if (pd.proctypeoption=potype_operator) or
- (
- not (po_classmethod in pd.procoptions) and
- not is_object(tprocdef(pd).struct)
- )
- then
- Message1(parser_e_dir_not_allowed,arraytokeninfo[_STATIC].str);
- include(pd.procoptions,po_staticmethod);
- end;
- procedure pd_override(pd:tabstractprocdef);
- begin
- if pd.typ<>procdef then
- internalerror(2003042611);
- if is_objectpascal_helper(tprocdef(pd).struct) then
- begin
- if m_objfpc in current_settings.modeswitches then
- Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_OVERRIDE].str)
- end
- else if not(is_class_or_interface_or_objc_or_java(tprocdef(pd).struct)) then
- Message(parser_e_no_object_override)
- else if is_objccategory(tprocdef(pd).struct) then
- Message(parser_e_no_category_override)
- else if (po_external in pd.procoptions) and
- not is_objc_class_or_protocol(tprocdef(pd).struct) and
- not is_cppclass(tprocdef(pd).struct) and
- not is_java_class_or_interface(tprocdef(pd).struct) then
- Message2(parser_e_proc_dir_conflict,'OVERRIDE','"EXTERNAL"');
- end;
- procedure pd_overload(pd:tabstractprocdef);
- begin
- if pd.typ<>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.typ<>procdef then
- internalerror(2003042613);
- if is_objectpascal_helper(tprocdef(pd).struct) then
- begin
- if m_objfpc in current_settings.modeswitches then
- Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_MESSAGE].str);
- end
- else
- if not is_class(tprocdef(pd).struct) and
- not is_objc_class_or_protocol(tprocdef(pd).struct) then
- Message(parser_e_msg_only_for_classes);
- if ([po_msgstr,po_msgint]*pd.procoptions)<>[] then
- Message(parser_e_multiple_messages);
- { check parameter type }
- if not is_objc_class_or_protocol(tprocdef(pd).struct) then
- begin
- if po_external in pd.procoptions then
- Message2(parser_e_proc_dir_conflict,'MESSAGE','"EXTERNAL"');
- paracnt:=0;
- pd.parast.SymList.ForEachCall(@check_msg_para,@paracnt);
- if paracnt<>1 then
- Message(parser_e_ill_msg_param);
- end;
- pt:=comp_expr([ef_accept_equal]);
- { message is 1-character long }
- if is_constcharnode(pt) then
- begin
- include(pd.procoptions,po_msgstr);
- tprocdef(pd).messageinf.str:=stringdup(chr(byte(tordconstnode(pt).value.uvalue and $FF)));
- end
- else if pt.nodetype=stringconstn then
- begin
- include(pd.procoptions,po_msgstr);
- if (tstringconstnode(pt).len>255) then
- Message(parser_e_message_string_too_long);
- tprocdef(pd).messageinf.str:=stringdup(tstringconstnode(pt).value_str);
- end
- else
- if is_constintnode(pt) and
- (is_class(tprocdef(pd).struct) or
- is_objectpascal_helper(tprocdef(pd).struct)) then
- begin
- include(pd.procoptions,po_msgint);
- if (Tordconstnode(pt).value<int64(low(Tprocdef(pd).messageinf.i))) or
- (Tordconstnode(pt).value>int64(high(Tprocdef(pd).messageinf.i))) then
- message3(type_e_range_check_error_bounds,tostr(Tordconstnode(pt).value),tostr(low(Tprocdef(pd).messageinf.i)),tostr(high(Tprocdef(pd).messageinf.i)))
- else
- Tprocdef(pd).messageinf.i:=tordconstnode(pt).value.svalue;
- end
- else
- Message(parser_e_ill_msg_expr);
- { check whether the selector name is valid in case of Objective-C }
- if (po_msgstr in pd.procoptions) and
- is_objc_class_or_protocol(tprocdef(pd).struct) and
- not objcvalidselectorname(@tprocdef(pd).messageinf.str^[1],length(tprocdef(pd).messageinf.str^)) then
- Message1(type_e_invalid_objc_selector_name,tprocdef(pd).messageinf.str^);
- pt.free;
- end;
- procedure pd_reintroduce(pd:tabstractprocdef);
- begin
- if pd.typ<>procdef then
- internalerror(200401211);
- if is_objectpascal_helper(tprocdef(pd).struct) then
- begin
- if m_objfpc in current_settings.modeswitches then
- Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_REINTRODUCE].str);
- end
- else
- if not(is_class_or_interface_or_object(tprocdef(pd).struct)) and
- not(is_objccategory(tprocdef(pd).struct)) and
- not(is_javaclass(tprocdef(pd).struct)) then
- Message(parser_e_no_object_reintroduce);
- end;
- procedure pd_syscall(pd:tabstractprocdef);
- procedure include_po_syscall;
- var
- syscall: psyscallinfo;
- begin
- case target_info.system of
- system_arm_palmos,
- system_m68k_palmos,
- system_m68k_atari,
- system_m68k_amiga,
- system_powerpc_amiga:
- include(pd.procoptions,get_default_syscall);
- system_powerpc_morphos,
- system_arm_aros,
- system_i386_aros,
- system_x86_64_aros:
- begin
- syscall:=get_syscall_by_token(idtoken);
- if assigned(syscall) then
- begin
- if target_info.system in syscall^.validon then
- begin
- consume(idtoken);
- include(pd.procoptions,syscall^.procoption);
- end
- end
- else
- include(pd.procoptions,get_default_syscall);
- end;
- else
- internalerror(2019050526);
- end;
- end;
- function po_syscall_to_varoptions: tvaroptions;
- begin
- result:=[vo_is_syscall_lib,vo_is_hidden_para];
- if ([po_syscall_legacy,po_syscall_basereg,po_syscall_basenone] * tprocdef(pd).procoptions) <> [] then
- include(result,vo_has_explicit_paraloc);
- end;
- function po_syscall_to_regname: string;
- begin
- if po_syscall_legacy in tprocdef(pd).procoptions then
- result:='a6'
- { let nobase on MorphOS store the libbase in r12 as well, because
- we will need the libbase anyway during the call generation }
- else if (po_syscall_basenone in tprocdef(pd).procoptions) and
- (target_info.system = system_powerpc_morphos) then
- result:='r12'
- else if po_syscall_basereg in tprocdef(pd).procoptions then
- begin
- case target_info.system of
- system_i386_aros:
- result:='eax';
- system_x86_64_aros:
- result:='r12';
- system_powerpc_morphos:
- result:='r12';
- else
- internalerror(2016090201);
- end;
- end
- else
- internalerror(2016090101);
- end;
- {$if defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64) or defined(arm)}
- const
- syscall_paranr: array[boolean] of aint =
- ( paranr_syscall_lib_last, paranr_syscall_lib_first );
- var
- vs : tparavarsym;
- sym : tsym;
- symtable : TSymtable;
- v: Tconstexprint;
- vo: tvaroptions;
- paranr: aint;
- {$endif defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64) or defined(arm)}
- begin
- if (pd.typ<>procdef) and (target_info.system <> system_powerpc_amiga) then
- internalerror(2003042614);
- tprocdef(pd).forwarddef:=false;
- {$if defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64) or defined(arm)}
- include_po_syscall;
- if target_info.system in [system_arm_palmos, system_m68k_palmos] then
- begin
- v:=get_intconst;
- tprocdef(pd).extnumber:=longint(v.svalue);
- if ((v<0) or (v>high(word))) then
- message(parser_e_range_check_error);
- if try_to_consume(_COMMA) then
- begin
- v:=get_intconst;
- if ((v<0) or (v>high(word))) then
- message(parser_e_range_check_error);
- tprocdef(pd).import_nr:=longint(v.svalue);
- include(pd.procoptions,po_syscall_has_importnr);
- end;
- exit;
- end;
- if target_info.system = system_m68k_atari then
- begin
- v:=get_intconst;
- if ((v<0) or (v>15)) then
- message(parser_e_range_check_error)
- else
- tprocdef(pd).extnumber:=longint(v.svalue);
- v:=get_intconst;
- if ((v<0) or (v>high(smallint))) then
- message(parser_e_range_check_error)
- else
- tprocdef(pd).import_nr:=longint(v.svalue);
- exit;
- end;
- if consume_sym(sym,symtable) then
- if ((sym.typ=staticvarsym) or
- (sym.typ=absolutevarsym) and (tabsolutevarsym(sym).abstyp=toaddr)) and
- ((tabstractvarsym(sym).vardef.typ=pointerdef) or
- is_32bitint(tabstractvarsym(sym).vardef)) then
- begin
- include(pd.procoptions,po_syscall_has_libsym);
- tcpuprocdef(pd).libsym:=sym;
- vo:=po_syscall_to_varoptions;
- paranr:=syscall_paranr[po_syscall_basefirst in tprocdef(pd).procoptions];
- vs:=cparavarsym.create('$syscalllib',paranr,vs_value,tabstractvarsym(sym).vardef,vo);
- if vo_has_explicit_paraloc in vo then
- if not paramanager.parseparaloc(vs,po_syscall_to_regname) then
- internalerror(2016120301);
- pd.parast.insert(vs);
- end
- else
- Message(parser_e_32bitint_or_pointer_variable_expected);
- paramanager.create_funcretloc_info(pd,calleeside);
- paramanager.create_funcretloc_info(pd,callerside);
- v:=get_intconst;
- if (v<low(Tprocdef(pd).extnumber)) or (v>high(Tprocdef(pd).extnumber)) then
- message3(type_e_range_check_error_bounds,tostr(v),tostr(low(Tprocdef(pd).extnumber)),tostr(high(Tprocdef(pd).extnumber)))
- else
- if target_info.system in [system_arm_aros,system_i386_aros,system_x86_64_aros] then
- Tprocdef(pd).extnumber:=v.uvalue * sizeof(pint)
- else
- Tprocdef(pd).extnumber:=v.uvalue;
- {$endif defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64) or defined(arm)}
- 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)
- }
- var
- hs : string;
- v:Tconstexprint;
- is_java_external: boolean;
- begin
- if pd.typ<>procdef then
- internalerror(2003042615);
- { Allow specifying a separate external name for methods in external Java
- because its identifier naming constraints are laxer than FPC's
- (e.g., case sensitive).
- Limitation: only allows specifying the symbol name and not the package name,
- and only for external classes/interfaces }
- is_java_external:=
- (pd.typ=procdef) and
- is_java_class_or_interface(tdef(pd.owner.defowner)) and
- (oo_is_external in tobjectdef(pd.owner.defowner).objectoptions);
- 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 is_java_external and
- not(token=_SEMICOLON) and not(idtoken=_NAME) then
- begin
- { Always add library prefix and suffix to create an uniform name }
- hs:=get_stringconst;
- if ExtractFileExt(hs)='' then
- hs:=ChangeFileExt(hs,target_info.sharedlibext);
- if Copy(hs,1,length(target_info.sharedlibprefix))<>target_info.sharedlibprefix then
- hs:=target_info.sharedlibprefix+hs;
- { the JVM expects java/lang/Object rather than java.lang.Object }
- if target_info.system in systems_jvm then
- Replace(hs,'.','/');
- import_dll:=stringdup(hs);
- include(procoptions,po_has_importdll);
- if (idtoken=_NAME) then
- begin
- consume(_NAME);
- import_name:=stringdup(get_stringconst);
- include(procoptions,po_has_importname);
- 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);
- v:=get_intconst;
- if (v<int64(low(import_nr))) or (v>int64(high(import_nr))) then
- message(parser_e_range_check_error)
- else
- import_nr:=longint(v.svalue);
- end;
- { default is to used the realname of the procedure }
- if (import_nr=0) and not assigned(import_name) then
- begin
- import_name:=stringdup(procsym.realname);
- include(procoptions,po_has_importname);
- end;
- end
- else
- begin
- if (idtoken=_NAME) or
- is_java_external then
- begin
- consume(_NAME);
- import_name:=stringdup(get_stringconst);
- include(procoptions,po_has_importname);
- if import_name^='' then
- message(parser_e_empty_import_name);
- end;
- end;
- end;
- end;
- procedure pd_weakexternal(pd:tabstractprocdef);
- begin
- if not(target_info.system in systems_weak_linking) then
- message(parser_e_weak_external_not_supported)
- else
- pd_external(pd);
- end;
- procedure pd_winapi(pd:tabstractprocdef);
- begin
- if not(target_info.system in systems_all_windows+[system_i386_nativent]) then
- pd.proccalloption:=pocall_cdecl
- else
- pd.proccalloption:=pocall_stdcall;
- include(pd.procoptions,po_hascallingconvention);
- end;
- procedure pd_hardfloat(pd:tabstractprocdef);
- begin
- if
- {$if defined(arm)}
- (current_settings.fputype=fpu_soft) or
- {$endif defined(arm)}
- (cs_fp_emulation in current_settings.moduleswitches) then
- message(parser_e_cannot_use_hardfloat_in_a_softfloat_environment);
- 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=53;
- proc_direcdata:array[1..num_proc_directives] of proc_dir_rec=
- (
- (
- idtok:_ABSTRACT;
- pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord,pd_javaclass];
- handler : @pd_abstract;
- pocall : pocall_none;
- pooption : [po_abstractmethod];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_exports,po_interrupt,po_inline]
- ),(
- idtok:_ALIAS;
- pd_flags : [pd_implemen,pd_body,pd_notobjintf];
- handler : @pd_alias;
- pocall : pocall_none;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [];
- mutexclpo : [po_external,po_inline]
- ),(
- idtok:_ASMNAME;
- pd_flags : [pd_interface,pd_implemen,pd_notobjintf];
- handler : @pd_asmname;
- pocall : pocall_cdecl;
- pooption : [po_external];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_external,po_inline]
- ),(
- 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,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_assembler,po_external]
- ),(
- idtok:_CBLOCK;
- pd_flags : [pd_procvar];
- handler : nil;
- pocall : pocall_none;
- pooption : [po_is_block];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_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,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_assembler,po_external]
- ),(
- idtok:_DISPID;
- pd_flags : [pd_dispinterface];
- handler : @pd_dispid;
- pocall : pocall_none;
- pooption : [po_dispid];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [potype_constructor,potype_destructor,potype_operator,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_interrupt,po_external,po_inline]
- ),(
- idtok:_DYNAMIC;
- pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord];
- handler : @pd_virtual;
- pocall : pocall_none;
- pooption : [po_virtualmethod];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_exports,po_interrupt,po_external,po_overridingmethod,po_inline]
- ),(
- idtok:_EXPORT;
- pd_flags : [pd_body,pd_interface,pd_implemen,pd_notobjintf,pd_notrecord,pd_nothelper];
- handler : @pd_export;
- pocall : pocall_none;
- pooption : [po_exports,po_global];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_external,po_interrupt,po_inline]
- ),(
- idtok:_EXTERNAL;
- pd_flags : [pd_implemen,pd_interface,pd_notobject,pd_notobjintf,pd_cppobject,pd_notrecord,pd_nothelper,pd_javaclass,pd_intfjava];
- handler : @pd_external;
- pocall : pocall_none;
- pooption : [po_external];
- mutexclpocall : [pocall_syscall];
- { allowed for external cpp classes }
- mutexclpotype : [{potype_constructor,potype_destructor}potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_public,po_exports,po_interrupt,po_assembler,po_inline]
- ),(
- idtok:_FAR;
- pd_flags : [pd_implemen,pd_body,pd_interface,pd_procvar,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper];
- handler : @pd_far;
- pocall : pocall_none;
- pooption : [];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_inline]
- ),(
- idtok:_FAR16;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar,pd_notobject,pd_notrecord,pd_nothelper];
- handler : nil;
- pocall : pocall_far16;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [];
- mutexclpo : [po_external]
- ),(
- idtok:_FINAL;
- pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord,pd_javaclass];
- handler : @pd_final;
- pocall : pocall_none;
- pooption : [po_finalmethod];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_exports,po_interrupt,po_inline]
- ),(
- idtok:_FORWARD;
- pd_flags : [pd_implemen,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper];
- handler : @pd_forward;
- pocall : pocall_none;
- pooption : [];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_external,po_inline]
- ),(
- 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 : nil;
- pocall : pocall_none;
- pooption : [po_inline];
- mutexclpocall : [pocall_safecall];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_noinline,po_exports,po_external,po_interrupt,po_virtualmethod,po_iocheck]
- ),(
- idtok:_NOINLINE;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
- handler : nil;
- pocall : pocall_none;
- pooption : [po_noinline];
- mutexclpocall : [];
- mutexclpotype : [];
- mutexclpo : [po_inline,po_external]
- ),(
- idtok:_INTERNCONST;
- pd_flags : [pd_interface,pd_body,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper];
- handler : @pd_internconst;
- pocall : pocall_none;
- pooption : [po_internconst];
- mutexclpocall : [];
- mutexclpotype : [potype_operator];
- mutexclpo : []
- ),(
- idtok:_INTERNPROC;
- pd_flags : [pd_interface,pd_implemen,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper];
- handler : @pd_internproc;
- pocall : pocall_internproc;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_operator,potype_class_constructor,potype_class_destructor];
- 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,pd_notrecord,pd_nothelper];
- handler : @pd_interrupt;
- {$ifdef i386}
- pocall : pocall_oldfpccall;
- {$else i386}
- pocall : pocall_stdcall;
- {$endif i386}
- pooption : [po_interrupt];
- mutexclpocall : [pocall_internproc,pocall_cdecl,pocall_cppdecl,pocall_stdcall,pocall_mwpascal,
- pocall_pascal,pocall_far16,pocall_oldfpccall,pocall_sysv_abi_cdecl,pocall_ms_abi_cdecl];
- mutexclpotype : [potype_constructor,potype_destructor,potype_operator,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_external,po_inline,po_exports]
- ),(
- 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:_LOCAL;
- pd_flags : [pd_implemen,pd_body];
- handler : nil;
- pocall : pocall_none;
- pooption : [po_kylixlocal];
- mutexclpocall : [pocall_internproc,pocall_far16];
- mutexclpotype : [];
- mutexclpo : [po_external,po_exports]
- ),(
- idtok:_MESSAGE;
- pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass,pd_objcprot,pd_notrecord];
- handler : @pd_message;
- pocall : pocall_none;
- pooption : []; { can be po_msgstr or po_msgint }
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [potype_constructor,potype_destructor,potype_operator,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_interrupt,po_inline]
- ),(
- idtok:_MWPASCAL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_mwpascal;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [];
- mutexclpo : []
- ),(
- idtok:_NEAR;
- pd_flags : [pd_implemen,pd_body,pd_procvar,pd_notobjintf,pd_notrecord,pd_nothelper];
- handler : @pd_near;
- pocall : pocall_none;
- pooption : [];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : []
- ),(
- idtok:_NORETURN;
- pd_flags : [pd_implemen,pd_interface,pd_body,pd_notobjintf];
- handler : nil;
- pocall : pocall_none;
- pooption : [po_noreturn];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_operator,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_interrupt,po_virtualmethod,po_iocheck]
- ),(
- 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,pd_javaclass,pd_intfjava,pd_objcclass,pd_objcprot];
- handler : @pd_overload;
- pocall : pocall_none;
- pooption : [po_overload];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : []
- ),(
- idtok:_OVERRIDE;
- pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass,pd_javaclass,pd_intfjava,pd_notrecord];
- handler : @pd_override;
- pocall : pocall_none;
- pooption : [po_overridingmethod,po_virtualmethod];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_exports,po_interrupt,po_virtualmethod,po_inline]
- ),(
- idtok:_PASCAL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_pascal;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_external]
- ),(
- idtok:_PUBLIC;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper];
- handler : @pd_public;
- pocall : pocall_none;
- pooption : [po_public,po_global];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_external,po_inline]
- ),(
- idtok:_REGISTER;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_register;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_external]
- ),(
- idtok:_REINTRODUCE;
- pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass,pd_notrecord,pd_javaclass];
- handler : @pd_reintroduce;
- pocall : pocall_none;
- pooption : [po_reintroduce];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_external,po_interrupt,po_exports,po_overridingmethod,po_inline]
- ),(
- idtok:_SAFECALL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_safecall;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_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,potype_class_constructor,potype_class_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_implemen,pd_body,pd_object,pd_record,pd_javaclass,pd_notobjintf];
- handler : @pd_static;
- pocall : pocall_none;
- pooption : [po_staticmethod];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_interrupt,po_exports,po_virtualmethod]
- ),(
- idtok:_STDCALL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_stdcall;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_external]
- ),(
- idtok:_SYSCALL;
- { Different kind of syscalls are valid for AOS68k, AOSPPC and MOS. }
- { FIX ME!!! MorphOS/AOS68k pd_flags should be:
- pd_interface, pd_implemen, pd_notobject, pd_notobjintf (KB) }
- pd_flags : [pd_interface,pd_implemen,pd_procvar];
- handler : @pd_syscall;
- pocall : pocall_syscall;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_external,po_assembler,po_interrupt,po_exports]
- ),(
- idtok:_VIRTUAL;
- pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord,pd_javaclass];
- handler : @pd_virtual;
- pocall : pocall_none;
- pooption : [po_virtualmethod];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [potype_class_constructor,potype_class_destructor];
- mutexclpo : PD_VIRTUAL_MUTEXCLPO
- ),(
- idtok:_CPPDECL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_cppdecl;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_assembler,po_external,po_virtualmethod]
- ),(
- idtok:_VARARGS;
- pd_flags : [pd_interface,pd_implemen,pd_procvar,pd_objcclass,pd_objcprot];
- handler : nil;
- pocall : pocall_none;
- pooption : [po_varargs];
- mutexclpocall : [pocall_internproc,pocall_register,
- pocall_far16,pocall_oldfpccall,pocall_mwpascal];
- mutexclpotype : [];
- mutexclpo : [po_assembler,po_interrupt,po_inline]
- ),(
- idtok:_COMPILERPROC;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
- handler : @pd_compilerproc;
- pocall : pocall_none;
- pooption : [po_compilerproc];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_interrupt]
- ),(
- idtok:_WEAKEXTERNAL;
- pd_flags : [pd_implemen,pd_interface,pd_notobject,pd_notobjintf,pd_cppobject,pd_notrecord,pd_nothelper];
- handler : @pd_weakexternal;
- pocall : pocall_none;
- { mark it both external and weak external, so we don't have to
- adapt all code for external symbols to also check for weak external
- }
- pooption : [po_external,po_weakexternal];
- mutexclpocall : [pocall_internproc,pocall_syscall];
- { allowed for external cpp classes }
- mutexclpotype : [{potype_constructor,potype_destructor}potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_public,po_exports,po_interrupt,po_assembler,po_inline]
- ),(
- idtok:_WINAPI;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : @pd_winapi;
- pocall : pocall_none;
- pooption : [];
- mutexclpocall : [pocall_stdcall,pocall_cdecl,pocall_mwpascal,pocall_sysv_abi_cdecl,pocall_ms_abi_cdecl];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_external]
- ),(
- idtok:_ENUMERATOR;
- pd_flags : [pd_interface,pd_object,pd_record];
- handler : @pd_enumerator;
- pocall : pocall_none;
- pooption : [];
- mutexclpocall : [pocall_internproc];
- mutexclpotype : [];
- mutexclpo : [po_exports,po_interrupt,po_external,po_inline]
- ),(
- idtok:_RTLPROC;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
- handler : nil;
- pocall : pocall_none;
- pooption : [po_rtlproc];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_interrupt]
- ),(
- idtok:_HARDFLOAT;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : @pd_hardfloat;
- pocall : pocall_hardfloat;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- { it's available with po_external because the libgcc floating point routines on the arm
- uses this calling convention }
- mutexclpo : []
- ),(
- idtok:_SYSV_ABI_DEFAULT;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_sysv_abi_default;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_interrupt]
- ),(
- idtok:_SYSV_ABI_CDECL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_sysv_abi_cdecl;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_interrupt]
- ),(
- idtok:_MS_ABI_DEFAULT;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_ms_abi_default;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_interrupt]
- ),(
- idtok:_MS_ABI_CDECL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_ms_abi_cdecl;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
- mutexclpo : [po_interrupt]
- ),(
- idtok:_VECTORCALL;
- pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
- handler : nil;
- pocall : pocall_vectorcall;
- pooption : [];
- mutexclpocall : [];
- mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_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.top.symtabletype=ObjectSymtable)) then
- result:=true;
- exit;
- end;
- end;
- function find_proc_directive_index(tok: ttoken): longint; inline;
- begin
- result:=-1;
- for result:=1 to num_proc_directives do
- if proc_direcdata[result].idtok=tok then
- exit;
- result:=-1;
- 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;
- name : TIDString;
- po_comp : tprocoptions;
- tokenloc : TFilePosInfo;
- begin
- parse_proc_direc:=false;
- name:=tokeninfo^[idtoken].str;
- { Hint directive? Then exit immediatly }
- if (m_hintdirective in current_settings.modeswitches) then
- begin
- case idtoken of
- _LIBRARY,
- _PLATFORM,
- _UNIMPLEMENTED,
- _EXPERIMENTAL,
- _DEPRECATED :
- if (m_delphi in current_settings.modeswitches) and (pd.typ=procdef) then
- begin
- maybe_parse_hint_directives(tprocdef(pd));
- { could the new token still be a directive? }
- if token<>_ID then
- exit;
- end
- else
- exit;
- else
- ;
- end;
- end;
- { C directive is MacPas only, because it breaks too much existing code
- on other platforms (PFV) }
- if (idtoken=_C) and
- not(m_mac in current_settings.modeswitches) then
- exit;
- { retrieve data for directive if found }
- p:=find_proc_directive_index(idtoken);
- { Check if the procedure directive is known }
- if p=-1 then
- begin
- { parsing a procvar type the name can be any
- next variable !! }
- if ((pdflags * [pd_procvar,pd_object,pd_record,pd_objcclass,pd_objcprot])=[]) and
- not(idtoken in [_PROPERTY,_GENERIC]) then
- Message1(parser_w_unknown_proc_directive_ignored,pattern);
- exit;
- end;
- { 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.top.symtabletype=ObjectSymtable) and
- { directive allowed for cpp classes? }
- not((pd_cppobject in proc_direcdata[p].pd_flags) and is_cppclass(tdef(symtablestack.top.defowner))) and
- not((pd_javaclass in proc_direcdata[p].pd_flags) and is_javaclass(tdef(symtablestack.top.defowner))) and
- not((pd_intfjava in proc_direcdata[p].pd_flags) and is_javainterface(tdef(symtablestack.top.defowner))) then
- exit;
- if (pd_notrecord in proc_direcdata[p].pd_flags) and
- (symtablestack.top.symtabletype=recordsymtable) then
- exit;
- { check if method and directive not for java class }
- if not(pd_javaclass in proc_direcdata[p].pd_flags) and
- is_javaclass(tdef(symtablestack.top.defowner)) then
- exit;
- { check if method and directive not for java interface }
- if not(pd_intfjava in proc_direcdata[p].pd_flags) and
- is_javainterface(tdef(symtablestack.top.defowner)) then
- exit;
- { Keep track of the token's position in the file so it's correctly indicated if an error occurs. }
- tokenloc := current_tokenpos;
- { consume directive, and turn flag on }
- consume(token);
- parse_proc_direc:=true;
- { Conflicts between directives? }
- if (pd.proctypeoption in proc_direcdata[p].mutexclpotype) then
- begin
- MessagePos2(tokenloc, parser_e_proc_dir_conflict,name,ProcTypeOptionKeywords[pd.proctypeoption]);
- exit;
- end;
- if (pd.proccalloption in proc_direcdata[p].mutexclpocall) then
- begin
- MessagePos2(tokenloc, parser_e_proc_dir_conflict,name,'"' + UpCase(proccalloptionStr[pd.proccalloption]) + '"');
- exit;
- end;
- po_comp := (pd.procoptions*proc_direcdata[p].mutexclpo);
- if (po_comp<>[]) then
- begin
- MessagePos2(tokenloc, parser_e_proc_dir_conflict,name,get_first_proc_str(po_comp));
- exit;
- end;
- { set calling convention }
- if proc_direcdata[p].pocall<>pocall_none then
- begin
- if (po_hascallingconvention in pd.procoptions) then
- begin
- MessagePos2(tokenloc, 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
- MessagePos1(tokenloc, 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.typ=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).struct) then
- exit;
- { Check if the directive is only for records }
- if (pd_record in proc_direcdata[p].pd_flags) and
- not assigned(tprocdef(pd).struct) then
- exit;
- { check if method and directive not for interface }
- if (pd_notobjintf in proc_direcdata[p].pd_flags) and
- is_interface(tprocdef(pd).struct) then
- exit;
- { check if method and directive not for interface }
- if is_dispinterface(tprocdef(pd).struct) and
- not(pd_dispinterface in proc_direcdata[p].pd_flags) then
- exit;
- { check if method and directive not for objcclass }
- if is_objcclass(tprocdef(pd).struct) and
- not(pd_objcclass in proc_direcdata[p].pd_flags) then
- exit;
- { check if method and directive not for objcprotocol }
- if is_objcprotocol(tprocdef(pd).struct) and
- not(pd_objcprot in proc_direcdata[p].pd_flags) then
- exit;
- { check if method and directive not for record/class helper }
- if is_objectpascal_helper(tprocdef(pd).struct) and
- (pd_nothelper in proc_direcdata[p].pd_flags) then
- exit;
- end;
- { 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
- MessagePos1(tokenloc, 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
- MessagePos1(tokenloc, 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
- MessagePos1(tokenloc, 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;
- var
- dllname, importname : string;
- begin
- result:='';
- if not(po_external in pd.procoptions) then
- internalerror(200412151);
- { external name or number is specified }
- if assigned(pd.import_name) or (pd.import_nr<>0) then
- begin
- if assigned(pd.import_dll) then
- dllname:=pd.import_dll^
- else
- dllname:='';
- if assigned(pd.import_name) then
- importname:=pd.import_name^
- else
- importname:='';
- proc_get_importname:=make_dllmangledname(dllname,
- importname,pd.import_nr,pd.proccalloption);
- end
- else
- begin
- { Default names when importing variables }
- case pd.proccalloption of
- pocall_cdecl,
- pocall_sysv_abi_cdecl,
- pocall_ms_abi_cdecl:
- begin
- if assigned(pd.struct) then
- result:=target_info.Cprefix+pd.struct.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'" }
- { but according to MacPas mode description
- Cprefix should still be used PM }
- if (m_mac in current_settings.modeswitches) then
- result:=target_info.Cprefix+tprocdef(pd).procsym.realname
- else
- result:=pd.procsym.realname;
- {$ifdef i8086}
- { Turbo Pascal expects names of external routines
- to be all uppercase }
- if (target_info.system=system_i8086_msdos) and
- (m_tp7 in current_settings.modeswitches) and
- (pd.proccalloption=pocall_pascal) then
- result:=UpCase(result);
- {$endif i8086}
- 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
- begin
- pd.setmangledname(s);
- end;
- { since this is an external declaration, there won't be an
- implementation that needs to match the original symbol
- again -> immediately convert here }
- if po_compilerproc in pd.procoptions then
- pd.setcompilerprocname;
- end
- end
- else
- { Normal procedures }
- begin
- if (po_compilerproc in pd.procoptions) then
- begin
- pd.setmangledname(lower(pd.procsym.name));
- end;
- end;
- end;
- { Public/exported alias names }
- if (([po_public,po_exports]*pd.procoptions)<>[]) and
- not(po_has_public_name in pd.procoptions) then
- begin
- case pd.proccalloption of
- pocall_cdecl,
- pocall_sysv_abi_cdecl,
- pocall_ms_abi_cdecl:
- begin
- if assigned(pd.struct) then
- pd.aliasnames.insert(target_info.Cprefix+pd.struct.objrealname^+'_'+pd.procsym.realname)
- else
- begin
- { Export names are not mangled on Windows and OS/2, see also pexports.pas }
- if (target_info.system in (systems_all_windows+[system_i386_emx, system_i386_os2])) and
- (po_exports in pd.procoptions) then
- pd.aliasnames.insert(pd.procsym.realname)
- else
- pd.aliasnames.insert(target_info.Cprefix+pd.procsym.realname);
- end;
- end;
- pocall_cppdecl :
- begin
- pd.aliasnames.insert(target_info.Cprefix+pd.cplusplusmangledname);
- end;
- else
- ;
- end;
- { prevent adding the alias a second time }
- include(pd.procoptions,po_has_public_name);
- end;
- 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
- stoprecording,
- res : boolean;
- begin
- if (m_mac in current_settings.modeswitches) and (cs_externally_visible in current_settings.localswitches) then
- begin
- tprocdef(pd).aliasnames.insert(target_info.Cprefix+tprocdef(pd).procsym.realname);
- include(pd.procoptions,po_public);
- include(pd.procoptions,po_has_public_name);
- include(pd.procoptions,po_global);
- end;
- { methods from external class definitions are all external themselves }
- if (pd.typ=procdef) and
- assigned(tprocdef(pd).struct) and
- (tprocdef(pd).struct.typ=objectdef) and
- (oo_is_external in tobjectdef(tprocdef(pd).struct).objectoptions) then
- tprocdef(pd).make_external;
- { Class constructors and destructor are static class methods in real. }
- { There are many places in the compiler where either class or static }
- { method flag changes the behavior. It is simplier to add them to }
- { the class constructors/destructors options than to fix all the }
- { occurencies. (Paul) }
- if pd.proctypeoption in [potype_class_constructor,potype_class_destructor] then
- begin
- include(pd.procoptions,po_classmethod);
- include(pd.procoptions,po_staticmethod);
- end;
- { for a generic routine we also need to record the procedure }
- { directives, but only if we aren't already recording for a }
- { surrounding generic }
- if pd.is_generic and (pd.typ=procdef) and not current_scanner.is_recording_tokens then
- begin
- current_scanner.startrecordtokens(tprocdef(pd).genericdecltokenbuf);
- stoprecording:=true;
- end
- else
- stoprecording:=false;
- while (token=_ID) or
- (
- not (m_prefixed_attributes in current_settings.modeswitches) and
- (token=_LECKKLAMMER)
- ) do
- begin
- if not (m_prefixed_attributes in current_settings.modeswitches) and
- 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 _EQ is found,
- because a constant/default value follows }
- if res then
- begin
- if (block_type=bt_const_type) and
- (token=_EQ) then
- break;
- { support procedure proc;stdcall export; }
- if not(check_proc_directive((pd.typ=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,_EQ]) then
- break
- else
- begin
- if (token=_COLON) then
- begin
- Message(parser_e_field_not_allowed_here);
- consume_all_until(_SEMICOLON);
- end;
- consume(_SEMICOLON)
- end;
- end;
- end
- else
- break;
- end;
- if stoprecording then
- current_scanner.stoprecordtokens;
- { nostackframe requires assembler, but assembler
- may be specified in the implementation part only,
- and in not required if the function is first forward declared
- if it is a procdef that has forwardef set to true
- we postpone the possible error message to the real implementation
- parse_only does not need to be considered as po_nostackframe
- is an implementation only directive }
- if (po_nostackframe in pd.procoptions) and
- not (po_assembler in pd.procoptions) and
- ((pd.typ<>procdef) or not tprocdef(pd).forwarddef) then
- message(parser_e_nostackframe_without_assembler);
- end;
- procedure parse_var_proc_directives(sym:tsym);
- var
- pdflags : tpdflags;
- pd : tabstractprocdef;
- begin
- pdflags:=[pd_procvar];
- pd:=nil;
- case sym.typ of
- fieldvarsym,
- staticvarsym,
- localvarsym,
- paravarsym :
- pd:=tabstractprocdef(tabstractvarsym(sym).vardef);
- typesym :
- pd:=tabstractprocdef(ttypesym(sym).typedef);
- else
- internalerror(2003042617);
- end;
- if pd.typ<>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;
- procedure parse_record_proc_directives(pd:tabstractprocdef);
- var
- pdflags : tpdflags;
- begin
- pdflags:=[pd_record];
- parse_proc_directives(pd,pdflags);
- end;
- end.
|