Browse Source

fcl-passrc: fixed some mem leaks

git-svn-id: trunk@39453 -
Mattias Gaertner 7 years ago
parent
commit
127c3eccb8

+ 2 - 2
packages/fcl-passrc/src/pasresolveeval.pas

@@ -4927,10 +4927,10 @@ procedure TResolveData.SetElement(AValue: TPasElement);
 begin
 begin
   if FElement=AValue then Exit;
   if FElement=AValue then Exit;
   if Element<>nil then
   if Element<>nil then
-    Element.Release;
+    Element.Release{$IFDEF CheckPasTreeRefCount}(ClassName+'.SetElement'){$ENDIF};
   FElement:=AValue;
   FElement:=AValue;
   if Element<>nil then
   if Element<>nil then
-    Element.AddRef;
+    Element.AddRef{$IFDEF CheckPasTreeRefCount}(ClassName+'.SetElement'){$ENDIF};
 end;
 end;
 
 
 constructor TResolveData.Create;
 constructor TResolveData.Create;

+ 68 - 52
packages/fcl-passrc/src/pasresolver.pp

@@ -2474,7 +2474,7 @@ end;
 
 
 destructor TResElDataBuiltInProc.Destroy;
 destructor TResElDataBuiltInProc.Destroy;
 begin
 begin
-  ReleaseAndNil(TPasElement(Proc));
+  ReleaseAndNil(TPasElement(Proc){$IFDEF CheckPasTreeRefCount},'TResElDataBuiltInProc.Proc'{$ENDIF});
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
@@ -2511,10 +2511,10 @@ procedure TPasScopeReference.SetElement(const AValue: TPasElement);
 begin
 begin
   if FElement=AValue then Exit;
   if FElement=AValue then Exit;
   if FElement<>nil then
   if FElement<>nil then
-    FElement.Release;
+    FElement.Release{$IFDEF CheckPasTreeRefCount}('TPasScopeReference.SetElement'){$ENDIF};
   FElement:=AValue;
   FElement:=AValue;
   if FElement<>nil then
   if FElement<>nil then
-    FElement.AddRef;
+    FElement.AddRef{$IFDEF CheckPasTreeRefCount}('TPasScopeReference.SetElement'){$ENDIF};
 end;
 end;
 
 
 destructor TPasScopeReference.Destroy;
 destructor TPasScopeReference.Destroy;
@@ -2680,7 +2680,7 @@ begin
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TPasPropertyScope.Destroy START ',ClassName);
   writeln('TPasPropertyScope.Destroy START ',ClassName);
   {$ENDIF}
   {$ENDIF}
-  ReleaseAndNil(TPasElement(AncestorProp));
+  AncestorProp:=nil;
   inherited Destroy;
   inherited Destroy;
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TPasPropertyScope.Destroy END',ClassName);
   writeln('TPasPropertyScope.Destroy END',ClassName);
@@ -2694,7 +2694,7 @@ begin
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TPasEnumTypeScope.Destroy START ',ClassName);
   writeln('TPasEnumTypeScope.Destroy START ',ClassName);
   {$ENDIF}
   {$ENDIF}
-  ReleaseAndNil(TPasElement(CanonicalSet));
+  ReleaseAndNil(TPasElement(CanonicalSet){$IFDEF CheckPasTreeRefCount},'TPasEnumTypeScope.CanonicalSet'{$ENDIF});
   inherited Destroy;
   inherited Destroy;
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TPasEnumTypeScope.Destroy END ',ClassName);
   writeln('TPasEnumTypeScope.Destroy END ',ClassName);
@@ -2847,7 +2847,7 @@ begin
   writeln('TPasProcedureScope.Destroy START ',ClassName);
   writeln('TPasProcedureScope.Destroy START ',ClassName);
   {$ENDIF}
   {$ENDIF}
   inherited Destroy;
   inherited Destroy;
-  ReleaseAndNil(TPasElement(SelfArg));
+  ReleaseAndNil(TPasElement(SelfArg){$IFDEF CheckPasTreeRefCount},'TPasProcedureScope.SelfArg'{$ENDIF});
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TPasProcedureScope.Destroy END ',ClassName);
   writeln('TPasProcedureScope.Destroy END ',ClassName);
   {$ENDIF}
   {$ENDIF}
@@ -2893,7 +2893,7 @@ begin
   if CanonicalClassOf<>nil then
   if CanonicalClassOf<>nil then
     begin
     begin
     CanonicalClassOf.Parent:=nil;
     CanonicalClassOf.Parent:=nil;
-    ReleaseAndNil(TPasElement(CanonicalClassOf));
+    ReleaseAndNil(TPasElement(CanonicalClassOf){$IFDEF CheckPasTreeRefCount},'TPasClassScope.CanonicalClassOf'{$ENDIF});
     end;
     end;
   inherited Destroy;
   inherited Destroy;
 end;
 end;
@@ -2939,10 +2939,10 @@ procedure TPasIdentifier.SetElement(AValue: TPasElement);
 begin
 begin
   if FElement=AValue then Exit;
   if FElement=AValue then Exit;
   if Element<>nil then
   if Element<>nil then
-    Element.Release;
+    Element.Release{$IFDEF CheckPasTreeRefCount}('TPasIdentifier.SetElement'){$ENDIF};
   FElement:=AValue;
   FElement:=AValue;
   if Element<>nil then
   if Element<>nil then
-    Element.AddRef;
+    Element.AddRef{$IFDEF CheckPasTreeRefCount}('TPasIdentifier.SetElement'){$ENDIF};
 end;
 end;
 
 
 destructor TPasIdentifier.Destroy;
 destructor TPasIdentifier.Destroy;
@@ -2963,10 +2963,10 @@ procedure EPasResolve.SetPasElement(AValue: TPasElement);
 begin
 begin
   if FPasElement=AValue then Exit;
   if FPasElement=AValue then Exit;
   if PasElement<>nil then
   if PasElement<>nil then
-    PasElement.Release;
+    PasElement.Release{$IFDEF CheckPasTreeRefCount}('EPasResolve.SetPasElement'){$ENDIF};
   FPasElement:=AValue;
   FPasElement:=AValue;
   if PasElement<>nil then
   if PasElement<>nil then
-    PasElement.AddRef;
+    PasElement.AddRef{$IFDEF CheckPasTreeRefCount}('EPasResolve.SetPasElement'){$ENDIF};
 end;
 end;
 
 
 destructor EPasResolve.Destroy;
 destructor EPasResolve.Destroy;
@@ -2987,10 +2987,10 @@ procedure TResolvedReference.SetDeclaration(AValue: TPasElement);
 begin
 begin
   if FDeclaration=AValue then Exit;
   if FDeclaration=AValue then Exit;
   if Declaration<>nil then
   if Declaration<>nil then
-    Declaration.Release;
+    Declaration.Release{$IFDEF CheckPasTreeRefCount}('TResolvedReference.SetDeclaration'){$ENDIF};
   FDeclaration:=AValue;
   FDeclaration:=AValue;
   if Declaration<>nil then
   if Declaration<>nil then
-    Declaration.AddRef;
+    Declaration.AddRef{$IFDEF CheckPasTreeRefCount}('TResolvedReference.SetDeclaration'){$ENDIF};
 end;
 end;
 
 
 destructor TResolvedReference.Destroy;
 destructor TResolvedReference.Destroy;
@@ -3030,10 +3030,10 @@ procedure TPasModuleDotScope.SetModule(AValue: TPasModule);
 begin
 begin
   if FModule=AValue then Exit;
   if FModule=AValue then Exit;
   if Module<>nil then
   if Module<>nil then
-    Module.Release;
+    Module.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleDotScope.SetModule'){$ENDIF};
   FModule:=AValue;
   FModule:=AValue;
   if Module<>nil then
   if Module<>nil then
-    Module.AddRef;
+    Module.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleDotScope.SetModule'){$ENDIF};
 end;
 end;
 
 
 destructor TPasModuleDotScope.Destroy;
 destructor TPasModuleDotScope.Destroy;
