mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-23 18:29:43 +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/tobjc35g.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/tobjc4a.pp svneol=native#text/plain
|
||||
tests/test/tobjc5.pp svneol=native#text/plain
|
||||
|
@ -1245,8 +1245,16 @@ implementation
|
||||
|
||||
objectdef :
|
||||
begin
|
||||
{ object pascal objects }
|
||||
{ Objective-C classes (handle anonymous externals) }
|
||||
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
|
||||
begin
|
||||
doconv:=tc_equal;
|
||||
|
@ -427,7 +427,9 @@ implementation
|
||||
end
|
||||
else
|
||||
Message(parser_e_mix_of_classes_and_objects);
|
||||
end;
|
||||
end
|
||||
else
|
||||
childof:=find_real_objcclass_definition(childof,true);
|
||||
odt_objcprotocol:
|
||||
begin
|
||||
if not(is_objcprotocol(childof)) then
|
||||
|
@ -223,6 +223,7 @@ interface
|
||||
|
||||
{*** Object Helpers ***}
|
||||
function search_default_property(pd : tobjectdef) : tpropertysym;
|
||||
function find_real_objcclass_definition(pd: tobjectdef; erroronfailure: boolean): tobjectdef;
|
||||
|
||||
{*** Macro Helpers ***}
|
||||
{If called initially, the following procedures manipulate macros in }
|
||||
@ -1963,13 +1964,19 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function find_real_objcclass_definition(pd: tobjectdef): tobjectdef;
|
||||
function find_real_objcclass_definition(pd: tobjectdef; erroronfailure: boolean): tobjectdef;
|
||||
var
|
||||
hashedid : THashedIDString;
|
||||
stackitem : psymtablestackitem;
|
||||
srsymtable : tsymtable;
|
||||
srsym : tsym;
|
||||
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;
|
||||
stackitem:=symtablestack.stack;
|
||||
while assigned(stackitem) do
|
||||
@ -1995,8 +2002,10 @@ implementation
|
||||
end;
|
||||
stackitem:=stackitem^.next;
|
||||
end;
|
||||
{ nothing found: give an error and return the original (empty) one }
|
||||
Message1(sym_e_objc_formal_class_not_resolved,pd.objrealname^);
|
||||
{ nothing found: optionally give an error and return the original
|
||||
(empty) one }
|
||||
if erroronfailure then
|
||||
Message1(sym_e_objc_formal_class_not_resolved,pd.objrealname^);
|
||||
result:=pd;
|
||||
end;
|
||||
|
||||
@ -2012,7 +2021,7 @@ implementation
|
||||
if assigned(classh) then
|
||||
begin
|
||||
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
|
||||
or be a parent of contextclassh. E.g. for inherited searches the classh is the
|
||||
parent. }
|
||||
@ -2077,7 +2086,7 @@ implementation
|
||||
{ in case this is a formal objcclass, first find the real definition }
|
||||
if assigned(classh) and
|
||||
(oo_is_formal in classh.objectoptions) then
|
||||
classh:=find_real_objcclass_definition(classh);
|
||||
classh:=find_real_objcclass_definition(classh,true);
|
||||
result:=false;
|
||||
def:=nil;
|
||||
while assigned(classh) do
|
||||
@ -2115,7 +2124,7 @@ implementation
|
||||
{ in case this is a formal objcclass, first find the real definition }
|
||||
if assigned(classh) and
|
||||
(oo_is_formal in classh.objectoptions) then
|
||||
classh:=find_real_objcclass_definition(classh);
|
||||
classh:=find_real_objcclass_definition(classh,true);
|
||||
result:=false;
|
||||
def:=nil;
|
||||
while assigned(classh) do
|
||||
@ -2376,7 +2385,7 @@ implementation
|
||||
begin
|
||||
{ in case this is a formal objcclass, first find the real definition }
|
||||
if (oo_is_formal in pd.objectoptions) then
|
||||
pd:=find_real_objcclass_definition(pd);
|
||||
pd:=find_real_objcclass_definition(pd,true);
|
||||
hashedid.id:=s;
|
||||
orgpd:=pd;
|
||||
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