* Mantis #27044: copy Variant to temp if it cannot be passed by reference to fpc_dispinvoke_variant helper. This provides behavior consistent to implicit 'self' parameter of objects/records.

git-svn-id: trunk@29093 -
This commit is contained in:
sergei 2014-11-20 18:36:10 +00:00
parent d844025ddf
commit 64af966eaa

View File

@ -336,6 +336,8 @@ implementation
pvardatadef : tdef; pvardatadef : tdef;
useresult: boolean; useresult: boolean;
restype: byte; restype: byte;
selftemp: ttempcreatenode;
selfpara: tnode;
names : ansistring; names : ansistring;
variantdispatch : boolean; variantdispatch : boolean;
@ -369,7 +371,7 @@ implementation
if is_interfacecom_or_dispinterface(sourcedef) then if is_interfacecom_or_dispinterface(sourcedef) then
begin begin
{ distinct IDispatch and IUnknown interfaces } { distinct IDispatch and IUnknown interfaces }
if def_is_related(tobjectdef(sourcedef),tobjectdef(search_system_type('IDISPATCH').typedef)) then if def_is_related(tobjectdef(sourcedef),interface_idispatch) then
result:=vardispatch result:=vardispatch
else else
result:=varunknown; result:=varunknown;
@ -382,6 +384,8 @@ implementation
variantdispatch:=selfnode.resultdef.typ=variantdef; variantdispatch:=selfnode.resultdef.typ=variantdef;
result:=internalstatements(statements); result:=internalstatements(statements);
result_data:=nil; result_data:=nil;
selftemp:=nil;
selfpara:=nil;
useresult := assigned(resultdef) and not is_void(resultdef); useresult := assigned(resultdef) and not is_void(resultdef);
if useresult then if useresult then
@ -527,13 +531,27 @@ implementation
{ actual call } { actual call }
vardatadef:=trecorddef(search_system_type('TVARDATA').typedef); vardatadef:=trecorddef(search_system_type('TVARDATA').typedef);
{ the Variant should behave similar to hidden 'self' parameter of objects/records,
see issues #26773 and #27044 }
if not valid_for_var(selfnode,false) then
begin
selftemp:=ctempcreatenode.create(selfnode.resultdef,selfnode.resultdef.size,tt_persistent,false);
addstatement(statements,selftemp);
addstatement(statements,cassignmentnode.create(ctemprefnode.create(selftemp),selfnode));
selfpara:=ctemprefnode.create(selftemp);
end
else
selfpara:=selfnode;
addstatement(statements,ccallnode.createintern('fpc_dispinvoke_variant', addstatement(statements,ccallnode.createintern('fpc_dispinvoke_variant',
{ parameters are passed always reverted, i.e. the last comes first } { parameters are passed always reverted, i.e. the last comes first }
ccallparanode.create(caddrnode.create(ctemprefnode.create(params)), ccallparanode.create(caddrnode.create(ctemprefnode.create(params)),
ccallparanode.create(caddrnode.create(calldescnode), ccallparanode.create(caddrnode.create(calldescnode),
ccallparanode.create(ctypeconvnode.create_internal(selfnode,vardatadef), ccallparanode.create(ctypeconvnode.create_internal(selfpara,vardatadef),
ccallparanode.create(ctypeconvnode.create_internal(resultvalue,pvardatadef),nil))))) ccallparanode.create(ctypeconvnode.create_internal(resultvalue,pvardatadef),nil)))))
); );
if assigned(selftemp) then
addstatement(statements,ctempdeletenode.create(selftemp));
end end
else else
begin begin