Browse Source

pastojs: ShortRefGlobals: same module class, record and enumtype

git-svn-id: trunk@46964 -
Mattias Gaertner 4 years ago
parent
commit
4d4cdfb804

+ 26 - 0
packages/fcl-passrc/src/pasresolver.pp

@@ -2308,6 +2308,7 @@ type
     function GetPasPropertyStoredExpr(El: TPasProperty): TPasExpr;
     function GetPasPropertyDefaultExpr(El: TPasProperty): TPasExpr;
     function GetPasClassAncestor(ClassEl: TPasClassType; SkipAlias: boolean): TPasType;
+    function GetPasClassForward(ClassEl: TPasClassType): TPasClassType;
     function GetParentProcBody(El: TPasElement): TProcedureBody;
     function ProcHasImplElements(Proc: TPasProcedure): boolean; virtual;
     function IndexOfImplementedInterface(ClassEl: TPasClassType; aType: TPasType): integer;
@@ -28009,6 +28010,31 @@ begin
     end;
 end;
 
+function TPasResolver.GetPasClassForward(ClassEl: TPasClassType): TPasClassType;
+var
+  Parent: TPasElement;
+  i: Integer;
+  CurClass: TPasClassType;
+  Ref: TResolvedReference;
+  Decls: TFPList;
+begin
+  Result:=nil;
+  if ClassEl=nil then exit;
+  Parent:=ClassEl.Parent;
+  if not (Parent is TPasDeclarations) then
+    RaiseNotYetImplemented(20200926214106,ClassEl);
+  Decls:=TPasDeclarations(Parent).Classes;
+  for i:=0 to Decls.Count-1 do
+    begin
+    CurClass:=TPasClassType(Decls[i]);
+    if CurClass=ClassEl then exit;
+    if not CurClass.IsForward then continue;
+    Ref:=TResolvedReference(CurClass.CustomData);
+    if Ref.Declaration=ClassEl then
+      exit(TPasClassType(Ref.Declaration));
+    end;
+end;
+
 function TPasResolver.GetParentProcBody(El: TPasElement): TProcedureBody;
 begin
   while El<>nil do

+ 109 - 40
packages/pastojs/src/fppas2js.pp

@@ -1673,6 +1673,7 @@ type
     function GetContextOfPasElement(El: TPasElement): TConvertContext;
     function GetFuncContextOfPasElement(El: TPasElement): TFunctionContext;
     function GetContextOfType(aType: TConvertContextClass): TConvertContext;
+    function GetMainSectionContext: TFunctionContext;
     function CurrentModeSwitches: TModeSwitches;
     function GetGlobalFunc: TFunctionContext;
     procedure WriteStack;
@@ -1922,7 +1923,9 @@ 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; JSPath: string; AContext: TConvertContext): string; virtual;
+    Function CreateGlobalAliasForeign(El: TPasElement; JSPath: string; AContext: TConvertContext): string; virtual; // El in other module
+    Function CreateGlobalAliasNull(El: TPasElement; Prefix: TPas2JSBuiltInName;
+      SectionContext: TSectionContext): TFCLocalIdentifier; virtual;
     // utility functions for creating stuff
     Function IsElementUsed(El: TPasElement): boolean; virtual;
     Function IsSystemUnit(aModule: TPasModule): boolean; virtual;
@@ -7541,6 +7544,18 @@ begin
   until ctx=nil;
 end;
 
+function TConvertContext.GetMainSectionContext: TFunctionContext;
+var
+  Ctx: TConvertContext;
+begin
+  Ctx:=Self;
+  repeat
+    if Ctx is TSectionContext then
+      Result:=TSectionContext(Ctx);
+    Ctx:=Ctx.Parent;
+  until Ctx=nil;
+end;
+
 function TConvertContext.CurrentModeSwitches: TModeSwitches;
 begin
   if Resolver=nil then
@@ -14650,6 +14665,29 @@ Var
       end;
   end;
 
