From 810ec836dd4e122f1844047feced78ae5819410d Mon Sep 17 00:00:00 2001 From: Mattias Gaertner Date: Wed, 10 Jun 2020 19:45:44 +0000 Subject: [PATCH] pas2js: started aliasglobals external types git-svn-id: trunk@45634 - --- packages/fcl-passrc/src/pasresolver.pp | 46 ++++--- packages/pastojs/src/fppas2js.pp | 147 ++++++++++++++------- packages/pastojs/tests/tcoptimizations.pas | 100 +++++++++++++- 3 files changed, 225 insertions(+), 68 deletions(-) diff --git a/packages/fcl-passrc/src/pasresolver.pp b/packages/fcl-passrc/src/pasresolver.pp index 19863f7356..c7a3b68119 100644 --- a/packages/fcl-passrc/src/pasresolver.pp +++ b/packages/fcl-passrc/src/pasresolver.pp @@ -1758,8 +1758,8 @@ type MaxCount: integer; RaiseOnError: boolean; Signature: string = ''): integer; function CheckRaiseTypeArgNo(id: TMaxPrecInt; ArgNo: integer; Param: TPasExpr; const ParamResolved: TPasResolverResult; Expected: string; RaiseOnError: boolean): integer; - function FindUsedUnitInSection(const aName: string; Section: TPasSection): TPasModule; - function FindUsedUnit(const aName: string; aMod: TPasModule): TPasModule; + function FindUsedUnitnameInSection(const aName: string; Section: TPasSection): TPasModule; + function FindUsedUnitname(const aName: string; aMod: TPasModule): TPasModule; procedure FinishAssertCall(Proc: TResElDataBuiltInProc; Params: TParamsExpr); virtual; function FindSystemClassType(const aUnitName, aClassName: string; @@ -2366,8 +2366,9 @@ type function GetCombinedBaseType(const A, B: TPasResolverResult; ErrorEl: TPasElement): TResolverBaseType; virtual; function IsElementSkipped(El: TPasElement): boolean; virtual; function FindLocalBuiltInSymbol(El: TPasElement): TPasElement; virtual; - function GetFirstSection: TPasSection; + function GetFirstSection(WithUnitImpl: boolean): TPasSection; function GetLastSection: TPasSection; + function FindUsedUnitInSection(aMod: TPasModule; Section: TPasSection): TPasUsesUnit; function GetShiftAndMaskForLoHiFunc(BaseType: TResolverBaseType; isLoFunc: Boolean; out Mask: LongWord): Integer; public @@ -14793,7 +14794,7 @@ begin Result:=cIncompatible; end; -function TPasResolver.FindUsedUnitInSection(const aName: string; Section: TPasSection): TPasModule; +function TPasResolver.FindUsedUnitnameInSection(const aName: string; Section: TPasSection): TPasModule; var Clause: TPasUsesClause; i: Integer; @@ -14813,20 +14814,20 @@ begin end; end; -function TPasResolver.FindUsedUnit(const aName: string; aMod: TPasModule): TPasModule; +function TPasResolver.FindUsedUnitname(const aName: string; aMod: TPasModule): TPasModule; var C: TClass; begin C:=aMod.ClassType; if C.InheritsFrom(TPasProgram) then - Result:=FindUsedUnitInSection(aName,TPasProgram(aMod).ProgramSection) + Result:=FindUsedUnitnameInSection(aName,TPasProgram(aMod).ProgramSection) else if C.InheritsFrom(TPasLibrary) then - Result:=FindUsedUnitInSection(aName,TPasLibrary(aMod).LibrarySection) + Result:=FindUsedUnitnameInSection(aName,TPasLibrary(aMod).LibrarySection) else begin - Result:=FindUsedUnitInSection(aName,aMod.InterfaceSection); + Result:=FindUsedUnitnameInSection(aName,aMod.InterfaceSection); if Result<>nil then exit; - Result:=FindUsedUnitInSection(aName,aMod.ImplementationSection); + Result:=FindUsedUnitnameInSection(aName,aMod.ImplementationSection); end end; @@ -14863,7 +14864,7 @@ begin // find unit in uses clauses aMod:=RootElement; - UtilsMod:=FindUsedUnit(aUnitName,aMod); + UtilsMod:=FindUsedUnitname(aUnitName,aMod); if UtilsMod=nil then if ErrorEl<>nil then RaiseIdentifierNotFound(20200523224738,'unit '+aUnitName,ErrorEl) @@ -15021,7 +15022,7 @@ begin if Result<>nil then exit; // find unit in uses clauses - UtilsMod:=FindUsedUnit('system',aMod); + UtilsMod:=FindUsedUnitname('system',aMod); if UtilsMod=nil then RaiseIdentifierNotFound(20190215101210,'System.TVarRec',ErrorEl); @@ -29154,7 +29155,7 @@ begin Result:=nil; end; -function TPasResolver.GetFirstSection: TPasSection; +function TPasResolver.GetFirstSection(WithUnitImpl: boolean): TPasSection; var Module: TPasModule; begin @@ -29165,10 +29166,12 @@ begin Result:=TPasProgram(Module).ProgramSection else if Module is TPasLibrary then Result:=TPasLibrary(Module).LibrarySection - else if Module.InterfaceSection<>nil then - Result:=Module.InterfaceSection else - Result:=Module.ImplementationSection; + begin + Result:=Module.InterfaceSection; + if WithUnitImpl and (Result=nil) then + Result:=Module.ImplementationSection; + end; end; function TPasResolver.GetLastSection: TPasSection; @@ -29188,6 +29191,19 @@ begin Result:=Module.InterfaceSection; end; +function TPasResolver.FindUsedUnitInSection(aMod: TPasModule; + Section: TPasSection): TPasUsesUnit; +var + Clause: TPasUsesClause; + i: Integer; +begin + Result:=nil; + if Section=nil then exit; + Clause:=Section.UsesClause; + for i:=0 to length(Clause)-1 do + if Clause[i].Module=aMod then exit(Clause[i]); +end; + function TPasResolver.GetShiftAndMaskForLoHiFunc(BaseType: TResolverBaseType; isLoFunc: Boolean; out Mask: LongWord): Integer; const diff --git a/packages/pastojs/src/fppas2js.pp b/packages/pastojs/src/fppas2js.pp index 206e8f895f..dc8efae2fc 100644 --- a/packages/pastojs/src/fppas2js.pp +++ b/packages/pastojs/src/fppas2js.pp @@ -1595,7 +1595,7 @@ type function GetRootContext: TConvertContext; function GetNonDotContext: TConvertContext; function GetFunctionContext: TFunctionContext; - function GetLocalName(El: TPasElement): string; virtual; + function GetLocalName(El: TPasElement; SkipSelf: boolean): string; virtual; function GetSelfContext: TFunctionContext; function GetContextOfPasElement(El: TPasElement): TConvertContext; function GetFuncContextOfPasElement(El: TPasElement): TFunctionContext; @@ -1655,7 +1655,7 @@ type procedure Add_InterfaceRelease(El: TPasElement); function CreateLocalIdentifier(const Prefix: string): string; function ToString: string; override; - function GetLocalName(El: TPasElement): string; override; + function GetLocalName(El: TPasElement; SkipSelf: boolean): string; override; function IndexOfLocalVar(const aName: string): integer; function IndexOfLocalVar(El: TPasElement): integer; function FindLocalVar(const aName: string; WithParents: boolean): TFCLocalIdentifier; @@ -1840,7 +1840,7 @@ type Function GetTypeInfoName(El: TPasType; AContext: TConvertContext; ErrorEl: TPasElement; Full: boolean = false): String; virtual; Function TransformArgName(Arg: TPasArgument; AContext: TConvertContext): string; virtual; - Function CreateGlobalAlias(El: TPasElement; RefPath: string; AContext: TConvertContext): string; virtual; + Function CreateGlobalAlias(El: TPasElement; JSPath: string; AContext: TConvertContext): string; virtual; // utility functions for creating stuff Function IsElementUsed(El: TPasElement): boolean; virtual; Function IsSystemUnit(aModule: TPasModule): boolean; virtual; @@ -1921,6 +1921,7 @@ type Kind: TRefPathKind; Full: boolean = false; Ref: TResolvedReference = nil): string; virtual; Function CreateReferencePathExpr(El: TPasElement; AContext : TConvertContext; Full: boolean = false; Ref: TResolvedReference = nil): TJSElement; virtual; + Function CreateGlobalTypePath(El: TPasType; AContext : TConvertContext): string; virtual; // section Function CreateImplementationSection(El: TPasModule; AContext: TConvertContext): TJSFunctionDeclarationStatement; virtual; Procedure CreateInitSection(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext); virtual; @@ -4551,7 +4552,7 @@ begin if Result<>nil then exit; // find unit in uses clauses - UtilsMod:=FindUsedUnit('system',aMod); + UtilsMod:=FindUsedUnitname('system',aMod); if UtilsMod=nil then RaiseIdentifierNotFound(20190215211531,'System.VarRecs',ErrorEl); @@ -6931,8 +6932,9 @@ begin Result:=Prefix; Ident:=FindLocalVar(Result,true); if Ident=nil then exit; - l:=1; + l:=0; repeat + inc(l); Result:=Prefix+IntToStr(l); until FindLocalVar(Result,true)=nil; end; @@ -6952,7 +6954,8 @@ begin end; end; -function TFunctionContext.GetLocalName(El: TPasElement): string; +function TFunctionContext.GetLocalName(El: TPasElement; SkipSelf: boolean + ): string; var V: TFCLocalIdentifier; begin @@ -6962,16 +6965,17 @@ begin begin Result:=V.Name; if Result=LocalVarHide then - Result:=''; + exit(''); + if SkipSelf and ((Result='this') or (Result='$Self')) then + // search further + else + exit; end - else if ThisPas=El then - Result:='this' - else - begin - Result:=inherited GetLocalName(El); - if Result='this' then - Result:=''; - end; + else if (ThisPas=El) and not SkipSelf then + exit('this'); + Result:=inherited GetLocalName(El,SkipSelf); + if Result='this' then + Result:=''; end; function TFunctionContext.IndexOfLocalVar(const aName: string): integer; @@ -7088,10 +7092,11 @@ begin Result:=TFunctionContext(GetContextOfType(TFunctionContext)); end; -function TConvertContext.GetLocalName(El: TPasElement): string; +function TConvertContext.GetLocalName(El: TPasElement; SkipSelf: boolean + ): string; begin if Parent<>nil then - Result:=Parent.GetLocalName(El) + Result:=Parent.GetLocalName(El,SkipSelf) else Result:=''; end; @@ -9050,7 +9055,7 @@ var begin if AContext.IsGlobal then begin - ParentName:=AContext.GetLocalName(El.Parent); + ParentName:=AContext.GetLocalName(El.Parent,false); if ParentName='' then ParentName:='this'; if JSName[1]='[' then @@ -9680,7 +9685,7 @@ function TPasToJSConverter.ConvertInheritedExpr(El: TInheritedExpr; SelfContext:=AContext.GetSelfContext; if SelfContext=nil then RaiseInconsistency(20170418114702,El); - SelfName:=SelfContext.GetLocalName(SelfContext.ThisPas); + SelfName:=SelfContext.GetLocalName(SelfContext.ThisPas,false); if Apply and (SelfContext<>AContext) then DoError(20170418204325,nNestedInheritedNeedsParameters,sNestedInheritedNeedsParameters, @@ -14423,9 +14428,9 @@ begin if (El.Parent=nil) or ((El.Parent is TPasSection) and (El.Parent.ClassType<>TImplementationSection)) then - OwnerName:=AContext.GetLocalName(El.GetModule) + OwnerName:=AContext.GetLocalName(El.GetModule,false) else - OwnerName:=AContext.GetLocalName(El.Parent); + OwnerName:=AContext.GetLocalName(El.Parent,false); if OwnerName='' then OwnerName:='this'; Call.AddArg(CreatePrimitiveDotExpr(OwnerName,El)); @@ -15598,6 +15603,7 @@ begin AssignSt:=nil; if AContext.IsGlobal then begin + // add 'this.FuncName = ...' AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,ImplProc)); Result:=AssignSt; AssignSt.LHS:=CreateSubDeclNameExpr(El,AContext,ImplProc); @@ -17343,6 +17349,7 @@ begin or (VarType.ClassType=TPasFunctionType) or (VarType.ClassType=TPasArrayType) then begin + // add 'this.FieldName = undefined;' AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El)); NewEl:=AssignSt; AssignSt.LHS:=CreateSubDeclNameExpr(P,New_FuncContext); @@ -17595,7 +17602,7 @@ begin if SelfScope=nil then RaiseNotSupported(PosEl,AContext,20190205230919); if SelfScope.SelfArg<>nil then - TargetName:=AContext.GetLocalName(SelfScope.SelfArg) + TargetName:=AContext.GetLocalName(SelfScope.SelfArg,false) else if SelfScope.ClassRecScope<>nil then begin TargetName:=CreateReferencePath(SelfScope.ClassRecScope.Element, @@ -19497,7 +19504,7 @@ var Result:=CreatePrimitiveDotExpr(WithExprScope.WithVarName,Expr) else if SelfScope<>nil then begin - Path:=AContext.GetLocalName(SelfScope.SelfArg); + Path:=AContext.GetLocalName(SelfScope.SelfArg,false); Result:=CreatePrimitiveDotExpr(Path,Expr); end else if Left=nil then @@ -22901,17 +22908,16 @@ var end; function PrependClassOrRecName(var Path: string; ClassOrRec: TPasMembersType): boolean; + // returns true if no parent path needed begin if (ClassOrRec.ClassType=TPasClassType) and TPasClassType(ClassOrRec).IsExternal then begin Prepend(Path,TPasClassType(ClassOrRec).ExternalName); - Result:=true; - end - else - begin - Prepend(Path,ClassOrRec.Name); - Result:=false; + exit(true); end; + Prepend(Path,CreateGlobalTypePath(ClassOrRec,AContext)); + //Prepend(Path,ClassOrRec.Name); + Result:=true; end; function NeedsWithExpr: boolean; @@ -23128,15 +23134,14 @@ begin RaiseNotSupported(El,AContext,20170201172141,GetObjName(El)); El:=ImplToDecl(El); - {if Kind=rpkPathAndName then + if Kind=rpkPathAndName then begin - ShortName:=AContext.GetLocalName(El); - if ShortName<>'' then + if El is TPasType then begin - Result:=ShortName; + Result:=CreateGlobalTypePath(TPasType(El),AContext); exit; end; - end;} + end; CurEl:=El; ParentEl:=CurEl.Parent; @@ -23148,7 +23153,7 @@ begin or (ParentEl.ClassType=TPasRecordType); // check if ParentEl has a JS var - ShortName:=AContext.GetLocalName(ParentEl); + ShortName:=AContext.GetLocalName(ParentEl,false); //writeln('TPasToJSConverter.CreateReferencePath El=',GetObjName(El),' ParentEl=',GetObjName(ParentEl),' ShortName=',ShortName); if IsClassRec then @@ -23165,7 +23170,7 @@ begin or (ParentEl.ClassType=TPasRecordType); if not IsClassRec then RaiseNotSupported(El,AContext,20190926091356); - ShortName:=AContext.GetLocalName(ParentEl); + ShortName:=AContext.GetLocalName(ParentEl,false); end; if Full then @@ -23197,7 +23202,7 @@ begin else if (SelfContext<>nil) and IsA(TPasType(SelfContext.ThisPas),TPasMembersType(ParentEl)) then begin - ShortName:=AContext.GetLocalName(SelfContext.ThisPas); + ShortName:=AContext.GetLocalName(SelfContext.ThisPas,false); if ShortName='' then begin if PrependClassOrRecName(Result,TPasMembersType(ParentEl)) then break; @@ -23304,6 +23309,47 @@ begin Result:=CreatePrimitiveDotExpr(Name,Src); end; +function TPasToJSConverter.CreateGlobalTypePath(El: TPasType; + AContext: TConvertContext): string; +var + aType: TPasType; + Parent: TPasElement; + CurModule: TPasModule; + AliasGlobals: Boolean; +begin + aType:=AContext.Resolver.ResolveAliasType(El); + Result:=AContext.GetLocalName(aType,true); + AliasGlobals:=coAliasGlobals in Options; + if Result<>'' then + exit; // already exists + + Parent:=El.Parent; + Result:=AContext.GetLocalName(Parent,AliasGlobals); + if Result<>'' then + else if Parent is TPasType then + Result:=CreateGlobalTypePath(TPasType(Parent),AContext) + else if Parent is TPasSection then + begin + // element is in foreign unit -> use pas.unitname + CurModule:=Parent.GetModule; + Result:=TransformModuleName(CurModule,true,AContext); + if (CurModule<>AContext.GetRootContext.PasElement.GetModule) + and (Parent is TImplementationSection) then + begin + // element is in foreign implementation section (not program/library section) + // -> use pas.unitname.$impl + Result:=Result+'.'+GetBIName(pbivnImplementation); + end; + end + else if Parent is TPasModule then + Result:=TransformModuleName(TPasModule(Parent),true,AContext) + else + RaiseNotSupported(El,AContext,20200609230526,GetObjName(aType)); + Result:=Result+'.'+TransformVariableName(aType,AContext); + if AliasGlobals then + Result:=CreateGlobalAlias(El,Result,AContext); +end; + procedure TPasToJSConverter.CreateProcedureCall(var Call: TJSCallExpression; Args: TParamsExpr; TargetProc: TPasProcedureType; AContext: TConvertContext); // create a call, adding call by reference and default values @@ -24446,9 +24492,9 @@ begin if (El.Parent=nil) or ((El.Parent is TPasSection) and (El.Parent.ClassType<>TImplementationSection)) then - JSParentName:=AContext.GetLocalName(El.GetModule) + JSParentName:=AContext.GetLocalName(El.GetModule,false) else - JSParentName:=AContext.GetLocalName(El.Parent); + JSParentName:=AContext.GetLocalName(El.Parent,false); if JSParentName='' then JSParentName:='this'; Call.AddArg(CreatePrimitiveDotExpr(JSParentName,El)); @@ -24733,7 +24779,7 @@ var begin if AddModulesPrefix then begin - Result:=AContext.GetLocalName(El); + Result:=AContext.GetLocalName(El,false); if Result<>'' then exit; end; if El is TPasProgram then @@ -24761,7 +24807,7 @@ begin else Result:=GetBIName(pbivnModules)+'.'+Result; - if coAliasGlobals in Options then + if (coAliasGlobals in Options) and (Result<>'this') then Result:=CreateGlobalAlias(El,Result,AContext); end; end; @@ -25000,7 +25046,7 @@ begin if (CompareText(Result,'Self')=0) and (Arg.Parent is TPasProcedure) then begin // hidden self argument - Result:=AContext.GetLocalName(Arg); + Result:=AContext.GetLocalName(Arg,false); if Result='' then RaiseNotSupported(Arg,AContext,20190205190114,GetObjName(Arg.Parent)); end @@ -25008,7 +25054,7 @@ begin Result:=TransformVariableName(Arg,Result,true,AContext); end; -function TPasToJSConverter.CreateGlobalAlias(El: TPasElement; RefPath: string; +function TPasToJSConverter.CreateGlobalAlias(El: TPasElement; JSPath: string; AContext: TConvertContext): string; var ElModule, MyModule: TPasModule; @@ -25018,7 +25064,7 @@ var Expr: TJSElement; V: TJSVariableStatement; begin - Result:=RefPath; + Result:=JSPath; if El is TPasUnresolvedSymbolRef then exit; // built-in element @@ -25034,17 +25080,26 @@ begin begin // El is from another unit SectionContext:=TSectionContext(AContext.GetContextOfType(TSectionContext)); + if SectionContext.PasElement is TInterfaceSection then + begin + // check if from impl uses clause + + end; + FuncContext:=AContext.GetFunctionContext; if El is TPasModule then Result:=GetBIName(pbivnLocalModuleRef) + else if El is TPasType then + Result:=GetBIName(pbivnLocalTypeRef) else RaiseNotSupported(El,AContext,20200608160225); Result:=FuncContext.CreateLocalIdentifier(Result); SectionContext.AddLocalVar(Result,El,false); - // insert var $lmr = pas.modulename; - Expr:=CreatePrimitiveDotExpr(RefPath,El); + // insert var $lmr = JSPath; + Expr:=CreatePrimitiveDotExpr(JSPath,El); V:=CreateVarStatement(Result,Expr,El); AddHeaderStatement(V,El,AContext); + // ToDo: check if from impl uses section and separate "var $lmr = null;" and "$lmr = JSPath"; end; end; diff --git a/packages/pastojs/tests/tcoptimizations.pas b/packages/pastojs/tests/tcoptimizations.pas index f6d384b857..1c031dfc1d 100644 --- a/packages/pastojs/tests/tcoptimizations.pas +++ b/packages/pastojs/tests/tcoptimizations.pas @@ -57,14 +57,15 @@ type TTestOptimizations = class(TCustomTestOptimizations) published // unit optimization: aliasglobals - procedure TestOptAliasGlobals_Program; // ToDo - // ToDo: procedure TestOptAliasGlobals_Unit; + procedure TestOptAliasGlobals_Program; + procedure TestOptAliasGlobals_Unit; // ToDo // ToDo: RTTI // ToDo: typeinfo(var), typeinfo(type) // ToDo: resourcestring // ToDo: Global EnumType, EnumValue, EnumType.Value, unit.EnumType.Value // ToDo: Nested EnumType: EnumValue, EnumType.Value, unit.aType.EnumType.Value, aType.EnumType.Value, Instance.EnumType.Value // ToDo: Instance.RecordType, Instance.RecordType.ClassVar + // ToDo: ClassVarRecord // Whole Program Optimization procedure TestWPO_OmitLocalVar; @@ -199,7 +200,6 @@ end; procedure TTestOptimizations.TestOptAliasGlobals_Program; begin - StartProgram(true,[supTObject]); AddModuleWithIntfImplSrc('UnitA.pas', LinesToStr([ 'const', @@ -217,6 +217,8 @@ begin '']), LinesToStr([ ''])); + + StartProgram(true,[supTObject]); Add([ '{$optimization AliasGlobals}', 'uses unita;', @@ -233,6 +235,7 @@ begin 'begin', ' e:=TEagle.Create;', ' b:=TBird.Create;', + ' e.c:=e.c+1;', ' r.x:=TBird.c;', ' r.x:=b.c;', ' r.x:=e.Run;', @@ -243,19 +246,22 @@ begin CheckSource('TestOptAliasGlobals_Program', LinesToStr([ 'var $lmr = pas.UnitA;', - 'rtl.createClass($mod, "TEagle", $lmr.TBird, function () {', + 'var $ltr = $lmr.TBird;', + 'var $ltr1 = $lmr.TRec;', + 'rtl.createClass($mod, "TEagle", $ltr, function () {', ' this.Run = function (w) {', ' var Result = 0;', ' return Result;', ' };', '});', 'this.e = null;', - 'this.r = $lmr.TRec.$new();', + 'this.r = $ltr1.$new();', '']), LinesToStr([ '$mod.e = $mod.TEagle.$create("Create");', - '$lmr.b = $lmr.TBird.$create("Create");', - '$mod.r.x = $lmr.TBird.c;', + '$lmr.b = $ltr.$create("Create");', + '$ltr.c = $mod.e.c + 1;', + '$mod.r.x = $ltr.c;', '$mod.r.x = $lmr.b.c;', '$mod.r.x = $mod.e.$class.Run(5);', '$mod.r.x = $mod.e.$class.Run(5);', @@ -263,6 +269,86 @@ begin ''])); end; +procedure TTestOptimizations.TestOptAliasGlobals_Unit; +begin + exit; + + AddModuleWithIntfImplSrc('UnitA.pas', + LinesToStr([ + 'const', + ' cWidth = 17;', + 'type', + ' TBird = class', + ' public', + ' class var Span: word;', + ' class procedure Fly(w: word); virtual; abstract;', + ' end;', + ' TRecA = record', + ' x: word;', + ' end;', + 'var Bird: TBird;', + '']), + LinesToStr([ + ''])); + AddModuleWithIntfImplSrc('UnitB.pas', + LinesToStr([ + 'const', + ' cHeight = 23;', + 'type', + ' TAnt = class', + ' public', + ' class var Legs: word;', + ' class procedure Run(w: word); virtual; abstract;', + ' end;', + ' TRecB = record', + ' y: word;', + ' end;', + 'var Ant: TAnt;', + '']), + LinesToStr([ + ''])); + StartUnit(true,[supTObject]); + Add([ + '{$optimization AliasGlobals}', + 'interface', + 'uses unita;', + 'type', + ' TEagle = class(TBird)', + ' class var EagleRec: TRecA;', + ' class procedure Fly(w: word = 5); override;', + ' end;', + 'implementation', + 'uses unitb;', + 'type', + ' TRedAnt = class(TAnt)', + ' class var RedAntRecA: TRecA;', + ' class var RedAntRecB: TRecB;', + ' class procedure Run(w: word = 6); override;', + ' end;', + 'class procedure TEagle.Fly(w: word);', + 'begin', + 'end;', + 'class procedure TRedAnt.Run(w: word);', + 'begin', + 'end;', + 'var', + ' Eagle: TEagle;', + ' RedAnt: TRedAnt;', + 'initialization', + ' Eagle:=TEagle.Create;', + ' RedAnt:=TRedAnt.Create;', + ' Bird:=TBird.Create;', + ' Ant:=TAnt.Create;', + ' TRedAnt.RedAntRecA.x:=TRedAnt.RedAntRecB.y;', + '']); + ConvertUnit; + CheckSource('TestOptAliasGlobals_Unit', + LinesToStr([ + '']), + LinesToStr([ + ''])); +end; + procedure TTestOptimizations.TestWPO_OmitLocalVar; begin StartProgram(false);