Browse Source

* let search_class_helper() only return class helper methods; it could
also return regular objcclass methods before, because these are also
registered under class helper procsyms for future id.anymethod support
* give an error when calling an inherited method from an objccategory
method, if that is not declared in the parent of the extended class
(since calling inherited in an objccategory method is the same as
calling inherited in a method of the extended class; if a method is
replaced, calling inherited will *not* call the original method
from the original class)

git-svn-id: trunk@14213 -

Jonas Maebe 15 năm trước cách đây
mục cha
commit
b495fbb991
6 tập tin đã thay đổi với 143 bổ sung1 xóa
  1. 3 0
      .gitattributes
  2. 6 0
      compiler/pexpr.pas
  3. 7 1
      compiler/symtable.pas
  4. 45 0
      tests/test/tobjc29.pp
  5. 35 0
      tests/test/tobjc29a.pp
  6. 47 0
      tests/test/tobjc29b.pp

+ 3 - 0
.gitattributes

@@ -8970,6 +8970,9 @@ tests/test/tobjc26a.pp svneol=native#text/plain
 tests/test/tobjc27a.pp svneol=native#text/plain
 tests/test/tobjc27b.pp svneol=native#text/plain
 tests/test/tobjc28.pp svneol=native#text/plain
+tests/test/tobjc29.pp svneol=native#text/plain
+tests/test/tobjc29a.pp svneol=native#text/plain
+tests/test/tobjc29b.pp svneol=native#text/plain
 tests/test/tobjc3.pp svneol=native#text/plain
 tests/test/tobjc4.pp svneol=native#text/plain
 tests/test/tobjc4a.pp svneol=native#text/plain

+ 6 - 0
compiler/pexpr.pas

@@ -2232,6 +2232,12 @@ implementation
                     assigned(current_objectdef) then
                   begin
                     hclassdef:=current_objectdef.childof;
+                    { Objective-C categories *replace* methods in the class
+                      they extend, or add methods to it. So calling an
+                      inherited method always calls the method inherited from
+                      the parent of the extended class }
+                    if is_objccategory(current_objectdef) then
+                      hclassdef:=hclassdef.childof;
                     { if inherited; only then we need the method with
                       the same name }
                     if token in endtokens then

+ 7 - 1
compiler/symtable.pas

@@ -2033,6 +2033,7 @@ implementation
         hashedid   : THashedIDString;
         stackitem  : psymtablestackitem;
         i          : longint;
+        defowner   : tobjectdef;
       begin
         hashedid.id:=class_helper_prefix+s;
         stackitem:=symtablestack.stack;
@@ -2051,8 +2052,13 @@ implementation
                   begin
                     { does pd inherit from (or is the same as) the class
                       that this method's category extended?
+
+                      Warning: this list contains both category and objcclass methods
+                       (for id.randommethod), so only check category methods here
                     }
-                    if pd.is_related(tobjectdef(tprocdef(tprocsym(srsym).procdeflist[i]).owner.defowner).childof) then
+                    defowner:=tobjectdef(tprocdef(tprocsym(srsym).procdeflist[i]).owner.defowner);
+                    if (oo_is_classhelper in defowner.objectoptions) and
+                       pd.is_related(defowner.childof) then
                       begin
                         { no need to keep looking. There might be other
                           categories that extend this, a parent or child

+ 45 - 0
tests/test/tobjc29.pp

@@ -0,0 +1,45 @@
+{ %target=darwin }
+{ %cpu=powerpc,powerpc64,i386,x86_64,arm }
+
+{$mode objfpc}
+{$modeswitch objectivec1}
+
+type
+  ta = objcclass(NSObject)
+    function tabaseproc(cp: longint): double; message 'tabaseproc:';
+  end;
+
+  ca = objccategory(ta)
+    function tabaseproc(cp: longint): double; reintroduce;
+  end;
+
+  nsobjectta = objccategory(NSObject)
+    function tabaseproc(cp: longint): double; message 'tabaseproc:';
+  end;
+
+function ta.tabaseproc(cp: longint): double;
+begin
+  result:=cp;
+  halt(1);
+end;
+
+function ca.tabaseproc(cp: longint): double;
+begin
+  result:=inherited tabaseproc(cp+1);
+end;
+
+function nsobjectta.tabaseproc(cp: longint): double;
+begin
+  if (cp<>4321) then
+    halt(1);
+  result:=123.625;
+end;
+
+var
+  a: ta;
+begin
+  a:=ta(ta.alloc).init;
+  if a.tabaseproc(4320)<>123.625 then
+    halt(2);
+  a.release;
+end.

+ 35 - 0
tests/test/tobjc29a.pp

@@ -0,0 +1,35 @@
+{ %target=darwin }
+{ %cpu=powerpc,powerpc64,i386,x86_64,arm }
+{ %fail }
+
+{$mode objfpc}
+{$modeswitch objectivec1}
+
+type
+  ta = objcclass(NSObject)
+    function tabaseproc(cp: longint): double; message 'tabaseproc:';
+  end;
+
+  ca = objccategory(ta)
+    function tabaseproc(cp: longint): double; reintroduce;
+  end;
+
+function ta.tabaseproc(cp: longint): double;
+begin
+  result:=cp;
+  halt(1);
+end;
+
+function ca.tabaseproc(cp: longint): double;
+begin
+  result:=inherited tabaseproc(cp+1);
+end;
+
+var
+  a: ta;
+begin
+  a:=ta(ta.alloc).init;
+  if a.tabaseproc(4320)<>123.625 then
+    halt(2);
+  a.release;
+end.

+ 47 - 0
tests/test/tobjc29b.pp

@@ -0,0 +1,47 @@
+{ %target=darwin }
+{ %cpu=powerpc,powerpc64,i386,x86_64,arm }
+{ %fail }
+
+{$mode objfpc}
+{$modeswitch objectivec1}
+
+type
+  ta = objcclass(NSObject)
+    function tabaseproc(cp: longint): double; message 'tabaseproc:';
+  end;
+
+  ca = objccategory(ta)
+    { should fail because of wrong message name }
+    function tabaseproc(cp: longint): double; message 'adifferentname:'; reintroduce;
+  end;
+
+  nsobjectta = objccategory(NSObject)
+    function tabaseproc(cp: longint): double; message 'tabaseproc:';
+  end;
+
+function ta.tabaseproc(cp: longint): double;
+begin
+  result:=cp;
+  halt(1);
+end;
+
+function ca.tabaseproc(cp: longint): double;
+begin
+  result:=inherited tabaseproc(cp+1);
+end;
+
+function nsobjectta.tabaseproc(cp: longint): double;
+begin
+  if (cp<>4321) then
+    halt(1);
+  result:=123.625;
+end;
+
+var
+  a: ta;
+begin
+  a:=ta(ta.alloc).init;
+  if a.tabaseproc(4320)<>123.625 then
+    halt(2);
+  a.release;
+end.