Просмотр исходного кода

* fixed assigning "id" to a protocol instance and using protocol instances
to call methods + test

git-svn-id: trunk@15453 -

Jonas Maebe 15 лет назад
Родитель
Сommit
790c7954b7
4 измененных файлов с 97 добавлено и 3 удалено
  1. 1 0
      .gitattributes
  2. 1 1
      compiler/defcmp.pas
  3. 28 2
      compiler/symtable.pas
  4. 67 0
      tests/test/tobjc22a.pp

+ 1 - 0
.gitattributes

@@ -9273,6 +9273,7 @@ tests/test/tobjc2.pp svneol=native#text/plain
 tests/test/tobjc20.pp svneol=native#text/plain
 tests/test/tobjc21.pp svneol=native#text/plain
 tests/test/tobjc22.pp svneol=native#text/plain
+tests/test/tobjc22a.pp svneol=native#text/plain
 tests/test/tobjc23.pp svneol=native#text/plain
 tests/test/tobjc24.pp svneol=native#text/plain
 tests/test/tobjc25.pp svneol=native#text/plain

+ 1 - 1
compiler/defcmp.pas

@@ -1268,7 +1268,7 @@ implementation
                        eq:=te_convert_l1;
                      end
                    { All Objective-C classes are compatible with ID }
-                   else if is_objcclass(def_to) and
+                   else if is_objc_class_or_protocol(def_to) and
                            (def_from=objc_idtype) then
                       begin
                        doconv:=tc_equal;

+ 28 - 2
compiler/symtable.pas

@@ -1981,6 +1981,7 @@ implementation
       var
         hashedid : THashedIDString;
         orgclass : tobjectdef;
+        i        : longint;
       begin
         orgclass:=classh;
         { The contextclassh is used for visibility. The classh must be equal to
@@ -1991,7 +1992,9 @@ implementation
           internalerror(200811161);
         result:=false;
         hashedid.id:=s;
-        while assigned(classh) do
+        { an Objective-C protocol can inherit from multiple other protocols
+          -> uses ImplementedInterfaces instead }
+        if is_objcprotocol(classh) then
           begin
             srsymtable:=classh.symtable;
             srsym:=tsym(srsymtable.FindWithHash(hashedid));
@@ -2002,7 +2005,30 @@ implementation
                 result:=true;
                 exit;
               end;
-            classh:=classh.childof;
+            for i:=0 to classh.ImplementedInterfaces.count-1 do
+              begin
+                if searchsym_in_class(TImplementedInterface(classh.ImplementedInterfaces[i]).intfdef,contextclassh,s,srsym,srsymtable) then
+                  begin
+                    result:=true;
+                    exit;
+                  end;
+              end;
+          end
+        else
+          begin
+            while assigned(classh) do
+              begin
+                srsymtable:=classh.symtable;
+                srsym:=tsym(srsymtable.FindWithHash(hashedid));
+                if assigned(srsym) and
+                   is_visible_for_object(srsym,contextclassh) then
+                  begin
+                    addsymref(srsym);
+                    result:=true;
+                    exit;
+                  end;
+                classh:=classh.childof;
+              end;
           end;
         if is_objcclass(orgclass) then
           result:=search_class_helper(orgclass,s,srsym,srsymtable)

+ 67 - 0
tests/test/tobjc22a.pp

@@ -0,0 +1,67 @@
+{ %target=darwin }
+{ %cpu=powerpc,powerpc64,i386,x86_64,arm }
+
+{ Written by Jonas Maebe in 2009, released into the public domain }
+
+program protocoltest;
+
+{$mode objfpc}{$H+}
+{$modeswitch objectivec1}
+
+type
+  MyProtocolA = objcprotocol
+    function newMethod: longint; message 'n';
+  end;
+
+  MyProtocolB = objcprotocol(MyProtocolA)
+    class function newClassMethod: longint; message 'newClassMethod';
+  end;
+
+
+  { TMyObject }
+
+  TMyObjectA = objcclass(NSObject, MyProtocolA)
+    function newMethod: longint;
+  end;
+
+  TMyObjectB = objcclass(NSObject,MyProtocolB)
+    function newMethod: longint;
+    class function newClassMethod: longint;
+  end;
+
+{ TMyObjectA }
+
+function TMyObjectA.newMethod: longint;
+begin
+  result:=1;
+end;
+
+{ TMyObjectB }
+
+function TMyObjectB.newMethod: longint;
+begin
+  result:=3;
+end;
+
+class function TMyObjectB.newClassMethod: longint;
+begin
+  result:=4;
+end;
+
+
+var
+  a   : MyProtocolA;
+  b   : MyProtocolB;
+begin
+  a:=TMyObjectA.alloc.init;
+  b:=TMyObjectB.alloc.init;
+  if a.newMethod<>1 then
+    halt(1);
+  if b.newMethod<>3 then
+    halt(3);
+  if b.newclassmethod<>4 then
+    halt(4);
+  id(a).release;
+  id(b).release;
+end.
+