mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-16 04:30:35 +01:00
* fixed typecasting to/from classrefdef
git-svn-id: branches/jvmbackend@18558 -
This commit is contained in:
parent
84640fe7f0
commit
b370314194
@ -62,10 +62,16 @@ interface
|
||||
|
||||
tjvmasnode = class(tcgasnode)
|
||||
protected
|
||||
{ to discern beween "obj as tclassref" and "tclassref(obj)" }
|
||||
classreftypecast: boolean;
|
||||
function target_specific_typecheck: boolean;override;
|
||||
public
|
||||
function pass_1 : tnode;override;
|
||||
procedure pass_generate_code; override;
|
||||
function dogetcopy: tnode; override;
|
||||
function docompare(p: tnode): boolean; override;
|
||||
constructor ppuload(t: tnodetype; ppufile: tcompilerppufile); override;
|
||||
procedure ppuwrite(ppufile: tcompilerppufile); override;
|
||||
end;
|
||||
|
||||
tjvmisnode = class(tisnode)
|
||||
@ -445,6 +451,8 @@ implementation
|
||||
fromdef:=tarraydef(fromdef).elementdef;
|
||||
todef:=tarraydef(todef).elementdef;
|
||||
end;
|
||||
fromdef:=maybe_find_real_class_definition(fromdef,false);
|
||||
todef:=maybe_find_real_class_definition(todef,false);
|
||||
end;
|
||||
|
||||
|
||||
@ -486,8 +494,7 @@ implementation
|
||||
toclasscompatible,
|
||||
procvarconv: boolean;
|
||||
fromdef,
|
||||
todef,
|
||||
jlclass: tdef;
|
||||
todef: tdef;
|
||||
fromarrtype,
|
||||
toarrtype: char;
|
||||
begin
|
||||
@ -503,13 +510,13 @@ implementation
|
||||
fromclasscompatible:=
|
||||
(left.resultdef.typ=objectdef) or
|
||||
is_dynamic_array(left.resultdef) or
|
||||
((left.resultdef.typ in [recorddef,stringdef]) and
|
||||
((left.resultdef.typ in [recorddef,stringdef,classrefdef]) and
|
||||
(resultdef.typ=objectdef)) or
|
||||
procvarconv;
|
||||
toclasscompatible:=
|
||||
(resultdef.typ=objectdef) or
|
||||
is_dynamic_array(resultdef) or
|
||||
((resultdef.typ in [recorddef,stringdef]) and
|
||||
((resultdef.typ in [recorddef,stringdef,classrefdef]) and
|
||||
(left.resultdef.typ=objectdef)) or
|
||||
procvarconv;
|
||||
if fromclasscompatible and toclasscompatible then
|
||||
@ -523,6 +530,8 @@ implementation
|
||||
* related to source
|
||||
* a primitive that are represented by the same type in Java
|
||||
(e.g., byte and shortint) }
|
||||
|
||||
{ in case of arrays, check the compatibility of the innermost types }
|
||||
fromdef:=left.resultdef;
|
||||
todef:=resultdef;
|
||||
get_most_nested_types(fromdef,todef);
|
||||
@ -532,7 +541,10 @@ implementation
|
||||
not fromdef.is_related(todef) and
|
||||
(todef<>java_jlobject) and
|
||||
((fromarrtype in ['A','R']) or
|
||||
(fromarrtype<>toarrtype)) then
|
||||
(fromarrtype<>toarrtype)) and
|
||||
((fromdef.typ<>classrefdef) or
|
||||
(todef.typ<>classrefdef) or
|
||||
not tclassrefdef(fromdef).pointeddef.is_related(tclassrefdef(todef).pointeddef)) then
|
||||
begin
|
||||
if not check_only and
|
||||
not assignment_side then
|
||||
@ -541,6 +553,8 @@ implementation
|
||||
if resultdef.typ=objectdef then
|
||||
resnode:=cloadvmtaddrnode.create(resnode);
|
||||
resnode:=casnode.create(left,resnode);
|
||||
if resultdef.typ=classrefdef then
|
||||
tjvmasnode(resnode).classreftypecast:=true;
|
||||
left:=nil;
|
||||
end
|
||||
end
|
||||
@ -553,31 +567,6 @@ implementation
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ from classrefdef to JLClass and JLObject and back }
|
||||
if (left.resultdef.typ=classrefdef) or
|
||||
(resultdef.typ=classrefdef) then
|
||||
begin
|
||||
if (left.resultdef.typ=classrefdef) and
|
||||
(resultdef.typ=classrefdef) then
|
||||
begin
|
||||
if not tclassrefdef(left.resultdef).pointeddef.is_related(resultdef) and
|
||||
not tclassrefdef(resultdef).pointeddef.is_related(left.resultdef) then
|
||||
CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
|
||||
end
|
||||
else
|
||||
begin
|
||||
jlclass:=search_system_type('JLCLASS').typedef;
|
||||
if (left.resultdef<>jlclass) and
|
||||
(left.resultdef<>java_jlobject) and
|
||||
(resultdef<>jlclass) and
|
||||
(resultdef<>java_jlobject) then
|
||||
CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
|
||||
end;
|
||||
result:=true;
|
||||
exit;
|
||||
end;
|
||||
|
||||
|
||||
{ don't allow conversions between different classes of primitive types,
|
||||
except for a few special cases }
|
||||
|
||||
@ -748,20 +737,67 @@ implementation
|
||||
result:=false;
|
||||
end;
|
||||
|
||||
function isclassrefconv(fromdef, todef: tdef): boolean;
|
||||
var
|
||||
jlclass: tdef;
|
||||
begin
|
||||
jlclass:=nil;
|
||||
if fromdef.typ=classrefdef then
|
||||
begin
|
||||
result:=todef=java_jlobject;
|
||||
if not result and
|
||||
(todef.typ=classrefdef) then
|
||||
{ the fromdef.is_related(todef) case should not become an as-node,
|
||||
handled in typeconversion itself and ignored since always ok
|
||||
-- this one is not very useful either since everything is plain
|
||||
JLClass anyway, but maybe in the future it will be different }
|
||||
result:=tclassrefdef(todef).pointeddef.is_related(tclassrefdef(fromdef).pointeddef);
|
||||
if not result then
|
||||
begin
|
||||
jlclass:=search_system_type('JLCLASS').typedef;
|
||||
result:=todef=jlclass;
|
||||
end;
|
||||
end
|
||||
else if todef.typ=classrefdef then
|
||||
begin
|
||||
result:=fromdef=java_jlobject;
|
||||
if not result then
|
||||
begin
|
||||
jlclass:=search_system_type('JLCLASS').typedef;
|
||||
result:=fromdef=jlclass;
|
||||
end;
|
||||
end
|
||||
else
|
||||
result:=false;
|
||||
end;
|
||||
|
||||
|
||||
var
|
||||
fromelt, toelt: tdef;
|
||||
realfromdef,
|
||||
realtodef: tdef;
|
||||
begin
|
||||
if is_java_class_or_interface(node.left.resultdef) and
|
||||
(node.right.resultdef.typ=classrefdef) and
|
||||
((node.nodetype<>asn) or
|
||||
not tjvmasnode(node).classreftypecast) then
|
||||
begin
|
||||
{ handle using normal code }
|
||||
result:=false;
|
||||
exit;
|
||||
end;
|
||||
realfromdef:=maybe_find_real_class_definition(node.left.resultdef,false);
|
||||
realtodef:=node.right.resultdef;
|
||||
if realtodef.typ=classrefdef then
|
||||
if (realtodef.typ=classrefdef) and
|
||||
((node.nodetype<>asn) or
|
||||
not tjvmasnode(node).classreftypecast) then
|
||||
realtodef:=tclassrefdef(realtodef).pointeddef;
|
||||
realtodef:=maybe_find_real_class_definition(realtodef,false);
|
||||
result:=isrecordconv(realfromdef,realtodef);
|
||||
if not result then
|
||||
result:=isstringconv(realfromdef,realtodef);
|
||||
if not result then
|
||||
result:=isclassrefconv(realfromdef,realtodef);
|
||||
if not result then
|
||||
{ dynamic arrays can be converted to java.lang.Object and vice versa }
|
||||
if realtodef=java_jlobject then
|
||||
@ -786,22 +822,10 @@ implementation
|
||||
(fromelt.typ=arraydef)) and
|
||||
((toelt.typ=objectdef) or
|
||||
(toelt.typ=arraydef)));
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (node.right.resultdef.typ<>classrefdef) then
|
||||
result:=false
|
||||
else
|
||||
result:=true;
|
||||
end;
|
||||
if result then
|
||||
if node.nodetype=asn then
|
||||
begin
|
||||
if realtodef.typ<>classrefdef then
|
||||
node.resultdef:=realtodef
|
||||
else
|
||||
node.resultdef:=tclassrefdef(realtodef).pointeddef
|
||||
end
|
||||
node.resultdef:=realtodef
|
||||
else
|
||||
node.resultdef:=pasbool8type;
|
||||
end;
|
||||
@ -885,6 +909,8 @@ implementation
|
||||
checkdef:=java_jlstring;
|
||||
if checkdef.typ in [objectdef,recorddef] then
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(tabstractrecorddef(checkdef).jvm_full_typename(true))))
|
||||
else if checkdef.typ=classrefdef then
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol('java/lang/Class')))
|
||||
else
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(jvmencodetype(checkdef,false))));
|
||||
location_reset(node.location,LOC_REGISTER,OS_ADDR);
|
||||
@ -915,6 +941,35 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function tjvmasnode.dogetcopy: tnode;
|
||||
begin
|
||||
result:=inherited dogetcopy;
|
||||
tjvmasnode(result).classreftypecast:=classreftypecast;
|
||||
end;
|
||||
|
||||
|
||||
function tjvmasnode.docompare(p: tnode): boolean;
|
||||
begin
|
||||
result:=
|
||||
inherited docompare(p) and
|
||||
(tjvmasnode(p).classreftypecast=classreftypecast);
|
||||
end;
|
||||
|
||||
|
||||
constructor tjvmasnode.ppuload(t: tnodetype; ppufile: tcompilerppufile);
|
||||
begin
|
||||
inherited;
|
||||
classreftypecast:=boolean(ppufile.getbyte);
|
||||
end;
|
||||
|
||||
|
||||
procedure tjvmasnode.ppuwrite(ppufile: tcompilerppufile);
|
||||
begin
|
||||
inherited ppuwrite(ppufile);
|
||||
ppufile.putbyte(byte(classreftypecast));
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
TJVMIsNode
|
||||
*****************************************************************************}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user