Browse Source

fcl-passrc: resolver: fixed CheckClassIsClass if DestType is forward class

git-svn-id: trunk@37434 -
Mattias Gaertner 7 years ago
parent
commit
bc6b6fe7c9
2 changed files with 32 additions and 15 deletions
  1. 12 15
      packages/fcl-passrc/src/pasresolver.pp
  2. 20 0
      packages/fcl-passrc/tests/tcresolver.pas

+ 12 - 15
packages/fcl-passrc/src/pasresolver.pp

@@ -920,7 +920,7 @@ type
     FLastMsgType: TMessageType;
     FLastMsgType: TMessageType;
     FLastSourcePos: TPasSourcePos;
     FLastSourcePos: TPasSourcePos;
     FOptions: TPasResolverOptions;
     FOptions: TPasResolverOptions;
-    FPendingForwards: TFPList; // list of TPasElement needed to check for forward procs
+    FPendingForwardProcs: TFPList; // list of TPasElement needed to check for forward procs
     FRootElement: TPasModule;
     FRootElement: TPasModule;
     FScopeClass_Class: TPasClassScopeClass;
     FScopeClass_Class: TPasClassScopeClass;
     FScopeClass_Proc: TPasProcedureScopeClass;
     FScopeClass_Proc: TPasProcedureScopeClass;
@@ -1055,7 +1055,7 @@ type
     procedure ReplaceProcScopeImplArgsWithDeclArgs(ImplProcScope: TPasProcedureScope);
     procedure ReplaceProcScopeImplArgsWithDeclArgs(ImplProcScope: TPasProcedureScope);
     procedure CheckConditionExpr(El: TPasExpr; const ResolvedEl: TPasResolverResult); virtual;
     procedure CheckConditionExpr(El: TPasExpr; const ResolvedEl: TPasResolverResult); virtual;
     procedure CheckProcSignatureMatch(DeclProc, ImplProc: TPasProcedure; CheckNames: boolean);
     procedure CheckProcSignatureMatch(DeclProc, ImplProc: TPasProcedure; CheckNames: boolean);
-    procedure CheckPendingForwards(El: TPasElement);
+    procedure CheckPendingForwardProcs(El: TPasElement);
     procedure ComputeBinaryExpr(Bin: TBinaryExpr;
     procedure ComputeBinaryExpr(Bin: TBinaryExpr;
       out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
       out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
       StartEl: TPasElement);
       StartEl: TPasElement);
@@ -3121,9 +3121,9 @@ begin
 
 
   // check all methods have bodies
   // check all methods have bodies
   // and all forward classes and pointers are resolved
   // and all forward classes and pointers are resolved
-  for i:=0 to FPendingForwards.Count-1 do
-    CheckPendingForwards(TPasElement(FPendingForwards[i]));
-  FPendingForwards.Clear;
+  for i:=0 to FPendingForwardProcs.Count-1 do
+    CheckPendingForwardProcs(TPasElement(FPendingForwardProcs[i]));
+  FPendingForwardProcs.Clear;
 
 
   // close all sections
   // close all sections
   while (TopScope<>nil) and (TopScope.ClassType=TPasSectionScope) do
   while (TopScope<>nil) and (TopScope.ClassType=TPasSectionScope) do
@@ -6046,7 +6046,7 @@ begin
     end;
     end;
 end;
 end;
 
 
-procedure TPasResolver.CheckPendingForwards(El: TPasElement);
+procedure TPasResolver.CheckPendingForwardProcs(El: TPasElement);
 var
 var
   i: Integer;
   i: Integer;
   DeclEl: TPasElement;
   DeclEl: TPasElement;
@@ -6108,7 +6108,7 @@ procedure TPasResolver.AddSection(El: TPasSection);
 // TInterfaceSection, TImplementationSection, TProgramSection, TLibrarySection
 // TInterfaceSection, TImplementationSection, TProgramSection, TLibrarySection
 // Note: implementation scope is within the interface scope
 // Note: implementation scope is within the interface scope
 begin
 begin
-  FPendingForwards.Add(El); // check forward declarations at the end
+  FPendingForwardProcs.Add(El); // check forward declarations at the end
   PushScope(El,TPasSectionScope);
   PushScope(El,TPasSectionScope);
 end;
 end;
 
 
@@ -6132,7 +6132,7 @@ begin
     RaiseInvalidScopeForElement(20160922163508,El);
     RaiseInvalidScopeForElement(20160922163508,El);
   if El.Name<>'' then begin
   if El.Name<>'' then begin
     AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
     AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
