summaryrefslogtreecommitdiff
path: root/fpcsrc/tests/tbs/tb0268.pp
blob: 083f4b775bf10930678642da8d64e5d3afd35120 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
{ Old file: tbs0312.pp }
{ Again the problem of local procs inside methods }

{ Program that showss a problem if
  Self is not reloaded in %esi register
  at entry in local procedure inside method }

uses
  objects;

type
{$ifndef FPC}
  sw_integer = integer;
{$endif not FPC}

  PMYObj = ^TMyObj;

  TMyObj = Object(TObject)
    x : longint;
    Constructor Init(ax : longint);
    procedure display;virtual;
    end;

  PMYObj2 = ^TMyObj2;

  TMyObj2 = Object(TMyObj)
    y : longint;
    Constructor Init(ax,ay : longint);
    procedure display;virtual;
    end;

  PMyCollection = ^TMyCollection;

  TMyCollection = Object(TCollection)
    function At(I : sw_integer) : PMyObj;
    procedure DummyThatShouldNotBeCalled;virtual;
    end;

  { TMy is also a TCollection so that
    ShowMy and DummyThatShouldNotBeCalled are at same position in VMT }
  TMy = Object(TCollection)
    Col : PMyCollection;
    MyObj : PMyObj;
    ShowMyCalled : boolean;
    constructor Init;
    destructor Done;virtual;
    procedure ShowAll;
    procedure AddMyObj(x : longint);
    procedure AddMyObj2(x,y : longint);
    procedure ShowMy;virtual;
    end;

  Constructor TMyObj.Init(ax : longint);
    begin
      Inherited Init;
      x:=ax;
    end;

  Procedure TMyObj.Display;
    begin
      Writeln('x = ',x);
    end;

  Constructor TMyObj2.Init(ax,ay : longint);
    begin
      Inherited Init(ax);
      y:=ay;
    end;

  Procedure TMyObj2.Display;
    begin
      Writeln('x = ',x,' y = ',y);
    end;

  Function TMyCollection.At(I : sw_integer) : PMyObj;
    begin
      At:=Inherited At(I);
    end;

  Procedure TMyCollection.DummyThatShouldNotBeCalled;
    begin
      Writeln('This method should never be called');
      Abstract;
    end;

  Constructor TMy.Init;

    begin
      New(Col,Init(5,5));
      MyObj:=nil;
      ShowMyCalled:=false;
    end;

  Destructor TMy.Done;
    begin
      Dispose(Col,Done);
      Inherited Done;
    end;

  Procedure TMy.ShowAll;

      procedure ShowIt(P : pointer);{$ifdef TP}far;{$endif}
        begin
          ShowMy;
          PMyObj(P)^.Display;
        end;
    begin
      Col^.ForEach(@ShowIt);
    end;

  Procedure TMy.ShowMy;
    begin
      if assigned(MyObj) then
        MyObj^.Display;
      ShowMyCalled:=true;
    end;

  Procedure TMy.AddMyObj(x : longint);

    begin
      MyObj:=New(PMyObj,Init(x));
      Col^.Insert(MyObj);
    end;

  Procedure TMy.AddMyObj2(x,y : longint);
    begin
      MyObj:=New(PMyObj2,Init(x,y));
      Col^.Insert(MyObj);
    end;

var
   My : TMy;
begin
   My.Init;
   My.AddMyObj(5);
   My.AddMyObj2(4,3);
   My.AddMyObj(43);
   { MyObj field is now a PMyObj with value 43 }
   My.ShowAll;
   If not My.ShowMyCalled then
     begin
       Writeln('ShowAll does not work correctly');
       Halt(1);
     end;
   My.Done;

end.