mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 03:06:34 +02:00
* (class_)constructor/destructor_head() now also parses hints,
handles modifiers and adds the procdefinition. This code was duplicated in several places (for objects and records) * properly handle introducing artificial class constructors (the manually constructed procdefs were wrong, now use str_parse_method_dec) git-svn-id: branches/jvmbackend@18482 -
This commit is contained in:
parent
474b7446ad
commit
834ea45be8
@ -35,8 +35,8 @@ interface
|
|||||||
{ parses a (class) method declaration }
|
{ parses a (class) method declaration }
|
||||||
function method_dec(astruct: tabstractrecorddef; is_classdef: boolean): tprocdef;
|
function method_dec(astruct: tabstractrecorddef; is_classdef: boolean): tprocdef;
|
||||||
|
|
||||||
function class_constructor_head:tprocdef;
|
function class_constructor_head(astruct: tabstractrecorddef):tprocdef;
|
||||||
function class_destructor_head:tprocdef;
|
function class_destructor_head(astruct: tabstractrecorddef):tprocdef;
|
||||||
function constructor_head:tprocdef;
|
function constructor_head:tprocdef;
|
||||||
function destructor_head:tprocdef;
|
function destructor_head:tprocdef;
|
||||||
procedure struct_property_dec(is_classproperty:boolean);
|
procedure struct_property_dec(is_classproperty:boolean);
|
||||||
@ -63,7 +63,31 @@ implementation
|
|||||||
var
|
var
|
||||||
current_objectdef : tobjectdef absolute current_structdef;
|
current_objectdef : tobjectdef absolute current_structdef;
|
||||||
|
|
||||||
function class_constructor_head:tprocdef;
|
|
||||||
|
procedure constr_destr_finish_head(pd: tprocdef; const astruct: tabstractrecorddef);
|
||||||
|
begin
|
||||||
|
case astruct.typ of
|
||||||
|
recorddef:
|
||||||
|
parse_record_proc_directives(pd);
|
||||||
|
objectdef:
|
||||||
|
parse_object_proc_directives(pd);
|
||||||
|
else
|
||||||
|
internalerror(2011040502);
|
||||||
|
end;
|
||||||
|
handle_calling_convention(pd);
|
||||||
|
|
||||||
|
{ 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
|
var
|
||||||
pd : tprocdef;
|
pd : tprocdef;
|
||||||
begin
|
begin
|
||||||
@ -80,10 +104,11 @@ implementation
|
|||||||
if (pd.maxparacount>0) then
|
if (pd.maxparacount>0) then
|
||||||
Message(parser_e_no_paras_for_class_constructor);
|
Message(parser_e_no_paras_for_class_constructor);
|
||||||
consume(_SEMICOLON);
|
consume(_SEMICOLON);
|
||||||
include(current_structdef.objectoptions,oo_has_class_constructor);
|
include(astruct.objectoptions,oo_has_class_constructor);
|
||||||
current_module.flags:=current_module.flags or uf_classinits;
|
current_module.flags:=current_module.flags or uf_classinits;
|
||||||
{ no return value }
|
{ no return value }
|
||||||
pd.returndef:=voidtype;
|
pd.returndef:=voidtype;
|
||||||
|
constr_destr_finish_head(pd,astruct);
|
||||||
result:=pd;
|
result:=pd;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -117,6 +142,7 @@ implementation
|
|||||||
{$else CPU64bitaddr}
|
{$else CPU64bitaddr}
|
||||||
pd.returndef:=bool32type;
|
pd.returndef:=bool32type;
|
||||||
{$endif CPU64bitaddr}
|
{$endif CPU64bitaddr}
|
||||||
|
constr_destr_finish_head(pd,pd.struct);
|
||||||
result:=pd;
|
result:=pd;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -179,7 +205,7 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function class_destructor_head:tprocdef;
|
function class_destructor_head(astruct: tabstractrecorddef):tprocdef;
|
||||||
var
|
var
|
||||||
pd : tprocdef;
|
pd : tprocdef;
|
||||||
begin
|
begin
|
||||||
@ -195,10 +221,11 @@ implementation
|
|||||||
if (pd.maxparacount>0) then
|
if (pd.maxparacount>0) then
|
||||||
Message(parser_e_no_paras_for_class_destructor);
|
Message(parser_e_no_paras_for_class_destructor);
|
||||||
consume(_SEMICOLON);
|
consume(_SEMICOLON);
|
||||||
include(current_structdef.objectoptions,oo_has_class_destructor);
|
include(astruct.objectoptions,oo_has_class_destructor);
|
||||||
current_module.flags:=current_module.flags or uf_classinits;
|
current_module.flags:=current_module.flags or uf_classinits;
|
||||||
{ no return value }
|
{ no return value }
|
||||||
pd.returndef:=voidtype;
|
pd.returndef:=voidtype;
|
||||||
|
constr_destr_finish_head(pd,astruct);
|
||||||
result:=pd;
|
result:=pd;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -225,6 +252,7 @@ implementation
|
|||||||
include(current_structdef.objectoptions,oo_has_destructor);
|
include(current_structdef.objectoptions,oo_has_destructor);
|
||||||
{ no return value }
|
{ no return value }
|
||||||
pd.returndef:=voidtype;
|
pd.returndef:=voidtype;
|
||||||
|
constr_destr_finish_head(pd,pd.struct);
|
||||||
result:=pd;
|
result:=pd;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -765,25 +793,6 @@ implementation
|
|||||||
{ nothing currently }
|
{ nothing currently }
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure maybe_parse_hint_directives(pd:tprocdef);
|
|
||||||
var
|
|
||||||
dummysymoptions : tsymoptions;
|
|
||||||
deprecatedmsg : pshortstring;
|
|
||||||
begin
|
|
||||||
dummysymoptions:=[];
|
|
||||||
deprecatedmsg:=nil;
|
|
||||||
while try_consume_hintdirective(dummysymoptions,deprecatedmsg) do
|
|
||||||
Consume(_SEMICOLON);
|
|
||||||
if assigned(pd) then
|
|
||||||
begin
|
|
||||||
pd.symoptions:=pd.symoptions+dummysymoptions;
|
|
||||||
pd.deprecatedmsg:=deprecatedmsg;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
stringdispose(deprecatedmsg);
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
var
|
||||||
oldparse_only: boolean;
|
oldparse_only: boolean;
|
||||||
begin
|
begin
|
||||||
@ -879,20 +888,11 @@ implementation
|
|||||||
oldparse_only:=parse_only;
|
oldparse_only:=parse_only;
|
||||||
parse_only:=true;
|
parse_only:=true;
|
||||||
if is_classdef then
|
if is_classdef then
|
||||||
result:=class_constructor_head
|
result:=class_constructor_head(current_structdef)
|
||||||
else
|
else
|
||||||
result:=constructor_head;
|
result:=constructor_head;
|
||||||
parse_object_proc_directives(result);
|
|
||||||
handle_calling_convention(result);
|
|
||||||
|
|
||||||
{ add definition to procsym }
|
|
||||||
proc_add_definition(result);
|
|
||||||
|
|
||||||
{ add procdef options to objectdef options }
|
|
||||||
if (po_virtualmethod in result.procoptions) then
|
|
||||||
include(astruct.objectoptions,oo_has_virtual);
|
|
||||||
chkcpp(result);
|
chkcpp(result);
|
||||||
maybe_parse_hint_directives(result);
|
|
||||||
|
|
||||||
parse_only:=oldparse_only;
|
parse_only:=oldparse_only;
|
||||||
end;
|
end;
|
||||||
@ -927,21 +927,11 @@ implementation
|
|||||||
oldparse_only:=parse_only;
|
oldparse_only:=parse_only;
|
||||||
parse_only:=true;
|
parse_only:=true;
|
||||||
if is_classdef then
|
if is_classdef then
|
||||||
result:=class_destructor_head
|
result:=class_destructor_head(current_structdef)
|
||||||
else
|
else
|
||||||
result:=destructor_head;
|
result:=destructor_head;
|
||||||
parse_object_proc_directives(result);
|
|
||||||
handle_calling_convention(result);
|
|
||||||
|
|
||||||
{ add definition to procsym }
|
|
||||||
proc_add_definition(result);
|
|
||||||
|
|
||||||
{ add procdef options to objectdef options }
|
|
||||||
if (po_virtualmethod in result.procoptions) then
|
|
||||||
include(astruct.objectoptions,oo_has_virtual);
|
|
||||||
|
|
||||||
chkcpp(result);
|
chkcpp(result);
|
||||||
maybe_parse_hint_directives(result);
|
|
||||||
|
|
||||||
parse_only:=oldparse_only;
|
parse_only:=oldparse_only;
|
||||||
end;
|
end;
|
||||||
|
@ -60,6 +60,7 @@ implementation
|
|||||||
pd: tprocdef;
|
pd: tprocdef;
|
||||||
topowner: tdefentry;
|
topowner: tdefentry;
|
||||||
i: longint;
|
i: longint;
|
||||||
|
sstate: symcreat.tscannerstate;
|
||||||
needclassconstructor: boolean;
|
needclassconstructor: boolean;
|
||||||
begin
|
begin
|
||||||
{ if there is at least one constructor for a class, do nothing (for
|
{ if there is at least one constructor for a class, do nothing (for
|
||||||
@ -156,35 +157,12 @@ implementation
|
|||||||
end;
|
end;
|
||||||
if needclassconstructor then
|
if needclassconstructor then
|
||||||
begin
|
begin
|
||||||
{ determine symtable level }
|
replace_scanner('custom_class_constructor',sstate);
|
||||||
topowner:=obj;
|
if str_parse_method_dec('constructor fpc_jvm_class_constructor;',potype_class_constructor,true,obj,pd) then
|
||||||
while not(topowner.owner.symtabletype in [staticsymtable,globalsymtable,localsymtable]) do
|
pd.synthetickind:=tsk_empty
|
||||||
topowner:=topowner.owner.defowner;
|
else
|
||||||
{ name doesn't matter, so pick something that hopefully conflict }
|
internalerror(2011040501);
|
||||||
ps:=tprocsym.create('$fpc_jvm_class_constructor');
|
restore_scanner(sstate);
|
||||||
obj.symtable.insert(ps);
|
|
||||||
{ create procdef }
|
|
||||||
pd:=tprocdef.create(topowner.owner.symtablelevel+1);
|
|
||||||
{ method of this objectdef }
|
|
||||||
pd.struct:=obj;
|
|
||||||
{ associated procsym }
|
|
||||||
pd.procsym:=ps;
|
|
||||||
{ constructor }
|
|
||||||
pd.proctypeoption:=potype_class_constructor;
|
|
||||||
{ needs to be exported }
|
|
||||||
include(pd.procoptions,po_global);
|
|
||||||
{ class constructor is a class method }
|
|
||||||
include(pd.procoptions,po_classmethod);
|
|
||||||
{ empty body; proc entry code will add inits for class fields }
|
|
||||||
pd.synthetickind:=tsk_empty;
|
|
||||||
{ private (= package visibility) }
|
|
||||||
pd.visibility:=vis_private;
|
|
||||||
{ result type }
|
|
||||||
pd.returndef:=obj;
|
|
||||||
{ calling convention, self, ... }
|
|
||||||
handle_calling_convention(pd);
|
|
||||||
{ register forward declaration with procsym }
|
|
||||||
proc_add_definition(pd);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -199,14 +177,14 @@ implementation
|
|||||||
replace_scanner('record_jvm_helpers',sstate);
|
replace_scanner('record_jvm_helpers',sstate);
|
||||||
{ no override, because not supported in records; the parser will still
|
{ no override, because not supported in records; the parser will still
|
||||||
accept "inherited" though }
|
accept "inherited" though }
|
||||||
if str_parse_method_dec('function clone: JLObject;',false,def,pd) then
|
if str_parse_method_dec('function clone: JLObject;',potype_function,false,def,pd) then
|
||||||
pd.synthetickind:=tsk_jvm_clone
|
pd.synthetickind:=tsk_jvm_clone
|
||||||
else
|
else
|
||||||
internalerror(2011032806);
|
internalerror(2011032806);
|
||||||
{ can't use def.typesym, not yet set at this point }
|
{ can't use def.typesym, not yet set at this point }
|
||||||
if def.symtable.realname^='' then
|
if def.symtable.realname^='' then
|
||||||
internalerror(2011032803);
|
internalerror(2011032803);
|
||||||
if str_parse_method_dec('procedure fpcDeepCopy(out result:'+def.symtable.realname^+');',false,def,pd) then
|
if str_parse_method_dec('procedure fpcDeepCopy(out result:'+def.symtable.realname^+');',potype_procedure,false,def,pd) then
|
||||||
pd.synthetickind:=tsk_record_deepcopy
|
pd.synthetickind:=tsk_record_deepcopy
|
||||||
else
|
else
|
||||||
internalerror(2011032807);
|
internalerror(2011032807);
|
||||||
|
@ -59,6 +59,9 @@ interface
|
|||||||
systems.systems_typed_constants_node_init) }
|
systems.systems_typed_constants_node_init) }
|
||||||
procedure add_typedconst_init_routine(def: tabstractrecorddef);
|
procedure add_typedconst_init_routine(def: tabstractrecorddef);
|
||||||
|
|
||||||
|
{ parse hint directives (platform, deprecated, ...) for a procdef }
|
||||||
|
procedure maybe_parse_hint_directives(pd:tprocdef);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
@ -83,6 +86,26 @@ implementation
|
|||||||
pjvm;
|
pjvm;
|
||||||
|
|
||||||
|
|
||||||
|
procedure maybe_parse_hint_directives(pd:tprocdef);
|
||||||
|
var
|
||||||
|
dummysymoptions : tsymoptions;
|
||||||
|
deprecatedmsg : pshortstring;
|
||||||
|
begin
|
||||||
|
dummysymoptions:=[];
|
||||||
|
deprecatedmsg:=nil;
|
||||||
|
while try_consume_hintdirective(dummysymoptions,deprecatedmsg) do
|
||||||
|
Consume(_SEMICOLON);
|
||||||
|
if assigned(pd) then
|
||||||
|
begin
|
||||||
|
pd.symoptions:=pd.symoptions+dummysymoptions;
|
||||||
|
pd.deprecatedmsg:=deprecatedmsg;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
stringdispose(deprecatedmsg);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
procedure resolve_forward_types;
|
procedure resolve_forward_types;
|
||||||
var
|
var
|
||||||
i: longint;
|
i: longint;
|
||||||
@ -664,25 +687,6 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure parse_record_members;
|
procedure parse_record_members;
|
||||||
|
|
||||||
procedure maybe_parse_hint_directives(pd:tprocdef);
|
|
||||||
var
|
|
||||||
dummysymoptions : tsymoptions;
|
|
||||||
deprecatedmsg : pshortstring;
|
|
||||||
begin
|
|
||||||
dummysymoptions:=[];
|
|
||||||
deprecatedmsg:=nil;
|
|
||||||
while try_consume_hintdirective(dummysymoptions,deprecatedmsg) do
|
|
||||||
Consume(_SEMICOLON);
|
|
||||||
if assigned(pd) then
|
|
||||||
begin
|
|
||||||
pd.symoptions:=pd.symoptions+dummysymoptions;
|
|
||||||
pd.deprecatedmsg:=deprecatedmsg;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
stringdispose(deprecatedmsg);
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
var
|
||||||
pd : tprocdef;
|
pd : tprocdef;
|
||||||
oldparse_only: boolean;
|
oldparse_only: boolean;
|
||||||
@ -905,16 +909,9 @@ implementation
|
|||||||
oldparse_only:=parse_only;
|
oldparse_only:=parse_only;
|
||||||
parse_only:=true;
|
parse_only:=true;
|
||||||
if is_classdef then
|
if is_classdef then
|
||||||
pd:=class_constructor_head
|
pd:=class_constructor_head(current_structdef)
|
||||||
else
|
else
|
||||||
pd:=constructor_head;
|
pd:=constructor_head;
|
||||||
parse_record_proc_directives(pd);
|
|
||||||
handle_calling_convention(pd);
|
|
||||||
|
|
||||||
{ add definition to procsym }
|
|
||||||
proc_add_definition(pd);
|
|
||||||
|
|
||||||
maybe_parse_hint_directives(pd);
|
|
||||||
|
|
||||||
parse_only:=oldparse_only;
|
parse_only:=oldparse_only;
|
||||||
fields_allowed:=false;
|
fields_allowed:=false;
|
||||||
@ -932,16 +929,9 @@ implementation
|
|||||||
oldparse_only:=parse_only;
|
oldparse_only:=parse_only;
|
||||||
parse_only:=true;
|
parse_only:=true;
|
||||||
if is_classdef then
|
if is_classdef then
|
||||||
pd:=class_destructor_head
|
pd:=class_destructor_head(current_structdef)
|
||||||
else
|
else
|
||||||
pd:=destructor_head;
|
pd:=destructor_head;
|
||||||
parse_record_proc_directives(pd);
|
|
||||||
handle_calling_convention(pd);
|
|
||||||
|
|
||||||
{ add definition to procsym }
|
|
||||||
proc_add_definition(pd);
|
|
||||||
|
|
||||||
maybe_parse_hint_directives(pd);
|
|
||||||
|
|
||||||
parse_only:=oldparse_only;
|
parse_only:=oldparse_only;
|
||||||
fields_allowed:=false;
|
fields_allowed:=false;
|
||||||
@ -1817,13 +1807,13 @@ implementation
|
|||||||
{ the class constructor }
|
{ the class constructor }
|
||||||
if not assigned(pd) then
|
if not assigned(pd) then
|
||||||
begin
|
begin
|
||||||
if str_parse_method_dec('constructor fpc_init_typed_consts_class_constructor;',true,def,pd) then
|
if str_parse_method_dec('constructor fpc_init_typed_consts_class_constructor;',potype_class_constructor,true,def,pd) then
|
||||||
pd.synthetickind:=tsk_empty
|
pd.synthetickind:=tsk_empty
|
||||||
else
|
else
|
||||||
internalerror(2011040206);
|
internalerror(2011040206);
|
||||||
end;
|
end;
|
||||||
{ the initialisation helper }
|
{ the initialisation helper }
|
||||||
if str_parse_method_dec('procedure fpc_init_typed_consts_helper; static;',true,def,pd) then
|
if str_parse_method_dec('procedure fpc_init_typed_consts_helper; static;',potype_procedure,true,def,pd) then
|
||||||
pd.synthetickind:=tsk_tcinit
|
pd.synthetickind:=tsk_tcinit
|
||||||
else
|
else
|
||||||
internalerror(2011040207);
|
internalerror(2011040207);
|
||||||
|
@ -48,7 +48,7 @@ interface
|
|||||||
|
|
||||||
WARNING: save the scanner state before calling this routine, and restore
|
WARNING: save the scanner state before calling this routine, and restore
|
||||||
when done. }
|
when done. }
|
||||||
function str_parse_method_dec(str: ansistring; is_classdef: boolean; astruct: tabstractrecorddef; out pd: tprocdef): boolean;
|
function str_parse_method_dec(str: ansistring; potype: tproctypeoption; is_classdef: boolean; astruct: tabstractrecorddef; out pd: tprocdef): boolean;
|
||||||
|
|
||||||
{ parses a (class or regular) method/constructor/destructor implementation
|
{ parses a (class or regular) method/constructor/destructor implementation
|
||||||
from str, as if it appeared in the current unit's implementation section
|
from str, as if it appeared in the current unit's implementation section
|
||||||
@ -101,7 +101,7 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function str_parse_method_dec(str: ansistring; is_classdef: boolean; astruct: tabstractrecorddef; out pd: tprocdef): boolean;
|
function str_parse_method_dec(str: ansistring; potype: tproctypeoption; is_classdef: boolean; astruct: tabstractrecorddef; out pd: tprocdef): boolean;
|
||||||
var
|
var
|
||||||
oldparse_only: boolean;
|
oldparse_only: boolean;
|
||||||
begin
|
begin
|
||||||
@ -114,7 +114,18 @@ implementation
|
|||||||
current_scanner.substitutemacro('meth_head_macro',@str[1],length(str),current_scanner.line_no,current_scanner.inputfile.ref_index);
|
current_scanner.substitutemacro('meth_head_macro',@str[1],length(str),current_scanner.line_no,current_scanner.inputfile.ref_index);
|
||||||
current_scanner.readtoken(false);
|
current_scanner.readtoken(false);
|
||||||
{ and parse it... }
|
{ and parse it... }
|
||||||
pd:=method_dec(astruct,is_classdef);
|
case potype of
|
||||||
|
potype_class_constructor:
|
||||||
|
pd:=class_constructor_head(astruct);
|
||||||
|
potype_class_destructor:
|
||||||
|
pd:=class_destructor_head(astruct);
|
||||||
|
potype_constructor:
|
||||||
|
pd:=constructor_head;
|
||||||
|
potype_destructor:
|
||||||
|
pd:=destructor_head;
|
||||||
|
else
|
||||||
|
pd:=method_dec(astruct,is_classdef);
|
||||||
|
end;
|
||||||
if assigned(pd) then
|
if assigned(pd) then
|
||||||
result:=true;
|
result:=true;
|
||||||
parse_only:=oldparse_only;
|
parse_only:=oldparse_only;
|
||||||
@ -191,7 +202,7 @@ implementation
|
|||||||
not(tprocdef(pd).proctypeoption in [potype_constructor,potype_destructor]);
|
not(tprocdef(pd).proctypeoption in [potype_constructor,potype_destructor]);
|
||||||
{ + 'overload' for Delphi modes }
|
{ + 'overload' for Delphi modes }
|
||||||
str:=tprocdef(pd).customprocname([pno_proctypeoption,pno_paranames,pno_noclassmarker,pno_noleadingdollar])+'overload;';
|
str:=tprocdef(pd).customprocname([pno_proctypeoption,pno_paranames,pno_noclassmarker,pno_noleadingdollar])+'overload;';
|
||||||
if not str_parse_method_dec(str,isclassmethod,obj,newpd) then
|
if not str_parse_method_dec(str,tprocdef(pd).proctypeoption,isclassmethod,obj,newpd) then
|
||||||
internalerror(2011032001);
|
internalerror(2011032001);
|
||||||
newpd.synthetickind:=tsk_anon_inherited;
|
newpd.synthetickind:=tsk_anon_inherited;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user