Browse Source

fcl-passrc: resolver: use function result.parent functype, added storage for procedure references

git-svn-id: trunk@38298 -
Mattias Gaertner 7 years ago
parent
commit
9255993eb4

+ 211 - 6
packages/fcl-passrc/src/pasresolver.pp

@@ -670,6 +670,32 @@ type
   end;
   end;
   TPasClassScopeClass = class of TPasClassScope;
   TPasClassScopeClass = class of TPasClassScope;
 
 
+  TPSRefAccess = (
+    psraNone,
+    psraRead,
+    psraWrite,
+    psraReadWrite,
+    psraWriteRead,
+    psraTypeInfo
+    );
+
+  { TPasProcScopeReference }
+
+  TPasProcScopeReference = class
+  private
+    FElement: TPasElement;
+    procedure SetElement(const AValue: TPasElement);
+  public
+    {$IFDEF VerbosePasResolver}
+    Owner: TObject;
+    {$ENDIF}
+    Access: TPSRefAccess;
+    NeedTypeInfo: boolean;
+    NextSameName: TPasProcScopeReference;
+    destructor Destroy; override;
+    property Element: TPasElement read FElement write SetElement;
+  end;
+
   TPasProcedureScopeFlag = (
   TPasProcedureScopeFlag = (
     ppsfIsGroupOverload // mode objfpc: one overload is enough for all procs in same scope
     ppsfIsGroupOverload // mode objfpc: one overload is enough for all procs in same scope
     );
     );
@@ -678,6 +704,8 @@ type
   { TPasProcedureScope }
   { TPasProcedureScope }
 
 
   TPasProcedureScope = Class(TPasIdentifierScope)
   TPasProcedureScope = Class(TPasIdentifierScope)
+  private
+    procedure OnClearReferenceItem(Item, Dummy: pointer);
   public
   public
     DeclarationProc: TPasProcedure; // the corresponding forward declaration
     DeclarationProc: TPasProcedure; // the corresponding forward declaration
     ImplProc: TPasProcedure; // the corresponding proc with Body
     ImplProc: TPasProcedure; // the corresponding proc with Body
@@ -687,6 +715,7 @@ type
     Mode: TModeSwitch;
     Mode: TModeSwitch;
     Flags: TPasProcedureScopeFlags;
     Flags: TPasProcedureScopeFlags;
     BoolSwitches: TBoolSwitches;
     BoolSwitches: TBoolSwitches;
+    References: TFPHashList; // list of TPasProcScopeReference, created by TPasAnalyzer
     function FindIdentifier(const Identifier: String): TPasIdentifier; override;
     function FindIdentifier(const Identifier: String): TPasIdentifier; override;
     procedure IterateElements(const aName: string; StartScope: TPasScope;
     procedure IterateElements(const aName: string; StartScope: TPasScope;
       const OnIterateElement: TIterateScopeElement; Data: Pointer;
       const OnIterateElement: TIterateScopeElement; Data: Pointer;
@@ -694,6 +723,9 @@ type
     function GetSelfScope: TPasProcedureScope; // get the next parent procscope with a classcope
     function GetSelfScope: TPasProcedureScope; // get the next parent procscope with a classcope
     procedure WriteIdentifiers(Prefix: string); override;
     procedure WriteIdentifiers(Prefix: string); override;
     destructor Destroy; override;
     destructor Destroy; override;
+    procedure ClearReferences;
+    function AddReference(El: TPasElement; Access: TPSRefAccess): TPasProcScopeReference;
+    function FindReference(const aName: string): TPasProcScopeReference;
   end;
   end;
   TPasProcedureScopeClass = class of TPasProcedureScope;
   TPasProcedureScopeClass = class of TPasProcedureScope;
 
 
@@ -858,6 +890,19 @@ type
     );
     );
   TPRResolveVarAccesses = set of TResolvedRefAccess;
   TPRResolveVarAccesses = set of TResolvedRefAccess;
 
 
