]> granicus.if.org Git - php/commitdiff
Fixed type-hint compatibility check in namespaces
authorDmitry Stogov <dmitry@php.net>
Fri, 9 Nov 2007 13:35:22 +0000 (13:35 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 9 Nov 2007 13:35:22 +0000 (13:35 +0000)
Zend/tests/ns_055.phpt [new file with mode: 0755]
Zend/tests/ns_056.phpt [new file with mode: 0755]
Zend/zend_compile.c

diff --git a/Zend/tests/ns_055.phpt b/Zend/tests/ns_055.phpt
new file mode 100755 (executable)
index 0000000..83d0613
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+055: typehints in namespaces
+--FILE--
+<?php
+namespace test::ns1;
+
+class Foo {
+       function test1(Foo $x) {
+               echo "ok\n";
+       }
+       function test2(test::ns1::Foo $x) {
+               echo "ok\n";
+       }
+       function test3(Exception $x) {
+               echo "ok\n";
+       }
+       function test4(::Exception $x) {
+               echo "ok\n";
+       }
+}
+
+$foo = new Foo();
+$ex = new Exception();
+$foo->test1($foo);
+$foo->test2($foo);
+$foo->test3($ex);
+$foo->test4($ex);
+?>
+--EXPECT--
+ok
+ok
+ok
+ok
diff --git a/Zend/tests/ns_056.phpt b/Zend/tests/ns_056.phpt
new file mode 100755 (executable)
index 0000000..0bc4f00
--- /dev/null
@@ -0,0 +1,31 @@
+--TEST--
+056: type-hint compatibility in namespaces
+--SKIPIF--
+<?php if (!extension_loaded("spl")) die("skip SPL is no available"); ?>
+--FILE--
+<?php
+namespace test::ns1;
+
+class Foo implements SplObserver {
+       function update(SplSubject $x) {
+               echo "ok\n";
+       }
+}
+
+class Bar implements SplSubject {
+       function attach(SplObserver $x) {
+               echo "ok\n";
+       }
+       function notify() {
+       }
+       function detach(SplObserver $x) {
+       }
+}
+$foo = new Foo();
+$bar = new Bar();
+$bar->attach($foo);
+$foo->update($bar);
+?>
+--EXPECT--
+ok
+ok
index 37d27d7a98097d6b1fd461856471d54533a9a8e5..f65cd5a6a6ac32b25ca61704e28d47a23890e058 100644 (file)
@@ -2372,7 +2372,31 @@ static zend_bool zend_do_perform_implementation_check(zend_function *fe, zend_fu
                        (fe->common.arg_info[i].class_name_len != proto->common.arg_info[i].class_name_len ||
                         (!UG(unicode) && zend_binary_strcasecmp(fe->common.arg_info[i].class_name.s, fe->common.arg_info[i].class_name_len, proto->common.arg_info[i].class_name.s, proto->common.arg_info[i].class_name_len) != 0) ||
                         (UG(unicode) && zend_u_binary_strcasecmp(fe->common.arg_info[i].class_name.u, fe->common.arg_info[i].class_name_len, proto->common.arg_info[i].class_name.u, proto->common.arg_info[i].class_name_len) != 0))) {
-                       return 0;
+
+                       zstr colon;
+
+                       if (fe->common.type == ZEND_USER_FUNCTION &&
+                           ((UG(unicode) &&
+                             u_strchr(proto->common.arg_info[i].class_name.u, ':') == NULL &&
+                             (colon.u = u_memrchr(fe->common.arg_info[i].class_name.u, ':', fe->common.arg_info[i].class_name_len)) != NULL &&
+                             fe->common.arg_info[i].class_name_len - (colon.u + 1 - fe->common.arg_info[i].class_name.u) == proto->common.arg_info[i].class_name_len &&
+                             zend_u_binary_strcasecmp(colon.u + 1, proto->common.arg_info[i].class_name_len, proto->common.arg_info[i].class_name.u, proto->common.arg_info[i].class_name_len) == 0) ||
+                            (!UG(unicode) &&
+                             strchr(proto->common.arg_info[i].class_name.s, ':') == NULL &&
+                             (colon.s = zend_memrchr(fe->common.arg_info[i].class_name.s, ':', fe->common.arg_info[i].class_name_len)) != NULL &&
+                             fe->common.arg_info[i].class_name_len - (colon.s + 1 - fe->common.arg_info[i].class_name.s) == proto->common.arg_info[i].class_name_len &&
+                             zend_binary_strcasecmp(colon.s + 1, proto->common.arg_info[i].class_name_len, proto->common.arg_info[i].class_name.s, proto->common.arg_info[i].class_name_len) == 0))) {
+
+                               efree((char*)fe->common.arg_info[i].class_name.v);
+                               if (UG(unicode)) {
+                                       fe->common.arg_info[i].class_name.u = eustrndup(proto->common.arg_info[i].class_name.u, proto->common.arg_info[i].class_name_len);
+                               } else {
+                                       fe->common.arg_info[i].class_name.s = estrndup(proto->common.arg_info[i].class_name.s, proto->common.arg_info[i].class_name_len);
+                               }
+                               fe->common.arg_info[i].class_name_len = proto->common.arg_info[i].class_name_len;
+                       } else {
+                               return 0;
+                       }
                }
                if (fe->common.arg_info[i].array_type_hint != proto->common.arg_info[i].array_type_hint) {
                        /* Only one has an array type hint and the other one doesn't */