浏览代码

* 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 -
sergei 10 年之前
父节点
当前提交
64af966eaa
共有 1 个文件被更改,包括 20 次插入2 次删除
  1. 20 2
      compiler/ncal.pas

+ 20 - 2
compiler/ncal.pas

@@ -336,6 +336,8 @@ implementation
         pvardatadef : tdef;
         useresult: boolean;
         restype: byte;
+        selftemp: ttempcreatenode;
+        selfpara: tnode;
 
         names : ansistring;
         variantdispatch : boolean;
@@ -369,7 +371,7 @@ implementation
           if is_interfacecom_or_dispinterface(sourcedef) then
             begin
               { 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
               else
                 result:=varunknown;
@@ -382,6 +384,8 @@ implementation
         variantdispatch:=selfnode.resultdef.typ=variantdef;
         result:=internalstatements(statements);
         result_data:=nil;
+        selftemp:=nil;
+        selfpara:=nil;
 
         useresult := assigned(resultdef) and not is_void(resultdef);
         if useresult then
@@ -527,13 +531,27 @@ implementation
             { actual call }
             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',
               { parameters are passed always reverted, i.e. the last comes first }
               ccallparanode.create(caddrnode.create(ctemprefnode.create(params)),
               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)))))
             );
+            if assigned(selftemp) then
+              addstatement(statements,ctempdeletenode.create(selftemp));
           end
         else
           begin