* merges recent class helper fixes by Sven Barth

git-svn-id: trunk@17887 -
This commit is contained in:
florian 2011-06-30 18:54:46 +00:00
parent c5dfa9d354
commit 570f3c4b39
14 changed files with 263 additions and 4 deletions

7
.gitattributes vendored
View File

@ -9846,6 +9846,10 @@ tests/test/tchlp51.pp svneol=native#text/pascal
tests/test/tchlp52.pp svneol=native#text/pascal
tests/test/tchlp53.pp svneol=native#text/pascal
tests/test/tchlp54.pp svneol=native#text/pascal
tests/test/tchlp55.pp svneol=native#text/pascal
tests/test/tchlp56.pp svneol=native#text/pascal
tests/test/tchlp57.pp svneol=native#text/pascal
tests/test/tchlp58.pp svneol=native#text/pascal
tests/test/tchlp6.pp svneol=native#text/pascal
tests/test/tchlp7.pp svneol=native#text/pascal
tests/test/tchlp8.pp svneol=native#text/pascal
@ -10055,6 +10059,7 @@ tests/test/thlp41.pp svneol=native#text/pascal
tests/test/thlp42.pp svneol=native#text/pascal
tests/test/thlp43.pp svneol=native#text/pascal
tests/test/thlp44.pp svneol=native#text/pascal
tests/test/thlp45.pp svneol=native#text/pascal
tests/test/thlp5.pp svneol=native#text/pascal
tests/test/thlp6.pp svneol=native#text/pascal
tests/test/thlp7.pp svneol=native#text/pascal
@ -10364,6 +10369,8 @@ tests/test/trhlp39.pp svneol=native#text/pascal
tests/test/trhlp4.pp svneol=native#text/pascal
tests/test/trhlp40.pp svneol=native#text/pascal
tests/test/trhlp41.pp svneol=native#text/pascal
tests/test/trhlp42.pp svneol=native#text/pascal
tests/test/trhlp43.pp svneol=native#text/pascal
tests/test/trhlp5.pp svneol=native#text/pascal
tests/test/trhlp6.pp svneol=native#text/pascal
tests/test/trhlp7.pp svneol=native#text/pascal

View File

@ -922,7 +922,7 @@ implementation
internalerror(200610011);
def.dwarf_lab:=current_asmdata.RefAsmSymbol(make_mangledname('DBG',def.owner,symname(def.typesym)));
def.dwarf_ref_lab:=current_asmdata.RefAsmSymbol(make_mangledname('DBGREF',def.owner,symname(def.typesym)));
if is_class_or_interface_or_dispinterface(def) then
if is_class_or_interface_or_dispinterface(def) or is_objectpascal_helper(def) then
tobjectdef(def).dwarf_struct_lab:=current_asmdata.RefAsmSymbol(make_mangledname('DBG2',def.owner,symname(def.typesym)));
def.dbg_state:=dbg_state_written;
end
@ -936,7 +936,7 @@ implementation
begin
def.dwarf_lab:=current_asmdata.DefineAsmSymbol(make_mangledname('DBG',def.owner,symname(def.typesym)),AB_GLOBAL,AT_DATA);
def.dwarf_ref_lab:=current_asmdata.DefineAsmSymbol(make_mangledname('DBGREF',def.owner,symname(def.typesym)),AB_GLOBAL,AT_DATA);
if is_class_or_interface_or_dispinterface(def) then
if is_class_or_interface_or_dispinterface(def) or is_objectpascal_helper(def) then
tobjectdef(def).dwarf_struct_lab:=current_asmdata.DefineAsmSymbol(make_mangledname('DBG2',def.owner,symname(def.typesym)),AB_GLOBAL,AT_DATA);
include(def.defstates,ds_dwarf_dbg_info_written);
end
@ -3541,6 +3541,7 @@ implementation
odt_interfacecom,
odt_interfacecorba,
odt_dispinterface,
odt_helper,
odt_class:
begin
{ implicit pointer }
@ -3948,6 +3949,7 @@ implementation
dostruct(DW_TAG_interface_type);
doparent(true);
end;
odt_helper,
odt_class:
begin
//dostruct(DW_TAG_class_type);

View File

