gron Tue, 01 Nov 2011 15:25:24 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=318650
Log: 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. Bug: https://bugs.php.net/60153 (Open) Interface method prototypes not enforced when implementd via traits. Changed paths: A php/php-src/branches/PHP_5_4/Zend/tests/traits/bug60153.phpt U php/php-src/branches/PHP_5_4/Zend/tests/traits/inheritance003.phpt U php/php-src/branches/PHP_5_4/Zend/zend_compile.c A php/php-src/trunk/Zend/tests/traits/bug60153.phpt U php/php-src/trunk/Zend/tests/traits/inheritance003.phpt U php/php-src/trunk/Zend/zend_compile.c Added: php/php-src/branches/PHP_5_4/Zend/tests/traits/bug60153.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/traits/bug60153.phpt (rev 0) +++ php/php-src/branches/PHP_5_4/Zend/tests/traits/bug60153.phpt 2011-11-01 15:25:24 UTC (rev 318650) @@ -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 Modified: php/php-src/branches/PHP_5_4/Zend/tests/traits/inheritance003.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/traits/inheritance003.phpt 2011-11-01 15:15:51 UTC (rev 318649) +++ php/php-src/branches/PHP_5_4/Zend/tests/traits/inheritance003.phpt 2011-11-01 15:25:24 UTC (rev 318650) @@ -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); Modified: php/php-src/branches/PHP_5_4/Zend/zend_compile.c =================================================================== --- php/php-src/branches/PHP_5_4/Zend/zend_compile.c 2011-11-01 15:15:51 UTC (rev 318649) +++ php/php-src/branches/PHP_5_4/Zend/zend_compile.c 2011-11-01 15:25:24 UTC (rev 318650) @@ -3831,14 +3831,6 @@ 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,7 +3863,24 @@ 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; } Added: php/php-src/trunk/Zend/tests/traits/bug60153.phpt =================================================================== --- php/php-src/trunk/Zend/tests/traits/bug60153.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/traits/bug60153.phpt 2011-11-01 15:25:24 UTC (rev 318650) @@ -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 Modified: php/php-src/trunk/Zend/tests/traits/inheritance003.phpt =================================================================== --- php/php-src/trunk/Zend/tests/traits/inheritance003.phpt 2011-11-01 15:15:51 UTC (rev 318649) +++ php/php-src/trunk/Zend/tests/traits/inheritance003.phpt 2011-11-01 15:25:24 UTC (rev 318650) @@ -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); Modified: php/php-src/trunk/Zend/zend_compile.c =================================================================== --- php/php-src/trunk/Zend/zend_compile.c 2011-11-01 15:15:51 UTC (rev 318649) +++ php/php-src/trunk/Zend/zend_compile.c 2011-11-01 15:25:24 UTC (rev 318650) @@ -3831,14 +3831,6 @@ 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,7 +3863,24 @@ 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; }
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php