mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-13 17:59:27 +02:00
* fixed with-support for classrefdefs (mantis 8150), with thanks to
Thorsten Engler for supplying an initial patch git-svn-id: trunk@6088 -
This commit is contained in:
parent
307adfc54a
commit
4e96fe8fac
8
.gitattributes
vendored
8
.gitattributes
vendored
@ -7138,6 +7138,12 @@ tests/webtbf/tw8140a.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8140c.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8140d.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8140e.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8150.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8150b.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8150c.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8150e.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8150f.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8150g.pp svneol=native#text/plain
|
||||
tests/webtbf/uw0744.pp svneol=native#text/plain
|
||||
tests/webtbf/uw0840a.pp svneol=native#text/plain
|
||||
tests/webtbf/uw0840b.pp svneol=native#text/plain
|
||||
@ -7981,6 +7987,8 @@ tests/webtbs/tw8140h.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8141.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8145.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8148.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8150a.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8150d.pp svneol=native#text/plain
|
||||
tests/webtbs/ub1873.pp svneol=native#text/plain
|
||||
tests/webtbs/ub1883.pp svneol=native#text/plain
|
||||
tests/webtbs/uw0555.pp svneol=native#text/plain
|
||||
|
@ -1299,7 +1299,11 @@ implementation
|
||||
else
|
||||
begin
|
||||
if isclassref then
|
||||
Message(parser_e_only_class_methods_via_class_ref);
|
||||
if assigned(p1) and
|
||||
is_self_node(p1) then
|
||||
Message(parser_e_only_class_methods)
|
||||
else
|
||||
Message(parser_e_only_class_methods_via_class_ref);
|
||||
p1:=csubscriptnode.create(sym,p1);
|
||||
end;
|
||||
end;
|
||||
@ -1323,6 +1327,41 @@ implementation
|
||||
Factor
|
||||
****************************************************************************}
|
||||
|
||||
|
||||
function is_member_read(sym: tsym; st: tsymtable; var p1: tnode;
|
||||
out memberparentdef: tdef): boolean;
|
||||
var
|
||||
hdef : tdef;
|
||||
begin
|
||||
result:=true;
|
||||
memberparentdef:=nil;
|
||||
|
||||
case st.symtabletype of
|
||||
ObjectSymtable:
|
||||
begin
|
||||
memberparentdef:=tdef(st.defowner);
|
||||
exit;
|
||||
end;
|
||||
WithSymtable:
|
||||
begin
|
||||
if assigned(p1) then
|
||||
internalerror(2007012002);
|
||||
|
||||
hdef:=tnode(twithsymtable(st).withrefnode).resultdef;
|
||||
p1:=tnode(twithsymtable(st).withrefnode).getcopy;
|
||||
|
||||
if not(hdef.typ in [objectdef,classrefdef]) then
|
||||
exit;
|
||||
|
||||
if (hdef.typ=classrefdef) then
|
||||
hdef:=tclassrefdef(hdef).pointeddef;
|
||||
memberparentdef:=hdef;
|
||||
end;
|
||||
else
|
||||
result:=false;
|
||||
end;
|
||||
end;
|
||||
|
||||
{$maxfpuregisters 0}
|
||||
|
||||
function factor(getaddr : boolean) : tnode;
|
||||
@ -1434,39 +1473,28 @@ implementation
|
||||
paravarsym,
|
||||
fieldvarsym :
|
||||
begin
|
||||
if (sp_static in srsym.symoptions) then
|
||||
begin
|
||||
static_name:=lower(srsym.owner.name^)+'_'+srsym.name;
|
||||
searchsym(static_name,srsym,srsymtable);
|
||||
if assigned(srsym) then
|
||||
check_hints(srsym,srsym.symoptions);
|
||||
end
|
||||
{ check if we are reading a field of an object/class/ }
|
||||
{ record. is_member_read() will deal with withsymtables }
|
||||
{ if needed. }
|
||||
if is_member_read(srsym,srsymtable,p1,hdef) then
|
||||
begin
|
||||
{ if the field was originally found in an }
|
||||
{ objectsymtable, it means it's part of self }
|
||||
if (srsymtable.symtabletype=ObjectSymtable) then
|
||||
p1:=load_self_node;
|
||||
{ now, if the field itself is part of an objectsymtab }
|
||||
{ (it can be even if it was found in a withsymtable, }
|
||||
{ e.g., "with classinstance do field := 5"), then }
|
||||
{ let do_member_read handle it }
|
||||
if (srsym.owner.symtabletype=ObjectSymtable) then
|
||||
do_member_read(tobjectdef(hdef),getaddr,srsym,p1,again,[])
|
||||
else
|
||||
{ otherwise it's a regular record subscript }
|
||||
p1:=csubscriptnode.create(srsym,p1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ are we in a class method, we check here the
|
||||
srsymtable, because a field in another object
|
||||
also has ObjectSymtable. And withsymtable is
|
||||
not possible for self in class methods (PFV) }
|
||||
if (srsymtable.symtabletype=ObjectSymtable) and
|
||||
assigned(current_procinfo) and
|
||||
(po_classmethod in current_procinfo.procdef.procoptions) then
|
||||
Message(parser_e_only_class_methods);
|
||||
end;
|
||||
|
||||
case srsymtable.symtabletype of
|
||||
ObjectSymtable :
|
||||
begin
|
||||
p1:=csubscriptnode.create(srsym,load_self_node);
|
||||
node_tree_set_filepos(p1,current_filepos);
|
||||
end;
|
||||
withsymtable :
|
||||
begin
|
||||
p1:=csubscriptnode.create(srsym,tnode(twithsymtable(srsymtable).withrefnode).getcopy);
|
||||
node_tree_set_filepos(p1,current_filepos);
|
||||
end;
|
||||
else
|
||||
p1:=cloadnode.create(srsym,srsymtable);
|
||||
end;
|
||||
{ regular non-field load }
|
||||
p1:=cloadnode.create(srsym,srsymtable);
|
||||
end;
|
||||
|
||||
syssym :
|
||||
@ -1633,38 +1661,43 @@ implementation
|
||||
|
||||
procsym :
|
||||
begin
|
||||
{ are we in a class method ? }
|
||||
possible_error:=(srsymtable.symtabletype<>withsymtable) and
|
||||
(srsym.owner.symtabletype=ObjectSymtable) and
|
||||
not(is_interface(tdef(srsym.owner.defowner))) and
|
||||
assigned(current_procinfo) and
|
||||
(po_classmethod in current_procinfo.procdef.procoptions);
|
||||
do_proc_call(srsym,srsymtable,nil,
|
||||
(getaddr and not(token in [_CARET,_POINT])),
|
||||
again,p1,[]);
|
||||
{ we need to know which procedure is called }
|
||||
if possible_error then
|
||||
begin
|
||||
do_typecheckpass(p1);
|
||||
if (p1.nodetype=calln) and
|
||||
assigned(tcallnode(p1).procdefinition) and
|
||||
not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) and
|
||||
not(po_classmethod in tcallnode(p1).procdefinition.procoptions) then
|
||||
Message(parser_e_only_class_methods);
|
||||
end;
|
||||
{ check if it's a method/class method }
|
||||
if is_member_read(srsym,srsymtable,p1,hdef) then
|
||||
begin
|
||||
{ not srsymtable.symtabletype since that can be }
|
||||
{ withsymtable as well }
|
||||
if (srsym.owner.symtabletype=ObjectSymtable) then
|
||||
do_member_read(tobjectdef(hdef),getaddr,srsym,p1,again,[])
|
||||
else
|
||||
{ no procsyms in records (yet) }
|
||||
internalerror(2007012006);
|
||||
end
|
||||
else
|
||||
{ regular procedure/function call }
|
||||
do_proc_call(srsym,srsymtable,nil,
|
||||
(getaddr and not(token in [_CARET,_POINT])),
|
||||
again,p1,[]);
|
||||
end;
|
||||
|
||||
propertysym :
|
||||
begin
|
||||
{ access to property in a method }
|
||||
{ are we in a class method ? }
|
||||
if (srsymtable.symtabletype=ObjectSymtable) and
|
||||
assigned(current_procinfo) and
|
||||
(po_classmethod in current_procinfo.procdef.procoptions) then
|
||||
Message(parser_e_only_class_methods);
|
||||
{ property of a class/object? }
|
||||
if is_member_read(srsym,srsymtable,p1,hdef) then
|
||||
begin
|
||||
{ not srsymtable.symtabletype since that can be }
|
||||
{ withsymtable as well }
|
||||
if (srsym.owner.symtabletype=ObjectSymtable) then
|
||||
do_member_read(tobjectdef(hdef),getaddr,srsym,p1,again,[])
|
||||
else
|
||||
{ no propertysyms in records (yet) }
|
||||
internalerror(2007012006);
|
||||
end
|
||||
else
|
||||
{ no method pointer }
|
||||
p1:=nil;
|
||||
handle_propertysym(tpropertysym(srsym),srsymtable,p1);
|
||||
begin
|
||||
p1:=nil;
|
||||
handle_propertysym(tpropertysym(srsym),srsymtable,p1);
|
||||
end;
|
||||
end;
|
||||
|
||||
labelsym :
|
||||
|
@ -454,18 +454,19 @@ implementation
|
||||
hasimplicitderef : boolean;
|
||||
withsymtablelist : TFPObjectList;
|
||||
|
||||
procedure pushobjchild(obj:tobjectdef);
|
||||
procedure pushobjchild(withdef,obj:tobjectdef);
|
||||
begin
|
||||
if not assigned(obj) then
|
||||
exit;
|
||||
pushobjchild(obj.childof);
|
||||
pushobjchild(withdef,obj.childof);
|
||||
{ keep the original tobjectdef as owner, because that is used for
|
||||
visibility of the symtable }
|
||||
st:=twithsymtable.create(tobjectdef(p.resultdef),obj.symtable.SymList,refnode.getcopy);
|
||||
st:=twithsymtable.create(withdef,obj.symtable.SymList,refnode.getcopy);
|
||||
symtablestack.push(st);
|
||||
withsymtablelist.add(st);
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
p:=comp_expr(true);
|
||||
do_typecheckpass(p);
|
||||
@ -474,7 +475,7 @@ implementation
|
||||
(nf_memseg in p.flags) then
|
||||
CGMessage(parser_e_no_with_for_variable_in_other_segments);
|
||||
|
||||
if (p.resultdef.typ in [objectdef,recorddef]) then
|
||||
if (p.resultdef.typ in [objectdef,recorddef,classrefdef]) then
|
||||
begin
|
||||
newblock:=nil;
|
||||
valuenode:=nil;
|
||||
@ -521,7 +522,8 @@ implementation
|
||||
typecheckpass(p);
|
||||
end;
|
||||
{ classes and interfaces have implicit dereferencing }
|
||||
hasimplicitderef:=is_class_or_interface(p.resultdef);
|
||||
hasimplicitderef:=is_class_or_interface(p.resultdef) or
|
||||
(p.resultdef.typ = classrefdef);
|
||||
if hasimplicitderef then
|
||||
hdef:=p.resultdef
|
||||
else
|
||||
@ -552,12 +554,21 @@ implementation
|
||||
objectdef :
|
||||
begin
|
||||
{ push symtables of all parents in reverse order }
|
||||
pushobjchild(tobjectdef(p.resultdef).childof);
|
||||
pushobjchild(tobjectdef(p.resultdef),tobjectdef(p.resultdef).childof);
|
||||
{ push object symtable }
|
||||
st:=twithsymtable.Create(tobjectdef(p.resultdef),tobjectdef(p.resultdef).symtable.SymList,refnode);
|
||||
symtablestack.push(st);
|
||||
withsymtablelist.add(st);
|
||||
end;
|
||||
classrefdef :
|
||||
begin
|
||||
{ push symtables of all parents in reverse order }
|
||||
pushobjchild(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).childof);
|
||||
{ push object symtable }
|
||||
st:=twithsymtable.Create(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).symtable.SymList,refnode);
|
||||
symtablestack.push(st);
|
||||
withsymtablelist.add(st);
|
||||
end;
|
||||
recorddef :
|
||||
begin
|
||||
st:=twithsymtable.create(trecorddef(p.resultdef),trecorddef(p.resultdef).symtable.SymList,refnode);
|
||||
|
31
tests/webtbf/tw8150.pp
Normal file
31
tests/webtbf/tw8150.pp
Normal file
@ -0,0 +1,31 @@
|
||||
{ %fail }
|
||||
{ %norun }
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
type
|
||||
tc = class
|
||||
class procedure classmethod;
|
||||
procedure method;
|
||||
a : longint;
|
||||
end;
|
||||
|
||||
ttc = class of tc;
|
||||
|
||||
class procedure tc.classmethod;
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure tc.method;
|
||||
begin
|
||||
end;
|
||||
|
||||
var
|
||||
c: ttc;
|
||||
begin
|
||||
c := tc;
|
||||
with c do
|
||||
a := 5;
|
||||
end.
|
32
tests/webtbf/tw8150b.pp
Normal file
32
tests/webtbf/tw8150b.pp
Normal file
@ -0,0 +1,32 @@
|
||||
{ %fail }
|
||||
{ %norun }
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
type
|
||||
tc = class
|
||||
class procedure classmethod;
|
||||
procedure method;
|
||||
a : longint;
|
||||
property x: longint read a;
|
||||
end;
|
||||
|
||||
ttc = class of tc;
|
||||
|
||||
class procedure tc.classmethod;
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure tc.method;
|
||||
begin
|
||||
end;
|
||||
|
||||
var
|
||||
c: ttc;
|
||||
begin
|
||||
c := tc;
|
||||
with c do
|
||||
writeln(x);
|
||||
end.
|
29
tests/webtbf/tw8150c.pp
Normal file
29
tests/webtbf/tw8150c.pp
Normal file
@ -0,0 +1,29 @@
|
||||
{ %fail }
|
||||
{ %norun }
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
type
|
||||
tc = class
|
||||
class procedure classmethod;
|
||||
procedure method;
|
||||
a : longint;
|
||||
end;
|
||||
|
||||
ttc = class of tc;
|
||||
|
||||
class procedure tc.classmethod;
|
||||
begin
|
||||
a:= 5;
|
||||
end;
|
||||
|
||||
procedure tc.method;
|
||||
begin
|
||||
end;
|
||||
|
||||
var
|
||||
c: ttc;
|
||||
begin
|
||||
end.
|
68
tests/webtbf/tw8150e.pp
Normal file
68
tests/webtbf/tw8150e.pp
Normal file
@ -0,0 +1,68 @@
|
||||
{ %fail }
|
||||
{ %norun }
|
||||
|
||||
program WithForClassTypes;
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$mode delphi}
|
||||
{$ENDIF}
|
||||
|
||||
type
|
||||
TMyObject = class
|
||||
x: Integer;
|
||||
class procedure Foo; virtual;
|
||||
procedure Bar; virtual;
|
||||
end;
|
||||
|
||||
TMyObject2 = class(TMyObject)
|
||||
class procedure Foo; override;
|
||||
procedure Bar; override;
|
||||
end;
|
||||
|
||||
TMyClass = class of TMyObject;
|
||||
|
||||
{ TMyObject }
|
||||
|
||||
procedure TMyObject.Bar;
|
||||
begin
|
||||
WriteLn('Bar ', Integer(Pointer(Self)),' ', x);
|
||||
end;
|
||||
|
||||
class procedure TMyObject.Foo;
|
||||
begin
|
||||
WriteLn('Foo');
|
||||
end;
|
||||
|
||||
{ TMyObject2 }
|
||||
|
||||
procedure TMyObject2.Bar;
|
||||
begin
|
||||
WriteLn('2Bar ', Integer(Pointer(Self)),' ', x);
|
||||
end;
|
||||
|
||||
class procedure TMyObject2.Foo;
|
||||
begin
|
||||
WriteLn('2Foo');
|
||||
end;
|
||||
|
||||
var
|
||||
MyClass : TMyClass = TMyObject2;
|
||||
|
||||
begin
|
||||
with MyClass do begin
|
||||
Foo; // should work
|
||||
|
||||
with Create do try // should work
|
||||
x := 3; // should work
|
||||
Bar; // should work
|
||||
finally
|
||||
Free; // should work
|
||||
end;
|
||||
|
||||
Foo; // should work
|
||||
|
||||
x := 1; // should not be allowed
|
||||
// Bar; // should not be allowed
|
||||
// Free; // should not be allowed
|
||||
end;
|
||||
end.
|
68
tests/webtbf/tw8150f.pp
Normal file
68
tests/webtbf/tw8150f.pp
Normal file
@ -0,0 +1,68 @@
|
||||
{ %fail }
|
||||
{ %norun }
|
||||
|
||||
program WithForClassTypes;
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$mode delphi}
|
||||
{$ENDIF}
|
||||
|
||||
type
|
||||
TMyObject = class
|
||||
x: Integer;
|
||||
class procedure Foo; virtual;
|
||||
procedure Bar; virtual;
|
||||
end;
|
||||
|
||||
TMyObject2 = class(TMyObject)
|
||||
class procedure Foo; override;
|
||||
procedure Bar; override;
|
||||
end;
|
||||
|
||||
TMyClass = class of TMyObject;
|
||||
|
||||
{ TMyObject }
|
||||
|
||||
procedure TMyObject.Bar;
|
||||
begin
|
||||
WriteLn('Bar ', Integer(Pointer(Self)),' ', x);
|
||||
end;
|
||||
|
||||
class procedure TMyObject.Foo;
|
||||
begin
|
||||
WriteLn('Foo');
|
||||
end;
|
||||
|
||||
{ TMyObject2 }
|
||||
|
||||
procedure TMyObject2.Bar;
|
||||
begin
|
||||
WriteLn('2Bar ', Integer(Pointer(Self)),' ', x);
|
||||
end;
|
||||
|
||||
class procedure TMyObject2.Foo;
|
||||
begin
|
||||
WriteLn('2Foo');
|
||||
end;
|
||||
|
||||
var
|
||||
MyClass : TMyClass = TMyObject2;
|
||||
|
||||
begin
|
||||
with MyClass do begin
|
||||
Foo; // should work
|
||||
|
||||
with Create do try // should work
|
||||
x := 3; // should work
|
||||
Bar; // should work
|
||||
finally
|
||||
Free; // should work
|
||||
end;
|
||||
|
||||
Foo; // should work
|
||||
|
||||
// x := 1; // should not be allowed
|
||||
Bar; // should not be allowed
|
||||
// Free; // should not be allowed
|
||||
end;
|
||||
end.
|
67
tests/webtbf/tw8150g.pp
Normal file
67
tests/webtbf/tw8150g.pp
Normal file
@ -0,0 +1,67 @@
|
||||
{ %fail }
|
||||
{ %norun }
|
||||
program WithForClassTypes;
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$mode delphi}
|
||||
{$ENDIF}
|
||||
|
||||
type
|
||||
TMyObject = class
|
||||
x: Integer;
|
||||
class procedure Foo; virtual;
|
||||
procedure Bar; virtual;
|
||||
end;
|
||||
|
||||
TMyObject2 = class(TMyObject)
|
||||
class procedure Foo; override;
|
||||
procedure Bar; override;
|
||||
end;
|
||||
|
||||
TMyClass = class of TMyObject;
|
||||
|
||||
{ TMyObject }
|
||||
|
||||
procedure TMyObject.Bar;
|
||||
begin
|
||||
WriteLn('Bar ', Integer(Pointer(Self)),' ', x);
|
||||
end;
|
||||
|
||||
class procedure TMyObject.Foo;
|
||||
begin
|
||||
WriteLn('Foo');
|
||||
end;
|
||||
|
||||
{ TMyObject2 }
|
||||
|
||||
procedure TMyObject2.Bar;
|
||||
begin
|
||||
WriteLn('2Bar ', Integer(Pointer(Self)),' ', x);
|
||||
end;
|
||||
|
||||
class procedure TMyObject2.Foo;
|
||||
begin
|
||||
WriteLn('2Foo');
|
||||
end;
|
||||
|
||||
var
|
||||
MyClass : TMyClass = TMyObject2;
|
||||
|
||||
begin
|
||||
with MyClass do begin
|
||||
Foo; // should work
|
||||
|
||||
with Create do try // should work
|
||||
x := 3; // should work
|
||||
Bar; // should work
|
||||
finally
|
||||
Free; // should work
|
||||
end;
|
||||
|
||||
Foo; // should work
|
||||
|
||||
// x := 1; // should not be allowed
|
||||
// Bar; // should not be allowed
|
||||
Free; // should not be allowed
|
||||
end;
|
||||
end.
|
37
tests/webtbs/tw8150a.pp
Normal file
37
tests/webtbs/tw8150a.pp
Normal file
@ -0,0 +1,37 @@
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}
|
||||
{$endif}
|
||||
|
||||
type
|
||||
tc = class
|
||||
class procedure classmethod;
|
||||
procedure method;
|
||||
a : longint;
|
||||
end;
|
||||
|
||||
ttc = class of tc;
|
||||
|
||||
var
|
||||
l : longint;
|
||||
|
||||
class procedure tc.classmethod;
|
||||
begin
|
||||
if l <> 1 then
|
||||
halt(1);
|
||||
l := 2;
|
||||
end;
|
||||
|
||||
procedure tc.method;
|
||||
begin
|
||||
end;
|
||||
|
||||
var
|
||||
c: ttc;
|
||||
begin
|
||||
c := tc;
|
||||
l := 1;
|
||||
with c do
|
||||
classmethod;
|
||||
if l <> 2 then
|
||||
halt(2);
|
||||
end.
|
67
tests/webtbs/tw8150d.pp
Normal file
67
tests/webtbs/tw8150d.pp
Normal file
@ -0,0 +1,67 @@
|
||||
program WithForClassTypes;
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$mode delphi}
|
||||
{$ENDIF}
|
||||
|
||||
type
|
||||
TMyObject = class
|
||||
x: Integer;
|
||||
class procedure Foo; virtual;
|
||||
procedure Bar; virtual;
|
||||
end;
|
||||
|
||||
TMyObject2 = class(TMyObject)
|
||||
class procedure Foo; override;
|
||||
procedure Bar; override;
|
||||
end;
|
||||
|
||||
TMyClass = class of TMyObject;
|
||||
|
||||
{ TMyObject }
|
||||
|
||||
procedure TMyObject.Bar;
|
||||
begin
|
||||
WriteLn('Bar ', Integer(Pointer(Self)),' ', x);
|
||||
end;
|
||||
|
||||
class procedure TMyObject.Foo;
|
||||
begin
|
||||
WriteLn('Foo');
|
||||
end;
|
||||
|
||||
{ TMyObject2 }
|
||||
|
||||
procedure TMyObject2.Bar;
|
||||
begin
|
||||
if (x <> 3) then
|
||||
halt(1);
|
||||
WriteLn('2Bar ', Integer(Pointer(Self)),' ', x);
|
||||
end;
|
||||
|
||||
class procedure TMyObject2.Foo;
|
||||
begin
|
||||
WriteLn('2Foo');
|
||||
end;
|
||||
|
||||
var
|
||||
MyClass : TMyClass = TMyObject2;
|
||||
|
||||
begin
|
||||
with MyClass do begin
|
||||
Foo; // should work
|
||||
|
||||
with Create do try // should work
|
||||
x := 3; // should work
|
||||
Bar; // should work
|
||||
finally
|
||||
Free; // should work
|
||||
end;
|
||||
|
||||
Foo; // should work
|
||||
|
||||
// x := 1; // should not be allowed
|
||||
// Bar; // should not be allowed
|
||||
// Free; // should not be allowed
|
||||
end;
|
||||
end.
|
Loading…
Reference in New Issue
Block a user