+const
+  ResolvedToPSRefAccess: array[TResolvedRefAccess] of TPSRefAccess = (
+    psraNone, // rraNone
+    psraRead,  // rraRead
+    psraWrite, // rraAssign
+    psraReadWrite, // rraReadAndAssign
+    psraReadWrite, // rraVarParam
+    psraWrite, // rraOutParam
+    psraNone // rraParamToUnknownProc
+    );
+
+type
+
   { TResolvedReference - CustomData for normal references }
   { TResolvedReference - CustomData for normal references }
 
 
   TResolvedReference = Class(TResolveData)
   TResolvedReference = Class(TResolveData)
@@ -1396,6 +1441,7 @@ type
     procedure RestoreSubScopes(Depth: integer);
     procedure RestoreSubScopes(Depth: integer);
     function GetInheritedExprScope(ErrorEl: TPasElement): TPasProcedureScope;
     function GetInheritedExprScope(ErrorEl: TPasElement): TPasProcedureScope;
     // log and messages
     // log and messages
+    class function MangleSourceLineNumber(Line, Column: integer): integer;
     class procedure UnmangleSourceLineNumber(LineNumber: integer;
     class procedure UnmangleSourceLineNumber(LineNumber: integer;
       out Line, Column: integer);
       out Line, Column: integer);
     class function GetDbgSourcePosStr(El: TPasElement): string;
     class function GetDbgSourcePosStr(El: TPasElement): string;
@@ -2092,6 +2138,30 @@ begin
   Result:='['+Result+']';
   Result:='['+Result+']';
 end;
 end;
 
 
+{ TPasProcScopeReference }
+
+procedure TPasProcScopeReference.SetElement(const AValue: TPasElement);
+begin
+  if FElement=AValue then Exit;
+  if FElement<>nil then
+    FElement.Release;
+  FElement:=AValue;
+  if FElement<>nil then
+    FElement.AddRef;
+end;
+
+destructor TPasProcScopeReference.Destroy;
+begin
+  {$IFDEF VerbosePasResolverMem}
+  writeln('TPasProcScopeReference.Destroy START ',ClassName,' "',GetObjName(Element),'"');
+  {$ENDIF}
+  Element:=nil;
+  inherited Destroy;
+  {$IFDEF VerbosePasResolverMem}
+  writeln('TPasProcScopeReference.Destroy END ',ClassName);
+  {$ENDIF}
+end;
+
 { TPasPropertyScope }
 { TPasPropertyScope }
 
 
 destructor TPasPropertyScope.Destroy;
 destructor TPasPropertyScope.Destroy;
@@ -2189,6 +2259,21 @@ end;
 
 
 { TPasProcedureScope }
 { TPasProcedureScope }
 
 
+procedure TPasProcedureScope.OnClearReferenceItem(Item, Dummy: pointer);
+var
+  Ref: TPasProcScopeReference absolute Item;
+  Ref2: TPasProcScopeReference;
+begin
+  if Dummy=nil then ;
+  //writeln('TPasProcedureScope.OnClearReferenceItem ',GetObjName(Ref.Element));
+  while Ref<>nil do
+    begin
+    Ref2:=Ref;
+    Ref:=Ref.NextSameName;
+    Ref2.Free;
+    end;
+end;
+
 function TPasProcedureScope.FindIdentifier(const Identifier: String
 function TPasProcedureScope.FindIdentifier(const Identifier: String
   ): TPasIdentifier;
   ): TPasIdentifier;
 begin
 begin
@@ -2231,6 +2316,7 @@ end;
 
 
 destructor TPasProcedureScope.Destroy;
 destructor TPasProcedureScope.Destroy;
 begin
 begin
+  ClearReferences;
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TPasProcedureScope.Destroy START ',ClassName);
   writeln('TPasProcedureScope.Destroy START ',ClassName);
   {$ENDIF}
   {$ENDIF}
@@ -2241,6 +2327,113 @@ begin
   {$ENDIF}
   {$ENDIF}
 end;
 end;
 
 
