diff options
author | Stefan Marr <gron@php.net> | 2011-11-01 15:25:24 +0000 |
---|---|---|
committer | Stefan Marr <gron@php.net> | 2011-11-01 15:25:24 +0000 |
commit | 4591498df78e5f80b6ae70f04bb39812de82c2b4 (patch) | |
tree | 53f7b5bd746b44a844320dd8d67b8aac1d7ef6bf | |
parent | d2881adcbc9be60de7e7d45a3316b0e11b7eb1e8 (diff) | |
download | php-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.phpt | 19 | ||||
-rw-r--r-- | Zend/tests/traits/inheritance003.phpt | 2 | ||||
-rw-r--r-- | Zend/zend_compile.c | 25 |
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; |