Pārlūkot izejas kodu

* 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 -

Jonas Maebe 15 gadi atpakaļ
vecāks
revīzija
1c9fed7ae3
5 mainītis faili ar 58 papildinājumiem un 9 dzēšanām
  1. 1 0
      .gitattributes
  2. 9 1
      compiler/defcmp.pas
  3. 3 1
      compiler/pdecobj.pas
  4. 16 7
      compiler/symtable.pas
  5. 29 0
      tests/test/tobjc35i.pp

+ 1 - 0
.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

+ 9 - 1
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;

+ 3 - 1
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

+ 16 - 7
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

+ 29 - 0
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.