+procedure TPasProcedureScope.ClearReferences;
+begin
+  if References=nil then exit;
+  References.ForEachCall(@OnClearReferenceItem,nil);
+  References.Clear;
+  FreeAndNil(References);
+end;
+
+function TPasProcedureScope.AddReference(El: TPasElement; Access: TPSRefAccess
+  ): TPasProcScopeReference;
+var
+  LoName: String;
+  OldItem, Item: TPasProcScopeReference;
+  Index: Integer;
+begin
+  if References=nil then
+    References:=TFPHashList.Create;
+  LoName:=lowercase(El.Name);
+  OldItem:=TPasProcScopeReference(References.Find(LoName));
+  Item:=OldItem;
+  while Item<>nil do
+    begin
+    if Item.Element=El then
+      begin
+      // already marked as used -> combine access
+      case Access of
+      psraNone: ;
+      psraRead:
+        case Item.Access of
+          psraNone: Item.Access:=Access;
+          //psraRead: ;
+          psraWrite: Item.Access:=psraWriteRead;
+          //psraReadWrite: ;
+          //psraWriteRead: ;
+          //psraTypeInfo: ;
+        end;
+      psraWrite:
+        case Item.Access of
+          psraNone: Item.Access:=Access;
+          psraRead: Item.Access:=psraReadWrite;
+          //psraWrite: ;
+          //psraReadWrite: ;
+          //psraWriteRead: ;
+          //psraTypeInfo: ;
+        end;
+      psraReadWrite:
+        case Item.Access of
+          psraNone: Item.Access:=Access;
+          psraRead: Item.Access:=psraReadWrite;
+          psraWrite: Item.Access:=psraWriteRead;
+          //psraReadWrite: ;
+          //psraWriteRead: ;
+          //psraTypeInfo: ;
+        end;
+      psraWriteRead:
+        case Item.Access of
+          psraNone: Item.Access:=Access;
+          psraRead: Item.Access:=psraReadWrite;
+          psraWrite: Item.Access:=psraWriteRead;
+          //psraReadWrite: ;
+          //psraWriteRead: ;
+          //psraTypeInfo: ;
+        end;
+      psraTypeInfo: Item.Access:=psraTypeInfo;
+      else
+        raise EPasResolve.Create(GetObjName(El)+' unknown Access');
+      end;
+      exit(Item);
+      end;
+    Item:=Item.NextSameName;
+    end;
+  // new reference
+  Item:=TPasProcScopeReference.Create;
+  Item.Element:=El;
+  Item.Access:=Access;
+  Index:=References.FindIndexOf(LoName);
+  if Index<0 then
+    begin
+    References.Add(LoName,Item);
+    {$IFDEF VerbosePJUFiler}
+    if TPasProcScopeReference(References.Find(LoName))<>Item then
+      raise EPasResolve.Create('20180219230028');
+    {$ENDIF}
+    end
+  else
+    begin
+    OldItem:=TPasProcScopeReference(References.List^[Index].Data);
+    {$IFDEF VerbosePJUFiler}
+    if lowercase(OldItem.Element.Name)<>LoName then
+      raise EPasResolve.Create('20180219230055');
+    {$ENDIF}
+    Item.NextSameName:=OldItem;
+    References.List^[Index].Data:=Item;
+    end;
+  Result:=Item;
+end;
+
+function TPasProcedureScope.FindReference(const aName: string
+  ): TPasProcScopeReference;
+var
+  LoName: String;
+begin
+  if References=nil then exit(nil);
+  LoName:=lowercase(aName);
+  Result:=TPasProcScopeReference(References.Find(LoName));
+end;
+
 { TPasClassScope }
 { TPasClassScope }
 
 
 destructor TPasClassScope.Destroy;
 destructor TPasClassScope.Destroy;
@@ -7390,7 +7583,13 @@ end;
 procedure TPasResolver.AddFunctionResult(El: TPasResultElement);
 procedure TPasResolver.AddFunctionResult(El: TPasResultElement);
 begin
 begin
   if TopScope.ClassType<>FScopeClass_Proc then exit;
   if TopScope.ClassType<>FScopeClass_Proc then exit;
-  if not (El.Parent is TPasProcedure) then exit;
+  if El.Parent is TPasProcedureType then
+    begin
+    if not (El.Parent.Parent is TPasProcedure) then
+      exit;
+    end
+  else if not (El.Parent is TPasProcedure) then
+    exit;
   AddIdentifier(TPasProcedureScope(TopScope),ResolverResultVar,El,pikSimple);
   AddIdentifier(TPasProcedureScope(TopScope),ResolverResultVar,El,pikSimple);
 end;
 end;
 
 
