From 1c9fed7ae3074765e42b5fd65aeccb3f64c07226 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sun, 19 Sep 2010 16:05:32 +0000 Subject: [PATCH] * 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 - --- .gitattributes | 1 + compiler/defcmp.pas | 10 +++++++++- compiler/pdecobj.pas | 4 +++- compiler/symtable.pas | 23 ++++++++++++++++------- tests/test/tobjc35i.pp | 29 +++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 tests/test/tobjc35i.pp diff --git a/.gitattributes b/.gitattributes index bc67cd0367..19a1cff018 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/compiler/defcmp.pas b/compiler/defcmp.pas index 0edd08b146..cb3d7ab6ba 100644 --- a/compiler/defcmp.pas +++ b/compiler/defcmp.pas @@ -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; diff --git a/compiler/pdecobj.pas b/compiler/pdecobj.pas index e3bd4b5c22..349cef87d0 100644 --- a/compiler/pdecobj.pas +++ b/compiler/pdecobj.pas @@ -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 diff --git a/compiler/symtable.pas b/compiler/symtable.pas index 4f908ce183..cdeca6a93c 100644 --- a/compiler/symtable.pas +++ b/compiler/symtable.pas @@ -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 diff --git a/tests/test/tobjc35i.pp b/tests/test/tobjc35i.pp new file mode 100644 index 0000000000..d29e14776c --- /dev/null +++ b/tests/test/tobjc35i.pp @@ -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.