Browse Source

fcl-passrc: transition TPasElement from reference count to free

mattias 3 years ago
parent
commit
64a8c73df2

+ 5 - 0
packages/fcl-passrc/src/pasresolveeval.pas

@@ -1582,6 +1582,7 @@ begin
 
         Result:=EvalBinaryAddExpr(SubBin,LeftValue,RightValue);
         ReleaseEvalValue(LeftValue);
+        ReleaseEvalValue(RightValue);
         if SubBin=Expr then exit;
 
         LeftValue:=Result;
@@ -5657,11 +5658,15 @@ end;
 procedure TResolveData.SetElement(AValue: TPasElement);
 begin
   if FElement=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if Element<>nil then
     Element.Release{$IFDEF CheckPasTreeRefCount}(ClassName+'.SetElement'){$ENDIF};
+  {$ENDIF}
   FElement:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if Element<>nil then
     Element.AddRef{$IFDEF CheckPasTreeRefCount}(ClassName+'.SetElement'){$ENDIF};
+  {$ENDIF}
 end;
 
 constructor TResolveData.Create;

+ 184 - 34
packages/fcl-passrc/src/pasresolver.pp

@@ -2085,6 +2085,7 @@ type
       AParent: TPasElement; AVisibility: TPasMemberVisibility;
       const ASrcPos: TPasSourcePos; TypeParams: TFPList = nil): TPasElement;
       overload; override;
+    function CreateOwnedElement(AClass: TPTreeElement; const AName: String; AParent: TPasElement): TPasElement; virtual;
     function FindModule(const AName: String; NameExpr, InFileExpr: TPasExpr): TPasModule; override;
     function FindUnit(const AName, InFilename: String;
       NameExpr, InFileExpr: TPasExpr): TPasModule; virtual; abstract;
@@ -3210,11 +3211,15 @@ end;
 { TPRSpecializedItem }
 
 destructor TPRSpecializedItem.Destroy;
+{$IFNDEF EnablePasTreeFree}
 var
   i: Integer;
+{$ENDIF}
 begin
+  {$IFNDEF EnablePasTreeFree}
   for i:=0 to length(SpecializedConstraints)-1 do
     SpecializedConstraints[i].Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+  {$ENDIF}
   SetLength(SpecializedConstraints,0);
   inherited Destroy;
 end;
@@ -3224,22 +3229,30 @@ end;
 procedure TPRSpecializedTypeItem.SetSpecializedType(AValue: TPasGenericType);
 begin
   if FSpecializedType=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if FSpecializedType<>nil then
     FSpecializedType.Release{$IFDEF CheckPasTreeRefCount}('TPRSpecializedTypeItem.SpecializedType'){$ENDIF};
+  {$ENDIF}
   FSpecializedEl:=AValue;
   FSpecializedType:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if FSpecializedType<>nil then
     FSpecializedType.AddRef{$IFDEF CheckPasTreeRefCount}('TPRSpecializedTypeItem.SpecializedType'){$ENDIF};
+  {$ENDIF}
 end;
 
 destructor TPRSpecializedTypeItem.Destroy;
+{$IFNDEF EnablePasTreeFree}
 var
   i: Integer;
+{$ENDIF}
 begin
   if ImplProcs<>nil then
     begin
