Browse Source

pas2js: started aliasglobals external types

git-svn-id: trunk@45634 -
Mattias Gaertner 5 years ago
parent
commit
810ec836dd

+ 31 - 15
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

+ 101 - 46
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;
 

+ 93 - 7
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);