@@ -3202,25 +3202,25 @@ end;
 
 
 { TPasModuleScope }
 { TPasModuleScope }
 
 
+procedure TPasModuleScope.SetAssertClass(const AValue: TPasClassType);
+begin
+  if FAssertClass=AValue then Exit;
+  if FAssertClass<>nil then
+    FAssertClass.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertClass'){$ENDIF};
+  FAssertClass:=AValue;
+  if FAssertClass<>nil then
+    FAssertClass.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertClass'){$ENDIF};
+end;
+
 procedure TPasModuleScope.SetAssertDefConstructor(const AValue: TPasConstructor
 procedure TPasModuleScope.SetAssertDefConstructor(const AValue: TPasConstructor
   );
   );
 begin
 begin
   if FAssertDefConstructor=AValue then Exit;
   if FAssertDefConstructor=AValue then Exit;
   if FAssertDefConstructor<>nil then
   if FAssertDefConstructor<>nil then
-    FAssertDefConstructor.Release;
+    FAssertDefConstructor.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertDefConstructor'){$ENDIF};
   FAssertDefConstructor:=AValue;
   FAssertDefConstructor:=AValue;
   if FAssertDefConstructor<>nil then
   if FAssertDefConstructor<>nil then
-    FAssertDefConstructor.AddRef;
-end;
-
-procedure TPasModuleScope.SetAssertClass(const AValue: TPasClassType);
-begin
-  if FAssertClass=AValue then Exit;
-  if FAssertClass<>nil then
-    FAssertClass.Release;
-  FAssertClass:=AValue;
-  if FAssertClass<>nil then
-    FAssertClass.AddRef;
+    FAssertDefConstructor.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertDefConstructor'){$ENDIF};
 end;
 end;
 
 
 procedure TPasModuleScope.SetAssertMsgConstructor(const AValue: TPasConstructor
 procedure TPasModuleScope.SetAssertMsgConstructor(const AValue: TPasConstructor
@@ -3228,20 +3228,20 @@ procedure TPasModuleScope.SetAssertMsgConstructor(const AValue: TPasConstructor
 begin
 begin
   if FAssertMsgConstructor=AValue then Exit;
   if FAssertMsgConstructor=AValue then Exit;
   if FAssertMsgConstructor<>nil then
   if FAssertMsgConstructor<>nil then
-    FAssertMsgConstructor.Release;
+    FAssertMsgConstructor.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertMsgConstructor'){$ENDIF};
   FAssertMsgConstructor:=AValue;
   FAssertMsgConstructor:=AValue;
   if FAssertMsgConstructor<>nil then
   if FAssertMsgConstructor<>nil then
-    FAssertMsgConstructor.AddRef;
+    FAssertMsgConstructor.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertMsgConstructor'){$ENDIF};
 end;
 end;
 
 
 procedure TPasModuleScope.SetRangeErrorClass(const AValue: TPasClassType);
 procedure TPasModuleScope.SetRangeErrorClass(const AValue: TPasClassType);
 begin
 begin
   if FRangeErrorClass=AValue then Exit;
   if FRangeErrorClass=AValue then Exit;
   if FRangeErrorClass<>nil then
   if FRangeErrorClass<>nil then
-    FRangeErrorClass.Release;
+    FRangeErrorClass.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetRangeErrorClass'){$ENDIF};
   FRangeErrorClass:=AValue;
   FRangeErrorClass:=AValue;
   if FRangeErrorClass<>nil then
   if FRangeErrorClass<>nil then
-    FRangeErrorClass.AddRef;
+    FRangeErrorClass.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetRangeErrorClass'){$ENDIF};
 end;
 end;
 
 
 procedure TPasModuleScope.SetRangeErrorConstructor(const AValue: TPasConstructor
 procedure TPasModuleScope.SetRangeErrorConstructor(const AValue: TPasConstructor
@@ -3249,10 +3249,10 @@ procedure TPasModuleScope.SetRangeErrorConstructor(const AValue: TPasConstructor
 begin
 begin
   if FRangeErrorConstructor=AValue then Exit;
   if FRangeErrorConstructor=AValue then Exit;
   if FRangeErrorConstructor<>nil then
   if FRangeErrorConstructor<>nil then
-    FRangeErrorConstructor.Release;
+    FRangeErrorConstructor.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetRangeErrorConstructor'){$ENDIF};
   FRangeErrorConstructor:=AValue;
   FRangeErrorConstructor:=AValue;
   if FRangeErrorConstructor<>nil then
   if FRangeErrorConstructor<>nil then
-    FRangeErrorConstructor.AddRef;
+    FRangeErrorConstructor.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetRangeErrorConstructor'){$ENDIF};
 end;
 end;
 
 
 constructor TPasModuleScope.Create;
 constructor TPasModuleScope.Create;
@@ -4567,7 +4567,8 @@ end;
 procedure TPasResolver.FinishTypeSection(El: TPasDeclarations);
 procedure TPasResolver.FinishTypeSection(El: TPasDeclarations);
 
 
   function ReplaceDestType(Decl: TPasType; var DestType: TPasType;
   function ReplaceDestType(Decl: TPasType; var DestType: TPasType;
-    const DestName: string; MustExist: boolean; ErrorEl: TPasElement): boolean;
+    const DestName: string; MustExist: boolean; ErrorEl: TPasElement
+    {$IFDEF CheckPasTreeRefCount}; const RefId: string{$ENDIF}): boolean;
   // returns true if replaces
   // returns true if replaces
   var
   var
     Abort: boolean;
     Abort: boolean;
@@ -4584,6 +4585,7 @@ procedure TPasResolver.FinishTypeSection(El: TPasDeclarations);
         RaiseIdentifierNotFound(20170216151543,DestName,ErrorEl)
         RaiseIdentifierNotFound(20170216151543,DestName,ErrorEl)
       else
       else
         exit(false);
         exit(false);
+    if Data.Found=DestType then exit;
     if Decl is TPasClassOfType then
     if Decl is TPasClassOfType then
       begin
       begin
       if Data.Found.ClassType<>TPasClassType then
       if Data.Found.ClassType<>TPasClassType then
@@ -4592,9 +4594,10 @@ procedure TPasResolver.FinishTypeSection(El: TPasDeclarations);
     // replace unresolved
     // replace unresolved
     OldDestType:=DestType;
     OldDestType:=DestType;
     DestType:=TPasType(Data.Found);
     DestType:=TPasType(Data.Found);
-    DestType.AddRef;
-    OldDestType.Release; // once for the create in TPasResolver
-    OldDestType.Release; // and once for the reference in TPasParser
+    DestType.AddRef{$IFDEF CheckPasTreeRefCount}(RefId){$ENDIF};
+    if OldDestType is TUnresolvedPendingRef then
+      OldDestType.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    OldDestType.Release{$IFDEF CheckPasTreeRefCount}(RefId){$ENDIF};
     // check cycles
     // check cycles
     if Decl is TPasPointerType then
     if Decl is TPasPointerType then
       CheckPointerCycle(TPasPointerType(Decl));
       CheckPointerCycle(TPasPointerType(Decl));
@@ -4632,7 +4635,8 @@ begin
         {$IFDEF VerbosePasResolver}
         {$IFDEF VerbosePasResolver}
         writeln('TPasResolver.FinishTypeSection resolving "',ClassOfEl.Name,'" = class of unresolved "',TypeEl.Name,'"');
         writeln('TPasResolver.FinishTypeSection resolving "',ClassOfEl.Name,'" = class of unresolved "',TypeEl.Name,'"');
         {$ENDIF}
         {$ENDIF}
-        ReplaceDestType(ClassOfEl,ClassOfEl.DestType,TypeEl.Name,true,UnresolvedEl);
+        ReplaceDestType(ClassOfEl,ClassOfEl.DestType,TypeEl.Name,true,UnresolvedEl
+          {$IFDEF CheckPasTreeRefCount},'TPasAliasType.DestType'{$ENDIF});
         end
         end
       else if TypeEl.ClassType=TPasClassType then
       else if TypeEl.ClassType=TPasClassType then
         begin
         begin
@@ -4645,7 +4649,8 @@ begin
         {$IFDEF VerbosePasResolver}
         {$IFDEF VerbosePasResolver}
         writeln('TPasResolver.FinishTypeSection improving "',ClassOfEl.Name,'" = class of resolved "',TypeEl.Name,'"');
         writeln('TPasResolver.FinishTypeSection improving "',ClassOfEl.Name,'" = class of resolved "',TypeEl.Name,'"');
         {$ENDIF}
         {$ENDIF}
-        ReplaceDestType(ClassOfEl,ClassOfEl.DestType,TypeEl.Name,false,ClassOfEl);
+        ReplaceDestType(ClassOfEl,ClassOfEl.DestType,ClassOfEl.DestType.Name,false,ClassOfEl
+          {$IFDEF CheckPasTreeRefCount},'TPasAliasType.DestType'{$ENDIF});
         end;
         end;
       end
       end
     else if C=TPasPointerType then
     else if C=TPasPointerType then
@@ -4659,7 +4664,8 @@ begin
         {$IFDEF VerbosePasResolver}
         {$IFDEF VerbosePasResolver}
         writeln('TPasResolver.FinishTypeSection resolving "',PtrType.Name,'" = pointer of unresolved "',TypeEl.Name,'"');
         writeln('TPasResolver.FinishTypeSection resolving "',PtrType.Name,'" = pointer of unresolved "',TypeEl.Name,'"');
         {$ENDIF}
         {$ENDIF}
-        ReplaceDestType(PtrType,PtrType.DestType,TypeEl.Name,true,UnresolvedEl);
+        ReplaceDestType(PtrType,PtrType.DestType,TypeEl.Name,true,UnresolvedEl
+          {$IFDEF CheckPasTreeRefCount},'TPasPointerType.DestType'{$ENDIF});
         end
         end
       else
       else
         begin
         begin
@@ -4671,7 +4677,8 @@ begin
         {$IFDEF VerbosePasResolver}
         {$IFDEF VerbosePasResolver}
         writeln('TPasResolver.FinishTypeSection improving "',PtrType.Name,'" = pointer of resolved "',TypeEl.Name,'"');
         writeln('TPasResolver.FinishTypeSection improving "',PtrType.Name,'" = pointer of resolved "',TypeEl.Name,'"');
         {$ENDIF}
         {$ENDIF}
-        ReplaceDestType(PtrType,PtrType.DestType,TypeEl.Name,false,PtrType);
+        ReplaceDestType(PtrType,PtrType.DestType,TypeEl.Name,false,PtrType
+          {$IFDEF CheckPasTreeRefCount},'TPasPointerType.DestType'{$ENDIF});
         end;
         end;
       end;
       end;
     end;
     end;
@@ -4773,7 +4780,7 @@ begin
   {$ENDIF}
   {$ENDIF}
   Decl:=TPasDeclarations(Parent.Parent);
   Decl:=TPasDeclarations(Parent.Parent);
   Decl.Declarations.Add(El);
   Decl.Declarations.Add(El);
-  El.AddRef;
+  El.AddRef{$IFDEF CheckPasTreeRefCount}('TPasDeclarations.Declarations'){$ENDIF};
   El.Parent:=Decl;
   El.Parent:=Decl;
   Decl.Types.Add(El);
   Decl.Types.Add(El);
   if (El.ClassType=TPasEnumType) and (Parent.ClassType=TPasSetType) then
   if (El.ClassType=TPasEnumType) and (Parent.ClassType=TPasSetType) then
@@ -4785,9 +4792,9 @@ begin
       // When a TPasEnumType is created a CanonicalSet is created.
       // When a TPasEnumType is created a CanonicalSet is created.
       // Release the autocreated CanonicalSet and use the parent.
       // Release the autocreated CanonicalSet and use the parent.
       if EnumScope.CanonicalSet<>nil then
       if EnumScope.CanonicalSet<>nil then
-        EnumScope.CanonicalSet.Release;
+        EnumScope.CanonicalSet.Release{$IFDEF CheckPasTreeRefCount}('TPasEnumTypeScope.CanonicalSet'){$ENDIF};
       EnumScope.CanonicalSet:=TPasSetType(Parent);
       EnumScope.CanonicalSet:=TPasSetType(Parent);
-      Parent.AddRef;
+      Parent.AddRef{$IFDEF CheckPasTreeRefCount}('TPasEnumTypeScope.CanonicalSet'){$ENDIF};
       end;
       end;
     end;
     end;
 end;
 end;
@@ -5498,9 +5505,10 @@ begin
         // 'Self' in a class proc is the hidden classtype argument
         // 'Self' in a class proc is the hidden classtype argument
         SelfArg:=TPasArgument.Create('Self',DeclProc);
         SelfArg:=TPasArgument.Create('Self',DeclProc);
         ImplProcScope.SelfArg:=SelfArg;
         ImplProcScope.SelfArg:=SelfArg;
+        {$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
         SelfArg.Access:=argConst;
         SelfArg.Access:=argConst;
         SelfArg.ArgType:=CurClassScope.CanonicalClassOf;
         SelfArg.ArgType:=CurClassScope.CanonicalClassOf;
-        SelfArg.ArgType.AddRef;
+        SelfArg.ArgType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
         AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
         AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
         end;
         end;
       end
       end
@@ -5509,9 +5517,10 @@ begin
       // 'Self' in a proc is the hidden instance argument
       // 'Self' in a proc is the hidden instance argument
       SelfArg:=TPasArgument.Create('Self',DeclProc);
       SelfArg:=TPasArgument.Create('Self',DeclProc);
       ImplProcScope.SelfArg:=SelfArg;
       ImplProcScope.SelfArg:=SelfArg;
+      {$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
       SelfArg.Access:=argConst;
       SelfArg.Access:=argConst;
       SelfArg.ArgType:=CurClassType;
       SelfArg.ArgType:=CurClassType;
-      CurClassType.AddRef;
+      CurClassType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
       AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
       AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
       end;
       end;
     end;
     end;
@@ -5639,7 +5648,6 @@ var
       // override or redeclaration property
       // override or redeclaration property
       AncestorProp:=TPasProperty(AncEl);
       AncestorProp:=TPasProperty(AncEl);
       TPasPropertyScope(PropEl.CustomData).AncestorProp:=AncestorProp;
       TPasPropertyScope(PropEl.CustomData).AncestorProp:=AncestorProp;
-      AncestorProp.AddRef;
       if proFixCaseOfOverrides in Options then
       if proFixCaseOfOverrides in Options then
         PropEl.Name:=AncestorProp.Name;
         PropEl.Name:=AncestorProp.Name;
       end
       end
@@ -6387,8 +6395,9 @@ begin
     // create canonical class-of for the "Self" in class functions
     // create canonical class-of for the "Self" in class functions
     CanonicalSelf:=TPasClassOfType.Create('Self',aClass);
     CanonicalSelf:=TPasClassOfType.Create('Self',aClass);
     ClassScope.CanonicalClassOf:=CanonicalSelf;
     ClassScope.CanonicalClassOf:=CanonicalSelf;
+    {$IFDEF CheckPasTreeRefCount}CanonicalSelf.RefIds.Add('TPasClassScope.CanonicalClassOf');{$ENDIF}
     CanonicalSelf.DestType:=aClass;
     CanonicalSelf.DestType:=aClass;
-    aClass.AddRef; // for the CanonicalSelf.DestType
+    aClass.AddRef{$IFDEF CheckPasTreeRefCount}('TPasAliasType.DestType'){$ENDIF};
     CanonicalSelf.Visibility:=visStrictPrivate;
     CanonicalSelf.Visibility:=visStrictPrivate;
     CanonicalSelf.SourceFilename:=aClass.SourceFilename;
     CanonicalSelf.SourceFilename:=aClass.SourceFilename;
     CanonicalSelf.SourceLinenumber:=aClass.SourceLinenumber;
     CanonicalSelf.SourceLinenumber:=aClass.SourceLinenumber;
@@ -9034,14 +9043,16 @@ begin
   // add canonical set
   // add canonical set
   if El.Parent is TPasSetType then
   if El.Parent is TPasSetType then
     begin
     begin
+    // anonymous enumtype, e.g. "set of ()"
     CanonicalSet:=TPasSetType(El.Parent);
     CanonicalSet:=TPasSetType(El.Parent);
-    CanonicalSet.AddRef;
+    CanonicalSet.AddRef{$IFDEF CheckPasTreeRefCount}('TPasEnumTypeScope.CanonicalSet'){$ENDIF};
     end
     end
   else
   else
     begin
     begin
     CanonicalSet:=TPasSetType.Create('',El);
     CanonicalSet:=TPasSetType.Create('',El);
+    {$IFDEF CheckPasTreeRefCount}CanonicalSet.RefIds.Add('TPasEnumTypeScope.CanonicalSet'){$ENDIF};
     CanonicalSet.EnumType:=El;
     CanonicalSet.EnumType:=El;
-    El.AddRef;
+    El.AddRef{$IFDEF CheckPasTreeRefCount}('TPasSetType.EnumType'){$ENDIF};
     end;
     end;
   TPasEnumTypeScope(TopScope).CanonicalSet:=CanonicalSet;
   TPasEnumTypeScope(TopScope).CanonicalSet:=CanonicalSet;
 end;
 end;
@@ -13705,6 +13716,7 @@ begin
 
 
   // create element
   // create element
   El:=AClass.Create(AName,AParent);
   El:=AClass.Create(AName,AParent);
+  {$IFDEF CheckPasTreeRefCount}El.RefIds.Add('CreateElement');{$ENDIF}
   FLastElement:=El;
   FLastElement:=El;
   Result:=El;
   Result:=El;
   El.Visibility:=AVisibility;
   El.Visibility:=AVisibility;
@@ -14407,10 +14419,11 @@ begin
     OldType := TPasTypeAliasType(NewType);
     OldType := TPasTypeAliasType(NewType);
     NewType := aClass;
     NewType := aClass;
     TPasTypeAliasType(OldType).DestType:=nil; // clear reference
     TPasTypeAliasType(OldType).DestType:=nil; // clear reference
-    OldType.Release;
+    OldType.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
 
 
     // set ancestor
     // set ancestor
     aClass.AncestorType := DestType;
     aClass.AncestorType := DestType;
+    {$IFDEF CheckPasTreeRefCount}DestType.ChangeRefId('TPasAliasType.DestType','TPasClassType.AncestorType');{$ENDIF}
     FinishScope(stAncestors,aClass);
     FinishScope(stAncestors,aClass);
     end;
     end;
 end;
 end;
@@ -14658,7 +14671,7 @@ var
 begin
 begin
   ClearResolveDataList(lkBuiltIn);
   ClearResolveDataList(lkBuiltIn);
   for bt in TResolverBaseType do
   for bt in TResolverBaseType do
-    ReleaseAndNil(TPasElement(FBaseTypes[bt]));
+    ReleaseAndNil(TPasElement(FBaseTypes[bt]){$IFDEF CheckPasTreeRefCount},'TPasResolver.AddBaseType'{$ENDIF});
   for bp in TResolverBuiltInProc do
   for bp in TResolverBuiltInProc do
     FBuiltInProcs[bp]:=nil;
     FBuiltInProcs[bp]:=nil;
 end;
 end;
@@ -14787,6 +14800,7 @@ var
   El: TPasUnresolvedSymbolRef;
   El: TPasUnresolvedSymbolRef;
 begin
 begin
   El:=TPasUnresolvedSymbolRef.Create(aName,nil);
   El:=TPasUnresolvedSymbolRef.Create(aName,nil);
+  {$IFDEF CheckPasTreeRefCount}El.RefIds.Add('TPasResolver.AddBaseType');{$ENDIF}
   if not (Typ in [btNone,btCustom]) then
   if not (Typ in [btNone,btCustom]) then
     FBaseTypes[Typ]:=El;
     FBaseTypes[Typ]:=El;
   Result:=TResElDataBaseType.Create;
   Result:=TResElDataBaseType.Create;
@@ -14801,6 +14815,7 @@ var
   CustomData: TResElDataBaseType;
   CustomData: TResElDataBaseType;
 begin
 begin
   Result:=TPasUnresolvedSymbolRef.Create(aName,nil);
   Result:=TPasUnresolvedSymbolRef.Create(aName,nil);
+  {$IFDEF CheckPasTreeRefCount}Result.RefIds.Add('TPasResolver.AddCustomBaseType');{$ENDIF}
   CustomData:=aClass.Create;
   CustomData:=aClass.Create;
   CustomData.BaseType:=btCustom;
   CustomData.BaseType:=btCustom;
   AddResolveData(Result,CustomData,lkBuiltIn);
   AddResolveData(Result,CustomData,lkBuiltIn);
@@ -14830,6 +14845,7 @@ begin
   El:=TPasUnresolvedSymbolRef.Create(aName,nil);
   El:=TPasUnresolvedSymbolRef.Create(aName,nil);
   Result:=TResElDataBuiltInProc.Create;
   Result:=TResElDataBuiltInProc.Create;
   Result.Proc:=El;
   Result.Proc:=El;
+  {$IFDEF CheckPasTreeRefCount}El.RefIds.Add('TResElDataBuiltInProc.Proc');{$ENDIF}
   Result.Signature:=Signature;
   Result.Signature:=Signature;
   Result.BuiltIn:=BuiltIn;
   Result.BuiltIn:=BuiltIn;
   Result.GetCallCompatibility:=GetCallCompatibility;
   Result.GetCallCompatibility:=GetCallCompatibility;

File diff suppressed because it is too large
+ 266 - 145
packages/fcl-passrc/src/pastree.pp


+ 6 - 6
packages/fcl-passrc/src/pasuseanalyzer.pas

@@ -363,10 +363,10 @@ procedure TPAOverrideList.SetElement(AValue: TPasElement);
 begin
 begin
   if FElement=AValue then Exit;
   if FElement=AValue then Exit;
   if FElement<>nil then
   if FElement<>nil then
-    FElement.Release;
+    FElement.Release{$IFDEF CheckPasTreeRefCount}('TPAOverrideList.Element'){$ENDIF};
   FElement:=AValue;
   FElement:=AValue;
   if FElement<>nil then
   if FElement<>nil then
-    FElement.AddRef;
+    FElement.AddRef{$IFDEF CheckPasTreeRefCount}('TPAOverrideList.Element'){$ENDIF};
 end;
 end;
 
 
 constructor TPAOverrideList.Create;
 constructor TPAOverrideList.Create;
@@ -379,7 +379,7 @@ var
   i: Integer;
   i: Integer;
 begin
 begin
   for i:=0 to FOverrides.Count-1 do
   for i:=0 to FOverrides.Count-1 do
-    TPasElement(FOverrides[i]).Release;
+    TPasElement(FOverrides[i]).Release{$IFDEF CheckPasTreeRefCount}('TPAOverrideList.Overrides'){$ENDIF};
   FreeAndNil(FOverrides);
   FreeAndNil(FOverrides);
   Element:=nil;
   Element:=nil;
   inherited Destroy;
   inherited Destroy;
@@ -388,7 +388,7 @@ end;
 procedure TPAOverrideList.Add(OverrideEl: TPasElement);
 procedure TPAOverrideList.Add(OverrideEl: TPasElement);
 begin
 begin
   FOverrides.Add(OverrideEl);
   FOverrides.Add(OverrideEl);
-  OverrideEl.AddRef;
+  OverrideEl.AddRef{$IFDEF CheckPasTreeRefCount}('TPAOverrideList.Overrides'){$ENDIF};
 end;
 end;
 
 
 function TPAOverrideList.Count: integer;
 function TPAOverrideList.Count: integer;
@@ -402,10 +402,10 @@ procedure TPAElement.SetElement(AValue: TPasElement);
 begin
 begin
   if FElement=AValue then Exit;
   if FElement=AValue then Exit;
   if FElement<>nil then
   if FElement<>nil then
-    FElement.Release;
+    FElement.Release{$IFDEF CheckPasTreeRefCount}('TPAElement.Element'){$ENDIF};
   FElement:=AValue;
   FElement:=AValue;
   if FElement<>nil then
   if FElement<>nil then
-    FElement.AddRef;
+    FElement.AddRef{$IFDEF CheckPasTreeRefCount}('TPAElement.Element'){$ENDIF};
 end;
 end;
 
 
 destructor TPAElement.Destroy;
 destructor TPAElement.Destroy;

+ 60 - 62
packages/fcl-passrc/src/pparser.pp

@@ -1337,7 +1337,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -1454,7 +1454,7 @@ begin
     if Result=nil then
     if Result=nil then
       begin
       begin
       Expr.Free;
       Expr.Free;
-      ReleaseAndNil(TPasElement(Ref));
+      ReleaseAndNil(TPasElement(Ref){$IFDEF CheckPasTreeRefCount},'ResolveTypeReference'{$ENDIF});
       ST.Free;
       ST.Free;
       end;
       end;
   end;
   end;
@@ -1475,7 +1475,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -1527,10 +1527,10 @@ begin
       begin
       begin
       // simple type reference
       // simple type reference
       if not NeedExpr then
       if not NeedExpr then
-        ReleaseAndNil(TPasElement(Expr));
+        ReleaseAndNil(TPasElement(Expr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
       end;
       end;
   finally
   finally
-    if ST<>nil then St.Release;
+    if ST<>nil then St.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -1548,7 +1548,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -1588,7 +1588,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
   Engine.FinishScope(stTypeDef,Result);
   Engine.FinishScope(stTypeDef,Result);
 end;
 end;
@@ -1608,7 +1608,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
   Engine.FinishScope(stTypeDef,Result);
   Engine.FinishScope(stTypeDef,Result);
 end;
 end;
@@ -1706,7 +1706,7 @@ begin
   finally
   finally
     if not ok then
     if not ok then
       if Result<>nil then
       if Result<>nil then
-        Result.Release;
+        Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -1809,7 +1809,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
   Engine.FinishScope(stTypeDef,Result);
   Engine.FinishScope(stTypeDef,Result);
 end;
 end;
@@ -1920,7 +1920,7 @@ begin
     Result:=TPasUnresolvedTypeRef(CreateElement(TPasUnresolvedTypeRef,Name,Parent))
     Result:=TPasUnresolvedTypeRef(CreateElement(TPasUnresolvedTypeRef,Name,Parent))
   else
   else
     begin
     begin
-    Ref.AddRef;
+    Ref.AddRef{$IFDEF CheckPasTreeRefCount}('ResolveTypeReference'){$ENDIF};
     Result:=TPasType(Ref);
     Result:=TPasType(Ref);
     end;
     end;
 end;
 end;
@@ -1988,7 +1988,8 @@ begin
     NextToken;
     NextToken;
     Result:=Params;
     Result:=Params;
   finally
   finally
-    if not Assigned(Result) then Params.Release;
+    if Result=nil then
+      Params.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -2059,7 +2060,7 @@ function TPasParser.ParseExpIdent(AParent: TPasElement): TPasExpr;
       b:=CreateBinaryExpr(AParent,Last, ParseExpIdent(AParent), TokenToExprOp(optk));
       b:=CreateBinaryExpr(AParent,Last, ParseExpIdent(AParent), TokenToExprOp(optk));
       if not Assigned(b.right) then
       if not Assigned(b.right) then
         begin
         begin
-        b.Release;
+        b.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
         ParseExcExpectedIdentifier;
         ParseExcExpectedIdentifier;
         end;
         end;
       Last:=b;
       Last:=b;
@@ -2162,7 +2163,7 @@ begin
         Bin:=CreateBinaryExpr(AParent,Last,ParseExpIdent(AParent),eopNone,SrcPos);
         Bin:=CreateBinaryExpr(AParent,Last,ParseExpIdent(AParent),eopNone,SrcPos);
         if not Assigned(Bin.right) then
         if not Assigned(Bin.right) then
           begin
           begin
-          Bin.Release;
+          Bin.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
           ParseExcExpectedIdentifier;
           ParseExcExpectedIdentifier;
           end;
           end;
         Result:=Bin;
         Result:=Bin;
@@ -2268,7 +2269,7 @@ begin
   finally
   finally
     if not ok then
     if not ok then
       begin
       begin
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       ISE.Free;
       ISE.Free;
       end;
       end;
   end;
   end;
@@ -2301,7 +2302,7 @@ type
   end;
   end;
 
 
 var
 var
-  ExpStack  : TFPList;
+  ExpStack  : TFPList; // list of TPasExpr
   OpStack   : array of TOpStackItem;
   OpStack   : array of TOpStackItem;
   OpStackTop: integer;
   OpStackTop: integer;
   PrefixCnt : Integer;
   PrefixCnt : Integer;
@@ -2412,7 +2413,7 @@ begin
             ParseExcSyntaxError;
             ParseExcSyntaxError;
           if (CurToken<>tkBraceClose) then
           if (CurToken<>tkBraceClose) then
             begin
             begin
-            x.Release;
+            x.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
             CheckToken(tkBraceClose);
             CheckToken(tkBraceClose);
             end;
             end;
           NextToken;
           NextToken;
@@ -2498,11 +2499,8 @@ begin
     // only 1 expression should be left on the OpStack
     // only 1 expression should be left on the OpStack
     if ExpStack.Count<>1 then
     if ExpStack.Count<>1 then
       ParseExcSyntaxError;
       ParseExcSyntaxError;
-    if ExpStack.Count=1 then
-      begin
-      Result:=TPasExpr(ExpStack[0]);
-      Result.Parent:=AParent;
-      end;
+    Result:=TPasExpr(ExpStack[0]);
+    Result.Parent:=AParent;
 
 
   finally
   finally
     {if Not Assigned(Result) then
     {if Not Assigned(Result) then
@@ -2512,7 +2510,7 @@ begin
     if not Assigned(Result) then begin
     if not Assigned(Result) then begin
       // expression error!
       // expression error!
       for i:=0 to ExpStack.Count-1 do
       for i:=0 to ExpStack.Count-1 do
-        TPasExpr(ExpStack[i]).Release;
+        TPasExpr(ExpStack[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
     end;
     end;
     SetLength(OpStack,0);
     SetLength(OpStack,0);
     ExpStack.Free;
     ExpStack.Free;
@@ -2629,7 +2627,7 @@ begin
         Result:=DoParseExpression(AParent,x);
         Result:=DoParseExpression(AParent,x);
         if CurToken<>tkBraceClose then
         if CurToken<>tkBraceClose then
           begin
           begin
-          ReleaseAndNil(TPasElement(Result));
+          ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
           ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
           ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
           end;
           end;
         NextToken;
         NextToken;
@@ -2640,7 +2638,7 @@ begin
       end;
       end;
     if CurToken<>tkBraceClose then
     if CurToken<>tkBraceClose then
       begin
       begin
-      ReleaseAndNil(TPasElement(Result));
+      ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
       ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
       ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
       end;
       end;
     NextToken;
     NextToken;
@@ -2777,7 +2775,7 @@ begin
       begin
       begin
       Module.PackageName := Engine.Package.Name;
       Module.PackageName := Engine.Package.Name;
       Engine.Package.Modules.Add(Module);
       Engine.Package.Modules.Add(Module);
-      Module.AddRef;
+      Module.AddRef{$IFDEF CheckPasTreeRefCount}('TPasPackage.Modules'){$ENDIF};
       end;
       end;
     CheckHint(Module,True);
     CheckHint(Module,True);
     ExpectToken(tkInterface);
     ExpectToken(tkInterface);
@@ -3344,7 +3342,7 @@ begin
                             Declarations.Declarations.Delete(j);
                             Declarations.Declarations.Delete(j);
                             break;
                             break;
                           end;
                           end;
-                        ClassEl.Release;
+                        ClassEl.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
                         break;
                         break;
                       end;
                       end;
                     end;
                     end;
@@ -3365,7 +3363,7 @@ begin
                 finally
                 finally
                   if not ok then
                   if not ok then
                     for i := 0 to List.Count - 1 do
                     for i := 0 to List.Count - 1 do
-                      TPasExportSymbol(List[i]).Release;
+                      TPasExportSymbol(List[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
                 end;
                 end;
                 for i := 0 to List.Count - 1 do
                 for i := 0 to List.Count - 1 do
                 begin
                 begin
@@ -3448,7 +3446,7 @@ begin
                  ParseExc(nParserGenericArray1Element,sParserGenericArray1Element);
                  ParseExc(nParserGenericArray1Element,sParserGenericArray1Element);
                ArrEl:=TPasArrayType(ParseArrayType(Declarations,NamePos,TypeName,pmNone));
                ArrEl:=TPasArrayType(ParseArrayType(Declarations,NamePos,TypeName,pmNone));
                CheckHint(ArrEl,True);
                CheckHint(ArrEl,True);
-               ArrEl.ElType.Release;
+               ArrEl.ElType.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
                ArrEl.ElType:=TPasGenericTemplateType(List[0]);
                ArrEl.ElType:=TPasGenericTemplateType(List[0]);
                Declarations.Declarations.Add(ArrEl);
                Declarations.Declarations.Add(ArrEl);
                Declarations.Types.Add(ArrEl);
                Declarations.Types.Add(ArrEl);
@@ -3552,7 +3550,7 @@ begin
 
 
     UnitRef := Engine.FindModule(AUnitName,NameExpr,InFileExpr);
     UnitRef := Engine.FindModule(AUnitName,NameExpr,InFileExpr);
     if Assigned(UnitRef) then
     if Assigned(UnitRef) then
-      UnitRef.AddRef
+      UnitRef.AddRef{$IFDEF CheckPasTreeRefCount}('TPasUsesUnit.Module'){$ENDIF}
     else
     else
       UnitRef := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef,
       UnitRef := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef,
         AUnitName, ASection, NamePos));
         AUnitName, ASection, NamePos));
@@ -3573,13 +3571,13 @@ begin
     if Result=nil then
     if Result=nil then
       begin
       begin
       if UsesUnit<>nil then
       if UsesUnit<>nil then
-        UsesUnit.Release;
+        UsesUnit.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       if NameExpr<>nil then
       if NameExpr<>nil then
-        NameExpr.Release;
+        NameExpr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       if InFileExpr<>nil then
       if InFileExpr<>nil then
-        InFileExpr.Release;
+        InFileExpr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       if UnitRef<>nil then
       if UnitRef<>nil then
-        UnitRef.Release;
+        UnitRef.Release{$IFDEF CheckPasTreeRefCount}('FindModule'){$ENDIF};
       end;
       end;
   end;
   end;
 end;
 end;
@@ -3660,8 +3658,8 @@ begin
   finally
   finally
     if FreeExpr then
     if FreeExpr then
       begin
       begin
-      ReleaseAndNil(TPasElement(NameExpr));
-      ReleaseAndNil(TPasElement(InFileExpr));
+      ReleaseAndNil(TPasElement(NameExpr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+      ReleaseAndNil(TPasElement(InFileExpr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
       end;
       end;
   end;
   end;
 end;
 end;
@@ -3759,7 +3757,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      ReleaseAndNil(TPasElement(Result));
+      ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
   end;
   end;
 end;
 end;
 
 
@@ -3780,7 +3778,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      ReleaseAndNil(TPasElement(Result));
+      ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
   end;
   end;
 end;
 end;
 
 
@@ -3903,8 +3901,8 @@ begin
     until false;
     until false;
   finally
   finally
     Expr.Free;
     Expr.Free;
-    if Ref<>nil then Ref.Release;
-    if NestedSpec<>nil then NestedSpec.Release;
+    if Ref<>nil then Ref.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    if NestedSpec<>nil then NestedSpec.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -3955,7 +3953,7 @@ begin
     PE:=DoParseExpression(Result,Nil,False);
     PE:=DoParseExpression(Result,Nil,False);
     if not ((PE is TBinaryExpr) and (TBinaryExpr(PE).Kind=pekRange)) then
     if not ((PE is TBinaryExpr) and (TBinaryExpr(PE).Kind=pekRange)) then
       begin
       begin
-      PE.Release;
+      PE.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       ParseExc(nRangeExpressionExpected,SRangeExpressionExpected);
       ParseExc(nRangeExpressionExpected,SRangeExpressionExpected);
       end;
       end;
     Result.RangeExpr:=PE as TBinaryExpr;
     Result.RangeExpr:=PE as TBinaryExpr;
@@ -3963,7 +3961,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
   Engine.FinishScope(stTypeDef,Result);
   Engine.FinishScope(stTypeDef,Result);
 end;
 end;
@@ -4020,7 +4018,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -4202,7 +4200,7 @@ begin
       VarEl.VarType := VarType;
       VarEl.VarType := VarType;
       //VarType.Parent := VarEl; // this is wrong for references
       //VarType.Parent := VarEl; // this is wrong for references
       if (i>OldListCount) then
       if (i>OldListCount) then
-        VarType.AddRef;
+        VarType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasVariable.VarType'){$ENDIF};
       end;
       end;
 
 
     H:=CheckHint(Nil,False);
     H:=CheckHint(Nil,False);
@@ -4278,15 +4276,15 @@ begin
       end;
       end;
     ok:=true;
     ok:=true;
   finally
   finally
-    if aLibName<>nil then aLibName.Release;
-    if aExpName<>nil then aExpName.Release;
-    if AbsoluteExpr<>nil then AbsoluteExpr.Release;
     if not ok then
     if not ok then
       begin
       begin
-        if Value<>nil then Value.Release;
-        for i:=OldListCount to VarList.Count-1 do
-          TPasElement(VarList[i]).Release;
-        VarList.Count:=OldListCount;
+      if aLibName<>nil then aLibName.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      if aExpName<>nil then aExpName.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      if AbsoluteExpr<>nil then AbsoluteExpr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      if Value<>nil then Value.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      for i:=OldListCount to VarList.Count-1 do
+        TPasElement(VarList[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      VarList.Count:=OldListCount;
       end;
       end;
   end;
   end;
 end;
 end;
@@ -4456,7 +4454,7 @@ begin
           begin
           begin
           if (Args.Count>OldArgCount+1) then
           if (Args.Count>OldArgCount+1) then
             begin
             begin
-            ArgType.Release;
+            ArgType.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
             ArgType:=nil;
             ArgType:=nil;
             ParseExc(nParserOnlyOneArgumentCanHaveDefault,SParserOnlyOneArgumentCanHaveDefault);
             ParseExc(nParserOnlyOneArgumentCanHaveDefault,SParserOnlyOneArgumentCanHaveDefault);
             end;
             end;
@@ -4475,7 +4473,7 @@ begin
         ok:=true;
         ok:=true;
       finally
       finally
         if (not ok) and (ArgType<>nil) then
         if (not ok) and (ArgType<>nil) then
-          ArgType.Release;
+          ArgType.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       end;
       end;
       end;
       end;
 
 
@@ -4486,7 +4484,7 @@ begin
       if Assigned(ArgType) then
       if Assigned(ArgType) then
         begin
         begin
         if (i > OldArgCount) then
         if (i > OldArgCount) then
-          ArgType.AddRef;
+          ArgType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
         end;
         end;
       Arg.ValueExpr := Value;
       Arg.ValueExpr := Value;
       Value:=Nil; // Only the first gets a value. OK, since Var A,B : Integer = 1 is not allowed.
       Value:=Nil; // Only the first gets a value. OK, since Var A,B : Integer = 1 is not allowed.
@@ -4964,7 +4962,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -5171,7 +5169,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -5526,7 +5524,7 @@ begin
           ok:=true;
           ok:=true;
         finally
         finally
           if not ok then
           if not ok then
-            El.Release;
+            El.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
         end;
         end;
         CreateBlock(TPasImplForLoop(El));
         CreateBlock(TPasImplForLoop(El));
         //WriteLn(i,'FOR "',VarName,'" := ',StartValue,' to ',EndValue,' Token=',CurTokenText);
         //WriteLn(i,'FOR "',VarName,'" := ',StartValue,' to ',EndValue,' Token=',CurTokenText);
@@ -5774,7 +5772,7 @@ begin
               TPasImplExceptOn(El).VarEl:=TPasVariable(CreateElement(TPasVariable,
               TPasImplExceptOn(El).VarEl:=TPasVariable(CreateElement(TPasVariable,
                                     Name,El,SrcPos));
                                     Name,El,SrcPos));
               TPasImplExceptOn(El).VarEl.VarType:=TypeEl;
               TPasImplExceptOn(El).VarEl.VarType:=TypeEl;
-              TypeEl.AddRef;
+              TypeEl.AddRef{$IFDEF CheckPasTreeRefCount}('TPasVariable.VarType'){$ENDIF};
               end
               end
             else
             else
               begin
               begin
@@ -5897,7 +5895,7 @@ function TPasParser.ParseProcedureOrFunctionDecl(Parent: TPasElement; ProcType:
             ReadGenericArguments(L,Parent);
             ReadGenericArguments(L,Parent);
           finally
           finally
             For I:=0 to L.Count-1 do
             For I:=0 to L.Count-1 do
-              TPasElement(L[i]).Release;
+              TPasElement(L[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
             L.Free;
             L.Free;
           end;
           end;
           end
           end
@@ -5970,7 +5968,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -6185,7 +6183,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 
@@ -6635,7 +6633,7 @@ begin
     ok:=true;
     ok:=true;
   finally
   finally
     if not ok then
     if not ok then
-      Result.Release;
+      Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
   end;
 end;
 end;
 
 

+ 2 - 2
packages/fcl-passrc/tests/tcbaseparser.pas

@@ -407,6 +407,7 @@ function TTestEngine.CreateElement(AClass: TPTreeElement; const AName: String;
 begin
 begin
   //writeln('TTestEngine.CreateElement ',AName,' ',AClass.ClassName);
   //writeln('TTestEngine.CreateElement ',AName,' ',AClass.ClassName);
   Result := AClass.Create(AName, AParent);
   Result := AClass.Create(AName, AParent);
+  {$IFDEF CheckPasTreeRefCount}Result.RefIds.Add('CreateElement');{$ENDIF}
   Result.Visibility := AVisibility;
   Result.Visibility := AVisibility;
   Result.SourceFilename := ASourceFilename;
   Result.SourceFilename := ASourceFilename;
   Result.SourceLinenumber := ASourceLinenumber;
   Result.SourceLinenumber := ASourceLinenumber;
@@ -485,8 +486,7 @@ begin
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TTestParser.CleanupParser FModule');
   writeln('TTestParser.CleanupParser FModule');
   {$ENDIF}
   {$ENDIF}
-  if Assigned(FModule) then
-    ReleaseAndNil(TPasElement(FModule));
+  ReleaseAndNil(TPasElement(FModule){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TTestParser.CleanupParser FSource');
   writeln('TTestParser.CleanupParser FSource');
   {$ENDIF}
   {$ENDIF}

+ 61 - 7
packages/fcl-passrc/tests/tcresolver.pas

@@ -65,6 +65,7 @@ type
   public
   public
     constructor Create;
     constructor Create;
     destructor Destroy; override;
     destructor Destroy; override;
+    procedure ReleaseUsedUnits;
     function CreateElement(AClass: TPTreeElement; const AName: String;
     function CreateElement(AClass: TPTreeElement; const AName: String;
       AParent: TPasElement; AVisibility: TPasMemberVisibility;
       AParent: TPasElement; AVisibility: TPasMemberVisibility;
       const ASrcPos: TPasSourcePos): TPasElement;
       const ASrcPos: TPasSourcePos): TPasElement;
@@ -110,6 +111,7 @@ type
 
 
   TCustomTestResolver = Class(TTestParser)
   TCustomTestResolver = Class(TTestParser)
   Private
   Private
+    FStartElementRefCount: int64;
     FFirstStatement: TPasImplBlock;
     FFirstStatement: TPasImplBlock;
     FModules: TObjectList;// list of TTestEnginePasResolver
     FModules: TObjectList;// list of TTestEnginePasResolver
     FResolverEngine: TTestEnginePasResolver;
     FResolverEngine: TTestEnginePasResolver;
@@ -347,6 +349,7 @@ type
     // units
     // units
     Procedure TestUnitForwardOverloads;
     Procedure TestUnitForwardOverloads;
     Procedure TestUnitIntfInitialization;
     Procedure TestUnitIntfInitialization;
+    Procedure TestUnitUseSystem;
     Procedure TestUnitUseIntf;
     Procedure TestUnitUseIntf;
     Procedure TestUnitUseImplFail;
     Procedure TestUnitUseImplFail;
     Procedure TestUnit_DuplicateUsesFail;
     Procedure TestUnit_DuplicateUsesFail;
@@ -843,10 +846,12 @@ procedure TTestEnginePasResolver.SetModule(AValue: TPasModule);
 begin
 begin
   if FModule=AValue then Exit;
   if FModule=AValue then Exit;
   if Module<>nil then
   if Module<>nil then
-    Module.Release;
+    Module.Release{$IFDEF CheckPasTreeRefCount}('TTestEnginePasResolver.Module'){$ENDIF};
   FModule:=AValue;
   FModule:=AValue;
+  {$IFDEF CheckPasTreeRefCount}
   if Module<>nil then
   if Module<>nil then
-    Module.AddRef;
+    Module.ChangeRefId('CreateElement','TTestEnginePasResolver.Module');
+  {$ENDIF}
 end;
 end;
 
 
 constructor TTestEnginePasResolver.Create;
 constructor TTestEnginePasResolver.Create;
@@ -858,10 +863,16 @@ end;
 destructor TTestEnginePasResolver.Destroy;
 destructor TTestEnginePasResolver.Destroy;
 begin
 begin
   FStreamResolver:=nil;
   FStreamResolver:=nil;
-  Module:=nil;
   FreeAndNil(FParser);
   FreeAndNil(FParser);
   FreeAndNil(FScanner);
   FreeAndNil(FScanner);
   inherited Destroy;
   inherited Destroy;
+  Module:=nil;
+end;
+
+procedure TTestEnginePasResolver.ReleaseUsedUnits;
+begin
+  if Module<>nil then
+    Module.ReleaseUsedUnits;
 end;
 end;
 
 
 function TTestEnginePasResolver.CreateElement(AClass: TPTreeElement;
 function TTestEnginePasResolver.CreateElement(AClass: TPTreeElement;
@@ -890,6 +901,9 @@ end;
 
 
 procedure TCustomTestResolver.SetUp;
 procedure TCustomTestResolver.SetUp;
 begin
 begin
+  {$IF defined(VerbosePasResolver) or defined(VerbosePasResolverMem)}
+  FStartElementRefCount:=TPasElement.GlobalRefCount;
+  {$ENDIF}
   FModules:=TObjectList.Create(true);
   FModules:=TObjectList.Create(true);
   inherited SetUp;
   inherited SetUp;
   Parser.Options:=Parser.Options+[po_ResolveStandardTypes];
   Parser.Options:=Parser.Options+[po_ResolveStandardTypes];
@@ -897,6 +911,12 @@ begin
 end;
 end;
 
 
 procedure TCustomTestResolver.TearDown;
 procedure TCustomTestResolver.TearDown;
+{$IFDEF CheckPasTreeRefCount}
+var El: TPasElement;
+{$ENDIF}
+{$IF defined(VerbosePasResolver) or defined(VerbosePasResolverMem)}
+var i: Integer;
+{$ENDIF}
 begin
 begin
   FResolverMsgs.Clear;
   FResolverMsgs.Clear;
   FResolverGoodMsgs.Clear;
   FResolverGoodMsgs.Clear;
@@ -915,6 +935,8 @@ begin
     {$IFDEF VerbosePasResolverMem}
     {$IFDEF VerbosePasResolverMem}
     writeln('TTestResolver.TearDown FModules');
     writeln('TTestResolver.TearDown FModules');
     {$ENDIF}
     {$ENDIF}
+    for i:=0 to FModules.Count-1 do
+      TTestEnginePasResolver(FModules[i]).ReleaseUsedUnits;
     FModules.OwnsObjects:=false;
     FModules.OwnsObjects:=false;
     FModules.Remove(ResolverEngine); // remove reference
     FModules.Remove(ResolverEngine); // remove reference
     FModules.OwnsObjects:=true;
     FModules.OwnsObjects:=true;
@@ -923,8 +945,27 @@ begin
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TTestResolver.TearDown inherited');
   writeln('TTestResolver.TearDown inherited');
   {$ENDIF}
   {$ENDIF}
+  if Module<>nil then
+    Module.AddRef{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF}; // for the Release in ancestor TTestParser
   inherited TearDown;
   inherited TearDown;
   FResolverEngine:=nil;
   FResolverEngine:=nil;
+  {$IF defined(VerbosePasResolver) or defined(VerbosePasResolverMem)}
+  if FStartElementRefCount<>TPasElement.GlobalRefCount then
+    begin
+    writeln('TCustomTestResolver.TearDown GlobalRefCount Was='+IntToStr(FStartElementRefCount)+' Now='+IntToStr(TPasElement.GlobalRefCount));
+    {$IFDEF CheckPasTreeRefCount}
+    El:=TPasElement.FirstRefEl;
+    while El<>nil do
+      begin
+      writeln('  ',GetObjName(El),' RefIds.Count=',El.RefIds.Count,':');
+      for i:=0 to El.RefIds.Count-1 do
+        writeln('    ',El.RefIds[i]);
+      El:=El.NextRefEl;
+      end;
+    {$ENDIF}
+    //Fail('TCustomTestResolver.TearDown Was='+IntToStr(FStartElementRefCount)+' Now='+IntToStr(TPasElement.GlobalRefCount));
+    end;
+  {$ENDIF}
   {$IFDEF VerbosePasResolverMem}
   {$IFDEF VerbosePasResolverMem}
   writeln('TTestResolver.TearDown END');
   writeln('TTestResolver.TearDown END');
   {$ENDIF}
   {$ENDIF}
@@ -1137,6 +1178,7 @@ var
     StartP:=p;
     StartP:=p;
     inc(p);
     inc(p);
     while p^ in ['a'..'z','A'..'Z','_','0'..'9'] do inc(p);
     while p^ in ['a'..'z','A'..'Z','_','0'..'9'] do inc(p);
+    Result:='';
     SetLength(Result,p-StartP);
     SetLength(Result,p-StartP);
     Move(StartP^,Result[1],length(Result));
     Move(StartP^,Result[1],length(Result));
   end;
   end;
@@ -2002,6 +2044,8 @@ function TCustomTestResolver.OnPasResolverFindUnit(SrcResolver: TPasResolver;
 
 
   function InitUnit(CurEngine: TTestEnginePasResolver): TPasModule;
   function InitUnit(CurEngine: TTestEnginePasResolver): TPasModule;
   begin
   begin
+    if CurEngine.Module<>nil then
+      Fail('InitUnit '+GetObjName(CurEngine.Module));
     CurEngine.StreamResolver:=Resolver;
     CurEngine.StreamResolver:=Resolver;
     //writeln('TTestResolver.OnPasResolverFindUnit SOURCE=',CurEngine.Source);
     //writeln('TTestResolver.OnPasResolverFindUnit SOURCE=',CurEngine.Source);
     CurEngine.StreamResolver.AddStream(CurEngine.FileName,
     CurEngine.StreamResolver.AddStream(CurEngine.FileName,
@@ -2517,7 +2561,7 @@ begin
   StartProgram(false);
   StartProgram(false);
   Add('const');
   Add('const');
   Add('  c1 = 3');
   Add('  c1 = 3');
-  Add('  c2: longint=c1;'); // defined in system.pp
+  Add('  c2: longint=c1;');
   Add('begin');
   Add('begin');
   CheckResolverUnexpectedHints;
   CheckResolverUnexpectedHints;
 end;
 end;
@@ -5218,6 +5262,15 @@ begin
   AssertSame('other unit assign var exitcode',(OtherUnit as TPasUsesUnit).Module,DeclEl.GetModule);
   AssertSame('other unit assign var exitcode',(OtherUnit as TPasUsesUnit).Module,DeclEl.GetModule);
 end;
 end;
 
 
+procedure TTestResolver.TestUnitUseSystem;
+begin
+  StartProgram(true);
+  Add('type number = system.integer;');
+  Add('begin');
+  Add('  if ExitCode=2 then ;');
+  ParseProgram;
+end;
+
 procedure TTestResolver.TestUnitUseIntf;
 procedure TTestResolver.TestUnitUseIntf;
 begin
 begin
   AddModuleWithIntfImplSrc('unit2.pp',
   AddModuleWithIntfImplSrc('unit2.pp',
@@ -10274,15 +10327,16 @@ begin
     '  TObject = class',
     '  TObject = class',
     '  end;',
     '  end;',
     '  TCar = class',
     '  TCar = class',
-    '  end;']),
+    '  end;',
+    '  TCarry = TCar;']),
     LinesToStr([
     LinesToStr([
     '']));
     '']));
 
 
   StartProgram(true);
   StartProgram(true);
   Add('uses unit2;');
   Add('uses unit2;');
   Add('type');
   Add('type');
-  Add('  {#C}{=A}TCars = class of TCar;');
-  Add('  {#A}TCar = class');
+  Add('  {#C}{=A}TCars = class of TCarry;');
+  Add('  {#A}TCarry = class');
   Add('    class var {#B}B: longint;');
   Add('    class var {#B}B: longint;');
   Add('  end;');
   Add('  end;');
   Add('begin');
   Add('begin');

+ 1 - 0
packages/fcl-passrc/tests/tcuseanalyzer.pas

@@ -510,6 +510,7 @@ var
 var
 var
   i: Integer;
   i: Integer;
 begin
 begin
+  Entries:=nil;
   SetLength(Entries,High(RefNames)-low(RefNames)+1);
   SetLength(Entries,High(RefNames)-low(RefNames)+1);
   for i:=low(RefNames) to high(RefNames) do
   for i:=low(RefNames) to high(RefNames) do
     begin
     begin

+ 1 - 0
packages/fcl-passrc/tests/testpassrc.lpr

@@ -3,6 +3,7 @@ program testpassrc;
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
 
 
 uses
 uses
+  //MemCheck,
   Classes, consoletestrunner, tcscanner, tctypeparser, tcstatements,
   Classes, consoletestrunner, tcscanner, tctypeparser, tcstatements,
   tcbaseparser, tcmoduleparser, tconstparser, tcvarparser, tcclasstype,
   tcbaseparser, tcmoduleparser, tconstparser, tcvarparser, tcclasstype,
   tcexprparser, tcprocfunc, tcpassrcutil, tcresolver, tcgenerics,
   tcexprparser, tcprocfunc, tcpassrcutil, tcresolver, tcgenerics,

Some files were not shown because too many files changed in this diff