pas2js: started aliasglobals external types

git-svn-id: trunk@45634 -
This commit is contained in:
Mattias Gaertner 2020-06-10 19:45:44 +00:00
parent 6698f6c56b
commit 810ec836dd
3 changed files with 225 additions and 68 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);