mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 08:27:02 +02:00
* 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:
parent
f88efa2072
commit
1c9fed7ae3
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
29
tests/test/tobjc35i.pp
Normal 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.
|
Loading…
Reference in New Issue
Block a user