+  procedure InitForwards(Decls: TFPList; SectionContext: TSectionContext);
+  var
+    i: Integer;
+    P: TPasElement;
+    C: TClass;
+  begin
+    For i:=0 to Decls.Count-1 do
+      begin
+      P:=TPasElement(Decls[i]);
+      if not IsElementUsed(P) then continue;
+      C:=P.ClassType;
+      if (C=TPasClassType) and TPasClassType(P).IsForward then
+        continue;
+      if (C=TPasClassType) or (C=TPasRecordType) or (C=TPasEnumType) then
+        begin
+        // add var $lt = null;
+        CreateGlobalAliasNull(P,pbivnLocalTypeRef,SectionContext);
+        if (C=TPasClassType) or (C=TPasRecordType) then
+          InitForwards(TPasMembersType(P).Members,SectionContext);
+        end;
+      end;
+  end;
+
   procedure InitSection(Section: TPasSection);
   var
     SectionScope: TPas2JSSectionScope;
@@ -14665,6 +14703,18 @@ Var
     SectionCtx:=TSectionContext(AContext);
     Src:=SectionCtx.JSElement as TJSSourceElements;
     SectionCtx.HeaderIndex:=Src.Statements.Count;
+
+    // add local vars for forward declarations
+    if (coShortRefGlobals in Options)
+        and (Section.ClassType<>TImplementationSection) then
+      begin
+      InitForwards(Section.Declarations,TSectionContext(AContext));
+      if Section is TInterfaceSection then
+        begin
+        InitForwards(TPasModule(Section.Parent).ImplementationSection.Declarations,
+                     TSectionContext(AContext));
+        end;
+      end;
   end;
 
 var
@@ -14846,7 +14896,7 @@ var
   P: TPasElement;
   Scope: TPas2JSClassScope;
   Ancestor: TPasType;
-  AncestorPath, OwnerName, DestructorName, FnName, IntfKind: String;
+  AncestorPath, OwnerName, DestructorName, FnName, IntfKind, JSName: String;
   C: TClass;
   AssignSt: TJSSimpleAssignStatement;
   NeedInitFunction, HasConstructor, IsJSFunction, NeedClassExt,
@@ -14926,7 +14976,8 @@ begin
     Call.AddArg(CreatePrimitiveDotExpr(OwnerName,El));
 
     // add parameter: string constant '"classname"'
-    ArgEx := CreateLiteralString(El,TransformElToJSName(El,AContext));
+    JSName:=TransformElToJSName(El,AContext);
+    ArgEx:=CreateLiteralString(El,JSName);
     Call.AddArg(ArgEx);
 
     if El.ObjKind=okInterface then
@@ -14985,6 +15036,18 @@ begin
       FuncContext.ThisVar.Element:=El;
       FuncContext.ThisVar.Kind:=cvkGlobal;
 
+      if coShortRefGlobals in Options then
+        begin
+        // $lt = this;
+        JSName:=AContext.GetLocalName(El,[cvkGlobal]);
+        if JSName='' then
+          RaiseNotSupported(El,AContext,20200926232402);
+        AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
+        AssignSt.LHS:=CreatePrimitiveDotExpr(JSName,El);
+        AssignSt.Expr:=CreatePrimitiveDotExpr('this',El);
+        AddToSourceElements(Src,AssignSt);
+        end;
+
       if IntfKind<>'' then
         begin
         // add this.$kind="com";