-    FPendingForwards.Add(El); // check forward declarations at the end
+    FPendingForwardProcs.Add(El); // check forward declarations at the end
   end;
   end;
 
 
   if El.Parent.ClassType<>TPasVariant then
   if El.Parent.ClassType<>TPasVariant then
@@ -6177,7 +6177,7 @@ begin
   else
   else
     AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
     AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
 
 
-  FPendingForwards.Add(El); // check forward declarations at the end
+  FPendingForwardProcs.Add(El); // check forward declarations at the end
 end;
 end;
 
 
 procedure TPasResolver.AddVariable(El: TPasVariable);
 procedure TPasResolver.AddVariable(El: TPasVariable);
@@ -9350,7 +9350,7 @@ constructor TPasResolver.Create;
 begin
 begin
   inherited Create;
   inherited Create;
   FDefaultScope:=TPasDefaultScope.Create;
   FDefaultScope:=TPasDefaultScope.Create;
-  FPendingForwards:=TFPList.Create;
+  FPendingForwardProcs:=TFPList.Create;
   FBaseTypeChar:=btAnsiChar;
   FBaseTypeChar:=btAnsiChar;
   FBaseTypeString:=btAnsiString;
   FBaseTypeString:=btAnsiString;
   FBaseTypeExtended:=btDouble;
   FBaseTypeExtended:=btDouble;
@@ -10059,7 +10059,7 @@ begin
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TPasResolver.Destroy FPendingForwards...');
   writeln('TPasResolver.Destroy FPendingForwards...');
   {$ENDIF}
   {$ENDIF}
-  FreeAndNil(FPendingForwards);
+  FreeAndNil(FPendingForwardProcs);
   FreeAndNil(fExprEvaluator);
   FreeAndNil(fExprEvaluator);
   inherited Destroy;
   inherited Destroy;
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
@@ -11391,7 +11391,6 @@ begin
     begin
     begin
     LBT:=GetActualBaseType(LHS.BaseType);
     LBT:=GetActualBaseType(LHS.BaseType);
     RBT:=GetActualBaseType(RHS.BaseType);
     RBT:=GetActualBaseType(RHS.BaseType);
-    writeln('AAA1 TPasResolver.CheckAssignResCompatibility ',lbt,' ',rbt);
     if LHS.TypeEl=nil then
     if LHS.TypeEl=nil then
       begin
       begin
       if LBT=btUntyped then
       if LBT=btUntyped then
@@ -14290,9 +14289,7 @@ begin
   writeln('TPasResolver.CheckClassIsClass SrcType=',GetObjName(SrcType),' DestType=',GetObjName(DestType));
   writeln('TPasResolver.CheckClassIsClass SrcType=',GetObjName(SrcType),' DestType=',GetObjName(DestType));
   {$ENDIF}
   {$ENDIF}
   if DestType=nil then exit(cIncompatible);
   if DestType=nil then exit(cIncompatible);
-  // skip Dest alias
-  while (DestType.ClassType=TPasAliasType) do
-    DestType:=TPasAliasType(DestType).DestType;
+  DestType:=ResolveAliasType(DestType);
 
 
   Result:=cExact;
   Result:=cExact;
   while SrcType<>nil do
   while SrcType<>nil do

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

@@ -486,6 +486,7 @@ type
     Procedure TestClassOf_AlwaysForward;
     Procedure TestClassOf_AlwaysForward;
     Procedure TestClassOf_ClassOfBeforeClass_FuncResult;
     Procedure TestClassOf_ClassOfBeforeClass_FuncResult;
     Procedure TestClassOf_Const;
     Procedure TestClassOf_Const;
+    Procedure TestClassOf_Const2;
 
 
     // property
     // property
     Procedure TestProperty1;
     Procedure TestProperty1;
@@ -7953,6 +7954,25 @@ begin
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
+procedure TTestResolver.TestClassOf_Const2;
+begin
+  StartProgram(false);
+  Add([
+  'type',
+  '  TObject = class',
+  '  end;',
+  '  TFieldType = (fta,ftb);',
+  '  TField = Class;',
+  '  TFieldClass = class of TField;',
+  '  TField = Class(TObject);',
+  '  TFieldA = Class(TField);',
+  '  TFieldB = Class(TField);',
+  'Const',
+  '  DefaultFieldClasses : Array [TFieldType] of TFieldClass = (TFieldA,TFieldB);',
+  'begin']);
+  ParseProgram;
+end;
+
 procedure TTestResolver.TestProperty1;
 procedure TTestResolver.TestProperty1;
 begin
 begin
   StartProgram(false);
   StartProgram(false);