@@ -10827,11 +11026,7 @@ begin
     end;
     end;
   SrcY:=ASrcPos.Row;
   SrcY:=ASrcPos.Row;
   if StoreSrcColumns then
   if StoreSrcColumns then
-    begin
-    if (ASrcPos.Column<ParserMaxEmbeddedColumn)
-        and (SrcY<ParserMaxEmbeddedRow) then
-      SrcY:=-(SrcY*ParserMaxEmbeddedColumn+integer(ASrcPos.Column));
-    end;
+    SrcY:=MangleSourceLineNumber(SrcY,ASrcPos.Column);
 
 
   // create element
   // create element
   El:=AClass.Create(AName,AParent);
   El:=AClass.Create(AName,AParent);
@@ -12061,6 +12256,16 @@ begin
   until false;
   until false;
 end;
 end;
 
 
+class function TPasResolver.MangleSourceLineNumber(Line, Column: integer
+  ): integer;
+begin
+  if (Column<ParserMaxEmbeddedColumn)
+      and (Line<ParserMaxEmbeddedRow) then
+    Result:=-(Line*ParserMaxEmbeddedColumn+integer(Column))
+  else
+    Result:=Line;
+end;
+
 procedure TPasResolver.SetLastMsg(const id: int64; MsgType: TMessageType;
 procedure TPasResolver.SetLastMsg(const id: int64; MsgType: TMessageType;
   MsgNumber: integer; const Fmt: String; Args: array of const;
   MsgNumber: integer; const Fmt: String; Args: array of const;
   PosEl: TPasElement);
   PosEl: TPasElement);

+ 9 - 14
packages/fcl-passrc/src/pasuseanalyzer.pas

@@ -617,6 +617,7 @@ begin
     UseExpr(TPasExpr(El))
     UseExpr(TPasExpr(El))
   else if C=TPasEnumValue then
   else if C=TPasEnumValue then
     begin
     begin
+    UseExpr(TPasEnumValue(El).Value);
     repeat
     repeat
       MarkElementAsUsed(El);
       MarkElementAsUsed(El);
       El:=El.Parent;
       El:=El.Parent;
@@ -665,6 +666,8 @@ begin
   else if (C=TPasAliasType) or (C=TPasTypeAliasType) then
   else if (C=TPasAliasType) or (C=TPasTypeAliasType) then
     UsePublished(TPasAliasType(El).DestType)
     UsePublished(TPasAliasType(El).DestType)
   else if C=TPasEnumType then
   else if C=TPasEnumType then
+    for i:=0 to TPasEnumType(El).Values.Count-1 do
+      UsePublished(TPasEnumValue(TPasEnumType(El).Values[i]))
   else if C=TPasSetType then
   else if C=TPasSetType then
     UsePublished(TPasSetType(El).EnumType)
     UsePublished(TPasSetType(El).EnumType)
   else if C=TPasRangeType then
   else if C=TPasRangeType then
@@ -991,7 +994,7 @@ var
   Params: TPasExprArray;
   Params: TPasExprArray;
   i: Integer;
   i: Integer;
   BuiltInProc: TResElDataBuiltInProc;
   BuiltInProc: TResElDataBuiltInProc;
-  ParamResolved, ResolvedAbs: TPasResolverResult;
+  ParamResolved: TPasResolverResult;
   Decl: TPasElement;
   Decl: TPasElement;
   ModScope: TPasModuleScope;
   ModScope: TPasModuleScope;
 begin
 begin
@@ -1006,13 +1009,6 @@ begin
     Decl:=Ref.Declaration;
     Decl:=Ref.Declaration;
     UseElement(Decl,Ref.Access,false);
     UseElement(Decl,Ref.Access,false);
 
 
-    if (Decl is TPasVariable) and (TPasVariable(Decl).AbsoluteExpr<>nil) then
-      begin
-      Resolver.ComputeElement(TPasVariable(Decl).AbsoluteExpr,ResolvedAbs,[rcNoImplicitProc]);
-      if ResolvedAbs.IdentEl is TPasVariable then
-        UseVariable(TPasVariable(ResolvedAbs.IdentEl),Ref.Access,false);
-      end;
-
     if Resolver.IsNameExpr(El) then
     if Resolver.IsNameExpr(El) then
       begin
       begin
       if Ref.WithExprScope<>nil then
       if Ref.WithExprScope<>nil then