@@ -15279,7 +15342,7 @@ function TPasToJSConverter.ConvertEnumType(El: TPasEnumType;
 //     maxvalue: 1
 //   });
 //  coShortRefGlobals:
-//  var $lt = this.TMyEnum ...
+//  $lt = this.TMyEnum ...
 var
   ObjectContect: TObjectContext;
   i: Integer;
@@ -15295,7 +15358,7 @@ var
   Src: TJSSourceElements;
   ProcScope: TPas2JSProcedureScope;
   VarSt: TJSVariableStatement;
-  GlobalCtx: TConvertContext;
+  SectionContext: TSectionContext;
 begin
   Result:=nil;
   for i:=0 to El.Values.Count-1 do
@@ -15344,32 +15407,17 @@ begin
       AssignSt.LHS:=CreateSubDeclNameExpr(El,AContext);
       AssignSt.Expr:=Obj;
       Result:=AssignSt;
-      if (coShortRefGlobals in Options) and (AContext is TFunctionContext) then
+      if coShortRefGlobals in Options then
         begin
-        GlobalCtx:=AContext;
-        while (GlobalCtx.PasElement is TPasMembersType) do
-          GlobalCtx:=GlobalCtx.Parent;
-        if (GlobalCtx<>AContext) and (GlobalCtx is TFunctionContext) then
-          begin
-          // add to GlobalCtx:      var $lt = {}
-          // add to local context:  this.TypeName = $lt
-          if not (GlobalCtx.JSElement is TJSSourceElements) then
-            RaiseNotSupported(El,AContext,20200926181516,GetObjName(GlobalCtx.JSElement));
-          Src:=TJSSourceElements(GlobalCtx.JSElement);
-          JSName:=TFunctionContext(AContext).CreateLocalIdentifier(GetBIName(pbivnLocalTypeRef));
-          AssignSt.Expr:=CreatePrimitiveDotExpr(JSName,El);
-
-          VarSt:=CreateVarStatement(JSName,Obj,El);
-          AddToSourceElements(Src,VarSt);
-          TFunctionContext(GlobalCtx).AddLocalVar(JSName,El,cvkGlobal,false);
-          end
-        else
-          begin
-          // var $lt = this.TypeName = {}
-          JSName:=TFunctionContext(AContext).CreateLocalIdentifier(GetBIName(pbivnLocalTypeRef));
-          TFunctionContext(AContext).AddLocalVar(JSName,El,cvkGlobal,false);
-          Result:=CreateVarStatement(JSName,AssignSt,El);
-          end;
+        SectionContext:=TSectionContext(AContext.GetMainSectionContext);
+        JSName:=SectionContext.GetLocalName(El,[cvkGlobal]);
+        if JSName='' then
+          RaiseNotSupported(El,AContext,20200926232620);
+        // $lt = this.TypeName = {}
+        AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
+        AssignSt.LHS:=CreatePrimitiveDotExpr(JSName,El);
+        AssignSt.Expr:=Result;
+        Result:=AssignSt;
         end;
       end;
 
@@ -16963,11 +17011,9 @@ var
   SectionCtx: TSectionContext;
 begin
   if JS=nil then exit;
-  SectionCtx:=TSectionContext(aContext.GetContextOfType(TSectionContext));
+  SectionCtx:=TSectionContext(aContext.GetMainSectionContext);
   if SectionCtx=nil then
     RaiseNotSupported(PosEl,aContext,20200606142555);
-  if SectionCtx.Parent is TSectionContext then
-    SectionCtx:=TSectionContext(SectionCtx.Parent);
   SectionCtx.AddHeaderStatement(JS);
 end;
 
@@ -24220,7 +24266,7 @@ begin
     RaiseNotSupported(El,AContext,20200609230526,GetObjPath(El));
   Result:=Result+'.'+TransformElToJSName(El,AContext);
   if ShortRefGlobals then
-    Result:=CreateGlobalAlias(El,Result,AContext);
+    Result:=CreateGlobalAliasForeign(El,Result,AContext);
 end;
 
 procedure TPasToJSConverter.CreateProcedureCall(var Call: TJSCallExpression;
@@ -25332,7 +25378,7 @@ var
   DelaySrc: TJSSourceElements;
   DelayFuncContext: TFunctionContext;
   Call: TJSCallExpression;
-  JSParentName: String;
+  JSParentName, JSName: String;
   FunDecl: TJSFunctionDeclarationStatement;
   Src: TJSSourceElements;
   FuncContext: TFunctionContext;
@@ -25345,6 +25391,7 @@ var
   NewFields, Vars, Methods: TFPList;
   ok, IsComplex, SpecializeDelay: Boolean;
   VarSt: TJSVariableStatement;
+  AssignSt: TJSSimpleAssignStatement;
 begin
   Result:=nil;
   if El.Name='' then
@@ -25413,6 +25460,18 @@ begin
     FuncContext.ThisVar.Element:=El;
     FuncContext.ThisVar.Kind:=cvkGlobal;
 
+    if coShortRefGlobals in Options then
+      begin
+      // $lt = this;
+      JSName:=AContext.GetLocalName(El,[cvkGlobal]);
+      if JSName='' then
+        RaiseNotSupported(El,AContext,20200926235501);
+      AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
+      AssignSt.LHS:=CreatePrimitiveDotExpr(JSName,El);
+      AssignSt.Expr:=CreatePrimitiveDotExpr('this',El);
+      AddToSourceElements(Src,AssignSt);
+      end;
+
     // init fields
     NewFields:=TFPList.Create;
     Vars:=TFPList.Create;
@@ -25725,7 +25784,7 @@ begin
       Result:=GetBIName(pbivnModules)+'.'+Result;
 
     if coShortRefGlobals in Options then
-      Result:=CreateGlobalAlias(El,Result,AContext);
+      Result:=CreateGlobalAliasForeign(El,Result,AContext);
     end;
 end;
 
@@ -25972,7 +26031,7 @@ begin
     Result:=TransformToJSName(Arg,Result,true,AContext);
 end;
 
-function TPasToJSConverter.CreateGlobalAlias(El: TPasElement; JSPath: string;
+function TPasToJSConverter.CreateGlobalAliasForeign(El: TPasElement; JSPath: string;
   AContext: TConvertContext): string;
 var
   ElModule, MyModule: TPasModule;
@@ -25998,9 +26057,7 @@ begin
   else
     begin
     // El is from another unit
-    SectionContext:=TSectionContext(AContext.GetContextOfType(TSectionContext));
-    if SectionContext.Parent is TSectionContext then
-      SectionContext:=TSectionContext(SectionContext.Parent);
+    SectionContext:=TSectionContext(AContext.GetMainSectionContext);
 
     FuncContext:=AContext.GetFunctionContext;
     if El is TPasModule then
@@ -26036,6 +26093,18 @@ begin
     end;
 end;
 
+function TPasToJSConverter.CreateGlobalAliasNull(El: TPasElement;
+  Prefix: TPas2JSBuiltInName; SectionContext: TSectionContext
+  ): TFCLocalIdentifier;
+var
+  V: TJSVariableStatement;
+begin
+  // insert var $lt = null;
+  Result:=SectionContext.AddLocalVar(GetBIName(Prefix),El,cvkGlobal,true);
+  V:=CreateVarStatement(Result.Name,CreateLiteralNull(El),El);
+  AddHeaderStatement(V,El,SectionContext);
+end;
+
 function TPasToJSConverter.ConvertPasElement(El: TPasElement;
   Resolver: TPas2JSResolver): TJSElement;
 var

+ 153 - 51
packages/pastojs/tests/tcoptimizations.pas

@@ -62,6 +62,7 @@ type
     procedure TestOptShortRefGlobals_Property;
     procedure TestOptShortRefGlobals_GenericFunction;
     procedure TestOptShortRefGlobals_SameUnit_EnumType;
+    procedure TestOptShortRefGlobals_SameUnit_ClassType;
 
     // Whole Program Optimization
     procedure TestWPO_OmitLocalVar;
@@ -246,24 +247,26 @@ begin
   ConvertProgram;
   CheckSource('TestOptShortRefGlobals_Program',
     LinesToStr([
+    'var $lt = null;',
     'var $lm = pas.UnitA;',
-    'var $lt = $lm.TBird;',
-    'var $lt1 = $lm.TRec;',
-    'rtl.createClass(this, "TEagle", $lt, function () {',
+    'var $lt1 = $lm.TBird;',
+    'var $lt2 = $lm.TRec;',
+    'rtl.createClass(this, "TEagle", $lt1, function () {',
+    '  $lt = this;',
     '  this.Run = function (w) {',
     '    var Result = 0;',
     '    return Result;',
     '  };',
     '});',
     'this.e = null;',
-    'this.r = $lt1.$new();',
+    'this.r = $lt2.$new();',
     'this.c = {};',
     '']),
     LinesToStr([
-    '$mod.e = $mod.TEagle.$create("Create");',
-    '$lm.b = $lt.$create("Create");',
-    '$lt.c = $mod.e.c + 1;',
-    '$mod.r.x = $lt.c;',
+    '$mod.e = $lt.$create("Create");',
+    '$lm.b = $lt1.$create("Create");',
+    '$lt1.c = $mod.e.c + 1;',
+    '$mod.r.x = $lt1.c;',
     '$mod.r.x = $lm.b.c;',
     '$mod.r.x = $mod.e.$class.Run(5);',
     '$mod.r.x = $mod.e.$class.Run(5);',
@@ -352,42 +355,46 @@ begin
   CheckSource('TestOptShortRefGlobals_Unit_FromIntfImpl_ToIntfImpl',
     LinesToStr([
     'var $impl = $mod.$impl;',
+    'var $lt = null;',
+    'var $lt1 = null;',
     'var $lm = pas.UnitA;',
-    'var $lt = $lm.TBird;',
+    'var $lt2 = $lm.TBird;',
     'var $lm1 = null;',
-    'var $lt1 = null;',
-    'var $lt2 = null;',
     'var $lt3 = null;',
-    'rtl.createClass(this, "TEagle", $lt, function () {',
+    'var $lt4 = null;',
+    'var $lt5 = null;',
+    'rtl.createClass(this, "TEagle", $lt2, function () {',
+    '  $lt = this;',
     '  this.Fly = function () {',
-    '    $impl.TRedAnt.$create("Create");',
     '    $lt1.$create("Create");',
+    '    $lt3.$create("Create");',
+    '    $lt2.$create("Create");',
     '    $lt.$create("Create");',
-    '    $mod.TEagle.$create("Create");',
     '  };',
     '});',
     '']),
     LinesToStr([
-    '$impl.RedAnt = $impl.TRedAnt.$create("Create");',
-    '$impl.Ant = $lt1.$create("Create");',
-    '$impl.Bird = $lt.$create("Create");',
-    '$impl.Eagle = $mod.TEagle.$create("Create");',
-    '$lt3.$create("Create");',
+    '$impl.RedAnt = $lt1.$create("Create");',
+    '$impl.Ant = $lt3.$create("Create");',
+    '$impl.Bird = $lt2.$create("Create");',
+    '$impl.Eagle = $lt.$create("Create");',
+    '$lt5.$create("Create");',
     '$impl.Eagle.Fly();',
     '$impl.RedAnt.Run();',
     '']),
     LinesToStr([
     '$lm1 = pas.UnitB;',
-    '$lt1 = $lm1.TAnt;',
-    '$lt2 = $lm1.TBear;',
-    '$lt3 = $lm1.TFrog;',
-    'rtl.createClass($impl, "TRedAnt", $lt1, function () {',
+    '$lt3 = $lm1.TAnt;',
+    '$lt4 = $lm1.TBear;',
+    '$lt5 = $lm1.TFrog;',
+    'rtl.createClass($impl, "TRedAnt", $lt3, function () {',
+    '  $lt1 = this;',
     '  this.Run = function () {',
-    '    $impl.TRedAnt.$create("Create");',
     '    $lt1.$create("Create");',
-    '    $lt.$create("Create");',
-    '    $mod.TEagle.$create("Create");',
+    '    $lt3.$create("Create");',
     '    $lt2.$create("Create");',
+    '    $lt.$create("Create");',
+    '    $lt4.$create("Create");',
     '  };',
     '});',
     '$impl.RedAnt = null;',
@@ -431,9 +438,11 @@ begin
   ConvertUnit;
   CheckSource('TestOptShortRefGlobals_Property',
     LinesToStr([
+    'var $lt = null;',
     'var $lm = pas.UnitA;',
-    'var $lt = $lm.TBird;',
-    'rtl.createClass(this, "TEagle", $lt, function () {',
+    'var $lt1 = $lm.TBird;',
+    'rtl.createClass(this, "TEagle", $lt1, function () {',
+    '  $lt = this;',
     '  this.Fly = function (o) {',
     '    this.Fly(this.FWing);',
     '    this.Fly(this.FLeg);',
@@ -475,11 +484,13 @@ begin
   ConvertUnit;
   CheckSource('TestOptShortRefGlobals_GenericFunction',
     LinesToStr([
+    'var $lt = null;',
     'var $lm = pas.system;',
-    'var $lt = $lm.TObject;',
+    'var $lt1 = $lm.TObject;',
     'var $lm1 = pas.UnitA;',
     'var $lp = $lm1.Run$G1;',
-    'rtl.createClass(this, "TEagle", $lt, function () {',
+    'rtl.createClass(this, "TEagle", $lt1, function () {',
+    '  $lt = this;',
     '});',
     'this.Fly = function () {',
     '  $lp(null);',
@@ -498,23 +509,25 @@ begin
   '{$optimization JSShortRefGlobals}',
   'interface',
   'type',
-  '  TEnum = (red,blue);',
   '  TBird = class',
   '  type',
   '    TFlag = (big,small);',
   '    procedure Fly;',
   '  end;',
-  'var f: TBird.TFlag;',
+  '  TEnum = (red,blue);',
+  'var',
+  '  e: TEnum;',
+  '  f: TBird.TFlag;',
   'procedure Run;',
   'implementation',
   'procedure TBird.Fly;',
   'begin',
+  '  e:=blue;',
   '  f:=small;',
   'end;',
   'procedure Run;',
   'type TSub = (left,right);',
-  'var e: TEnum;',
-  '  s: TSub;',
+  'var s: TSub;',
   'begin',
   '  e:=red;',
   '  s:=right;',
@@ -524,26 +537,31 @@ begin
   ConvertUnit;
   CheckSource('TestOptShortRefGlobals_SameUnit_EnumType',
     LinesToStr([
+    'var $lt = null;',
+    'var $lt1 = null;',
+    'var $lt2 = null;',
     'var $lm = pas.system;',
-    'var $lt1 = $lm.TObject;',
-    'var $lt = this.TEnum = {',
-    '  "0": "red",',
-    '  red: 0,',
-    '  "1": "blue",',
-    '  blue: 1',
-    '};',
-    'var $lt2 = {',
+    'var $lt3 = $lm.TObject;',
+    'rtl.createClass(this, "TBird", $lt3, function () {',
+    '  $lt = this;',
+    '  $lt1 = this.TFlag = {',
     '    "0": "big",',
     '    big: 0,',
     '    "1": "small",',
     '    small: 1',
     '  };',
-    'rtl.createClass(this, "TBird", $lt1, function () {',
-    '  this.TFlag = $lt2;',
     '  this.Fly = function () {',
-    '    $mod.f = $lt2.small;',
+    '    $mod.e = $lt2.blue;',
+    '    $mod.f = $lt1.small;',
     '  };',
     '});',
+    '$lt2 = this.TEnum = {',
+    '  "0": "red",',
+    '  red: 0,',
+    '  "1": "blue",',
+    '  blue: 1',
+    '};',
+    'this.e = 0;',
     'this.f = 0;',
     'var TSub = {',
     '  "0": "left",',
@@ -552,11 +570,10 @@ begin
     '  right: 1',
     '};',
     'this.Run = function () {',
-    '  var e = 0;',
     '  var s = 0;',
-    '  e = $lt.red;',
+    '  $mod.e = $lt2.red;',
     '  s = TSub.right;',
-    '  $mod.f = $lt2.big;',
+    '  $mod.f = $lt1.big;',
     '};',
     '']),
     LinesToStr([
@@ -565,6 +582,91 @@ begin
     '']));
 end;
 
+procedure TTestOptimizations.TestOptShortRefGlobals_SameUnit_ClassType;
+begin
+  WithTypeInfo:=true;
+  StartUnit(true,[supTObject]);
+  Add([
+  '{$optimization JSShortRefGlobals}',
+  'interface',
+  'type',
+  '  TBird = class;',
+  '  TAnt = class',
+  '  type',
+  '    TLeg = class',
+  '    end;',
+  '    procedure Run;',
+  '  published',
+  '    Bird: TBird;',
+  '  end;',
+  '  TBird = class',
+  '    procedure Fly;',
+  '  end;',
+  'implementation',
+  'type',
+  '  TFrog = class',
+  '  end;',
+  'procedure TAnt.Run;',
+  'begin',
+  '  if typeinfo(TBird)=nil then;',
+  '  Bird:=TBird.Create;',
+  '  TLeg.Create;',
+  '  TFrog.Create;',
+  'end;',
+  'procedure TBird.Fly;',
+  'begin',
+  '  if typeinfo(TAnt)=nil then;',
+  'end;',
+  '']);
+  ConvertUnit;
+  CheckSource('TestOptShortRefGlobals_SameUnit_EnumType',
+    LinesToStr([
+    'var $impl = $mod.$impl;',
+    'var $lt = null;',
+    'var $lt1 = null;',
+    'var $lt2 = null;',
+    'var $lt3 = null;',
+    'var $lm = pas.system;',
+    'var $lt4 = $lm.TObject;',
+    'this.$rtti.$Class("TBird");',
+    'rtl.createClass(this, "TAnt", $lt4, function () {',
+    '  $lt = this;',
+    '  rtl.createClass(this, "TLeg", $lt4, function () {',
+    '    $lt1 = this;',
+    '  });',
+    '  this.$init = function () {',
+    '    $lt4.$init.call(this);',
+    '    this.Bird = null;',
+    '  };',
+    '  this.$final = function () {',
+    '    this.Bird = undefined;',
+    '    $lt4.$final.call(this);',
+    '  };',
+    '  this.Run = function () {',
+    '    if ($mod.$rtti["TBird"] === null) ;',
+    '    this.Bird = $lt2.$create("Create");',
+    '    $lt1.$create("Create");',
+    '    $lt3.$create("Create");',
+    '  };',
+    '  var $r = this.$rtti;',
+    '  $r.addField("Bird", $mod.$rtti["TBird"]);',
+    '});',
+    'rtl.createClass(this, "TBird", $lt4, function () {',
+    '  $lt2 = this;',
+    '  this.Fly = function () {',
+    '    if ($mod.$rtti["TAnt"] === null) ;',
+    '  };',
+    '});',
+    '']),
+    LinesToStr([
+    '']),
+    LinesToStr([
+    'rtl.createClass($impl, "TFrog", $lt4, function () {',
+    '  $lt3 = this;',
+    '});',
+    '']));
+end;
+
 procedure TTestOptimizations.TestWPO_OmitLocalVar;
 begin
   StartProgram(false);
@@ -1386,7 +1488,7 @@ procedure TTestOptimizations.TestWPO_ConstructorDefaultValueConst;
 var
   ActualSrc, ExpectedSrc: String;
 begin
-  Converter.Options:=Converter.Options-[coNoTypeInfo];
+  WithTypeInfo:=true;
   StartProgram(true);
   Add([
   'const gcBlack = 0;',
@@ -1437,7 +1539,7 @@ procedure TTestOptimizations.TestWPO_RTTI_PublishedField;
 var
   ActualSrc, ExpectedSrc: String;
 begin
-  Converter.Options:=Converter.Options-[coNoTypeInfo];
+  WithTypeInfo:=true;
   StartProgram(true);
   Add('type');
   Add('  TArrA = array of char;');
@@ -1485,7 +1587,7 @@ procedure TTestOptimizations.TestWPO_RTTI_TypeInfo;
 var
   ActualSrc, ExpectedSrc: String;
 begin
-  Converter.Options:=Converter.Options-[coNoTypeInfo];
+  WithTypeInfo:=true;
   StartProgram(true);
   Add('type');
   Add('  TArrA = array of char;');