gron Mon, 15 Aug 2011 22:16:58 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=314981
Log: Bug #55424 Fatal error when calling a method from a trait that is defined in parent class and required by using an abstract method in the trait. # The method got unconditionally deleted from the class, since it was assumed that we override it, but we did not in case of abstract methods coming from a trait. Thus, dont delete when we try to merge in an abstract method. Bug: https://bugs.php.net/55424 (Open) Fatal error when calling a method from a trait that is defined in parent class Changed paths: A php/php-src/branches/PHP_5_4/Zend/tests/traits/bug55424.phpt U php/php-src/branches/PHP_5_4/Zend/zend_compile.c A php/php-src/trunk/Zend/tests/traits/bug55424.phpt U php/php-src/trunk/Zend/zend_compile.c Added: php/php-src/branches/PHP_5_4/Zend/tests/traits/bug55424.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/traits/bug55424.phpt (rev 0) +++ php/php-src/branches/PHP_5_4/Zend/tests/traits/bug55424.phpt 2011-08-15 22:16:58 UTC (rev 314981) @@ -0,0 +1,35 @@ +--TEST-- +Bug #55424 (Method got missing from class when a trait defined an abstract method to express a requirement) +--FILE-- +<?php + + trait ATrait + { + function setRequired() + { + $this->setAttribute(); + } + + abstract function setAttribute(); + } + + class Base + { + function setAttribute() { } + } + + class MyClass extends Base + { + use ATrait; + } + + $i = new Base(); + $i->setAttribute(); + + $t = new MyClass(); + /* setAttribute used to disappear for no good reason. */ + $t->setRequired(); + echo 'DONE'; +?> +--EXPECT-- +DONE Modified: php/php-src/branches/PHP_5_4/Zend/zend_compile.c =================================================================== --- php/php-src/branches/PHP_5_4/Zend/zend_compile.c 2011-08-15 20:41:33 UTC (rev 314980) +++ php/php-src/branches/PHP_5_4/Zend/zend_compile.c 2011-08-15 22:16:58 UTC (rev 314981) @@ -3635,10 +3635,13 @@ } 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 */ - /* prototype = existing_fn; */ - /* memory is scrambled anyway???? */ - /* function_add_ref(prototype); */ - zend_hash_quick_del(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h); + /* 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) { Added: php/php-src/trunk/Zend/tests/traits/bug55424.phpt =================================================================== --- php/php-src/trunk/Zend/tests/traits/bug55424.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/traits/bug55424.phpt 2011-08-15 22:16:58 UTC (rev 314981) @@ -0,0 +1,35 @@ +--TEST-- +Bug #55424 (Method got missing from class when a trait defined an abstract method to express a requirement) +--FILE-- +<?php + + trait ATrait + { + function setRequired() + { + $this->setAttribute(); + } + + abstract function setAttribute(); + } + + class Base + { + function setAttribute() { } + } + + class MyClass extends Base + { + use ATrait; + } + + $i = new Base(); + $i->setAttribute(); + + $t = new MyClass(); + /* setAttribute used to disappear for no good reason. */ + $t->setRequired(); + echo 'DONE'; +?> +--EXPECT-- +DONE Modified: php/php-src/trunk/Zend/zend_compile.c =================================================================== --- php/php-src/trunk/Zend/zend_compile.c 2011-08-15 20:41:33 UTC (rev 314980) +++ php/php-src/trunk/Zend/zend_compile.c 2011-08-15 22:16:58 UTC (rev 314981) @@ -3635,10 +3635,13 @@ } 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 */ - /* prototype = existing_fn; */ - /* memory is scrambled anyway???? */ - /* function_add_ref(prototype); */ - zend_hash_quick_del(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h); + /* 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) {
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php