浏览代码

fcl-passrc: on incompatible procedural arg types write params

git-svn-id: trunk@44207 -
Mattias Gaertner 5 年之前
父节点
当前提交
06a6bfd981
共有 2 个文件被更改,包括 64 次插入33 次删除
  1. 43 33
      packages/fcl-passrc/src/pasresolver.pp
  2. 21 0
      packages/fcl-passrc/tests/tcresolver.pas

+ 43 - 33
packages/fcl-passrc/src/pasresolver.pp

@@ -22613,16 +22613,10 @@ procedure TPasResolver.RaiseIncompatibleType(id: TMaxPrecInt; MsgNumber: integer
   const Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif};
   const Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif};
   GotType, ExpType: TPasType; ErrorEl: TPasElement);
   GotType, ExpType: TPasType; ErrorEl: TPasElement);
 var
 var
-  DescA, DescB: String;
+  GotDesc, ExpDesc: String;
 begin
 begin
-  DescA:=GetTypeDescription(GotType);
-  DescB:=GetTypeDescription(ExpType);
-  if DescA=DescB then
-    begin
-    DescA:=GetTypeDescription(GotType,true);
-    DescB:=GetTypeDescription(ExpType,true);
-    end;
-  RaiseIncompatibleTypeDesc(id,MsgNumber,Args,DescA,DescB,ErrorEl);
+  GetIncompatibleTypeDesc(GotType,ExpType,GotDesc,ExpDesc);
+  RaiseIncompatibleTypeDesc(id,MsgNumber,Args,GotDesc,ExpDesc,ErrorEl);
 end;
 end;
 
 
 procedure TPasResolver.RaiseIncompatibleTypeRes(id: TMaxPrecInt; MsgNumber: integer;
 procedure TPasResolver.RaiseIncompatibleTypeRes(id: TMaxPrecInt; MsgNumber: integer;
@@ -22784,50 +22778,66 @@ begin
       ExpDesc:=BaseTypeNames[btPointer]
       ExpDesc:=BaseTypeNames[btPointer]
     else
     else
       ExpDesc:=GetBaseDescription(ExpType);
       ExpDesc:=GetBaseDescription(ExpType);
-    if GotDesc=ExpDesc then
-      begin
-      GotDesc:=GetBaseDescription(GotType,true);
-      ExpDesc:=GetBaseDescription(ExpType,true);
-      end;
+    if GotDesc<>ExpDesc then
+      exit;
+    GotDesc:=GetBaseDescription(GotType,true);
+    ExpDesc:=GetBaseDescription(ExpType,true);
     end
     end
   else if (GotType.LoTypeEl<>nil) and (ExpType.LoTypeEl<>nil) then
   else if (GotType.LoTypeEl<>nil) and (ExpType.LoTypeEl<>nil) then
     begin
     begin
     if (GotType.LoTypeEl.ClassType=ExpType.LoTypeEl.ClassType)
     if (GotType.LoTypeEl.ClassType=ExpType.LoTypeEl.ClassType)
         and (GotType.LoTypeEl is TPasProcedureType) then
         and (GotType.LoTypeEl is TPasProcedureType) then
+      begin
       // procedural types
       // procedural types
       GetIncompatibleProcParamsDesc(TPasProcedureType(GotType.LoTypeEl),
       GetIncompatibleProcParamsDesc(TPasProcedureType(GotType.LoTypeEl),
-        TPasProcedureType(ExpType.LoTypeEl),GotDesc,ExpDesc)
-    else
+        TPasProcedureType(ExpType.LoTypeEl),GotDesc,ExpDesc);
+      if GotDesc<>ExpDesc then
+        exit;
+      end;
+    GotDesc:=GetTypeDescription(GotType);
+    ExpDesc:=GetTypeDescription(ExpType);
+    if GotDesc<>ExpDesc then
+      exit;
+    if GotType.HiTypeEl<>ExpType.HiTypeEl then
       begin
       begin
-      GotDesc:=GetTypeDescription(GotType);
-      ExpDesc:=GetTypeDescription(ExpType);
-      if (GotDesc=ExpDesc) and (GotType.HiTypeEl<>ExpType.HiTypeEl) then
-        begin
-        GotDesc:=GetTypeDescription(GotType.HiTypeEl);
-        ExpDesc:=GetTypeDescription(ExpType.HiTypeEl);
-        end;
-      if GotDesc=ExpDesc then
-        begin
-        GotDesc:=GetTypeDescription(GotType,true);
-        ExpDesc:=GetTypeDescription(ExpType,true);
-        end;
+      GotDesc:=GetTypeDescription(GotType.HiTypeEl);
+      ExpDesc:=GetTypeDescription(ExpType.HiTypeEl);
+      if GotDesc<>ExpDesc then
+        exit;
       end;
       end;
+    GotDesc:=GetTypeDescription(GotType,true);
+    ExpDesc:=GetTypeDescription(ExpType,true);
     end
     end
   else
   else
     begin
     begin
     GotDesc:=GetResolverResultDescription(GotType,true);
     GotDesc:=GetResolverResultDescription(GotType,true);
     ExpDesc:=GetResolverResultDescription(ExpType,true);
     ExpDesc:=GetResolverResultDescription(ExpType,true);
-    if GotDesc=ExpDesc then
-      begin
-      GotDesc:=GetResolverResultDescription(GotType,false);
-      ExpDesc:=GetResolverResultDescription(ExpType,false);
-      end;
+    if GotDesc<>ExpDesc then
+      exit;
+    GotDesc:=GetResolverResultDescription(GotType,false);
+    ExpDesc:=GetResolverResultDescription(ExpType,false);
     end;
     end;
 end;
 end;
 
 
 procedure TPasResolver.GetIncompatibleTypeDesc(const GotType,
 procedure TPasResolver.GetIncompatibleTypeDesc(const GotType,
   ExpType: TPasType; out GotDesc, ExpDesc: String);
   ExpType: TPasType; out GotDesc, ExpDesc: String);
+var
+  GotLoType, ExpLoType: TPasType;
 begin
 begin
+  GotLoType:=ResolveAliasType(GotType);
+  ExpLoType:=ResolveAliasType(ExpType);
+  if (GotLoType<>nil) and (ExpLoType<>nil) then
+    begin
+    if (GotLoType.ClassType=ExpLoType.ClassType)
+        and (GotLoType is TPasProcedureType) then
+      begin
+      // procedural types
+      GetIncompatibleProcParamsDesc(TPasProcedureType(GotLoType),
+        TPasProcedureType(ExpLoType),GotDesc,ExpDesc);
+      if GotDesc<>ExpDesc then
+        exit;
+      end;
+    end;
   GotDesc:=GetTypeDescription(GotType);
   GotDesc:=GetTypeDescription(GotType);
   ExpDesc:=GetTypeDescription(ExpType);
   ExpDesc:=GetTypeDescription(ExpType);
   if GotDesc<>ExpDesc then exit;
   if GotDesc<>ExpDesc then exit;

+ 21 - 0
packages/fcl-passrc/tests/tcresolver.pas

@@ -853,6 +853,7 @@ type
     Procedure TestAssignProcToFunctionFail;
     Procedure TestAssignProcToFunctionFail;
     Procedure TestAssignProcWrongArgsFail;
     Procedure TestAssignProcWrongArgsFail;
     Procedure TestAssignProcWrongArgAccessFail;
     Procedure TestAssignProcWrongArgAccessFail;
+    Procedure TestProcType_SameSignatureObjFPC; // ToDo
     Procedure TestProcType_AssignNestedProcFail;
     Procedure TestProcType_AssignNestedProcFail;
     Procedure TestArrayOfProc;
     Procedure TestArrayOfProc;
     Procedure TestProcType_Assigned;
     Procedure TestProcType_Assigned;
@@ -15630,6 +15631,26 @@ begin
     nIncompatibleTypeArgNo);
     nIncompatibleTypeArgNo);
 end;
 end;
 
 
+procedure TTestResolver.TestProcType_SameSignatureObjFPC;
+begin
+  exit;
+  StartProgram(false);
+  Add([
+  '{$mode objfpc}',
+  'type',
+  '  TRun = procedure(a: Word);',
+  '  TRunIt = procedure(a: TRun);',
+  '  TFly = procedure(a: Word);',
+  'procedure FlyIt(a: TFly);',
+  'begin',
+  'end;',
+  'var RunIt: TRunIt;',
+  'begin',
+  '  RunIt:=@FlyIt;',
+  '']);
+  ParseProgram;
+end;
+
 procedure TTestResolver.TestProcType_AssignNestedProcFail;
 procedure TTestResolver.TestProcType_AssignNestedProcFail;
 begin
 begin
   StartProgram(false);
   StartProgram(false);