* resolve anonymous external objcclass definitions to the real type also when

a) defining a child class
     b) checking for type conversion compatibility

git-svn-id: trunk@16013 -
This commit is contained in:
Jonas Maebe 2010-09-19 16:05:32 +00:00
parent f88efa2072
commit 1c9fed7ae3
5 changed files with 58 additions and 9 deletions

1
.gitattributes vendored
View File

@ -9401,6 +9401,7 @@ tests/test/tobjc35d.pp svneol=native#text/plain
tests/test/tobjc35f.pp svneol=native#text/plain tests/test/tobjc35f.pp svneol=native#text/plain
tests/test/tobjc35g.pp svneol=native#text/plain tests/test/tobjc35g.pp svneol=native#text/plain
tests/test/tobjc35h.pp svneol=native#text/plain tests/test/tobjc35h.pp svneol=native#text/plain
tests/test/tobjc35i.pp svneol=native#text/plain
tests/test/tobjc4.pp svneol=native#text/plain tests/test/tobjc4.pp svneol=native#text/plain
tests/test/tobjc4a.pp svneol=native#text/plain tests/test/tobjc4a.pp svneol=native#text/plain
tests/test/tobjc5.pp svneol=native#text/plain tests/test/tobjc5.pp svneol=native#text/plain

View File

@ -1245,8 +1245,16 @@ implementation
objectdef : objectdef :
begin begin
{ object pascal objects } { Objective-C classes (handle anonymous externals) }
if (def_from.typ=objectdef) and if (def_from.typ=objectdef) and
(find_real_objcclass_definition(tobjectdef(def_from),false) =
find_real_objcclass_definition(tobjectdef(def_to),false)) then
begin
doconv:=tc_equal;
eq:=te_equal;
end
{ object pascal objects }
else if (def_from.typ=objectdef) and
(tobjectdef(def_from).is_related(tobjectdef(def_to))) then (tobjectdef(def_from).is_related(tobjectdef(def_to))) then
begin begin
doconv:=tc_equal; doconv:=tc_equal;

View File

@ -427,7 +427,9 @@ implementation
end end
else else
Message(parser_e_mix_of_classes_and_objects); Message(parser_e_mix_of_classes_and_objects);
end; end
else
childof:=find_real_objcclass_definition(childof,true);
odt_objcprotocol: odt_objcprotocol:
begin begin
if not(is_objcprotocol(childof)) then if not(is_objcprotocol(childof)) then

View File

@ -223,6 +223,7 @@ interface
{*** Object Helpers ***} {*** Object Helpers ***}
function search_default_property(pd : tobjectdef) : tpropertysym; function search_default_property(pd : tobjectdef) : tpropertysym;
function find_real_objcclass_definition(pd: tobjectdef; erroronfailure: boolean): tobjectdef;
{*** Macro Helpers ***} {*** Macro Helpers ***}
{If called initially, the following procedures manipulate macros in } {If called initially, the following procedures manipulate macros in }
@ -1963,13 +1964,19 @@ implementation
end; end;
function find_real_objcclass_definition(pd: tobjectdef): tobjectdef; function find_real_objcclass_definition(pd: tobjectdef; erroronfailure: boolean): tobjectdef;
var var
hashedid : THashedIDString; hashedid : THashedIDString;
stackitem : psymtablestackitem; stackitem : psymtablestackitem;
srsymtable : tsymtable; srsymtable : tsymtable;
srsym : tsym; srsym : tsym;
begin begin
{ not a formal definition -> return it }
if not(oo_is_formal in pd.objectoptions) then
begin
result:=pd;
exit;
end;
hashedid.id:=pd.typesym.name; hashedid.id:=pd.typesym.name;
stackitem:=symtablestack.stack; stackitem:=symtablestack.stack;
while assigned(stackitem) do while assigned(stackitem) do
@ -1995,8 +2002,10 @@ implementation
end; end;
stackitem:=stackitem^.next; stackitem:=stackitem^.next;
end; end;
{ nothing found: give an error and return the original (empty) one } { nothing found: optionally give an error and return the original
Message1(sym_e_objc_formal_class_not_resolved,pd.objrealname^); (empty) one }
if erroronfailure then
Message1(sym_e_objc_formal_class_not_resolved,pd.objrealname^);
result:=pd; result:=pd;
end; end;
@ -2012,7 +2021,7 @@ implementation
if assigned(classh) then if assigned(classh) then
begin begin
if (oo_is_formal in classh.objectoptions) then if (oo_is_formal in classh.objectoptions) then
classh:=find_real_objcclass_definition(classh); classh:=find_real_objcclass_definition(classh,true);
{ The contextclassh is used for visibility. The classh must be equal to { The contextclassh is used for visibility. The classh must be equal to
or be a parent of contextclassh. E.g. for inherited searches the classh is the or be a parent of contextclassh. E.g. for inherited searches the classh is the
parent. } parent. }
@ -2077,7 +2086,7 @@ implementation
{ in case this is a formal objcclass, first find the real definition } { in case this is a formal objcclass, first find the real definition }
if assigned(classh) and if assigned(classh) and
(oo_is_formal in classh.objectoptions) then (oo_is_formal in classh.objectoptions) then
classh:=find_real_objcclass_definition(classh); classh:=find_real_objcclass_definition(classh,true);
result:=false; result:=false;
def:=nil; def:=nil;
while assigned(classh) do while assigned(classh) do
@ -2115,7 +2124,7 @@ implementation
{ in case this is a formal objcclass, first find the real definition } { in case this is a formal objcclass, first find the real definition }
if assigned(classh) and if assigned(classh) and
(oo_is_formal in classh.objectoptions) then (oo_is_formal in classh.objectoptions) then
classh:=find_real_objcclass_definition(classh); classh:=find_real_objcclass_definition(classh,true);
result:=false; result:=false;
def:=nil; def:=nil;
while assigned(classh) do while assigned(classh) do
@ -2376,7 +2385,7 @@ implementation
begin begin
{ in case this is a formal objcclass, first find the real definition } { in case this is a formal objcclass, first find the real definition }
if (oo_is_formal in pd.objectoptions) then if (oo_is_formal in pd.objectoptions) then
pd:=find_real_objcclass_definition(pd); pd:=find_real_objcclass_definition(pd,true);
hashedid.id:=s; hashedid.id:=s;
orgpd:=pd; orgpd:=pd;
while assigned(pd) do while assigned(pd) do

29
tests/test/tobjc35i.pp Normal file
View File

@ -0,0 +1,29 @@
{ %target=darwin }
{ %cpu=powerpc,powerpc64,i386,x86_64,arm }
{ %norun }
{ Written by Jonas Maebe in 2010, released into the public domain }
{$mode objfpc}
{$modeswitch objectivec1}
// will refer to the real NSObject in objcbase
procedure mytest(a: NSObject);
begin
end;
// define external incomplete version
type
NSObject = objcclass; external;
// NSObject should still resolve to the full definition in objcbase
MyObject = objcclass(NSObject)
end;
var
// refers to external incomplete version
a: NSObject;
begin
// compiler should treat external and real type as compatible
mytest(a);
end.