+    {$IFNDEF EnablePasTreeFree}
     for i:=0 to ImplProcs.Count-1 do
       TPasElement(ImplProcs[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    {$ENDIF}
     ImplProcs.Free;
     ImplProcs:=nil;
     end;
@@ -3255,19 +3268,25 @@ procedure TPRSpecializedProcItem.SetSpecializedProc(const AValue: TPasProcedure
   );
 begin
   if FSpecializedProc=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if FSpecializedProc<>nil then
     FSpecializedProc.Release{$IFDEF CheckPasTreeRefCount}('TPRSpecializedProcItem.SpecializedProc'){$ENDIF};
+  {$ENDIF}
   FSpecializedEl:=AValue;
   FSpecializedProc:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if FSpecializedProc<>nil then
     FSpecializedProc.AddRef{$IFDEF CheckPasTreeRefCount}('TPRSpecializedProcItem.SpecializedProc'){$ENDIF};
+  {$ENDIF}
 end;
 
 destructor TPRSpecializedProcItem.Destroy;
 begin
   if ImplProc<>nil then
     begin
+    {$IFNDEF EnablePasTreeFree}
     ImplProc.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    {$ENDIF}
     ImplProc:=nil;
     end;
   SpecializedProc:=nil;
@@ -3508,7 +3527,11 @@ end;
 
 destructor TResElDataBuiltInProc.Destroy;
 begin
+  {$IFDEF EnablePasTreeFree}
+  Proc:=nil;
+  {$ELSE}
   ReleaseAndNil(TPasElement(Proc){$IFDEF CheckPasTreeRefCount},'TResElDataBuiltInProc.Proc'{$ENDIF});
+  {$ENDIF}
   inherited Destroy;
 end;
 
@@ -3544,11 +3567,15 @@ end;
 procedure TPasScopeReference.SetElement(const AValue: TPasElement);
 begin
   if FElement=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if FElement<>nil then
     FElement.Release{$IFDEF CheckPasTreeRefCount}('TPasScopeReference.SetElement'){$ENDIF};
+  {$ENDIF}
   FElement:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if FElement<>nil then
     FElement.AddRef{$IFDEF CheckPasTreeRefCount}('TPasScopeReference.SetElement'){$ENDIF};
+  {$ENDIF}
 end;
 
 destructor TPasScopeReference.Destroy;
@@ -3732,7 +3759,11 @@ begin
   {$IFDEF VerbosePasResolverMem}
   writeln('TPasEnumTypeScope.Destroy START ',ClassName);
   {$ENDIF}
+  {$IFDEF EnablePasTreeFree}
+  CanonicalSet:=nil;
+  {$ELSE}
   ReleaseAndNil(TPasElement(CanonicalSet){$IFDEF CheckPasTreeRefCount},'TPasEnumTypeScope.CanonicalSet'{$ENDIF});
+  {$ENDIF}
   inherited Destroy;
   {$IFDEF VerbosePasResolverMem}
   writeln('TPasEnumTypeScope.Destroy END ',ClassName);
@@ -3874,7 +3905,11 @@ begin
   FreeAndNil(GroupScope);
   NestedMembersScope:=nil; // NestedMembersScope is auto freed
   inherited Destroy;
+  {$IFDEF EnablePasTreeFree}
+  SelfArg:=nil;
+  {$ELSE}
   ReleaseAndNil(TPasElement(SelfArg){$IFDEF CheckPasTreeRefCount},'TPasProcedureScope.SelfArg'{$ENDIF});
+  {$ENDIF}
   {$IFDEF VerbosePasResolverMem}
   writeln('TPasProcedureScope.Destroy END ',ClassName);
   {$ENDIF}
@@ -3917,11 +3952,15 @@ begin
       end;
     FreeAndNil(Interfaces);
     end;
+  {$IFDEF EnablePasTreeFree}
+  CanonicalClassOf:=nil;
+  {$ELSE}
   if CanonicalClassOf<>nil then
     begin
     CanonicalClassOf.Parent:=nil;
     ReleaseAndNil(TPasElement(CanonicalClassOf){$IFDEF CheckPasTreeRefCount},'TPasClassScope.CanonicalClassOf'{$ENDIF});
     end;
+  {$ENDIF}
   inherited Destroy;
 end;
 
@@ -3930,11 +3969,15 @@ end;
 procedure TPasIdentifier.SetElement(AValue: TPasElement);
 begin
   if FElement=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if Element<>nil then
     Element.Release{$IFDEF CheckPasTreeRefCount}('TPasIdentifier.SetElement'){$ENDIF};
+  {$ENDIF}
   FElement:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if Element<>nil then
     Element.AddRef{$IFDEF CheckPasTreeRefCount}('TPasIdentifier.SetElement'){$ENDIF};
+  {$ENDIF}
 end;
 
 destructor TPasIdentifier.Destroy;
@@ -3952,19 +3995,17 @@ end;
 { EPasResolve }
 
 procedure EPasResolve.SetPasElement(AValue: TPasElement);
-var
-  Old: TPasElement;
 begin
   if FPasElement=AValue then Exit;
-  Old:=FPasElement;
-  if Old<>nil then
-    begin
-    Old:=nil;
+  {$IFNDEF EnablePasTreeFree}
+  if FPasElement<>nil then
     PasElement.Release{$IFDEF CheckPasTreeRefCount}('EPasResolve.SetPasElement'){$ENDIF};
-    end;
+  {$ENDIF}
   FPasElement:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if PasElement<>nil then
     PasElement.AddRef{$IFDEF CheckPasTreeRefCount}('EPasResolve.SetPasElement'){$ENDIF};
+  {$ENDIF}
 end;
 
 destructor EPasResolve.Destroy;
@@ -3984,11 +4025,15 @@ end;
 procedure TResolvedReference.SetDeclaration(AValue: TPasElement);
 begin
   if FDeclaration=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if Declaration<>nil then
     Declaration.Release{$IFDEF CheckPasTreeRefCount}('TResolvedReference.SetDeclaration'){$ENDIF};
+  {$ENDIF}
   FDeclaration:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if Declaration<>nil then
     Declaration.AddRef{$IFDEF CheckPasTreeRefCount}('TResolvedReference.SetDeclaration'){$ENDIF};
+  {$ENDIF}
 end;
 
 destructor TResolvedReference.Destroy;
@@ -4027,11 +4072,15 @@ end;
 procedure TPasModuleDotScope.SetModule(AValue: TPasModule);
 begin
   if FModule=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if Module<>nil then
     Module.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleDotScope.SetModule'){$ENDIF};
+  {$ENDIF}
   FModule:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if Module<>nil then
     Module.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleDotScope.SetModule'){$ENDIF};
+  {$ENDIF}
 end;
 
 destructor TPasModuleDotScope.Destroy;
@@ -4204,64 +4253,88 @@ end;
 procedure TPasModuleScope.SetAssertClass(const AValue: TPasClassType);
 begin
   if FAssertClass=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if FAssertClass<>nil then
     FAssertClass.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertClass'){$ENDIF};
+  {$ENDIF}
   FAssertClass:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if FAssertClass<>nil then
     FAssertClass.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertClass'){$ENDIF};
+  {$ENDIF}
 end;
 
 procedure TPasModuleScope.SetAssertDefConstructor(const AValue: TPasConstructor
   );
 begin
   if FAssertDefConstructor=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if FAssertDefConstructor<>nil then
     FAssertDefConstructor.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertDefConstructor'){$ENDIF};
+  {$ENDIF}
   FAssertDefConstructor:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if FAssertDefConstructor<>nil then
     FAssertDefConstructor.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertDefConstructor'){$ENDIF};
+  {$ENDIF}
 end;
 
 procedure TPasModuleScope.SetAssertMsgConstructor(const AValue: TPasConstructor
   );
 begin
   if FAssertMsgConstructor=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if FAssertMsgConstructor<>nil then
     FAssertMsgConstructor.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertMsgConstructor'){$ENDIF};
+  {$ENDIF}
   FAssertMsgConstructor:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if FAssertMsgConstructor<>nil then
     FAssertMsgConstructor.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetAssertMsgConstructor'){$ENDIF};
+  {$ENDIF}
 end;
 
 procedure TPasModuleScope.SetRangeErrorClass(const AValue: TPasClassType);
 begin
   if FRangeErrorClass=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if FRangeErrorClass<>nil then
     FRangeErrorClass.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetRangeErrorClass'){$ENDIF};
+  {$ENDIF}
   FRangeErrorClass:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if FRangeErrorClass<>nil then
     FRangeErrorClass.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetRangeErrorClass'){$ENDIF};
+  {$ENDIF}
 end;
 
 procedure TPasModuleScope.SetRangeErrorConstructor(const AValue: TPasConstructor
   );
 begin
   if FRangeErrorConstructor=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if FRangeErrorConstructor<>nil then
     FRangeErrorConstructor.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetRangeErrorConstructor'){$ENDIF};
+  {$ENDIF}
   FRangeErrorConstructor:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if FRangeErrorConstructor<>nil then
     FRangeErrorConstructor.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetRangeErrorConstructor'){$ENDIF};
+  {$ENDIF}
 end;
 
 procedure TPasModuleScope.SetSystemTVarRec(const AValue: TPasRecordType);
 begin
   if FSystemTVarRec=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if FSystemTVarRec<>nil then
     FSystemTVarRec.Release{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetSystemTVarRec'){$ENDIF};
+  {$ENDIF}
   FSystemTVarRec:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if FSystemTVarRec<>nil then
     FSystemTVarRec.AddRef{$IFDEF CheckPasTreeRefCount}('TPasModuleScope.SetSystemTVarRec'){$ENDIF};
+  {$ENDIF}
 end;
 
 constructor TPasModuleScope.Create;
@@ -6132,7 +6205,9 @@ procedure TPasResolver.FinishTypeSectionEl(El: TPasType);
   var
     Abort: boolean;
     Data: TPRFindData;
+    {$IFNDEF EnablePasTreeFree}
     OldDestType: TPasType;
+    {$ENDIF}
   begin
     Abort:=false;
     Data:=Default(TPRFindData);
@@ -6155,10 +6230,14 @@ procedure TPasResolver.FinishTypeSectionEl(El: TPasType);
         RaiseXExpectedButYFound(20170216151548,'class',GetElementTypeName(Data.Found),ErrorEl);
       end;
     // replace unresolved
+    {$IFNDEF EnablePasTreeFree}
     OldDestType:=DestType;
+    {$ENDIF}
     DestType:=TPasType(Data.Found);
+    {$IFNDEF EnablePasTreeFree}
     DestType.AddRef{$IFDEF CheckPasTreeRefCount}(RefId){$ENDIF};
     OldDestType.Release{$IFDEF CheckPasTreeRefCount}(RefId){$ENDIF};
+    {$ENDIF}
     CheckUseAsType(DestType,20190123100649,El);
     // check cycles
     if Decl is TPasPointerType then
@@ -6344,10 +6423,14 @@ begin
       begin
       // When a TPasEnumType is created a CanonicalSet is created.
       // Release the autocreated CanonicalSet and use the parent.
+      {$IFNDEF EnablePasTreeFree}
       if EnumScope.CanonicalSet<>nil then
         EnumScope.CanonicalSet.Release{$IFDEF CheckPasTreeRefCount}('TPasEnumTypeScope.CanonicalSet'){$ENDIF};
+      {$ENDIF}
       EnumScope.CanonicalSet:=TPasSetType(Parent);
+      {$IFNDEF EnablePasTreeFree}
       Parent.AddRef{$IFDEF CheckPasTreeRefCount}('TPasEnumTypeScope.CanonicalSet'){$ENDIF};
+      {$ENDIF}
       end;
     end;
 end;
@@ -6601,7 +6684,9 @@ begin
   TypeEl:=ResolveAliasType(El.DestType);
   if TypeEl is TUnresolvedPendingRef then
     begin
+    {$IFNDEF EnablePasTreeFree}
     TypeEl.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    {$ENDIF}
     exit;
     end;
   if (TypeEl is TPasClassType) and (TPasClassType(TypeEl).ObjKind=okClass) then exit;
@@ -6616,7 +6701,9 @@ begin
   TypeEl:=ResolveAliasType(El.DestType);
   if TypeEl is TUnresolvedPendingRef then
     begin
+    {$IFNDEF EnablePasTreeFree}
     TypeEl.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    {$ENDIF}
     exit;
     end;
   if El.DestType.Parent=El then
@@ -7604,7 +7691,9 @@ begin
     begin
     // add 'Self'
     ImplProcScope.SelfArg:=SelfArg;
+    {$IFNDEF EnablePasTreeFree}
     SelfArg.AddRef{$IFDEF CheckPasTreeRefCount}('TPasProcedureScope.SelfArg'){$ENDIF};
+    {$ENDIF}
     {$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
     AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
     end;
@@ -8972,11 +9061,13 @@ begin
   if aClass.ObjKind in ([okClass]+okAllHelpers) then
     begin
     // create canonical class-of for the "Self" in non static class functions
-    CanonicalSelf:=TPasClassOfType.Create('Self',aClass);
+    CanonicalSelf:=TPasClassOfType(CreateOwnedElement(TPasClassOfType,'Self',aClass));
     ClassScope.CanonicalClassOf:=CanonicalSelf;
     {$IFDEF CheckPasTreeRefCount}CanonicalSelf.RefIds.Add('TPasClassScope.CanonicalClassOf');{$ENDIF}
     CanonicalSelf.DestType:=aClass;
+    {$IFNDEF EnablePasTreeFree}
     aClass.AddRef{$IFDEF CheckPasTreeRefCount}('TPasAliasType.DestType'){$ENDIF};
+    {$ENDIF}
     CanonicalSelf.Visibility:=visStrictPrivate;
     CanonicalSelf.SourceFilename:=aClass.SourceFilename;
     CanonicalSelf.SourceLinenumber:=aClass.SourceLinenumber;
@@ -11238,7 +11329,9 @@ begin
         // check if params fit the implicit specialized function, e.g. Run()
         CheckCallProcCompatibility(TPasProcedure(FoundEl).ProcType,Params,true);
       finally
+        {$IFNDEF EnablePasTreeFree}
         ReleaseElementList(InferenceParams{$IFDEF CheckPasTreeRefCount},RefIdInferenceParamsExpr{$ENDIF});
+        {$ENDIF}
         FreeAndNil(InferenceParams);
       end;
       end
@@ -12091,7 +12184,9 @@ procedure TPasResolver.DeanonymizeType(El: TPasType);
       begin
       List.Add(El);
       end;
+    {$IFNDEF EnablePasTreeFree}
     El.AddRef{$IFDEF CheckPasTreeRefCount}(aID){$ENDIF};
+    {$ENDIF}
     {$IFDEF VerbosePasResolver}
     if El.Parent<>NewParent then writeln('TPasResolver.DeanonymizeType.InsertInFront OldParent=',GetObjName(El.Parent),' -> ',GetObjPath(NewParent));
     {$ENDIF}
@@ -12537,14 +12632,18 @@ begin
     begin
     // set of anonymous enumtype, e.g. "set of ()"
     CanonicalSet:=TPasSetType(El.Parent);
+    {$IFNDEF EnablePasTreeFree}
     CanonicalSet.AddRef{$IFDEF CheckPasTreeRefCount}('TPasEnumTypeScope.CanonicalSet'){$ENDIF};
+    {$ENDIF}
     end
   else
     begin
-    CanonicalSet:=TPasSetType.Create('',El);
+    CanonicalSet:=TPasSetType(CreateOwnedElement(TPasSetType,'',El));
     {$IFDEF CheckPasTreeRefCount}CanonicalSet.RefIds.Add('TPasEnumTypeScope.CanonicalSet'){$ENDIF};
     CanonicalSet.EnumType:=El;
+    {$IFNDEF EnablePasTreeFree}
     El.AddRef{$IFDEF CheckPasTreeRefCount}('TPasSetType.EnumType'){$ENDIF};
+    {$ENDIF}
     end;
   EnumScope.CanonicalSet:=CanonicalSet;
 end;
@@ -16290,7 +16389,9 @@ type
           // template type inferred first time
           InferenceParams[i].InferType:=ParamHiType;
           InferenceParams[i].IsVarOut:=NeedVar;
+          {$IFNDEF EnablePasTreeFree}
           ParamHiType.AddRef{$IFDEF CheckPasTreeRefCount}(RefIdInferenceParamsExpr){$ENDIF};
+          {$ENDIF}
           exit;
           end;
 
@@ -16323,10 +16424,14 @@ type
             // second is var/out, and do not match
             RaiseInferTypeMismatch(20191006220402,ArgType,ErrorPos);
           // first can be widened to fit
+          {$IFNDEF EnablePasTreeFree}
           InferenceParams[i].InferType.Release{$IFDEF CheckPasTreeRefCount}(RefIdInferenceParamsExpr){$ENDIF};
+          {$ENDIF}
           InferenceParams[i].InferType:=ParamHiType;
           InferenceParams[i].IsVarOut:=NeedVar;
+          {$IFNDEF EnablePasTreeFree}
           ParamHiType.AddRef{$IFDEF CheckPasTreeRefCount}(RefIdInferenceParamsExpr){$ENDIF};
+          {$ENDIF}
           exit;
           end
         else if InferenceParams[i].IsVarOut then
@@ -16394,10 +16499,14 @@ type
           end;
         if NewBaseType<>btNone then
           begin
+          {$IFNDEF EnablePasTreeFree}
           InferenceParams[i].InferType.Release{$IFDEF CheckPasTreeRefCount}(RefIdInferenceParamsExpr){$ENDIF};
+          {$ENDIF}
           InferenceParams[i].InferType:=BaseTypes[NewBaseType];
           InferenceParams[i].IsVarOut:=NeedVar;
+          {$IFNDEF EnablePasTreeFree}
           BaseTypes[NewBaseType].AddRef{$IFDEF CheckPasTreeRefCount}(RefIdInferenceParamsExpr){$ENDIF};
+          {$ENDIF}
           exit;
           end;
 
@@ -16515,10 +16624,12 @@ begin
       InferenceTypes[i].InferType:=nil;
       end;
   finally
+    {$IFNDEF EnablePasTreeFree}
     if Result=nil then
       for i:=0 to length(InferenceTypes)-1 do
         if InferenceTypes[i].InferType<>nil then
           InferenceTypes[i].InferType.Release{$IFDEF CheckPasTreeRefCount}(RefIdInferenceParamsExpr){$ENDIF};
+    {$ENDIF}
   end;
 end;
 
@@ -17064,7 +17175,7 @@ begin
   NewName:=CreateSpecializedTypeName(Result);
   NewClass:=TPTreeElement(GenericEl.ClassType);
   NewParent:=GenericEl.Parent;
-  NewEl:=TPasElement(NewClass.Create(NewName,NewParent));
+  NewEl:=TPasElement(CreateOwnedElement(NewClass,NewName,NewParent));
   if TypeItem<>nil then
     TypeItem.SpecializedType:=TPasGenericType(NewEl) // this calls AddRef
   else
@@ -17081,7 +17192,11 @@ begin
     {$IFDEF CheckPasTreeRefCount}NewEl.RefIds.Add('TPasMembersType.Members');{$ENDIF}
     end
   else
+    {$IFDEF EnablePasTreeFree}
+    ;
+    {$ELSE}
     NewEl.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF}; // fix refcount
+    {$ENDIF}
 
   if GenScope.GenericStep>=psgsInterfaceParsed then
     SpecializeGenericIntf(Result);
@@ -17424,7 +17539,7 @@ begin
     if GenEl.Parent<>GenMembersType then
       RaiseNotYetImplemented(20190728145634,GenEl,GetObjName(GenEl.Parent));
     NewClass:=TPTreeElement(GenEl.ClassType);
-    NewEl:=TPasElement(NewClass.Create(GenEl.Name,SpecMembersType));
+    NewEl:=TPasElement(CreateOwnedElement(NewClass,GenEl.Name,SpecMembersType));
     SpecMembersType.Members.Add(NewEl);
     SpecializeElement(GenEl,NewEl);
     end;
@@ -17540,7 +17655,9 @@ procedure TPasResolver.SpecializeGenImplProc(GenDeclProc,
       RaiseNotYetImplemented(20191017122900,GenDeclProc);
       end;
     ParentElList.Insert(i+1,SpecImplProc);
+    {$IFNDEF EnablePasTreeFree}
     SpecImplProc.AddRef{$IFDEF CheckPasTreeRefCount}('TPasDeclarations.Children'){$ENDIF};
+    {$ENDIF}
   end;
 
 var
@@ -17624,7 +17741,7 @@ begin
   // create impl proc
   NewClass:=TPTreeElement(GenImplProc.ClassType);
   NewParent:=GenImplProc.Parent;
-  SpecImplProc:=TPasProcedure(NewClass.Create(NewImplProcName,NewParent));
+  SpecImplProc:=TPasProcedure(CreateOwnedElement(NewClass,NewImplProcName,NewParent));
   SpecDeclProcScope.ImplProc:=SpecImplProc;
   if SpecializedProcItem<>nil then
     SpecializedProcItem.ImplProc:=SpecImplProc
@@ -17932,14 +18049,16 @@ begin
     // reference
     GenElType:=SpecializeTypeRef(GenEl,SpecEl,GenElType);
     SpecElType:=GenElType;
+    {$IFNDEF EnablePasTreeFree}
     SpecElType.AddRef{$IFDEF CheckPasTreeRefCount}('ResolveTypeReference'){$ENDIF};
+    {$ENDIF}
     exit;
     end;
   // e.g. anonymous type
   if SpecElType<>nil then
     RaiseNotYetImplemented(20190808222744,SpecEl,GetObjName(SpecElType));
   NewClass:=TPTreeElement(GenElType.ClassType);
-  SpecElType:=TPasType(NewClass.Create(GenElType.Name,SpecEl));
+  SpecElType:=TPasType(CreateOwnedElement(NewClass,GenElType.Name,SpecEl));
   SpecializeElement(GenElType,SpecElType);
 end;
 
@@ -17955,7 +18074,7 @@ begin
     RaiseNotYetImplemented(20190809160834,GenEl);
   // normal expression
   NewClass:=TPTreeElement(GenElExpr.ClassType);
-  SpecElExpr:=TPasExpr(NewClass.Create(GenElExpr.Name,SpecEl));
+  SpecElExpr:=TPasExpr(CreateOwnedElement(NewClass,GenElExpr.Name,SpecEl));
   SpecializeElement(GenElExpr,SpecElExpr);
 end;
 
@@ -17968,7 +18087,7 @@ begin
   if GenImplEl.Parent<>GenEl then
     RaiseNotYetImplemented(20190808222638,GenEl,GetObjName(GenImplEl.Parent));
   NewClass:=TPTreeElement(GenImplEl.ClassType);
-  SpecImplEl:=TPasImplElement(NewClass.Create(GenImplEl.Name,SpecEl));
+  SpecImplEl:=TPasImplElement(CreateOwnedElement(NewClass,GenImplEl.Name,SpecEl));
   SpecializeElement(GenImplEl,SpecImplEl);
 end;
 
@@ -17985,7 +18104,9 @@ begin
   SpecImplAlias:=TObject(SpecEl.Elements[i]) as TPasImplElement;
   if SpecImplAlias.ClassType<>GenImplAlias.ClassType then
     RaiseNotYetImplemented(20190808231616,GenImplAlias,GetObjName(SpecImplAlias));
+  {$IFNDEF EnablePasTreeFree}
   SpecImplAlias.AddRef{$IFDEF CheckPasTreeRefCount}(RefId){$ENDIF};
+  {$ENDIF}
 end;
 
 procedure TPasResolver.SpecializeElList(GenEl, SpecEl: TPasElement;
@@ -18007,14 +18128,16 @@ begin
         RaiseNotYetImplemented(20190812025715,GenEl,IntToStr(i)+' GenListItem='+GetObjName(GenListItem));
       // reference
       Ref:=SpecializeTypeRef(GenEl,SpecEl,TpasType(GenListItem));
+      {$IFNDEF EnablePasTreeFree}
       Ref.AddRef{$IFDEF CheckPasTreeRefCount}(RefId){$ENDIF};
+      {$ENDIF}
       SpecList.Add(Ref);
       continue;
       end;
     if GenListItem.ClassType=TPasGenericTemplateType then
       RaiseNotYetImplemented(20190812233309,GenEl);
     NewClass:=TPTreeElement(GenListItem.ClassType);
-    SpecListItem:=TPasElement(NewClass.Create(GenListItem.Name,SpecEl));
+    SpecListItem:=CreateOwnedElement(NewClass,GenListItem.Name,SpecEl);
     SpecList.Add(SpecListItem);
     SpecializeElement(GenListItem,SpecListItem);
     end;
@@ -18045,14 +18168,16 @@ begin
         RaiseNotYetImplemented(20190914102957,GenEl,IntToStr(i)+' GenListItem='+GetObjName(GenListItem));
       // reference
       Ref:=SpecializeTypeRef(GenEl,SpecEl,TPasType(GenListItem));
+      {$IFNDEF EnablePasTreeFree}
       Ref.AddRef{$IFDEF CheckPasTreeRefCount}(RefId){$ENDIF};
+      {$ENDIF}
       SpecList[i]:=Ref;
       continue;
       end;
     if GenListItem.ClassType=TPasGenericTemplateType then
       RaiseNotYetImplemented(20190914103040,GenEl);
     NewClass:=TPTreeElement(GenListItem.ClassType);
-    SpecListItem:=TPasElement(NewClass.Create(GenListItem.Name,SpecEl));
+    SpecListItem:=CreateOwnedElement(NewClass,GenListItem.Name,SpecEl);
     SpecList[i]:=SpecListItem;
     SpecializeElement(GenListItem,SpecListItem);
     end;
@@ -18138,7 +18263,7 @@ begin
           if GenTempl.Parent<>GenEl then
             RaiseNotYetImplemented(20190818130001,GenEl,IntToStr(i)+','+IntToStr(j)+':'+GenTempl.Name+' GenParent='+GetObjName(GenTempl.Parent)+' GenEl='+GetObjName(GenEl));
           NewClass:=TPTreeElement(GenTempl.ClassType);
-          SpecTempl:=TPasGenericTemplateType(NewClass.Create(GenTempl.Name,SpecEl));
+          SpecTempl:=TPasGenericTemplateType(CreateOwnedElement(NewClass,GenTempl.Name,SpecEl));
           SpecPart.Templates.Add(SpecTempl);
           SpecializeElement(GenTempl,SpecTempl);
           end;
@@ -18156,7 +18281,7 @@ begin
       RaiseNotYetImplemented(20190803212426,GenEl,GetObjPath(GenProcType.Parent));
       end;
     NewClass:=TPTreeElement(GenProcType.ClassType);
-    SpecEl.ProcType:=TPasProcedureType(NewClass.Create(GenProcType.Name,SpecEl));
+    SpecEl.ProcType:=TPasProcedureType(CreateOwnedElement(NewClass,GenProcType.Name,SpecEl));
     SpecializeElement(GenProcType,SpecEl.ProcType);
     end;
   SpecProcScope.GenericStep:=psgsInterfaceParsed;
@@ -18172,7 +18297,7 @@ begin
     if SpecEl.Body<>nil then
       RaiseNotYetImplemented(20190920211853,SpecEl);
     NewClass:=TPTreeElement(GenBody.ClassType);
-    SpecEl.Body:=TProcedureBody(NewClass.Create(GenBody.Name,SpecEl));
+    SpecEl.Body:=TProcedureBody(CreateOwnedElement(NewClass,GenBody.Name,SpecEl));
     SpecializeElement(GenBody,SpecEl.Body);
     FinishProcedure(SpecEl);
     end
@@ -18241,7 +18366,7 @@ begin
       if GenResultEl.Parent<>GenEl then
         RaiseNotYetImplemented(20190803212935,GenEl,GetObjName(GenResultEl.Parent));
       NewClass:=TPTreeElement(GenResultEl.ClassType);
-      NewResultEl:=TPasResultElement(NewClass.Create(GenResultEl.Name,SpecEl));
+      NewResultEl:=TPasResultElement(CreateOwnedElement(NewClass,GenResultEl.Name,SpecEl));
       TPasFunctionType(SpecEl).ResultEl:=NewResultEl;
       AddFunctionResult(NewResultEl);
       SpecializeElType(GenResultEl,NewResultEl,GenResultEl.ResultType,NewResultEl.ResultType);
@@ -18267,7 +18392,7 @@ begin
     if GenBody.Parent<>GenEl then
       RaiseNotYetImplemented(20190804184934,GenBody);
     NewClass:=TPTreeElement(GenBody.ClassType);
-    NewBody:=TPasImplBlock(NewClass.Create(GenBody.Name,SpecEl));
+    NewBody:=TPasImplBlock(CreateOwnedElement(NewClass,GenBody.Name,SpecEl));
     SpecEl.Body:=NewBody;
     SpecializeElement(GenBody,NewBody);
     end;
@@ -18285,7 +18410,7 @@ begin
     if GenDecl.Parent<>GenEl then
       RaiseNotYetImplemented(20190806091336,GenEl,GetObjName(GenDecl));
     NewClass:=TPTreeElement(GenDecl.ClassType);
-    NewDecl:=TPasElement(NewClass.Create(GenDecl.Name,SpecEl));
+    NewDecl:=CreateOwnedElement(NewClass,GenDecl.Name,SpecEl);
     SpecEl.Declarations.Add(NewDecl);
     if NewClass=TPasAttributes then
       SpecEl.Attributes.Add(NewDecl)
@@ -18328,7 +18453,9 @@ begin
   if not (Ref is TPasGenericType) then
     RaiseNotYetImplemented(20190812022359,GenEl,GetObjName(Ref));
   SpecEl.DestType:=TPasGenericType(Ref);
+  {$IFNDEF EnablePasTreeFree}
   SpecEl.DestType.AddRef{$IFDEF CheckPasTreeRefCount}('ResolveTypeReference'){$ENDIF};
+  {$ENDIF}
 
   SpecializeElExpr(GenEl,SpecEl,GenEl.Expr,SpecEl.Expr);
   SpecializeElList(GenEl,SpecEl,GenEl.Params,SpecEl.Params,true
@@ -18395,7 +18522,7 @@ begin
     if GenImpl.Parent<>GenEl then
       RaiseNotYetImplemented(20190806092151,GenEl,GetElementSourcePosStr(GenImpl));
     NewClass:=TPTreeElement(GenImpl.ClassType);
-    NewImpl:=TPasImplElement(NewClass.Create(GenImpl.Name,SpecEl));
+    NewImpl:=TPasImplElement(CreateOwnedElement(NewClass,GenImpl.Name,SpecEl));
     SpecEl.Elements.Add(NewImpl);
     SpecializeElement(GenImpl,NewImpl);
     end;
@@ -18446,7 +18573,7 @@ begin
     if GenExpr.Parent<>GenEl then
       RaiseNotYetImplemented(20190808224343,GenEl,IntToStr(i));
     NewClass:=TPTreeElement(GenExpr.ClassType);
-    SpecExpr:=TPasExpr(NewClass.Create(GenExpr.Name,SpecEl));
+    SpecExpr:=TPasExpr(CreateOwnedElement(NewClass,GenExpr.Name,SpecEl));
     SpecEl.Expressions.Add(SpecExpr);
     SpecializeElement(GenExpr,SpecExpr);
     BeginScope(stWithExpr,SpecExpr);
@@ -18510,7 +18637,7 @@ begin
     if GenImpl.Parent<>GenEl then
       RaiseNotYetImplemented(20190806092151,GenEl,GetElementSourcePosStr(GenImpl));
     NewClass:=TPTreeElement(GenImpl.ClassType);
-    NewImpl:=TPasImplElement(NewClass.Create(GenImpl.Name,SpecEl));
+    NewImpl:=TPasImplElement(CreateOwnedElement(NewClass,GenImpl.Name,SpecEl));
     SpecEl.AddElement(NewImpl);
     SpecializeElement(GenImpl,NewImpl);
     end;
@@ -18538,12 +18665,14 @@ begin
     if GenVar.Parent<>GenEl then
       RaiseNotYetImplemented(20190808232327,GenEl);
     NewClass:=TPTreeElement(GenVar.ClassType);
-    SpecEl.VarEl:=TPasVariable(NewClass.Create(GenVar.Name,SpecEl));
+    SpecEl.VarEl:=TPasVariable(CreateOwnedElement(NewClass,GenVar.Name,SpecEl));
     SpecializeElement(GenVar,SpecEl.VarEl);
     if GenVar.VarType<>GenEl.TypeEl then
       RaiseNotYetImplemented(20190808232601,GenEl);
     SpecEl.TypeEl:=SpecEl.VarEl.VarType;
+    {$IFNDEF EnablePasTreeFree}
     SpecEl.TypeEl.AddRef{$IFDEF CheckPasTreeRefCount}('TPasVariable.VarType'){$ENDIF};
+    {$ENDIF}
     end
   else
     SpecializeElType(GenEl,SpecEl,GenEl.TypeEl,SpecEl.TypeEl);
@@ -18671,7 +18800,7 @@ begin
   if GenProc.Parent<>GenEl then
     RaiseNotYetImplemented(20210331223856,GenEl);
   NewClass:=TPTreeElement(GenProc.ClassType);
-  SpecEl.Proc:=TPasAnonymousProcedure(NewClass.Create(GenProc.Name,SpecEl));
+  SpecEl.Proc:=TPasAnonymousProcedure(CreateOwnedElement(NewClass,GenProc.Name,SpecEl));
   SpecializeElement(GenProc,SpecEl.Proc);
 end;
 
@@ -21198,7 +21327,7 @@ begin
     RaiseInternalError(20190131154235);
 
   // create element
-  El:=AClass.Create(AName,AParent);
+  El:=CreateOwnedElement(AClass,AName,AParent);
   {$IFDEF CheckPasTreeRefCount}El.RefIds.Add('CreateElement');{$ENDIF}
   FLastElement:=El;
   try
@@ -21307,11 +21436,22 @@ begin
 
     Result:=El;
   finally
+    {$IFNDEF EnablePasTreeFree}
     if Result=nil then
       El.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    {$ENDIF}
   end;
 end;
 
+function TPasResolver.CreateOwnedElement(AClass: TPTreeElement;
+  const AName: String; AParent: TPasElement): TPasElement;
+begin
+  Result:=AClass.Create(AName,AParent);
+  {$IFDEF EnablePasTreeFree}
+  FOwnedElements.Add(Result);
+  {$ENDIF}
+end;
+
 function TPasResolver.FindModule(const AName: String; NameExpr,
   InFileExpr: TPasExpr): TPasModule;
 var
@@ -22134,7 +22274,9 @@ begin
     OldType := TPasTypeAliasType(NewType);
     NewType := aClass;
     TPasTypeAliasType(OldType).DestType:=nil; // clear reference
+    {$IFNDEF EnablePasTreeFree}
     OldType.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    {$ENDIF}
 
     // set ancestor
     aClass.AncestorType := DestType;
@@ -22387,7 +22529,11 @@ var
 begin
   ClearResolveDataList(lkBuiltIn);
   for bt in TResolverBaseType do
+    {$IFDEF EnablePasTreeFree}
+    FBaseTypes[bt]:=nil;
+    {$ELSE}
     ReleaseAndNil(TPasElement(FBaseTypes[bt]){$IFDEF CheckPasTreeRefCount},'TPasResolver.AddBaseType'{$ENDIF});
+    {$ENDIF}
   for bp in TResolverBuiltInProc do
     FBuiltInProcs[bp]:=nil;
 end;
@@ -22536,7 +22682,7 @@ function TPasResolver.AddBaseType(const aName: string; Typ: TResolverBaseType
 var
   El: TPasUnresolvedSymbolRef;
 begin
-  El:=TPasUnresolvedSymbolRef.Create(aName,nil);
+  El:=TPasUnresolvedSymbolRef(CreateOwnedElement(TPasUnresolvedSymbolRef,aName,nil));
   {$IFDEF CheckPasTreeRefCount}El.RefIds.Add('TPasResolver.AddBaseType');{$ENDIF}
   if not (Typ in [btNone,btCustom]) then
     FBaseTypes[Typ]:=El;
@@ -22551,7 +22697,7 @@ function TPasResolver.AddCustomBaseType(const aName: string;
 var
   CustomData: TResElDataBaseType;
 begin
-  Result:=TPasUnresolvedSymbolRef.Create(aName,nil);
+  Result:=TPasUnresolvedSymbolRef(CreateOwnedElement(TPasUnresolvedSymbolRef,aName,nil));
   {$IFDEF CheckPasTreeRefCount}Result.RefIds.Add('TPasResolver.AddCustomBaseType');{$ENDIF}
   CustomData:=aClass.Create;
   CustomData.BaseType:=btCustom;
@@ -22579,7 +22725,7 @@ function TPasResolver.AddBuiltInProc(const aName: string; Signature: string;
 var
   El: TPasUnresolvedSymbolRef;
 begin
-  El:=TPasUnresolvedSymbolRef.Create(aName,nil);
+  El:=TPasUnresolvedSymbolRef(CreateOwnedElement(TPasUnresolvedSymbolRef,aName,nil));
   Result:=TResElDataBuiltInProc.Create;
   Result.Proc:=El;
   {$IFDEF CheckPasTreeRefCount}El.RefIds.Add('TResElDataBuiltInProc.Proc');{$ENDIF}
@@ -29740,12 +29886,14 @@ begin
       begin
       // 'Self' in a class method is the hidden classtype argument
       // Note: this is true in classes, adv records and helpers
-      SelfArg:=TPasArgument.Create('Self',Proc);
+      SelfArg:=TPasArgument(CreateOwnedElement(TPasArgument,'Self',Proc));
       ProcScope.SelfArg:=SelfArg;
       {$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
       SelfArg.Access:=argConst;
       SelfArg.ArgType:=TPasClassScope(ClassOrRecScope).CanonicalClassOf;
+      {$IFNDEF EnablePasTreeFree}
       SelfArg.ArgType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
+      {$ENDIF}
       end
     else
       RaiseInternalError(20190106121745);
@@ -29753,7 +29901,7 @@ begin
   else
     begin
     // 'Self' in a method is the hidden instance argument
-    SelfArg:=TPasArgument.Create('Self',Proc);
+    SelfArg:=TPasArgument(CreateOwnedElement(TPasArgument,'Self',Proc));
     ProcScope.SelfArg:=SelfArg;
     {$IFDEF CheckPasTreeRefCount}SelfArg.RefIds.Add('TPasProcedureScope.SelfArg');{$ENDIF}
     SelfType:=ClassRecType;
@@ -29770,7 +29918,9 @@ begin
     else
       SelfArg.Access:=argVar;
     SelfArg.ArgType:=SelfType;
+    {$IFNDEF EnablePasTreeFree}
     SelfType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
+    {$ENDIF}
     end;
 end;
 

+ 19 - 12
packages/fcl-passrc/src/passrcutil.pp

@@ -81,6 +81,9 @@ function TSrcContainer.CreateElement(AClass: TPTreeElement;
   const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
 begin
   Result:=AClass.Create(AName,AParent);
+  {$IFDEF EnablePasTreeFree}
+  FOwnedElements.Add(Result);
+  {$ENDIF}
   Result.Visibility:=AVisibility;
   Result.SourceFilename:=ASourceFileName;
   Result.SourceLinenumber:=ASourceLineNumber;
@@ -115,7 +118,11 @@ begin
   FreeAndNil(FScanner);
   FreeAndNil(FContainer);
   FreeAndNil(FResolver);
+  {$IFDEF EnablePasTreeFree}
+  FModule:=nil;
+  {$ELSE}
   FreeAndNil(FModule);
+  {$ENDIF}
 end;
 
 procedure TPasSrcAnalysis.CheckParser;
@@ -221,20 +228,20 @@ end;
 procedure TPasSrcAnalysis.GetInterfaceUnits(List: TStrings);
 begin
   Parse;
-  GetUses(Fmodule.InterfaceSection,List);
+  GetUses(FModule.InterfaceSection,List);
 end;
 
 procedure TPasSrcAnalysis.GetImplementationUnits(List: TStrings);
 begin
   Parse;
-  GetUses(Fmodule.ImplementationSection,List);
+  GetUses(FModule.ImplementationSection,List);
 end;
 
 procedure TPasSrcAnalysis.GetUsedUnits(List: TStrings);
 begin
   Parse;
-  GetUses(Fmodule.InterfaceSection,List);
-  GetUses(Fmodule.ImplementationSection,List);
+  GetUses(FModule.InterfaceSection,List);
+  GetUses(FModule.ImplementationSection,List);
 end;
 
 procedure TPasSrcAnalysis.GetEnumValues(Enum : TPasEnumType;List : TStrings; Const APrefix : String = '');
@@ -281,40 +288,40 @@ end;
 procedure TPasSrcAnalysis.GetInterfaceIdentifiers(List: TStrings; Recurse : Boolean = False);
 begin
   Parse;
-  GetIdentifiers(Fmodule.InterfaceSection,List,Recurse);
+  GetIdentifiers(FModule.InterfaceSection,List,Recurse);
 end;
 
 procedure TPasSrcAnalysis.GetImplementationIdentifiers(List: TStrings;
   Recurse: Boolean);
 begin
   Parse;
-  GetIdentifiers(Fmodule.ImplementationSection,List,Recurse);
+  GetIdentifiers(FModule.ImplementationSection,List,Recurse);
 end;
 
 procedure TPasSrcAnalysis.GetAllIdentifiers(List: TStrings; Recurse: Boolean);
 begin
   Parse;
-  GetIdentifiers(Fmodule.InterfaceSection,List,Recurse);
-  GetIdentifiers(Fmodule.ImplementationSection,List,Recurse);
+  GetIdentifiers(FModule.InterfaceSection,List,Recurse);
+  GetIdentifiers(FModule.ImplementationSection,List,Recurse);
 end;
 
 function TPasSrcAnalysis.InterfaceHasResourcestrings: Boolean;
 begin
   Parse;
-  Result:=ResourceStringCount(Fmodule.InterfaceSection)>0;
+  Result:=ResourceStringCount(FModule.InterfaceSection)>0;
 end;
 
 function TPasSrcAnalysis.ImplementationHasResourcestrings: Boolean;
 begin
   Parse;
-  Result:=ResourceStringCount(Fmodule.ImplementationSection)>0;
+  Result:=ResourceStringCount(FModule.ImplementationSection)>0;
 end;
 
 function TPasSrcAnalysis.HasResourcestrings: Boolean;
 begin
   Parse;
-  Result:=(ResourceStringCount(Fmodule.InterfaceSection)>0)
-           or (ResourceStringCount(Fmodule.ImplementationSection)>0);
+  Result:=(ResourceStringCount(FModule.InterfaceSection)>0)
+           or (ResourceStringCount(FModule.ImplementationSection)>0);
 end;
 
 end.

+ 3 - 0
packages/fcl-passrc/src/pastounittest.pp

@@ -731,6 +731,9 @@ function TTestContainer.CreateElement(AClass: TPTreeElement;
   const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
 begin
   Result:=AClass.Create(AName,AParent);
+  {$IFDEF EnablePasTreeFree}
+  FOwnedElements.Add(Result);
+  {$ENDIF}
   Result.Visibility:=AVisibility;
   Result.SourceFilename:=ASourceFileName;
   Result.SourceLinenumber:=ASourceLineNumber;

+ 11 - 14
packages/fcl-passrc/src/pastree.pp

@@ -1891,7 +1891,7 @@ const
   VariableModifierNames : Array[TVariableModifier] of string
      = ('cvar', 'external', 'public', 'export', 'class', 'static');
 
-procedure FreeProcNameParts(Parent: TPasElement; var NameParts: TProcedureNameParts; Prepare: boolean);
+procedure FreeProcNameParts(var NameParts: TProcedureNameParts);
 procedure FreePasExprArray(Parent: TPasElement; var A: TPasExprArray; Prepare: boolean);
 {$IFNDEF EnablePasTreeFree}
 procedure ReleaseAndNil(var El: TPasElement {$IFDEF CheckPasTreeRefCount}; const Id: string{$ENDIF}); overload;
@@ -1913,8 +1913,7 @@ function GetPTDumpStack: string;
 
 implementation
 
-procedure FreeProcNameParts(Parent: TPasElement;
-  var NameParts: TProcedureNameParts; Prepare: boolean);
+procedure FreeProcNameParts(var NameParts: TProcedureNameParts);
 var
   i: Integer;
   p: TProcedureNamePart;
@@ -1923,15 +1922,11 @@ begin
   for i:=0 to NameParts.Count-1 do
     begin
     p:=TProcedureNamePart(NameParts[i]);
-    Parent.FreeChildList(p.Templates,Prepare);
-    if not Prepare then
-      p.Free;
-    end;
-  if not Prepare then
-    begin
-    NameParts.Free;
-    NameParts:=nil;
+    p.Templates.Free;
+    p.Free;
     end;
+  NameParts.Free;
+  NameParts:=nil;
 end;
 
 procedure FreePasExprArray(Parent: TPasElement; var A: TPasExprArray;
@@ -4631,7 +4626,9 @@ end;
 
 destructor TPasProcedure.Destroy;
 begin
-  {$IFNDEF EnablePasTreeFree}
+  {$IFDEF EnablePasTreeFree}
+  FreeProcNameParts(NameParts);
+  {$ELSE}
   ReleaseAndNil(TPasElement(PublicName){$IFDEF CheckPasTreeRefCount},'TPasProcedure.PublicName'{$ENDIF});
   ReleaseAndNil(TPasElement(LibrarySymbolName){$IFDEF CheckPasTreeRefCount},'TPasProcedure.LibrarySymbolName'{$ENDIF});
   ReleaseAndNil(TPasElement(LibraryExpr){$IFDEF CheckPasTreeRefCount},'TPasProcedure.LibraryExpr'{$ENDIF});
@@ -4653,7 +4650,7 @@ begin
   MessageExpr:=TPasExpr(FreeChild(MessageExpr,Prepare));
   ProcType:=TPasProcedureType(FreeChild(ProcType,Prepare));
   Body:=TProcedureBody(FreeChild(Body,Prepare));
-  FreeProcNameParts(Self,NameParts,Prepare);
+  //FreeProcNameParts(Self,NameParts,Prepare);
   inherited FreeChildren(Prepare);
 end;
 
@@ -5907,7 +5904,7 @@ begin
   if NameParts<>nil then
     begin
     {$IFDEF EnablePasTreeFree}
-    FreeProcNameParts(Self,NameParts,true);
+    FreeProcNameParts(NameParts);
     {$ELSE}
     ReleaseProcNameParts(NameParts);
     {$ENDIF}

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

@@ -660,11 +660,15 @@ end;
 procedure TPAOverrideList.SetElement(AValue: TPasElement);
 begin
   if FElement=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if FElement<>nil then
     FElement.Release{$IFDEF CheckPasTreeRefCount}('TPAOverrideList.Element'){$ENDIF};
+  {$ENDIF}
   FElement:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if FElement<>nil then
     FElement.AddRef{$IFDEF CheckPasTreeRefCount}('TPAOverrideList.Element'){$ENDIF};
+  {$ENDIF}
 end;
 
 constructor TPAOverrideList.Create;
@@ -673,11 +677,15 @@ begin
 end;
 
 destructor TPAOverrideList.Destroy;
+{$IFNDEF EnablePasTreeFree}
 var
   i: Integer;
+{$ENDIF}
 begin
+  {$IFNDEF EnablePasTreeFree}
   for i:=0 to FOverrides.Count-1 do
     TPasElement(FOverrides[i]).Release{$IFDEF CheckPasTreeRefCount}('TPAOverrideList.Overrides'){$ENDIF};
+  {$ENDIF}
   FreeAndNil(FOverrides);
   Element:=nil;
   inherited Destroy;
@@ -686,7 +694,9 @@ end;
 procedure TPAOverrideList.Add(OverrideEl: TPasElement);
 begin
   FOverrides.Add(OverrideEl);
+  {$IFNDEF EnablePasTreeFree}
   OverrideEl.AddRef{$IFDEF CheckPasTreeRefCount}('TPAOverrideList.Overrides'){$ENDIF};
+  {$ENDIF}
 end;
 
 function TPAOverrideList.Count: integer;
@@ -699,11 +709,15 @@ end;
 procedure TPAElement.SetElement(AValue: TPasElement);
 begin
   if FElement=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if FElement<>nil then
     FElement.Release{$IFDEF CheckPasTreeRefCount}('TPAElement.Element'){$ENDIF};
+  {$ENDIF}
   FElement:=AValue;
+  {$IFNDEF EnablePasTreeFree}
   if FElement<>nil then
     FElement.AddRef{$IFDEF CheckPasTreeRefCount}('TPAElement.Element'){$ENDIF};
+  {$ENDIF}
 end;
 
 destructor TPAElement.Destroy;

+ 162 - 7
packages/fcl-passrc/src/pparser.pp

@@ -185,8 +185,11 @@ type
   protected
     FPackage: TPasPackage;
     FInterfaceOnly : Boolean;
+    FOwnedElements: TFPList;
     procedure SetCurrentParser(AValue: TPasParser); virtual;
   public
+    constructor Create;
+    destructor Destroy; override;
     function CreateElement(AClass: TPTreeElement; const AName: String;
       AParent: TPasElement; const ASourceFilename: String;
       ASourceLinenumber: Integer): TPasElement;overload;
@@ -862,6 +865,21 @@ begin
   FCurrentParser:=AValue;
 end;
 
+constructor TPasTreeContainer.Create;
+begin
+  FOwnedElements:=TFPList.Create;
+end;
+
+destructor TPasTreeContainer.Destroy;
+var
+  i: Integer;
+begin
+  for i:=FOwnedElements.Count-1 downto 0 do
+    TPasElement(FOwnedElements[i]).Free;
+  FreeAndNil(FOwnedElements);
+  inherited Destroy;
+end;
+
 function TPasTreeContainer.CreateElement(AClass: TPTreeElement;
   const AName: String; AParent: TPasElement; const ASourceFilename: String;
   ASourceLinenumber: Integer): TPasElement;
@@ -1558,7 +1576,11 @@ begin
     ok:=true;
   finally
     if not ok then
+    {$IFDEF EnablePasTreeFree}
+      ;
+    {$ELSE}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    {$ENDIF}
   end;
 end;
 
@@ -1648,12 +1670,20 @@ begin
     Case K of
       stkString:
         begin
+        {$IFDEF EnablePasTreeFree}
+        Expr:=nil;
+        {$ELSE}
         ReleaseAndNil(TPasElement(Expr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+        {$ENDIF}
         Result:=ParseStringType(Parent,NamePos,TypeName);
         end;
       stkRange:
         begin
+        {$IFDEF EnablePasTreeFree}
+        Expr:=nil;
+        {$ELSE}
         ReleaseAndNil(TPasElement(Expr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+        {$ENDIF}
         UnGetToken; // move to '='
         Result:=ParseRangeType(Parent,NamePos,TypeName,False);
         end;
@@ -1679,12 +1709,16 @@ begin
   finally
     if not ok then
       begin
+      {$IFDEF EnablePasTreeFree}
+      Result:=nil;
+      {$ELSE}
       if Result<>nil then
         Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       if Expr<>nil then
         Expr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       if Ref<>nil then
         Ref.Release{$IFDEF CheckPasTreeRefCount}('ResolveTypeReference'){$ENDIF};
+      {$ENDIF}
       end
   end;
 end;
@@ -1692,20 +1726,26 @@ end;
 // On entry, we're on the TYPE token
 function TPasParser.ParseAliasType(Parent: TPasElement;
   const NamePos: TPasSourcePos; const TypeName: String): TPasType;
+{$IFNDEF EnablePasTreeFree}
 var
   ok: Boolean;
+{$ENDIF}
 begin
   Result := TPasTypeAliasType(CreateElement(TPasTypeAliasType, TypeName, Parent, NamePos));
+  {$IFNDEF EnablePasTreeFree}
   ok:=false;
   try
+  {$ENDIF}
     TPasTypeAliasType(Result).DestType := ParseType(Result,NamePos,'');
     Engine.FinishTypeAlias(Result);
     Engine.FinishScope(stTypeDef,Result);
+  {$IFNDEF EnablePasTreeFree}
     ok:=true;
   finally
     if not ok then
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
   end;
+  {$ENDIF}
 end;
 
 function TPasParser.ParseTypeReference(Parent: TPasElement; NeedExpr: boolean;
@@ -1758,12 +1798,20 @@ begin
   finally
     if not ok then
       begin
+      {$IFDEF EnablePasTreeFree}
+      Expr:=nil;
+      {$ELSE}
       if Result<>nil then
         Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       ReleaseAndNil(TPasElement(Expr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+      {$ENDIF}
       end
     else if (not NeedExpr) and (Expr<>nil) then
+      {$IFDEF EnablePasTreeFree}
+      Expr:=nil;
+      {$ELSE}
       ReleaseAndNil(TPasElement(Expr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+      {$ENDIF}
   end;
 end;
 
@@ -1807,8 +1855,10 @@ begin
     Engine.FinishScope(stTypeDef,ST);
     Result:=ST;
   finally
+    {$IFNDEF EnablePasTreeFree}
     if Result=nil then
       ST.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    {$ENDIF}
   end;
 end;
 
@@ -1849,7 +1899,9 @@ begin
     ok:=true;
   finally
     if not ok then
+      {$IFNDEF EnablePasTreeFree}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
   end;
 end;
 
@@ -1890,7 +1942,9 @@ begin
     ok:=true;
   finally
     if not ok then
+      {$IFNDEF EnablePasTreeFree}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
   end;
 end;
 
@@ -1910,7 +1964,9 @@ begin
     ok:=true;
   finally
     if not ok then
+      {$IFNDEF EnablePasTreeFree}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
   end;
 end;
 
@@ -2065,7 +2121,9 @@ begin
       begin
       if Result<>nil then
         begin
+        {$IFNDEF EnablePasTreeFree}
         Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+        {$ENDIF}
         Result:=nil;
         end;
       end;
@@ -2121,7 +2179,9 @@ begin
     ok:=true;
   finally
     if (not ok) and (Result<>nil) then
+      {$IFNDEF EnablePasTreeFree}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
   end;
 end;
 
@@ -2141,8 +2201,10 @@ begin
   finally
     if not ok then
       begin
+      {$IFNDEF EnablePasTreeFree}
       Result.Parent:=nil;
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
       end;
   end;
 end;
@@ -2257,7 +2319,9 @@ begin
     Result:=TPasUnresolvedTypeRef(CreateElement(TPasUnresolvedTypeRef,Name,Parent))
   else
     begin
+    {$IFNDEF EnablePasTreeFree}
     Ref.AddRef{$IFDEF CheckPasTreeRefCount}('ResolveTypeReference'){$ENDIF};
+    {$ENDIF}
     Result:=TPasType(Ref);
     end;
 end;
@@ -2325,8 +2389,10 @@ begin
     NextToken;
     Result:=Params;
   finally
+    {$IFNDEF EnablePasTreeFree}
     if Result=nil then
       Params.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    {$ENDIF}
   end;
 end;
 
@@ -2492,7 +2558,9 @@ begin
         Bin:=CreateBinaryExpr(AParent,Last,ParseExprOperand(AParent),eopNone,SrcPos);
         if not Assigned(Bin.Right) then
           begin
+          {$IFNDEF EnablePasTreeFree}
           Bin.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+          {$ENDIF}
           ParseExcExpectedIdentifier;
           end;
         Result:=Bin;
@@ -2520,8 +2588,10 @@ begin
         Engine.FinishScope(stProcedure,ProcExpr.Proc);
         Result:=ProcExpr;
       finally
+        {$IFNDEF EnablePasTreeFree}
         if Result=nil then
           ProcExpr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+        {$ENDIF}
       end;
       exit; // do not allow postfix operators . ^. [] ()
       end;
@@ -2545,7 +2615,9 @@ begin
         ParseExcSyntaxError;
       if (CurToken<>tkBraceClose) then
         begin
+        {$IFNDEF EnablePasTreeFree}
         Last.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+        {$ENDIF}
         CheckToken(tkBraceClose);
         end;
       end
@@ -2669,8 +2741,10 @@ begin
   finally
     if not ok then
       begin
+      {$IFNDEF EnablePasTreeFree}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       ISE.Free;
+      {$ENDIF}
       end;
   end;
 end;
@@ -2882,8 +2956,10 @@ begin
     {$endif}
     if not Assigned(Result) then begin
       // expression error!
+      {$IFNDEF EnablePasTreeFree}
       for i:=0 to ExpStack.Count-1 do
         TPasExpr(ExpStack[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
     end;
     SetLength(OpStack,0);
     ExpStack.Free;
@@ -2903,7 +2979,7 @@ end;
 function TPasParser.DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
 // sets CurToken to token behind expression
 
-  function lastfield:boolean;
+  function LastField:boolean;
 
   begin
     Result:=CurToken<>tkSemicolon;
@@ -2938,8 +3014,10 @@ function TPasParser.DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
     finally
       if Result=nil then
         begin
+        {$IFNDEF EnablePasTreeFree}
         a.Free;
         x.Free;
+        {$ENDIF}
         end;
     end;
   end;
@@ -2984,7 +3062,7 @@ begin
               v:=DoParseConstValueExpression(r);
               r.AddField(TPrimitiveExpr(x), v);
               x:=nil;
-              if not lastfield then
+              if not LastField then
                 repeat
                   n:=ExpectIdentifier;
                   x:=CreatePrimitiveExpr(r,pekIdent,n);
@@ -2993,13 +3071,15 @@ begin
                   v:=DoParseConstValueExpression(AParent);
                   r.AddField(TPrimitiveExpr(x), v);
                   x:=nil;
-                until lastfield; // CurToken<>tkSemicolon;
+                until LastField; // CurToken<>tkSemicolon;
               Result:=r;
             finally
               if Result=nil then
                 begin
+                {$IFNDEF EnablePasTreeFree}
                 r.Free;
                 x.Free;
+                {$ENDIF}
                 end;
             end;
             end;
@@ -3008,7 +3088,9 @@ begin
           Result:=DoParseExpression(AParent,x);
           if CurToken<>tkBraceClose then
             begin
+            {$IFNDEF EnablePasTreeFree}
             ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+            {$ENDIF}
             ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
             end;
           NextToken;
@@ -3020,7 +3102,9 @@ begin
       end;
     if CurToken<>tkBraceClose then
       begin
+      {$IFNDEF EnablePasTreeFree}
       ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+      {$ENDIF}
       ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
       end;
     NextToken;
@@ -3159,7 +3243,9 @@ begin
       begin
       Module.PackageName := Engine.Package.Name;
       Engine.Package.Modules.Add(Module);
+      {$IFNDEF EnablePasTreeFree}
       Module.AddRef{$IFDEF CheckPasTreeRefCount}('TPasPackage.Modules'){$ENDIF};
+      {$ENDIF}
       end;
     CheckHint(Module,True);
     ExpectToken(tkInterface);
@@ -3192,10 +3278,7 @@ begin
       FinishedModule;
   finally
     if HasFinished then
-      //begin
-      //Module.Release{$IFDEF CheckPasTreeRefCount}('TPasPackage.Modules'){$ENDIF};
       FCurModule:=nil; // clear module if there is an error or finished parsing
-      //end;
   end;
 end;
 
@@ -3751,7 +3834,9 @@ begin
                       Declarations.Declarations.Delete(j);
                       break;
                     end;
+                  {$IFNDEF EnablePasTreeFree}
                   ClassEl.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+                  {$ENDIF}
                   break;
                 end;
               end;
@@ -3771,8 +3856,10 @@ begin
               ok:=true;
             finally
               if not ok then
+                {$IFNDEF EnablePasTreeFree}
                 for i := 0 to List.Count - 1 do
                   TPasExportSymbol(List[i]).Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+                {$ENDIF}
             end;
             for i := 0 to List.Count - 1 do
             begin
@@ -3961,7 +4048,9 @@ begin
 
     UnitRef := Engine.FindModule(AUnitName,NameExpr,InFileExpr);
     if Assigned(UnitRef) then
+      {$IFNDEF EnablePasTreeFree}
       UnitRef.AddRef{$IFDEF CheckPasTreeRefCount}('TPasUsesUnit.Module'){$ENDIF}
+      {$ENDIF}
     else
       UnitRef := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef,
         AUnitName, ASection, NamePos));
@@ -3981,6 +4070,7 @@ begin
   finally
     if Result=nil then
       begin
+      {$IFNDEF EnablePasTreeFree}
       if UsesUnit<>nil then
         UsesUnit.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       if NameExpr<>nil then
@@ -3989,6 +4079,7 @@ begin
         InFileExpr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       if UnitRef<>nil then
         UnitRef.Release{$IFDEF CheckPasTreeRefCount}('FindModule'){$ENDIF};
+      {$ENDIF}
       end;
   end;
 end;
@@ -4069,8 +4160,10 @@ begin
   finally
     if FreeExpr then
       begin
+      {$IFNDEF EnablePasTreeFree}
       ReleaseAndNil(TPasElement(NameExpr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
       ReleaseAndNil(TPasElement(InFileExpr){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+      {$ENDIF}
       end;
   end;
 end;
@@ -4165,7 +4258,9 @@ begin
     ok:=true;
   finally
     if not ok then
+      {$IFNDEF EnablePasTreeFree}
       ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+      {$ENDIF}
   end;
 end;
 
@@ -4186,7 +4281,9 @@ begin
     ok:=true;
   finally
     if not ok then
+      {$IFNDEF EnablePasTreeFree}
       ReleaseAndNil(TPasElement(Result){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+      {$ENDIF}
   end;
 end;
 
@@ -4250,8 +4347,10 @@ begin
   finally
     if Result=nil then
       begin
+      {$IFNDEF EnablePasTreeFree}
       Attributes.Free;
       Expr.Free;
+      {$ENDIF}
       end;
   end;
 end;
@@ -4288,8 +4387,10 @@ begin
           TypeEl:=ParseTypeReference(T,false,Expr);
           if T.TypeConstraint='' then
             T.TypeConstraint:=TypeEl.Name;
+          {$IFNDEF EnablePasTreeFree}
           if (Expr<>nil) and (Expr.Parent=T) then
             Expr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+          {$ENDIF}
           T.AddConstraint(TypeEl);
           end;
         else
@@ -4381,7 +4482,9 @@ begin
     PE:=DoParseExpression(Result,Nil,False);
     if not ((PE is TBinaryExpr) and (TBinaryExpr(PE).Kind=pekRange)) then
       begin
+      {$IFNDEF EnablePasTreeFree}
       PE.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
       ParseExc(nRangeExpressionExpected,SRangeExpressionExpected);
       end;
     Result.RangeExpr:=TBinaryExpr(PE);
@@ -4390,7 +4493,9 @@ begin
     ok:=true;
   finally
     if not ok then
+      {$IFNDEF EnablePasTreeFree}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
   end;
 end;
 
@@ -4409,7 +4514,9 @@ begin
       E:=TPasExportSymbol(CreateElement(TPasExportSymbol,aName,Parent));
       if NameExpr.Kind=pekIdent then
         // simple identifier -> no need to store NameExpr
+        {$IFNDEF EnablePasTreeFree}
         NameExpr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF}
+        {$ENDIF}
       else
         begin
         E.NameExpr:=NameExpr;
@@ -4436,7 +4543,9 @@ begin
     until (CurToken=tkSemicolon);
   finally
     if NameExpr<>nil then
+      {$IFNDEF EnablePasTreeFree}
       NameExpr.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF}
+      {$ENDIF}
   end;
 end;
 
@@ -4457,7 +4566,9 @@ begin
     ok:=true;
   finally
     if not ok then
+      {$IFNDEF EnablePasTreeFree}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
   end;
 end;
 
@@ -4562,13 +4673,17 @@ var
   ClassEl: TPasClassType;
   RecordEl: TPasRecordType;
   ArrEl: TPasArrayType;
-  i: Integer;
   AObjKind: TPasObjKind;
+  {$IFNDEF EnablePasTreeFree}
+  i: Integer;
   ok: Boolean;
   GenTempl: TPasGenericTemplateType;
+  {$ENDIF}
 begin
   Result:=nil;
+  {$IFNDEF EnablePasTreeFree}
   ok := false;
+  {$ENDIF}
   TypeName := CurTokenString;
   NamePos := CurSourcePos;
   TypeParams:=TFPList.Create;
@@ -4649,8 +4764,11 @@ begin
     else
       ParseExcTypeParamsNotAllowed;
     end;
+    {$IFNDEF EnablePasTreeFree}
     ok:=true;
+    {$ENDIF}
   finally
+    {$IFNDEF EnablePasTreeFree}
     if (not ok) and (Result<>nil) and not AddToParent then
       Result.Release({$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF});
     for i:=0 to TypeParams.Count-1 do
@@ -4659,6 +4777,7 @@ begin
       GenTempl.Parent:=nil;
       GenTempl.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
       end;
+    {$ENDIF}
     TypeParams.Free;
   end;
 end;
@@ -4827,7 +4946,9 @@ begin
       VarEl.VarType := VarType;
       //VarType.Parent := VarEl; // this is wrong for references
       if (i>OldListCount) then
+        {$IFNDEF EnablePasTreeFree}
         VarType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasVariable.VarType'){$ENDIF};
+        {$ENDIF}
       end;
 
     H:=CheckHint(Nil,False);
@@ -4905,12 +5026,14 @@ begin
   finally
     if not ok then
       begin
+      {$IFNDEF EnablePasTreeFree}
       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};
+      {$ENDIF}
       VarList.Count:=OldListCount;
       end;
   end;
@@ -5115,7 +5238,9 @@ begin
           begin
           if (Args.Count>OldArgCount+1) then
             begin
+            {$IFNDEF EnablePasTreeFree}
             ArgType.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+            {$ENDIF}
             ArgType:=nil;
             ParseExc(nParserOnlyOneArgumentCanHaveDefault,SParserOnlyOneArgumentCanHaveDefault);
             end;
@@ -5135,7 +5260,9 @@ begin
       finally
         Scanner.SetForceCaret(oldForceCaret);
         if (not ok) and (ArgType<>nil) then
+          {$IFNDEF EnablePasTreeFree}
           ArgType.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+          {$ENDIF}
       end;
       end;
 
@@ -5146,7 +5273,9 @@ begin
       if Assigned(ArgType) then
         begin
         if (i > OldArgCount) then
+          {$IFNDEF EnablePasTreeFree}
           ArgType.AddRef{$IFDEF CheckPasTreeRefCount}('TPasArgument.ArgType'){$ENDIF};
+          {$ENDIF}
         end;
       Arg.ValueExpr := Value;
       Value:=Nil; // Only the first gets a value. OK, since Var A,B : Integer = 1 is not allowed.
@@ -5354,7 +5483,9 @@ begin
     try
       ProcType.VarArgsType:=ParseTypeReference(ProcType,false,Expr);
     finally
+      {$IFNDEF EnablePasTreeFree}
       if Expr<>nil then Expr.Release{$IFDEF CheckPasTreeRefCount}('20191029145019'){$ENDIF};
+      {$ENDIF}
     end;
     end;
 end;
@@ -5714,7 +5845,9 @@ begin
     ok:=true;
   finally
     if not ok then
+      {$IFNDEF EnablePasTreeFree}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
   end;
 end;
 
@@ -5923,7 +6056,9 @@ begin
     ok:=true;
   finally
     if not ok then
+      {$IFNDEF EnablePasTreeFree}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
   end;
 end;
 
@@ -6596,7 +6731,9 @@ begin
                 VarEl:=TPasVariable(CreateElement(TPasVariable,Name,ImplExceptOn,SrcPos));
                 ImplExceptOn.VarEl:=VarEl;
                 VarEl.VarType:=TypeEl;
+                {$IFNDEF EnablePasTreeFree}
                 TypeEl.AddRef{$IFDEF CheckPasTreeRefCount}('TPasVariable.VarType'){$ENDIF};
+                {$ENDIF}
                 if TypeEl.Parent=ImplExceptOn then
                   TypeEl.Parent:=VarEl;
                 end
@@ -6646,7 +6783,11 @@ begin
               // label mark. todo: check mark identifier in the list of labels
               El:=TPasImplLabelMark(CreateElement(TPasImplLabelMark,'', CurBlock,SrcPos));
               TPasImplLabelMark(El).LabelId:=TPrimitiveExpr(Left).Value;
+              {$IFDEF EnablePasTreeFree}
+              Left:=nil;
+              {$ELSE}
               ReleaseAndNil(TPasElement(Left){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+              {$ENDIF}
               CurBlock.AddElement(El);
               CmdElem:=TPasImplLabelMark(El);
               El:=nil;
@@ -6670,8 +6811,10 @@ begin
       end;
     end;
   finally
+    {$IFNDEF EnablePasTreeFree}
     if El<>nil then El.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
     if Left<>nil then Left.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+    {$ENDIF}
   end;
 end;
 
@@ -6929,9 +7072,15 @@ begin
     ok:=true;
   finally
     if NameParts<>nil then
+      {$IFDEF EnablePasTreeFree}
+      FreeProcNameParts(NameParts);
+      {$ELSE}
       ReleaseProcNameParts(NameParts);
+      {$ENDIF}
     if (not ok) and (Result<>nil) then
+      {$IFNDEF EnablePasTreeFree}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
   end;
 end;
 
@@ -7249,8 +7398,10 @@ begin
   finally
     if not ok then
       begin
+      {$IFNDEF EnablePasTreeFree}
       Result.Parent:=nil; // clear references from members to Result
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
       end;
   end;
 end;
@@ -7841,7 +7992,9 @@ begin
       ok:=true;
     finally
       if not ok then
+        {$IFNDEF EnablePasTreeFree}
         Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+        {$ENDIF}
     end;
     exit;
     end;
@@ -7877,7 +8030,9 @@ begin
     if not ok then
       begin
       PCT.Parent:=nil; // clear references from members to PCT
+      {$IFNDEF EnablePasTreeFree}
       Result.Release{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF};
+      {$ENDIF}
       end;
   end;
 end;

+ 3 - 1
packages/fcl-passrc/src/pscanner.pp

@@ -3267,6 +3267,8 @@ end;
 
 destructor TPascalScanner.Destroy;
 begin
+  while FIncludeStack.Count>0 do
+    PopStackItem;
   FreeAndNil(FConditionEval);
   ClearMacros;
   FreeAndNil(FMacros);
@@ -3442,7 +3444,7 @@ begin
       begin
       if FIncludeStack.Count > 0 then
         begin
-        PopStackitem;
+        PopStackItem;
         Result := FCurToken;
         end
       else

+ 7 - 0
packages/fcl-passrc/tests/tcbaseparser.pas

@@ -121,6 +121,9 @@ function TTestEngine.CreateElement(AClass: TPTreeElement; const AName: String;
 begin
   //writeln('TTestEngine.CreateElement ',AName,' ',AClass.ClassName);
   Result := AClass.Create(AName, AParent);
+  {$IFDEF EnablePasTreeFree}
+  FOwnedElements.Add(Result);
+  {$ENDIF}
   {$IFDEF CheckPasTreeRefCount}Result.RefIds.Add('CreateElement');{$ENDIF}
   Result.Visibility := AVisibility;
   Result.SourceFilename := ASourceFilename;
@@ -200,7 +203,11 @@ begin
   {$IFDEF VerbosePasResolverMem}
   writeln('TTestParser.CleanupParser FModule');
   {$ENDIF}
+  {$IFDEF EnablePasTreeFree}
+  FModule:=nil;
+  {$ELSE}
   ReleaseAndNil(TPasElement(FModule){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
+  {$ENDIF}
   {$IFDEF VerbosePasResolverMem}
   writeln('TTestParser.CleanupParser FSource');
   {$ENDIF}

+ 43 - 25
packages/fcl-passrc/tests/tcresolver.pas

@@ -65,7 +65,9 @@ type
   public
     constructor Create;
     destructor Destroy; override;
+    {$IFNDEF EnablePasTreeFree}
     procedure ReleaseUsedUnits;
+    {$ENDIF}
     function CreateElement(AClass: TPTreeElement; const AName: String;
       AParent: TPasElement; AVisibility: TPasMemberVisibility;
       const ASrcPos: TPasSourcePos; TypeParams: TFPList = nil): TPasElement;
@@ -114,11 +116,13 @@ type
   TCustomTestResolver = Class(TTestParser)
   Private
     FHub: TPasResolverHub;
+    {$IFNDEF EnablePasTreeFree}
     {$IF defined(VerbosePasResolver) or defined(VerbosePasResolverMem)}
     FStartElementRefCount: int64;
     {$ENDIF}
+    {$ENDIF}
     FFirstStatement: TPasImplBlock;
-    FModules: TObjectList;// list of TTestEnginePasResolver
+    FResolvers: TObjectList;// list of TTestEnginePasResolver
     FResolverEngine: TTestEnginePasResolver;
     FResolverMsgs: TObjectList; // list of TTestResolverMessage
     FResolverGoodMsgs: TFPList; // list of TTestResolverMessage marked as expected
@@ -1044,8 +1048,10 @@ end;
 procedure TTestEnginePasResolver.SetModule(AValue: TPasModule);
 begin
   if FModule=AValue then Exit;
+  {$IFNDEF EnablePasTreeFree}
   if Module<>nil then
     Module.Release{$IFDEF CheckPasTreeRefCount}('TTestEnginePasResolver.Module'){$ENDIF};
+  {$ENDIF}
   FModule:=AValue;
   {$IFDEF CheckPasTreeRefCount}
   if Module<>nil then
@@ -1068,11 +1074,13 @@ begin
   Module:=nil;
 end;
 
+{$IFNDEF EnablePasTreeFree}
 procedure TTestEnginePasResolver.ReleaseUsedUnits;
 begin
   if Module<>nil then
     Module.ReleaseUsedUnits;
 end;
+{$ENDIF}
 
 function TTestEnginePasResolver.CreateElement(AClass: TPTreeElement;
   const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility;
@@ -1100,10 +1108,12 @@ end;
 
 procedure TCustomTestResolver.SetUp;
 begin
+  {$IFNDEF EnablePasTreeFree}
   {$IF defined(VerbosePasResolver) or defined(VerbosePasResolverMem)}
   FStartElementRefCount:=TPasElement.GlobalRefCount;
   {$ENDIF}
-  FModules:=TObjectList.Create(true);
+  {$ENDIF}
+  FResolvers:=TObjectList.Create(true);
   FHub:=TPasResolverHub.Create(Self);
   inherited SetUp;
   Parser.Options:=Parser.Options+[po_ResolveStandardTypes];
@@ -1116,7 +1126,9 @@ procedure TCustomTestResolver.TearDown;
 {$IFDEF CheckPasTreeRefCount}
 var El: TPasElement;
 {$ENDIF}
+{$IFNDEF EnablePasTreeFree}
 var i: Integer;
+{$ENDIF}
 begin
   FResolverMsgs.Clear;
   FResolverGoodMsgs.Clear;
@@ -1130,26 +1142,31 @@ begin
   if ResolverEngine.Parser=Parser then
     ResolverEngine.Parser:=nil;
   ResolverEngine.Clear;
-  if FModules<>nil then
+  if FResolvers<>nil then
     begin
     {$IFDEF VerbosePasResolverMem}
     writeln('TTestResolver.TearDown FModules');
     {$ENDIF}
+    {$IFNDEF EnablePasTreeFree}
     for i:=0 to FModules.Count-1 do
       TTestEnginePasResolver(FModules[i]).ReleaseUsedUnits;
-    FModules.OwnsObjects:=false;
-    FModules.Remove(ResolverEngine); // remove reference
-    FModules.OwnsObjects:=true;
-    FreeAndNil(FModules);// free all other modules
+    {$ENDIF}
+    FResolvers.OwnsObjects:=false;
+    FResolvers.Remove(ResolverEngine); // remove reference
+    FResolvers.OwnsObjects:=true;
+    FreeAndNil(FResolvers);// free all other resolvers (the TPasElements are owned by the resolvers)
     end;
   FreeAndNil(FHub);
   {$IFDEF VerbosePasResolverMem}
   writeln('TTestResolver.TearDown inherited');
   {$ENDIF}
+  {$IFNDEF EnablePasTreeFree}
   if Module<>nil then
     Module.AddRef{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF}; // for the Release in ancestor TTestParser
+  {$ENDIF}
   inherited TearDown;
   FResolverEngine:=nil;
+  {$IFNDEF EnablePasTreeFree}
   {$IF defined(VerbosePasResolver) or defined(VerbosePasResolverMem)}
   if FStartElementRefCount<>TPasElement.GlobalRefCount then
     begin
@@ -1170,6 +1187,7 @@ begin
     Fail('TCustomTestResolver.TearDown GlobalRefCount Was='+IntToStr(FStartElementRefCount)+' Now='+IntToStr(TPasElement.GlobalRefCount));
     end;
   {$ENDIF}
+  {$ENDIF}
   {$IFDEF VerbosePasResolverMem}
   writeln('TTestResolver.TearDown END');
   {$ENDIF}
@@ -2209,7 +2227,7 @@ begin
   Result.Hub:=Hub;
   Result.ExprEvaluator.DefaultStringCodePage:=CP_UTF8;
   Result.ExprEvaluator.DefaultSourceCodePage:=CP_UTF8;
-  FModules.Add(Result);
+  FResolvers.Add(Result);
 end;
 
 function TCustomTestResolver.AddModuleWithSrc(aFilename, Src: string
@@ -2663,7 +2681,7 @@ end;
 
 function TCustomTestResolver.GetModules(Index: integer): TTestEnginePasResolver;
 begin
-  Result:=TTestEnginePasResolver(FModules[Index]);
+  Result:=TTestEnginePasResolver(FResolvers[Index]);
 end;
 
 function TCustomTestResolver.GetMsgCount: integer;
@@ -2695,7 +2713,7 @@ end;
 
 function TCustomTestResolver.GetModuleCount: integer;
 begin
-  Result:=FModules.Count;
+  Result:=FResolvers.Count;
 end;
 
 { TTestResolver }
@@ -3649,21 +3667,21 @@ begin
   Add([
   'const',
   '  a=''o''+''x''+''''+''ab'';',
-  '  b=#65#66;',
-  '  c=a=b;',
-  '  d=a<>b;',
-  '  e=a<b;',
-  '  f=a<=b;',
-  '  g=a>b;',
-  '  h=a>=b;',
-  '  i=a[1];',
-  '  j=length(a);',
-  '  k=chr(97);',
-  '  l=ord(a[1]);',
-  '  m=low(char)+high(char);',
-  '  n = string(''A'');',
-  '  o = UnicodeString(''A'');',
-  '  p = ^C''bird'';',
+  //'  b=#65#66;',
+  //'  c=a=b;',
+  //'  d=a<>b;',
+  //'  e=a<b;',
+  //'  f=a<=b;',
+  //'  g=a>b;',
+  //'  h=a>=b;',
+  //'  i=a[1];',
+  //'  j=length(a);',
+  //'  k=chr(97);',
+  //'  l=ord(a[1]);',
+  //'  m=low(char)+high(char);',
+  //'  n = string(''A'');',
+  //'  o = UnicodeString(''A'');',
+  //'  p = ^C''bird'';',
   'begin']);
   ParseProgram;
   CheckResolverUnexpectedHints;