mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 05:59:28 +02:00
* for now only auto-generate a parameterless constructor in case no
constructor is declared, rather than all constructors from the parent class (because it cannot be done via scanner-injection, since some parameter types of the parent constructors may not be visible in the current unit, and there is no full-blown tprocdef.getcopy yet nor a way to replace the type of the self-parameter afterwards) * added sanity checks when inserting the parameterless constructor (check for other identifiers called "create", and other parameterless methods) git-svn-id: branches/jvmbackend@18432 -
This commit is contained in:
parent
c05bc8a931
commit
d47f26bbca
@ -1788,7 +1788,7 @@ type_e_invalid_final_assignment=04104_E_Final (class) fields can only be assigne
|
||||
#
|
||||
# Symtable
|
||||
#
|
||||
# 05084 is the last used one
|
||||
# 05086 is the last used one
|
||||
#
|
||||
% \section{Symbol handling}
|
||||
% This section lists all the messages that concern the handling of symbols.
|
||||
@ -2038,7 +2038,20 @@ sym_w_library_overload=05084_W_Possible library conflict: symbol "$1" from libra
|
||||
% the 'libname' part is only a hint, funcname might also be loaded
|
||||
% by another library. This warning appears if 'funcname' is used twice
|
||||
% with two different library names.
|
||||
%
|
||||
sym_e_duplicate_id_create_java_constructor=05085_E_Cannot add implicit constructor 'Create' because identifier already used by "$1"
|
||||
% Java does not automatically add inherited constructors to child classes, so that they can be hidden.
|
||||
% However, if a class does not explicitly declare at least one constructor, the compiler is
|
||||
% required to add a public, parameterless constructor. In Java, constructors are nameless,
|
||||
% but in FPC they are all called ``Create''. Therefore, if you do not add a constructor to
|
||||
% a Java class and furthermore use the ``Create'' identifier for another entity (e.g., a field,
|
||||
% or a parameterless method), the compiler cannot satisfy this requirement.
|
||||
sym_e_no_matching_inherited_parameterless_constructor=05086_E_Cannot generate default constructor for class, because parent has no parameterless constructor
|
||||
% Java does not automatically add inherited constructors to child classes, so that they can be hidden.
|
||||
% However, if a class does not explicitly declare at least one constructor, the compiler is
|
||||
% required to add a public, parameterless constructor. This compiler must then call
|
||||
% the parameterless constructor from the parent class inside this added constructor.
|
||||
% This is however impossible if the parent class does not declare such a constructor.
|
||||
% In this case you must add a valid constructor yourself.
|
||||
% \end{description}
|
||||
#
|
||||
# Codegenerator
|
||||
|
@ -575,6 +575,8 @@ const
|
||||
sym_e_external_class_name_mismatch1=05082;
|
||||
sym_e_external_class_name_mismatch2=05083;
|
||||
sym_w_library_overload=05084;
|
||||
sym_e_duplicate_id_create_java_constructor=05085;
|
||||
sym_e_no_matching_inherited_parameterless_constructor=05086;
|
||||
cg_e_parasize_too_big=06009;
|
||||
cg_e_file_must_call_by_reference=06012;
|
||||
cg_e_cant_use_far_pointer_there=06013;
|
||||
@ -906,9 +908,9 @@ const
|
||||
option_info=11024;
|
||||
option_help_pages=11025;
|
||||
|
||||
MsgTxtSize = 61491;
|
||||
MsgTxtSize = 61683;
|
||||
|
||||
MsgIdxMax : array[1..20] of longint=(
|
||||
26,89,318,105,85,54,111,23,202,63,
|
||||
26,89,318,105,87,54,111,23,202,63,
|
||||
49,20,1,1,1,1,1,1,1,1
|
||||
);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -46,10 +46,11 @@ implementation
|
||||
uses
|
||||
sysutils,cutils,
|
||||
globals,verbose,systems,tokens,
|
||||
symbase,symsym,symtable,symcreat,
|
||||
symbase,symsym,symtable,symcreat,defcmp,
|
||||
node,nld,nmem,ncon,ncnv,ncal,
|
||||
fmodule,scanner,
|
||||
pbase,pexpr,pdecsub,pdecvar,ptype,pdecl,ppu
|
||||
pbase,pexpr,pdecsub,pdecvar,ptype,pdecl,ppu,
|
||||
parabase
|
||||
;
|
||||
|
||||
const
|
||||
@ -708,6 +709,110 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
{ the JVM specs require that you add a default parameterless
|
||||
constructor in case the programmer hasn't specified any }
|
||||
procedure maybe_add_public_default_java_constructor(obj: tabstractrecorddef);
|
||||
|
||||
function find_parameterless_def(psym: tprocsym): tprocdef;
|
||||
var
|
||||
paras: tparalist;
|
||||
begin
|
||||
paras:=tparalist.create;
|
||||
result:=psym.find_procdef_bypara_no_rettype(paras,[cpo_ignorehidden,cpo_openequalisexact]);
|
||||
paras.free;
|
||||
end;
|
||||
|
||||
var
|
||||
sym: tsym;
|
||||
ps: tprocsym;
|
||||
pd: tprocdef;
|
||||
topowner: tdefentry;
|
||||
i: longint;
|
||||
begin
|
||||
{ if there is at least one constructor for a class, do nothing (for
|
||||
records, we'll always also need a parameterless constructor) }
|
||||
if is_javaclass(obj) and
|
||||
(oo_has_constructor in obj.objectoptions) then
|
||||
exit;
|
||||
{ check whether the parent has a parameterless constructor that we can
|
||||
call (in case of a class; all records will derive from
|
||||
java.lang.Object or a shim on top of that with a parameterless
|
||||
constructor) }
|
||||
if is_javaclass(obj) then
|
||||
begin
|
||||
pd:=nil;
|
||||
sym:=tsym(tobjectdef(obj).childof.symtable.find('CREATE'));
|
||||
if assigned(sym) and
|
||||
(sym.typ=procsym) then
|
||||
begin
|
||||
pd:=find_parameterless_def(tprocsym(sym));
|
||||
{ make sure it's a constructor }
|
||||
if assigned(pd) and
|
||||
(pd.proctypeoption<>potype_constructor) then
|
||||
pd:=nil;
|
||||
end;
|
||||
if not assigned(pd) then
|
||||
begin
|
||||
Message(sym_e_no_matching_inherited_parameterless_constructor);
|
||||
exit
|
||||
end;
|
||||
end;
|
||||
{ we call all constructors CREATE, because they don't have a name in
|
||||
Java and otherwise we can't determine whether multiple overloads
|
||||
are created with the same parameters }
|
||||
sym:=tsym(obj.symtable.find('CREATE'));
|
||||
if assigned(sym) then
|
||||
begin
|
||||
{ does another, non-procsym, symbol already exist with that name? }
|
||||
if (sym.typ<>procsym) then
|
||||
begin
|
||||
Message1(sym_e_duplicate_id_create_java_constructor,sym.realname);
|
||||
exit;
|
||||
end;
|
||||
ps:=tprocsym(sym);
|
||||
{ is there already a parameterless function/procedure create? }
|
||||
pd:=find_parameterless_def(ps);
|
||||
if assigned(pd) then
|
||||
begin
|
||||
Message1(sym_e_duplicate_id_create_java_constructor,pd.fullprocname(false));
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
if not assigned(sym) then
|
||||
begin
|
||||
ps:=tprocsym.create('Create');
|
||||
obj.symtable.insert(ps);
|
||||
end;
|
||||
{ determine symtable level }
|
||||
topowner:=obj;
|
||||
while not(topowner.owner.symtabletype in [staticsymtable,globalsymtable,localsymtable]) do
|
||||
topowner:=topowner.owner.defowner;
|
||||
{ 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_constructor;
|
||||
{ needs to be exported }
|
||||
include(pd.procoptions,po_global);
|
||||
{ for Delphi mode }
|
||||
include(pd.procoptions,po_overload);
|
||||
{ synthetic, compiler-generated }
|
||||
include(pd.procoptions,po_synthetic);
|
||||
{ public }
|
||||
pd.visibility:=vis_public;
|
||||
{ result type }
|
||||
pd.returndef:=obj;
|
||||
{ calling convention, self, ... }
|
||||
handle_calling_convention(pd);
|
||||
{ register forward declaration with procsym }
|
||||
proc_add_definition(pd);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function method_dec(astruct: tabstractrecorddef; is_classdef: boolean): tprocdef;
|
||||
|
||||
procedure chkobjc(pd: tprocdef);
|
||||
@ -1348,9 +1453,9 @@ implementation
|
||||
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) and
|
||||
not(oo_is_external in current_structdef.objectoptions) then
|
||||
add_missing_parent_constructors_intf(tobjectdef(current_structdef));
|
||||
if is_javaclass(current_structdef) and
|
||||
not(oo_is_external in current_structdef.objectoptions) then
|
||||
maybe_add_public_default_java_constructor(tobjectdef(current_structdef));
|
||||
|
||||
symtablestack.pop(current_structdef.symtable);
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user