| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769 | {    Copyright (c) 1998-2002 by Florian Klaempfl    Does object types for Free Pascal    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 pdecobj;{$i fpcdefs.inc}interface    uses      cclasses,      globtype,symconst,symtype,symdef;    { parses a object declaration }    function object_dec(objecttype:tobjecttyp;const n:tidstring;objsym:tsym;genericdef:tstoreddef;genericlist:tfphashobjectlist;fd : tobjectdef;helpertype:thelpertype) : tobjectdef;    { parses a (class) method declaration }    function method_dec(astruct: tabstractrecorddef; is_classdef: boolean;hadgeneric:boolean): tprocdef;    function class_constructor_head(astruct: tabstractrecorddef):tprocdef;    function class_destructor_head(astruct: tabstractrecorddef):tprocdef;    function constructor_head:tprocdef;    function destructor_head:tprocdef;    procedure struct_property_dec(is_classproperty:boolean;var rtti_attrs_def: trtti_attribute_list);implementation    uses      sysutils,cutils,      globals,verbose,systems,tokens,      symbase,symsym,symtable,symcreat,defcmp,      node,ncon,      fmodule,scanner,      pbase,pexpr,pdecsub,pdecvar,ptype,pdecl,pgenutil,pparautl,ppu{$ifdef jvm}      ,jvmdef,pjvm;{$else}      ;{$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';    var      current_objectdef : tobjectdef absolute current_structdef;    procedure constr_destr_finish_head(pd: tprocdef; const astruct: tabstractrecorddef);      begin        case astruct.typ of          recorddef:            begin              parse_record_proc_directives(pd);            end;          objectdef:            begin              parse_object_proc_directives(pd);            end          else            internalerror(2011040502);        end;        // We can't add hidden params here because record is not yet defined        // and therefore record size which has influence on parameter passing rules may change too        // look at record_dec to see where calling conventions are applied (issue #0021044).        // The same goes for objects/classes due to the calling convention that may only be set        // later (mantis #35233).        handle_calling_convention(pd,hcc_default_actions_intf_struct);        { add definition to procsym }        proc_add_definition(pd);        { add procdef options to objectdef options }        if (po_virtualmethod in pd.procoptions) then          include(astruct.objectoptions,oo_has_virtual);        maybe_parse_hint_directives(pd);      end;    function class_constructor_head(astruct: tabstractrecorddef):tprocdef;      var        pd : tprocdef;      begin        result:=nil;        consume(_CONSTRUCTOR);        { must be at same level as in implementation }        parse_proc_head(current_structdef,potype_class_constructor,[],nil,nil,pd);        if not assigned(pd) then          begin            consume(_SEMICOLON);            exit;          end;        pd.calcparas;        if (pd.maxparacount>0) then          Message(parser_e_no_paras_for_class_constructor);        consume(_SEMICOLON);        include(astruct.objectoptions,oo_has_class_constructor);        include(current_module.moduleflags,mf_classinits);        { no return value }        pd.returndef:=voidtype;        constr_destr_finish_head(pd,astruct);        result:=pd;      end;    function constructor_head:tprocdef;      var        pd : tprocdef;      begin        result:=nil;        consume(_CONSTRUCTOR);        { must be at same level as in implementation }        parse_proc_head(current_structdef,potype_constructor,[],nil,nil,pd);        if not assigned(pd) then          begin            consume(_SEMICOLON);            exit;          end;        if (cs_constructor_name in current_settings.globalswitches) and           (pd.procsym.name<>'INIT') then          Message(parser_e_constructorname_must_be_init);        consume(_SEMICOLON);        include(current_structdef.objectoptions,oo_has_constructor);        { Set return type, class and record constructors return the          created instance, helper types return the extended type,          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}        constr_destr_finish_head(pd,pd.struct);        result:=pd;      end;    procedure struct_property_dec(is_classproperty:boolean;var rtti_attrs_def: trtti_attribute_list);      var        p : tpropertysym;        _deprecatedmsg: pshortstring;        _symoptions: tsymoptions;      begin        { check for a class, record or helper }        if not((is_class_or_interface_or_dispinterface(current_structdef) or is_record(current_structdef) or                is_objectpascal_helper(current_structdef) or is_java_class_or_interface(current_structdef)) or               (not(m_tp7 in current_settings.modeswitches) and (is_object(current_structdef)))) then          Message(parser_e_syntax_error);        consume(_PROPERTY);        p:=read_property_dec(is_classproperty,current_structdef);        consume(_SEMICOLON);        if try_to_consume(_DEFAULT) then          begin            if oo_has_default_property in current_structdef.objectoptions then              message(parser_e_only_one_default_property);            include(current_structdef.objectoptions,oo_has_default_property);            include(p.propoptions,ppo_defaultproperty);            if not(ppo_hasparameters in p.propoptions) then              message(parser_e_property_need_paras);            if (token=_COLON) then              begin                Message(parser_e_field_not_allowed_here);                consume_all_until(_SEMICOLON);              end;            consume(_SEMICOLON);          end;        { parse possible enumerator modifier }        if try_to_consume(_ENUMERATOR) then          begin            if (token = _ID) then            begin              if pattern='CURRENT' then              begin                if oo_has_enumerator_current in current_structdef.objectoptions then                  message(parser_e_only_one_enumerator_current);                if not p.propaccesslist[palt_read].empty then                begin                  include(current_structdef.objectoptions,oo_has_enumerator_current);                  include(p.propoptions,ppo_enumerator_current);                end                else                  Message(parser_e_enumerator_current_is_not_valid) // property has no reader              end              else                Message1(parser_e_invalid_enumerator_identifier, pattern);              consume(token);            end            else              Message(parser_e_enumerator_identifier_required);            consume(_SEMICOLON);          end;        { in case of a previous error, p might not be assigned }        if assigned(p) then          begin            trtti_attribute_list.bind(rtti_attrs_def,p.rtti_attribute_list);            { hint directives, these can be separated by semicolons here,              that needs to be handled here with a loop (PFV) }            while try_consume_hintdirective(p.symoptions,p.deprecatedmsg) do              Consume(_SEMICOLON);          end        else          begin            { recover from error so we can continue to parse }            { hint directives, these can be separated by semicolons here,              that needs to be handled here with a loop (PFV) }            while try_consume_hintdirective(_symoptions,_deprecatedmsg) do              Consume(_SEMICOLON);          end;      end;    function class_destructor_head(astruct: tabstractrecorddef):tprocdef;      var        pd : tprocdef;      begin        result:=nil;        consume(_DESTRUCTOR);        parse_proc_head(current_structdef,potype_class_destructor,[],nil,nil,pd);        if not assigned(pd) then          begin            consume(_SEMICOLON);            exit;          end;        pd.calcparas;        if (pd.maxparacount>0) then          Message(parser_e_no_paras_for_class_destructor);        consume(_SEMICOLON);        include(astruct.objectoptions,oo_has_class_destructor);        include(current_module.moduleflags,mf_classinits);        { no return value }        pd.returndef:=voidtype;        constr_destr_finish_head(pd,astruct);        result:=pd;      end;    function destructor_head:tprocdef;      var        pd : tprocdef;      begin        result:=nil;        consume(_DESTRUCTOR);        parse_proc_head(current_structdef,potype_destructor,[],nil,nil,pd);        if not assigned(pd) then          begin            consume(_SEMICOLON);            exit;          end;        if (cs_constructor_name in current_settings.globalswitches) and           (pd.procsym.name<>'DONE') then          Message(parser_e_destructorname_must_be_done);        pd.calcparas;        if not(pd.maxparacount=0) and           (m_fpc in current_settings.modeswitches) then          Message(parser_e_no_paras_for_destructor);        consume(_SEMICOLON);        include(current_structdef.objectoptions,oo_has_destructor);        include(current_structdef.objectoptions,oo_has_new_destructor);        { no return value }        pd.returndef:=voidtype;        constr_destr_finish_head(pd,pd.struct);        result:=pd;      end;    procedure setinterfacemethodoptions;      var        i   : longint;        def : tdef;      begin        include(current_structdef.objectoptions,oo_has_virtual);        for i:=0 to current_structdef.symtable.DefList.count-1 do          begin            def:=tdef(current_structdef.symtable.DefList[i]);            if assigned(def) and               (def.typ=procdef) then              begin                include(tprocdef(def).procoptions,po_virtualmethod);                tprocdef(def).forwarddef:=false;              end;          end;      end;    procedure setobjcclassmethodoptions;      var        i   : longint;        def : tdef;      begin        for i:=0 to current_structdef.symtable.DefList.count-1 do          begin            def:=tdef(current_structdef.symtable.DefList[i]);            if assigned(def) and               (def.typ=procdef) then              begin                include(tprocdef(def).procoptions,po_virtualmethod);              end;          end;      end;    procedure handleImplementedInterface(intfdef : tobjectdef);      begin        if not is_interface(intfdef) then          begin             Message1(type_e_interface_type_expected,intfdef.typename);             exit;          end;        if ([oo_is_forward,oo_is_formal] * intfdef.objectoptions <> []) then          begin             Message1(parser_e_forward_intf_declaration_must_be_resolved,intfdef.objrealname^);             exit;          end;        if find_implemented_interface(current_objectdef,intfdef)<>nil then          Message1(sym_e_duplicate_id,intfdef.objname^)        else          current_objectdef.register_implemented_interface(intfdef,true);      end;    procedure handleImplementedProtocolOrJavaIntf(intfdef : tobjectdef);      begin        intfdef:=find_real_class_definition(intfdef,false);        case current_objectdef.objecttype of          odt_objcclass,          odt_objccategory,          odt_objcprotocol:            if not is_objcprotocol(intfdef) then              begin                 Message1(type_e_protocol_type_expected,intfdef.typename);                 exit;              end;          odt_javaclass,          odt_interfacejava:            if not is_javainterface(intfdef) then              begin                Message1(type_e_interface_type_expected,intfdef.typename);                exit              end;          else            internalerror(2011010807);        end;        if ([oo_is_forward,oo_is_formal] * intfdef.objectoptions <> []) then          begin             Message1(parser_e_forward_intf_declaration_must_be_resolved,intfdef.objrealname^);             exit;          end;        if find_implemented_interface(current_objectdef,intfdef)<>nil then          Message1(sym_e_duplicate_id,intfdef.objname^)        else          current_objectdef.register_implemented_interface(intfdef,false);      end;    procedure readImplementedInterfacesAndProtocols(intf: boolean);      var        hdef : tdef;      begin        while try_to_consume(_COMMA) do          begin             { use single_type instead of id_type for specialize support }             single_type(hdef,[stoAllowSpecialization,stoParseClassParent]);             if (hdef.typ<>objectdef) then               begin                  if intf then                    Message1(type_e_interface_type_expected,hdef.typename)                  else                    Message1(type_e_protocol_type_expected,hdef.typename);                  continue;               end;             if intf then               handleImplementedInterface(tobjectdef(hdef))             else               handleImplementedProtocolOrJavaIntf(tobjectdef(hdef));          end;      end;    procedure readinterfaceiid;      var        p : tnode;        valid : boolean;      begin        p:=comp_expr([ef_accept_equal]);        if p.nodetype=stringconstn then          begin            stringdispose(current_objectdef.iidstr);            current_objectdef.iidstr:=stringdup(strpas(tstringconstnode(p).value_str));            valid:=string2guid(current_objectdef.iidstr^,current_objectdef.iidguid^);            if (current_objectdef.objecttype in [odt_interfacecom,odt_dispinterface]) and               not valid then              Message(parser_e_improper_guid_syntax);            include(current_structdef.objectoptions,oo_has_valid_guid);          end        else          Message(parser_e_illegal_expression);        p.free;      end;    procedure get_cpp_or_java_class_external_status(od: tobjectdef);      var        hs: string;      begin        { C++ classes can be external -> all methods inside are external         (defined at the class level instead of per method, so that you cannot         define some methods as external and some not)        }        if try_to_consume(_EXTERNAL) then          begin            hs:='';            if token in [_CSTRING,_CWSTRING,_CCHAR,_CWCHAR] 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;              end;            if hs<>'' then              begin                { the JVM expects java/lang/Object rather than java.lang.Object }                if target_info.system in systems_jvm then                  Replace(hs,'.','/');                stringdispose(od.import_lib);                od.import_lib:=stringdup(hs);              end;            { check if we shall use another name for the class }            if try_to_consume(_NAME) then              od.objextname:=stringdup(get_stringconst)            else              od.objextname:=stringdup(od.objrealname^);            include(od.objectoptions,oo_is_external);          end        else          begin            od.objextname:=stringdup(od.objrealname^);          end;      end;    procedure get_objc_class_or_protocol_external_status(od: tobjectdef);      begin        { Objective-C classes can be external -> all messages inside are          external (defined at the class level instead of per method, so          that you cannot define some methods as external and some not)        }        if try_to_consume(_EXTERNAL) then          begin            if try_to_consume(_NAME) then              od.objextname:=stringdup(get_stringconst)            else              { the external name doesn't matter for formally declared                classes, and allowing to specify one would mean that we would                have to check it for consistency with the actual definition                later on }              od.objextname:=stringdup(od.objrealname^);            include(od.objectoptions,oo_is_external);          end        else          od.objextname:=stringdup(od.objrealname^);      end;    procedure parse_object_options;      var        gotexternal: boolean;      begin        case current_objectdef.objecttype of          odt_object,odt_class,          odt_javaclass:            begin              gotexternal:=false;              while true do                begin                  if try_to_consume(_ABSTRACT) then                    include(current_structdef.objectoptions,oo_is_abstract)                  else                  if try_to_consume(_SEALED) then                    include(current_structdef.objectoptions,oo_is_sealed)                  else if (current_objectdef.objecttype=odt_javaclass) and                          (token=_ID) and                          (idtoken=_EXTERNAL) then                    begin                      get_cpp_or_java_class_external_status(current_objectdef);                      gotexternal:=true;                    end                  else                    break;                end;              { don't use <=, because there's a bug in the 2.6.0 SPARC code                generator regarding handling this expression }              if ([oo_is_abstract, oo_is_sealed] * current_structdef.objectoptions) = [oo_is_abstract, oo_is_sealed] then                Message(parser_e_abstract_and_sealed_conflict);              { set default external name in case of no external directive }              if (current_objectdef.objecttype=odt_javaclass) and                 not gotexternal then               get_cpp_or_java_class_external_status(current_objectdef)            end;          odt_cppclass,          odt_interfacejava:            get_cpp_or_java_class_external_status(current_objectdef);          odt_objcclass,odt_objcprotocol,odt_objccategory:            get_objc_class_or_protocol_external_status(current_objectdef);          odt_helper: ; // nothing          else            ;        end;      end;    procedure parse_parent_classes;      var        intfchildof,        childof : tobjectdef;        hdef : tdef;        hasparentdefined : boolean;      begin        childof:=nil;        intfchildof:=nil;        hasparentdefined:=false;        { reads the parent class }        if (token=_LKLAMMER) or           is_objccategory(current_structdef) then          begin            consume(_LKLAMMER);            { use single_type instead of id_type for specialize support }            single_type(hdef,[stoAllowSpecialization, stoParseClassParent]);            if (not assigned(hdef)) or               (hdef.typ<>objectdef) then              begin                if assigned(hdef) then                  Message1(type_e_class_type_expected,hdef.typename)                else if is_objccategory(current_structdef) then                  { a category must specify the class to extend }                  Message(type_e_objcclass_type_expected);              end            else              begin                childof:=tobjectdef(hdef);                { a mix of class, interfaces, objects and cppclasses                  isn't allowed }                case current_objectdef.objecttype of                   odt_class,                   odt_javaclass:                     if (childof.objecttype<>current_objectdef.objecttype) then                       begin                          if (is_interface(childof) and                              is_class(current_objectdef)) or                             (is_javainterface(childof) and                              is_javaclass(current_objectdef)) then                            begin                               { we insert the interface after the child                                 is set, see below                               }                               intfchildof:=childof;                               childof:=class_tobject;                            end                          else                            Message(parser_e_mix_of_classes_and_objects);                       end                     else                       if oo_is_sealed in childof.objectoptions then                         Message1(parser_e_sealed_descendant,childof.typename)                       else                         childof:=find_real_class_definition(childof,true);                   odt_interfacecorba,                   odt_interfacecom:                     begin                       if not(is_interface(childof)) then                         Message(parser_e_mix_of_classes_and_objects);                       current_objectdef.objecttype:=childof.objecttype;                     end;                   odt_cppclass:                     if not(is_cppclass(childof)) then                       Message(parser_e_mix_of_classes_and_objects);                   odt_objcclass:                     if not(is_objcclass(childof) or                        is_objccategory(childof)) then                       begin                         if is_objcprotocol(childof) then                           begin                             if not(oo_is_classhelper in current_structdef.objectoptions) then                               begin                                 intfchildof:=childof;                                 childof:=nil;                                 CGMessage(parser_h_no_objc_parent);                               end                             else                               { a category must specify the class to extend }                               CGMessage(type_e_objcclass_type_expected);                           end                         else                           Message(parser_e_mix_of_classes_and_objects);                       end                     else                       childof:=find_real_class_definition(childof,true);                   odt_objcprotocol:                     begin                       if not(is_objcprotocol(childof)) then                         Message(parser_e_mix_of_classes_and_objects);                       intfchildof:=childof;                       childof:=nil;                     end;                   odt_interfacejava:                     begin                       if not(is_javainterface(childof)) then                         Message(parser_e_mix_of_classes_and_objects);                       intfchildof:=find_real_class_definition(childof,true);                       childof:=nil;                     end;                   odt_object:                     if not(is_object(childof)) then                       Message(parser_e_mix_of_classes_and_objects)                     else                       if oo_is_sealed in childof.objectoptions then                         Message1(parser_e_sealed_descendant,childof.typename);                   odt_dispinterface:                     Message(parser_e_dispinterface_cant_have_parent);                   odt_helper:                     if not is_objectpascal_helper(childof) then                       begin                         Message(type_e_helper_type_expected);                         childof:=nil;                       end;                   else                     ;                end;              end;            hasparentdefined:=true;          end;        { if no parent class, then a class get tobject as parent }        if not assigned(childof) then          begin            case current_objectdef.objecttype of              odt_class:                if current_objectdef<>class_tobject then                  childof:=class_tobject;              odt_interfacecom:                if current_objectdef<>interface_iunknown then                  childof:=interface_iunknown;              odt_dispinterface:                childof:=interface_idispatch;              odt_objcclass:                CGMessage(parser_h_no_objc_parent);              odt_javaclass:                { inherit from TObject by default for compatibility }                if current_objectdef<>java_jlobject then                  childof:=class_tobject;              else                ;            end;          end;        if assigned(childof) then          begin            { Forbid not completly defined objects to be used as parents. This will              also prevent circular loops of classes, because we set the forward flag              at the start of the new definition and will reset it below after the              parent has been set }            if (oo_is_forward in childof.objectoptions) then              Message1(parser_e_forward_declaration_must_be_resolved,childof.objrealname^)            else if not(oo_is_formal in childof.objectoptions) then              current_objectdef.set_parent(childof)            else              Message1(sym_e_formal_class_not_resolved,childof.objrealname^);          end;        if hasparentdefined then          begin            if current_objectdef.objecttype in [odt_class,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava] then              begin                if assigned(intfchildof) then                  if current_objectdef.objecttype=odt_class then                    handleImplementedInterface(intfchildof)                  else                    handleImplementedProtocolOrJavaIntf(intfchildof);                readImplementedInterfacesAndProtocols(current_objectdef.objecttype=odt_class);              end;            consume(_RKLAMMER);          end;        { remove forward flag, is resolved }        exclude(current_structdef.objectoptions,oo_is_forward);      end;    procedure parse_extended_type(helpertype:thelpertype);      procedure validate_extendeddef_typehelper(var def:tdef);        begin          if (def.typ in [undefineddef,procvardef,procdef,              filedef,classrefdef,abstractdef,forwarddef,formaldef]) or              (                (def.typ=objectdef) and                not (tobjectdef(def).objecttype in objecttypes_with_helpers)              ) then            begin              Message1(type_e_type_not_allowed_for_type_helper,def.typename);              def:=generrordef;            end;        end;      procedure check_inheritance_record_type_helper(var def:tdef);        var          tmp : tstoreddef;        begin          if (def.typ<>errordef) and assigned(current_objectdef.childof) then            begin              if def<>current_objectdef.childof.extendeddef then                begin                  { a type helper may extend a type alias of the type its                    parent type helper extends }                  tmp:=tstoreddef(def);                  while (df_unique in tmp.defoptions) and assigned(tstoreddef(tmp).orgdef) do                    begin                      if tmp.orgdef=current_objectdef.childof.extendeddef then                        exit;                      tmp:=tstoreddef(tmp.orgdef);                    end;                  Message1(type_e_record_helper_must_extend_same_record,current_objectdef.childof.extendeddef.typename);                  def:=generrordef;                end;            end;        end;      procedure check_inheritance_class_helper(var def:tdef);        begin          if (def.typ<>errordef) and assigned(current_objectdef.childof) then            begin              if (current_objectdef.childof.extendeddef.typ<>objectdef) or                 not (tobjectdef(current_objectdef.childof.extendeddef).objecttype in objecttypes_with_helpers) then                Internalerror(2011021101);              if not def_is_related(def,current_objectdef.childof.extendeddef) then                begin                  Message1(type_e_class_helper_must_extend_subclass,current_objectdef.childof.extendeddef.typename);                  def:=generrordef;                end;            end;        end;      var        hdef: tdef;      begin        if not is_objectpascal_helper(current_structdef) then          Internalerror(2011021103);        consume(_FOR);        single_type(hdef,[stoParseClassParent]);        if not assigned(hdef) or (hdef.typ=errordef) then          begin            case helpertype of              ht_class:                Message1(type_e_class_type_expected,hdef.typename);              ht_record:                Message(type_e_record_type_expected);              ht_type:                Message1(type_e_type_id_expected,hdef.typename);              else                internalerror(2019050532);            end;          end        else          begin            case helpertype of              ht_class:                if (hdef.typ<>objectdef) or                    not is_class(hdef) then                  Message1(type_e_class_type_expected,hdef.typename)                else                  begin                    { a class helper must extend the same class or a subclass                      of the class extended by the parent class helper }                    check_inheritance_class_helper(hdef);                  end;              ht_record:                if (hdef.typ=objectdef) or                    (                      { primitive types are allowed for record helpers in mode                        delphi }                      (hdef.typ<>recorddef) and                      not (m_delphi in current_settings.modeswitches)                    ) then                  Message1(type_e_record_type_expected,hdef.typename)                else                  begin                    if hdef.typ<>recorddef then                      { this is a primitive type in mode delphi, so validate                        the def }                      validate_extendeddef_typehelper(hdef);                    { a record helper must extend the same record as the                      parent helper }                    check_inheritance_record_type_helper(hdef);                  end;              ht_type:                begin                  validate_extendeddef_typehelper(hdef);                  if (hdef.typ=objectdef) and                      (tobjectdef(hdef).objecttype in objecttypes_with_helpers) then                    check_inheritance_class_helper(hdef)                  else                    { a type helper must extend the same type as the                      parent helper }                    check_inheritance_record_type_helper(hdef);                end;              else                internalerror(2019050531);            end;          end;        if assigned(hdef) then          current_objectdef.extendeddef:=hdef        else          current_objectdef.extendeddef:=generrordef;      end;    procedure parse_guid;      begin        { read GUID }        if (current_objectdef.objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface]) and           try_to_consume(_LECKKLAMMER) then          begin            readinterfaceiid;            consume(_RECKKLAMMER);          end        else if (current_objectdef.objecttype=odt_dispinterface) then          message(parser_e_dispinterface_needs_a_guid);      end;    function method_dec(astruct: tabstractrecorddef; is_classdef: boolean;hadgeneric:boolean): tprocdef;      procedure chkobjc(pd: tprocdef);        begin          if is_objc_class_or_protocol(pd.struct) then            begin              include(pd.procoptions,po_objc);            end;        end;      procedure chkjava(pd: tprocdef);        begin{$ifdef jvm}          if is_java_class_or_interface(pd.struct) then            begin              { mark all non-virtual instance methods as "virtual; final;",                because                 a) that's the only way to guarantee "non-virtual" behaviour                    (other than making them class methods with an explicit self                     pointer, but that causes problems with interface mappings                     and procvars)                 b) if we don't mark them virtual, they don't get added to the                    vmt and we can't check whether child classes try to override                    them              }              if is_javaclass(pd.struct) then                begin                  if not(po_virtualmethod in pd.procoptions) and                     not(po_classmethod in pd.procoptions) then                    begin                      include(pd.procoptions,po_virtualmethod);                      include(pd.procoptions,po_finalmethod);                      include(pd.procoptions,po_java_nonvirtual);                    end                  else if [po_virtualmethod,po_classmethod]<=pd.procoptions then                    begin                      if po_staticmethod in pd.procoptions then                        Message(type_e_java_class_method_not_static_virtual);                    end;                end;            end;{$endif}        end;        procedure chkcpp(pd:tprocdef);          begin            { nothing currently }          end;      var        oldparse_only: boolean;        flags : tparse_proc_flags;      begin        case token of          _PROCEDURE,          _FUNCTION:            begin              if (astruct.symtable.currentvisibility=vis_published) and                 not(oo_can_have_published in astruct.objectoptions) then                Message(parser_e_cant_have_published);              oldparse_only:=parse_only;              parse_only:=true;              flags:=[];              if is_classdef then                include(flags,ppf_classmethod);              if hadgeneric then                include(flags,ppf_generic);              result:=parse_proc_dec(flags,astruct);              { 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_object_proc_directives(result);                  { check if dispid is set }                  if is_dispinterface(result.struct) and not (po_dispid in result.procoptions) then                    begin                      result.dispid:=tobjectdef(result.struct).get_next_dispid;                      include(result.procoptions, po_dispid);                    end;                  { all Macintosh Object Pascal methods are virtual.  }                  { this can't be a class method, because macpas mode }                  { has no m_class                                    }                  if (m_mac in current_settings.modeswitches) then                    include(result.procoptions,po_virtualmethod);                  { for record and type helpers only static class methods are                    allowed }                  if is_objectpascal_helper(astruct) and                     (                       (tobjectdef(astruct).extendeddef.typ<>objectdef) or                       (tobjectdef(tobjectdef(astruct).extendeddef).objecttype<>odt_class)                     ) and                     is_classdef and not (po_staticmethod in result.procoptions) then                    MessagePos(result.fileinfo,parser_e_class_methods_only_static_in_records);                  handle_calling_convention(result,hcc_default_actions_intf_struct);                  { add definition to procsym }                  proc_add_definition(result);                  { add procdef options to objectdef options }                  if (po_msgint in result.procoptions) then                    include(astruct.objectoptions,oo_has_msgint);                  if (po_msgstr in result.procoptions) then                    include(astruct.objectoptions,oo_has_msgstr);                  if (po_virtualmethod in result.procoptions) then                    include(astruct.objectoptions,oo_has_virtual);                  if result.is_generic then                    astruct.symtable.includeoption(sto_has_generic);                  chkcpp(result);                  chkobjc(result);                  chkjava(result);                end;              maybe_parse_hint_directives(result);              parse_only:=oldparse_only;            end;          _CONSTRUCTOR :            begin              if (astruct.symtable.currentvisibility=vis_published) and                not(oo_can_have_published in astruct.objectoptions) then                Message(parser_e_cant_have_published);              if not is_classdef and not(astruct.symtable.currentvisibility in [vis_public,vis_published]) then                Message(parser_w_constructor_should_be_public);              if is_interface(astruct) then                Message(parser_e_no_con_des_in_interfaces);              { Objective-C does not know the concept of a constructor }              if is_objc_class_or_protocol(astruct) then                Message(parser_e_objc_no_constructor_destructor);              if is_objectpascal_helper(astruct) then                if is_classdef then                  { class constructors are not allowed in class helpers }                  Message(parser_e_no_class_constructor_in_helpers);              { only 1 class constructor is allowed }              if is_classdef and (oo_has_class_constructor in astruct.objectoptions) then                Message1(parser_e_only_one_class_constructor_allowed, astruct.objrealname^);              oldparse_only:=parse_only;              parse_only:=true;              if is_classdef then                result:=class_constructor_head(current_structdef)              else                begin                  result:=constructor_head;                  if is_objectpascal_helper(astruct) and                     (tobjectdef(astruct).extendeddef.typ<>objectdef) and                     (result.minparacount=0) then                      { as long as parameterless constructors aren't allowed in records they                       aren't allowed in record/type helpers either }                    MessagePos(result.procsym.fileinfo,parser_e_no_parameterless_constructor_in_records);                end;              chkcpp(result);              parse_only:=oldparse_only;            end;          _DESTRUCTOR :            begin              if (astruct.symtable.currentvisibility=vis_published) and                 not(oo_can_have_published in astruct.objectoptions) then                Message(parser_e_cant_have_published);              if not is_classdef then                if (oo_has_new_destructor in astruct.objectoptions) then                  Message(parser_n_only_one_destructor);              if is_interface(astruct) then                Message(parser_e_no_con_des_in_interfaces);              { (class) destructors are not allowed in class helpers }              if is_objectpascal_helper(astruct) then                Message(parser_e_no_destructor_in_records);              if not is_classdef and (astruct.symtable.currentvisibility<>vis_public) then                Message(parser_w_destructor_should_be_public);              { Objective-C does not know the concept of a destructor }              if is_objc_class_or_protocol(astruct) then                Message(parser_e_objc_no_constructor_destructor);              { only 1 class destructor is allowed }              if is_classdef and (oo_has_class_destructor in astruct.objectoptions) then                Message1(parser_e_only_one_class_destructor_allowed, astruct.objrealname^);              oldparse_only:=parse_only;              parse_only:=true;              if is_classdef then                result:=class_destructor_head(current_structdef)              else                result:=destructor_head;              chkcpp(result);              parse_only:=oldparse_only;            end;          else            internalerror(2011032102);        end;      end;    procedure parse_object_members;      var        typedconstswritable: boolean;        object_member_blocktype : tblock_type;        hadgeneric,        fields_allowed, is_classdef, class_fields, is_final, final_fields,        threadvar_fields : boolean;        vdoptions: tvar_dec_options;        fieldlist: tfpobjectlist;        rtti_attrs_def: trtti_attribute_list;      procedure parse_const;        begin          if not(current_objectdef.objecttype in [odt_class,odt_object,odt_helper,odt_javaclass,odt_interfacejava]) then            Message(parser_e_type_var_const_only_in_records_and_classes);          consume(_CONST);          object_member_blocktype:=bt_const;          final_fields:=is_final;          is_final:=false;        end;      procedure parse_var(isthreadvar:boolean);        begin          if not(current_objectdef.objecttype in [odt_class,odt_object,odt_helper,odt_javaclass]) and             { Java interfaces can contain static final class vars }             not((current_objectdef.objecttype=odt_interfacejava) and                 is_final and is_classdef) then            Message(parser_e_type_var_const_only_in_records_and_classes);          if isthreadvar then            consume(_THREADVAR)          else            consume(_VAR);          fields_allowed:=true;          object_member_blocktype:=bt_general;          class_fields:=is_classdef;          final_fields:=is_final;          threadvar_fields:=isthreadvar;          is_classdef:=false;          is_final:=false;        end;      procedure parse_class;        begin          is_classdef:=false;          { read class method/field/property }          consume(_CLASS);          { class modifier is only allowed for procedures, functions, }          { constructors, destructors, fields and properties          }          if not((token in [_FUNCTION,_PROCEDURE,_PROPERTY,_VAR,_DESTRUCTOR,_THREADVAR]) or (token=_CONSTRUCTOR)) then            Message(parser_e_procedure_or_function_expected);          { Java interfaces can contain final class vars }          if is_interface(current_structdef) or             (is_javainterface(current_structdef) and              (not(is_final) or               (token<>_VAR))) then            Message(parser_e_no_static_method_in_interfaces)          else            { class methods are also allowed for Objective-C protocols }            is_classdef:=true;        end;      procedure parse_visibility(vis: tvisibility; oo: tobjectoption);        begin          { Objective-C and Java classes do not support "published",            as basically everything is published.  }          if (vis=vis_published) and             (is_objc_class_or_protocol(current_structdef) or              is_java_class_or_interface(current_structdef)) then             Message(parser_e_no_objc_published)          else if is_interface(current_structdef) or             is_objc_protocol_or_category(current_structdef) or             is_javainterface(current_structdef) then            Message(parser_e_no_access_specifier_in_interfaces);          current_structdef.symtable.currentvisibility:=vis;          consume(token);          if (oo<>oo_none) then            include(current_structdef.objectoptions,oo);          fields_allowed:=true;          is_classdef:=false;          class_fields:=false;          threadvar_fields:=false;          is_final:=false;          object_member_blocktype:=bt_general;        end;      procedure check_unbound_attributes;        begin          if assigned(rtti_attrs_def) and (rtti_attrs_def.get_attribute_count>0) then            Message1(parser_e_unbound_attribute,trtti_attribute(rtti_attrs_def.rtti_attributes[0]).typesym.prettyname);          rtti_attrs_def.free;          rtti_attrs_def:=nil;        end;      begin        { empty class declaration ? }        if (current_objectdef.objecttype in [odt_class,odt_objcclass,odt_javaclass]) and           (token=_SEMICOLON) then          exit;        { in "publishable" classes the default access type is published }        if (oo_can_have_published in current_structdef.objectoptions) then          current_structdef.symtable.currentvisibility:=vis_published        else          current_structdef.symtable.currentvisibility:=vis_public;        fields_allowed:=true;        is_classdef:=false;        class_fields:=false;        is_final:=false;        final_fields:=false;        rtti_attrs_def:=nil;        hadgeneric:=false;        threadvar_fields:=false;        object_member_blocktype:=bt_general;        fieldlist:=tfpobjectlist.create(false);        repeat          case token of            _TYPE :              begin                check_unbound_attributes;                if not(current_objectdef.objecttype in [odt_class,odt_object,odt_helper,odt_javaclass,odt_interfacejava]) then                  Message(parser_e_type_var_const_only_in_records_and_classes);                consume(_TYPE);                object_member_blocktype:=bt_type;                { expect at least one type declaration }                if token<>_ID then                  consume(_ID);              end;            _VAR :              begin                check_unbound_attributes;                rtti_attrs_def := nil;                parse_var(false);                { expect at least one var declaration }                if token<>_ID then                  consume(_ID);              end;            _CONST:              begin                check_unbound_attributes;                rtti_attrs_def := nil;                parse_const;                { expect at least one constant declaration }                if token<>_ID then                  consume(_ID);              end;            _THREADVAR :              begin                check_unbound_attributes;                if not is_classdef then                  begin                    Message(parser_e_threadvar_must_be_class);                    { for error recovery we enforce class fields }                    is_classdef:=true;                  end;                parse_var(true);                { expect at least one threadvar declaration }                if token<>_ID then                  consume(_ID);              end;            _ID :              begin                check_unbound_attributes;                if is_objcprotocol(current_structdef) and                   ((idtoken=_REQUIRED) or                    (idtoken=_OPTIONAL)) then                  begin                    current_structdef.symtable.currentlyoptional:=(idtoken=_OPTIONAL);                    consume(idtoken)                  end                else case idtoken of                  _PRIVATE :                    begin                      parse_visibility(vis_private,oo_has_private);                     end;                   _PROTECTED :                     begin                       parse_visibility(vis_protected,oo_has_protected);                     end;                   _PUBLIC :                     begin                       parse_visibility(vis_public,oo_none);                     end;                   _PUBLISHED :                     begin                       parse_visibility(vis_published,oo_none);                     end;                   _STRICT :                     begin                       if is_interface(current_structdef) or                          is_objc_protocol_or_category(current_structdef) or                          is_javainterface(current_structdef) then                         Message(parser_e_no_access_specifier_in_interfaces);                         consume(_STRICT);                        if token=_ID then                          begin                            case idtoken of                              _PRIVATE:                                begin                                  consume(_PRIVATE);                                  current_structdef.symtable.currentvisibility:=vis_strictprivate;                                  include(current_structdef.objectoptions,oo_has_strictprivate);                                end;                              _PROTECTED:                                begin                                  consume(_PROTECTED);                                  current_structdef.symtable.currentvisibility:=vis_strictprotected;                                  include(current_structdef.objectoptions,oo_has_strictprotected);                                end;                              else                                message(parser_e_protected_or_private_expected);                            end;                          end                        else                          message(parser_e_protected_or_private_expected);                        fields_allowed:=true;                        is_classdef:=false;                        class_fields:=false;                        threadvar_fields:=false;                        is_final:=false;                        final_fields:=false;                        object_member_blocktype:=bt_general;                     end                    else if (m_final_fields in current_settings.modeswitches) and                            (token=_ID) and                            (idtoken=_FINAL) then                      begin                        { currently only supported for external classes, because                          requires fully working DFA otherwise }                        if (current_structdef.typ<>objectdef) or                           not(oo_is_external in tobjectdef(current_structdef).objectoptions) then                          Message(parser_e_final_only_external);                        consume(_final);                        is_final:=true;                        if token=_CLASS then                          parse_class;                        if not(token in [_CONST,_VAR]) then                          message(parser_e_final_only_const_var);                      end                    else                      begin                        if object_member_blocktype=bt_general then                          begin                            rtti_attrs_def := nil;                            if (idtoken=_GENERIC) and                                not (m_delphi in current_settings.modeswitches) and                                (                                  not fields_allowed or                                  is_objectpascal_helper(current_structdef)                                ) then                              begin                                if hadgeneric then                                  Message(parser_e_procedure_or_function_expected);                                consume(_ID);                                hadgeneric:=true;                                if not (token in [_PROCEDURE,_FUNCTION,_CLASS]) then                                  Message(parser_e_procedure_or_function_expected);                              end                            else                              begin                                if is_interface(current_structdef) or                                   is_objc_protocol_or_category(current_structdef) or                                   (                                     is_objectpascal_helper(current_structdef) and                                     not class_fields                                   ) or                                   (is_javainterface(current_structdef) and                                    not(class_fields and final_fields)) then                                  Message(parser_e_no_vars_in_interfaces);                                if (current_structdef.symtable.currentvisibility=vis_published) and                                   not(oo_can_have_published in current_structdef.objectoptions) then                                  Message(parser_e_cant_have_published);                                if (not fields_allowed) then                                  Message(parser_e_field_not_allowed_here);                                vdoptions:=[vd_object];                                if not (m_delphi in current_settings.modeswitches) then                                  include(vdoptions,vd_check_generic);                                if class_fields then                                  include(vdoptions,vd_class);                                if is_class(current_structdef) then                                  include(vdoptions,vd_canreorder);                                if final_fields then                                  include(vdoptions,vd_final);                                if threadvar_fields then                                  include(vdoptions,vd_threadvar);                                read_record_fields(vdoptions,fieldlist,nil,hadgeneric);                              end;                          end                        else if object_member_blocktype=bt_type then                          types_dec(true,hadgeneric, rtti_attrs_def)                        else if object_member_blocktype=bt_const then                          begin                            typedconstswritable:=false;                            if final_fields then                              begin                                { the value of final fields cannot be changed                                  once they've been assigned a value }                                typedconstswritable:=cs_typed_const_writable in current_settings.localswitches;                                exclude(current_settings.localswitches,cs_typed_const_writable);                              end;                            consts_dec(true,not is_javainterface(current_structdef),hadgeneric);                            if final_fields and                               typedconstswritable then                              include(current_settings.localswitches,cs_typed_const_writable);                          end                        else                          internalerror(2010011103);                      end;                end;              end;            _PROPERTY :              begin                { for now attributes are only allowed on published properties }                if current_structdef.symtable.currentvisibility<>vis_published then                  check_unbound_attributes;                struct_property_dec(is_classdef, rtti_attrs_def);                fields_allowed:=false;                is_classdef:=false;              end;            _CLASS:              begin                { class properties currently can't have attributes, so it's safe                  to check for unbound attributes here }                check_unbound_attributes;                parse_class;              end;            _PROCEDURE,            _FUNCTION,            _CONSTRUCTOR,            _DESTRUCTOR :              begin                check_unbound_attributes;                rtti_attrs_def := nil;                method_dec(current_structdef,is_classdef,hadgeneric);                fields_allowed:=false;                is_classdef:=false;                hadgeneric:=false;              end;            _LECKKLAMMER:              begin                if m_prefixed_attributes in current_settings.modeswitches then                  parse_rttiattributes(rtti_attrs_def)                else                  consume(_ID);              end;            _END :              begin                check_unbound_attributes;                consume(_END);                break;              end;            else              consume(_ID); { Give a ident expected message, like tp7 }          end;        until false;        if is_class(current_structdef) then          tabstractrecordsymtable(current_structdef.symtable).addfieldlist(fieldlist,true);        fieldlist.free;      end;    function object_dec(objecttype:tobjecttyp;const n:tidstring;objsym:tsym;genericdef:tstoreddef;genericlist:tfphashobjectlist;fd : tobjectdef;helpertype:thelpertype) : tobjectdef;      var        old_current_structdef: tabstractrecorddef;        old_current_genericdef,        old_current_specializedef: tstoreddef;        old_parse_generic: boolean;        list: TFPObjectList;        s: TSymStr;        st: TSymtable;        olddef: tdef;      begin        old_current_structdef:=current_structdef;        old_current_genericdef:=current_genericdef;        old_current_specializedef:=current_specializedef;        old_parse_generic:=parse_generic;        current_structdef:=nil;        current_genericdef:=nil;        current_specializedef:=nil;        { objects and class types can't be declared local }        if not(symtablestack.top.symtabletype in [globalsymtable,staticsymtable,objectsymtable,recordsymtable]) and           not assigned(genericlist) then          Message(parser_e_no_local_objects);        { reuse forward objectdef? }        if assigned(fd) then          begin            if (fd.objecttype<>objecttype) or ((fd.is_generic or fd.is_specialization) xor assigned(genericlist)) then              begin                Message(parser_e_forward_mismatch);                { recover }                current_structdef:=cobjectdef.create(objecttype,n,nil,true);                include(current_structdef.objectoptions,oo_is_forward);              end            else              current_structdef:=fd          end        else          begin            { anonym objects aren't allow (o : object a : longint; end;) }            if n='' then              Message(parser_f_no_anonym_objects);            { create new class }            current_structdef:=cobjectdef.create(objecttype,n,nil,true);            tobjectdef(current_structdef).helpertype:=helpertype;            { include always the forward flag, it'll be removed after the parent class have been              added. This is to prevent circular childof loops }            include(current_structdef.objectoptions,oo_is_forward);            if (cs_compilesystem in current_settings.moduleswitches) then              begin                case current_objectdef.objecttype of                  odt_interfacecom :                    if (current_structdef.objname^='IUNKNOWN') then                      interface_iunknown:=current_objectdef                    else                    if (current_structdef.objname^='IDISPATCH') then                      interface_idispatch:=current_objectdef;                  odt_class :                    if (current_structdef.objname^='TOBJECT') then                      class_tobject:=current_objectdef;                  odt_javaclass:                    begin                      if (current_structdef.objname^='TOBJECT') then                        class_tobject:=current_objectdef                      else if (current_objectdef.objname^='JLOBJECT') then                        java_jlobject:=current_objectdef                      else if (current_objectdef.objname^='JLTHROWABLE') then                        java_jlthrowable:=current_objectdef                      else if (current_objectdef.objname^='FPCBASERECORDTYPE') then                        java_fpcbaserecordtype:=current_objectdef                      else if (current_objectdef.objname^='JLSTRING') then                        java_jlstring:=current_objectdef                      else if (current_objectdef.objname^='ANSISTRINGCLASS') then                        java_ansistring:=current_objectdef                      else if (current_objectdef.objname^='SHORTSTRINGCLASS') then                        java_shortstring:=current_objectdef                      else if (current_objectdef.objname^='JLENUM') then                        java_jlenum:=current_objectdef                      else if (current_objectdef.objname^='JUENUMSET') then                        java_juenumset:=current_objectdef                      else if (current_objectdef.objname^='FPCBITSET') then                        java_jubitset:=current_objectdef                      else if (current_objectdef.objname^='FPCBASEPROCVARTYPE') then                        java_procvarbase:=current_objectdef;                    end;                  else                    ;                end;              end;            if (current_module.modulename^='OBJCBASE') then              begin                case current_objectdef.objecttype of                  odt_objcclass:                    if (current_objectdef.objname^='Protocol') then                      objc_protocoltype:=current_objectdef;                  else                    ;                end;              end;          end;        { usage of specialized type inside its generic template }        if assigned(genericdef) then          current_specializedef:=current_structdef;        { reject declaration of generic class inside generic class }        if assigned(genericlist) then          current_genericdef:=current_structdef;        { nested types of specializations are specializations as well }        if assigned(old_current_structdef) and            (df_specialization in old_current_structdef.defoptions) then          include(current_structdef.defoptions,df_specialization);        if assigned(old_current_structdef) and            (df_generic in old_current_structdef.defoptions) then          begin            include(current_structdef.defoptions,df_generic);            current_genericdef:=current_structdef;          end;        { set published flag in $M+ mode, it can also be inherited and will          be added when the parent class set with tobjectdef.set_parent (PFV) }        if (cs_generate_rtti in current_settings.localswitches) and           (current_objectdef.objecttype in [odt_interfacecom,odt_interfacecorba,odt_class,odt_helper]) then          include(current_structdef.objectoptions,oo_can_have_published);        { Objective-C/Java objectdefs can be "formal definitions", in which case          the syntax is "type tc = objcclass external;" -> we have to parse          its object options (external) already here, to make sure that such          definitions are recognised as formal defs }        if objecttype in [odt_objcclass,odt_objcprotocol,odt_objccategory,odt_javaclass,odt_interfacejava] then          parse_object_options;        { forward def? }        if not assigned(fd) and           (token=_SEMICOLON) then          begin            if is_objectpascal_helper(current_structdef) then              consume(_FOR);            { add to the list of definitions to check that the forward              is resolved. this is required for delphi mode }            current_module.checkforwarddefs.add(current_structdef);            symtablestack.push(current_structdef.symtable);            insert_generic_parameter_types(current_structdef,genericdef,genericlist,false);            { when we are parsing a generic already then this is a generic as              well }            if old_parse_generic then              include(current_structdef.defoptions,df_generic);            parse_generic:=(df_generic in current_structdef.defoptions);            { *don't* add the strict private symbol for non-Delphi modes for              forward defs }            symtablestack.pop(current_structdef.symtable);          end        else          begin            { change objccategories into objcclass helpers }            if (objecttype=odt_objccategory) then              begin                current_objectdef.objecttype:=odt_objcclass;                include(current_structdef.objectoptions,oo_is_classhelper);              end;            { include the class helper flag for Object Pascal helpers }            if (objecttype=odt_helper) then              include(current_objectdef.objectoptions,oo_is_classhelper);            { parse list of options (abstract / sealed) }            if not(objecttype in [odt_objcclass,odt_objcprotocol,odt_objccategory,odt_javaclass,odt_interfacejava]) then              parse_object_options;            symtablestack.push(current_structdef.symtable);            insert_generic_parameter_types(current_structdef,genericdef,genericlist,assigned(fd));            { when we are parsing a generic already then this is a generic as              well }            if old_parse_generic then              include(current_structdef.defoptions, df_generic);            parse_generic:=(df_generic in current_structdef.defoptions);            { in non-Delphi modes we need a strict private symbol without type              count and type parameters in the name to simplify resolving }            maybe_insert_generic_rename_symbol(n,genericlist);            { parse list of parent classes }            { for record helpers in mode Delphi this is not allowed }            if not (is_objectpascal_helper(current_objectdef) and                (m_delphi in current_settings.modeswitches) and                (helpertype=ht_record)) then              parse_parent_classes            else              { remove forward flag, is resolved (this is normally done inside                parse_parent_classes) }              exclude(current_structdef.objectoptions,oo_is_forward);            { parse extended type for helpers }            if is_objectpascal_helper(current_structdef) then              parse_extended_type(helpertype);            if is_interface(current_objectdef) and                is_interface(current_objectdef.childof) and                (oo_is_invokable in tobjectdef(current_objectdef.childof).objectoptions) then              include(current_objectdef.objectoptions,oo_is_invokable);            { parse optional GUID for interfaces }            parse_guid;            { classes can handle links to themself not only inside type blocks              but in const blocks too. Additionally this is needed to parse parameters that are              specializations of the currently parsed type in basically everything except C++ and              ObjC classes. To make this possible we need to set their symbols to real defs instead              of errordef }            if assigned(objsym) and not (objecttype in [odt_cppclass,odt_objccategory,odt_objcclass,odt_objcprotocol]) then              begin                olddef:=ttypesym(objsym).typedef;                ttypesym(objsym).typedef:=current_structdef;                current_structdef.typesym:=objsym;              end            else              olddef:=nil;            { parse and insert object members }            parse_object_members;            if assigned(olddef) then              begin                ttypesym(objsym).typedef:=olddef;                current_structdef.typesym:=nil;              end;          if not(oo_is_external in current_structdef.objectoptions) then            begin              { In Java, constructors are not automatically inherited (so you can                hide them). Emulate the Pascal behaviour for classes implemented                in Pascal (we cannot do it for classes implemented in Java, since                we obviously cannot add constructors to those) }              if is_javaclass(current_structdef) then                begin                  add_missing_parent_constructors_intf(tobjectdef(current_structdef),true,vis_none);{$ifdef jvm}                  maybe_add_public_default_java_constructor(tobjectdef(current_structdef));                  jvm_wrap_virtual_class_methods(tobjectdef(current_structdef));{$endif}                end;              { need method to hold the initialization code for typed constants? }              if (target_info.system in systems_typed_constants_node_init) and                 not is_any_interface_kind(current_structdef) then                add_typedconst_init_routine(current_structdef);            end;            symtablestack.pop(current_structdef.symtable);          end;        { generate vmt space if needed }        if not(oo_has_vmt in current_structdef.objectoptions) and           not(oo_is_forward in current_structdef.objectoptions) and           not(parse_generic) and           { no vmt for helpers ever }           not is_objectpascal_helper(current_structdef) and           (            ([oo_has_virtual,oo_has_constructor,oo_has_destructor]*current_structdef.objectoptions<>[]) or            (current_objectdef.objecttype in [odt_class])           ) then          current_objectdef.insertvmt;        { for implemented classes with a vmt check if there is a constructor }        if (oo_has_vmt in current_structdef.objectoptions) and           not(oo_is_forward in current_structdef.objectoptions) and           not(oo_has_constructor in current_structdef.objectoptions) and           not is_objc_class_or_protocol(current_structdef) and           not is_java_class_or_interface(current_structdef) then          Message1(parser_w_virtual_without_constructor,current_structdef.objrealname^);        if is_interface(current_structdef) or           is_objcprotocol(current_structdef) or           is_javainterface(current_structdef) then          setinterfacemethodoptions        else if is_objcclass(current_structdef) then          setobjcclassmethodoptions;        { we need to add this helper to the extendeddefs of the current module,          as the global and static symtable are not pushed onto the symtable          stack again (it will be removed when poping the symtable) }        if is_objectpascal_helper(current_structdef) and            (current_objectdef.extendeddef.typ<>errordef) then          begin            { the topmost symtable must be a static symtable }            st:=current_structdef.owner;            while st.symtabletype in [objectsymtable,recordsymtable] do              st:=st.defowner.owner;            if st.symtabletype in [staticsymtable,globalsymtable] then              begin                if current_objectdef.extendeddef.typ in [recorddef,objectdef] then                  s:=make_mangledname('',tabstractrecorddef(current_objectdef.extendeddef).symtable,'')                else                  s:=make_mangledname('',current_objectdef.extendeddef.owner,current_objectdef.extendeddef.typesym.name);                Message1(sym_d_adding_helper_for,s);                list:=TFPObjectList(current_module.extendeddefs.Find(s));                if not assigned(list) then                  begin                    list:=TFPObjectList.Create(false);                    current_module.extendeddefs.Add(s, list);                  end;                list.add(current_structdef);              end;          end;        tabstractrecordsymtable(current_objectdef.symtable).addalignmentpadding;        { return defined objectdef }        result:=current_objectdef;        { restore old state }        current_structdef:=old_current_structdef;        current_genericdef:=old_current_genericdef;        current_specializedef:=old_current_specializedef;        parse_generic:=old_parse_generic;      end;end.
 |