@ -1865,6 +1865,22 @@ implementation
if not hasoverload then
break;
end;
if is_objectpascal_helper(structdef) then
begin
if not assigned(tobjectdef(structdef).extendeddef) then
Internalerror(2011062601);
{ search methods in the extended type as well }
srsym:=tprocsym(tobjectdef(structdef).extendeddef.symtable.FindWithHash(hashedid));
if assigned(srsym) and
{ Delphi allows hiding a property by a procedure with the same name }
(srsym.typ=procsym) then
begin
hasoverload:=processprocsym(tprocsym(srsym));
{ when there is no explicit overload we stop searching }
if not hasoverload then
break;
end;
end;
{ next parent }
if (structdef.typ=objectdef) then
structdef:=tobjectdef(structdef).childof

View File

@ -1638,6 +1638,7 @@ implementation
function tcallnode.gen_self_tree:tnode;
var
selftree : tnode;
selfdef : tabstractrecorddef;
begin
selftree:=nil;
@ -1685,7 +1686,13 @@ implementation
begin
if (procdefinition.typ<>procdef) then
internalerror(200305062);
if (oo_has_vmt in tprocdef(procdefinition).struct.objectoptions) then
{ if the method belongs to a helper then we need to use the
extended type for references to Self }
if is_objectpascal_helper(tprocdef(procdefinition).struct) then
selfdef:=tobjectdef(tprocdef(procdefinition).struct).extendeddef
else
selfdef:=tprocdef(procdefinition).struct;
if (oo_has_vmt in selfdef.objectoptions) then
begin
{ we only need the vmt, loading self is not required and there is no
need to check for typen, because that will always get the

View File

@ -516,19 +516,36 @@ implementation
hp,
refnode : tnode;
hdef : tdef;
extendeddef : tabstractrecorddef;
helperdef : tobjectdef;
hasimplicitderef : boolean;
withsymtablelist : TFPObjectList;
procedure pushobjchild(withdef,obj:tobjectdef);
var
parenthelperdef : tobjectdef;
begin
if not assigned(obj) then
exit;
pushobjchild(withdef,obj.childof);
{ we need to look for helpers that were defined for the parent
class as well }
search_last_objectpascal_helper(obj,current_structdef,parenthelperdef);
{ push the symtables of the helper's parents in reverse order }
if assigned(parenthelperdef) then
pushobjchild(withdef,parenthelperdef.childof);
{ keep the original tobjectdef as owner, because that is used for
visibility of the symtable }
st:=twithsymtable.create(withdef,obj.symtable.SymList,refnode.getcopy);
symtablestack.push(st);
withsymtablelist.add(st);
{ push the symtable of the helper }
if assigned(parenthelperdef) then
begin
st:=twithsymtable.create(withdef,parenthelperdef.symtable.SymList,refnode.getcopy);
symtablestack.push(st);
withsymtablelist.add(st);
end;
end;
@ -625,12 +642,25 @@ implementation
typecheckpass(refnode);
end;
{ do we have a helper for this type? }
if p.resultdef.typ=classrefdef then
extendeddef:=tobjectdef(tclassrefdef(p.resultdef).pointeddef)
else
extendeddef:=tabstractrecorddef(p.resultdef);
search_last_objectpascal_helper(extendeddef,current_structdef,helperdef);
{ Note: the symtable of the helper is pushed after the following
"case", the symtables of the helper's parents are passed in
the "case" branches }
withsymtablelist:=TFPObjectList.create(true);
case p.resultdef.typ of
objectdef :
begin
{ push symtables of all parents in reverse order }
pushobjchild(tobjectdef(p.resultdef),tobjectdef(p.resultdef).childof);
{ push symtables of all parents of the helper in reverse order }
if assigned(helperdef) then
pushobjchild(helperdef,helperdef.childof);
{ push object symtable }
st:=twithsymtable.Create(tobjectdef(p.resultdef),tobjectdef(p.resultdef).symtable.SymList,refnode);
symtablestack.push(st);
@ -640,6 +670,9 @@ implementation
begin
{ push symtables of all parents in reverse order }
pushobjchild(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).childof);
{ push symtables of all parents of the helper in reverse order }
if assigned(helperdef) then
pushobjchild(helperdef,helperdef.childof);
{ push object symtable }
st:=twithsymtable.Create(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).symtable.SymList,refnode);
symtablestack.push(st);
@ -647,6 +680,10 @@ implementation
end;
recorddef :
begin
{ push symtables of all parents of the helper in reverse order }
if assigned(helperdef) then
pushobjchild(helperdef,helperdef.childof);
{ push record symtable }
st:=twithsymtable.create(trecorddef(p.resultdef),trecorddef(p.resultdef).symtable.SymList,refnode);
symtablestack.push(st);
withsymtablelist.add(st);
@ -655,6 +692,14 @@ implementation
internalerror(200601271);
end;
{ push helper symtable }
if assigned(helperdef) then
begin
st:=twithsymtable.Create(helperdef,helperdef.symtable.SymList,refnode.getcopy);
symtablestack.push(st);
withsymtablelist.add(st);
end;
if try_to_consume(_COMMA) then
p:=_with_statement()
else

