summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Marr <gron@php.net>2011-11-01 15:25:24 +0000
committerStefan Marr <gron@php.net>2011-11-01 15:25:24 +0000
commit4591498df78e5f80b6ae70f04bb39812de82c2b4 (patch)
tree53f7b5bd746b44a844320dd8d67b8aac1d7ef6bf
parentd2881adcbc9be60de7e7d45a3316b0e11b7eb1e8 (diff)
downloadphp-git-4591498df78e5f80b6ae70f04bb39812de82c2b4.tar.gz
Fixed Bug #60153 (Interface method prototypes not enforced when implementd via traits.)
# Moved the freeing of overriden functions to a point after the check. # The new check comes after the normal inheritance check to give the first check # the opportunity to abort with a more detailed error. # Also fixed a small type in an unrelated test.
-rw-r--r--Zend/tests/traits/bug60153.phpt19
-rw-r--r--Zend/tests/traits/inheritance003.phpt2
-rw-r--r--Zend/zend_compile.c25
3 files changed, 37 insertions, 9 deletions
diff --git a/Zend/tests/traits/bug60153.phpt b/Zend/tests/traits/bug60153.phpt
new file mode 100644
index 0000000000..8f01e72c2d
--- /dev/null
+++ b/Zend/tests/traits/bug60153.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #60153 (Interface method prototypes not enforced when implementd via traits.)
+--FILE--
+<?php
+
+interface IFoo {
+ public function oneArgument($a);
+}
+
+trait TFoo {
+ public function oneArgument() {}
+}
+
+class C implements IFoo {
+ use TFoo;
+}
+
+--EXPECTF--
+Fatal error: Declaration of C::oneArgument() must be compatible with IFoo::oneArgument($a) in %s on line %d
diff --git a/Zend/tests/traits/inheritance003.phpt b/Zend/tests/traits/inheritance003.phpt
index b457a73fea..a41c4e484a 100644
--- a/Zend/tests/traits/inheritance003.phpt
+++ b/Zend/tests/traits/inheritance003.phpt
@@ -1,5 +1,5 @@
--TEST--
-Trait method overriddes base class method and satisfies prototype
+Trait method overrides base class method and satisfies prototype
--FILE--
<?php
error_reporting(E_ALL);
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index cb79e34bed..ea75088dd3 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -3831,14 +3831,6 @@ static int zend_traits_merge_functions_to_class(zend_function *fn TSRMLS_DC, int
add = 1; /* not found */
} else if (existing_fn->common.scope != ce) {
add = 1; /* or inherited from other class or interface */
- /* it is just a reference which was added to the subclass while doing the inheritance */
- /* so we can deleted now, and will add the overriding method afterwards */
-
- /* except, if we try to add an abstract function, then we should not delete the inherited one */
- /* delete inherited fn if the function to be added is not abstract */
- if ((fn->common.fn_flags & ZEND_ACC_ABSTRACT) == 0) {
- zend_hash_quick_del(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h);
- }
}
if (add) {
@@ -3871,6 +3863,23 @@ static int zend_traits_merge_functions_to_class(zend_function *fn TSRMLS_DC, int
if (prototype) {
do_inheritance_check_on_method(fn, prototype TSRMLS_CC);
}
+ /* one more thing: make sure we properly implement an abstract method */
+ if (existing_fn && existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
+ do_inheritance_check_on_method(fn, existing_fn TSRMLS_CC);
+ }
+
+ /* delete inherited fn if the function to be added is not abstract */
+ if (existing_fn
+ && existing_fn->common.scope != ce
+ && (fn->common.fn_flags & ZEND_ACC_ABSTRACT) == 0) {
+ /* it is just a reference which was added to the subclass while doing
+ the inheritance, so we can deleted now, and will add the overriding
+ method afterwards.
+ Except, if we try to add an abstract function, then we should not
+ delete the inherited one */
+ zend_hash_quick_del(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h);
+ }
+
if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;