@@ -1318,6 +1314,8 @@ begin
     else if C=TPasEnumType then
     else if C=TPasEnumType then
       begin
       begin
       if not MarkElementAsUsed(El) then exit;
       if not MarkElementAsUsed(El) then exit;
+      for i:=0 to TPasEnumType(El).Values.Count-1 do
+        UseElement(TPasEnumValue(TPasEnumType(El).Values[i]),rraRead,false);
       end
       end
     else if C=TPasPointerType then
     else if C=TPasPointerType then
       begin
       begin
@@ -1531,18 +1529,15 @@ begin
     UseExpr(El.Expr);
     UseExpr(El.Expr);
     UseExpr(El.LibraryName);
     UseExpr(El.LibraryName);
     UseExpr(El.ExportName);
     UseExpr(El.ExportName);
+    UseExpr(El.AbsoluteExpr);
     if Prop<>nil then
     if Prop<>nil then
       begin
       begin
       for i:=0 to Prop.Args.Count-1 do
       for i:=0 to Prop.Args.Count-1 do
         UseType(TPasArgument(Prop.Args[i]).ArgType,paumElement);
         UseType(TPasArgument(Prop.Args[i]).ArgType,paumElement);
       UseExpr(Prop.IndexExpr);
       UseExpr(Prop.IndexExpr);
-      // ToDo: Prop.ImplementsFunc
-      // ToDo: Prop.DispIDExpr
+      UseExpr(Prop.ImplementsFunc);
+      // ToDo: UseExpr(Prop.DispIDExpr);
       // see UsePublished: Prop.StoredAccessor, Prop.DefaultExpr
       // see UsePublished: Prop.StoredAccessor, Prop.DefaultExpr
-      end;
-    if El.AbsoluteExpr<>nil then
-      begin
-
       end;
       end;
     end
     end
   else
   else

+ 1 - 1
packages/fcl-passrc/src/pparser.pp

@@ -5596,7 +5596,7 @@ begin
       Result.ProcType := TPasProcedureType(CreateElement(TPasProcedureType, '', Result))
       Result.ProcType := TPasProcedureType(CreateElement(TPasProcedureType, '', Result))
     else
     else
       begin
       begin
-      Result.ProcType := CreateFunctionType('', 'Result', Result, True, CurTokenPos);
+      Result.ProcType := CreateFunctionType('', 'Result', Result, False, CurTokenPos);
       if (ProcType in [ptOperator, ptClassOperator]) then
       if (ProcType in [ptOperator, ptClassOperator]) then
         begin
         begin
         TPasOperator(Result).TokenBased:=IsTokenBased;
         TPasOperator(Result).TokenBased:=IsTokenBased;

+ 1 - 1
packages/fcl-passrc/tests/tcresolver.pas

@@ -6104,7 +6104,7 @@ begin
         //writeln('TTestResolver.TestProc_FunctionResult_DeclProc ',GetObjName(Ref.Declaration));
         //writeln('TTestResolver.TestProc_FunctionResult_DeclProc ',GetObjName(Ref.Declaration));
         if not (Ref.Declaration is TPasResultElement) then continue;
         if not (Ref.Declaration is TPasResultElement) then continue;
         ResultEl:=TPasResultElement(Ref.Declaration);
         ResultEl:=TPasResultElement(Ref.Declaration);
-        Proc:=ResultEl.Parent as TPasProcedure;
+        Proc:=ResultEl.Parent.Parent as TPasProcedure;
         ProcScope:=Proc.CustomData as TPasProcedureScope;
         ProcScope:=Proc.CustomData as TPasProcedureScope;
         if ProcScope.DeclarationProc<>nil then
         if ProcScope.DeclarationProc<>nil then
           RaiseErrorAtSrcMarker('expected Result to resolve to declaration at "#'+aMarker^.Identifier+', but was implproc"',aMarker);
           RaiseErrorAtSrcMarker('expected Result to resolve to declaration at "#'+aMarker^.Identifier+', but was implproc"',aMarker);