View File

@ -5783,7 +5783,7 @@ implementation
result:=
assigned(def) and
(def.typ=objectdef) and
(tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol]);
(tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_helper]);
end;
function is_class_or_object(def: tdef): boolean;

View File

@ -2560,6 +2560,7 @@ implementation
st: tsymtable;
begin
result:=false;
odef:=nil;
{ when there are no helpers active currently then we don't need to do
anything }
if current_module.extendeddefs.count=0 then

21
tests/test/tchlp55.pp Normal file
View File

@ -0,0 +1,21 @@
{ %NORUN }
{ This tests that methods introduced by a helper can be found in
with-Statements as well - Case 1: normal method in current helper }
program tchlp55;
{$mode objfpc}
type
TObjectHelper = class helper for TObject
procedure Test;
end;
procedure TObjectHelper.Test;
begin
end;
begin
with TObject.Create do
Test;
end.

21
tests/test/tchlp56.pp Normal file
View File

@ -0,0 +1,21 @@
{ %NORUN }
{ This tests that methods introduced by a helper can be found in
with-Statements as well - Case 2: class method in current helper }
program tchlp56;
{$mode objfpc}
type
TObjectHelper = class helper for TObject
class procedure Test;
end;
class procedure TObjectHelper.Test;
begin
end;
begin
with TObject do
Test;
end.

24
tests/test/tchlp57.pp Normal file
View File

@ -0,0 +1,24 @@
{ %NORUN }
{ This tests that methods introduced by a helper can be found in
with-Statements as well - Case 3: normal method in parent's helper }
program tchlp57;
{$mode objfpc}
type
TObjectHelper = class helper for TObject
procedure Test;
end;
TTest = class
end;
procedure TObjectHelper.Test;
begin
end;
begin
with TTest.Create do
Test;
end.

24
tests/test/tchlp58.pp Normal file
View File

@ -0,0 +1,24 @@
{ %NORUN }
{ This tests that methods introduced by a helper can be found in
with-Statements as well - Case 4: class method in parent's helper }
program tchlp58;
{$mode objfpc}
type
TObjectHelper = class helper for TObject
class procedure Test;
end;
TTest = class
end;
class procedure TObjectHelper.Test;
begin
end;
begin
with TTest do
Test;
end.

39
tests/test/thlp45.pp Normal file
View File

@ -0,0 +1,39 @@
{ this tests that the correct method is called if a helper overloads an
existing function and calls the original one recursively }
program thlp45;
{$mode objfpc}{$H+}
type
TTest = class
function Test(aRecurse: Boolean; aTest: String): Integer;
end;
TTestHelper = class helper for TTest
function Test(aRecurse: Boolean; aTest: array of String): Integer; overload;
end;
function TTest.Test(aRecurse: Boolean; aTest: String): Integer;
begin
Result := 1;
end;
function TTestHelper.Test(aRecurse: Boolean; aTest: array of String): Integer;
begin
if aRecurse then
Result := Test(False, aTest[0])
else
Result := 2;
end;
var
t: TTest;
res: Integer;
begin
t := TTest.Create;
res := t.Test(True, ['Test']);
Writeln('t.Test: ', res);
if res <> 1 then
Halt(1);
Writeln('ok');
end.

27
tests/test/trhlp42.pp Normal file
View File

@ -0,0 +1,27 @@
{ %NORUN }
{ This tests that methods introduced by a helper can be found in
with-Statements as well - Case 1: normal method in current helper }
program trhlp42;
{$mode objfpc}
{$modeswitch advancedrecords}
type
TTest = record
end;
TTestHelper = record helper for TTest
procedure Test;
end;
procedure TTestHelper.Test;
begin
end;
var
t: TTest;
begin
with t do
Test;
end.

25
tests/test/trhlp43.pp Normal file
View File

@ -0,0 +1,25 @@
{ %NORUN }
{ This tests that methods introduced by a helper can be found in
with-Statements as well - Case 2: class method in current helper }
program trhlp43;
{$mode objfpc}
{$modeswitch advancedrecords}
type
TTest = record
end;
TTestHelper = record helper for TTest
class procedure Test; static;
end;
class procedure TTestHelper.Test;
begin
end;
begin
with TTest do
Test;
end.