gron Mon, 15 Aug 2011 11:16:18 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=314943
Log: Fixed Bug #55355: Inheritance chain was not regarded when checking whether the abstract method of a trait is satisfied. Bug: https://bugs.php.net/55355 (Open) Unexpected fatal error when using abstract functions with traits Changed paths: A php/php-src/branches/PHP_5_4/Zend/tests/traits/bug55355.phpt U php/php-src/branches/PHP_5_4/Zend/zend_compile.c A php/php-src/trunk/Zend/tests/traits/bug55355.phpt U php/php-src/trunk/Zend/zend_compile.c Added: php/php-src/branches/PHP_5_4/Zend/tests/traits/bug55355.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/traits/bug55355.phpt (rev 0) +++ php/php-src/branches/PHP_5_4/Zend/tests/traits/bug55355.phpt 2011-08-15 11:16:18 UTC (rev 314943) @@ -0,0 +1,46 @@ +--TEST-- +Bug #55355 (Abstract functions required by a trait are not correctly found when implemented in an ancestor class) +--FILE-- +<?php + +// A trait that has a abstract function +trait ATrait { + function bar() { + $this->foo(); + } + abstract function foo(); +} + +// A class on the second level in the +// inheritance chain +class Level2Impl { + function foo() {} +} + +class Level1Indirect extends Level2Impl {} + +// A class on the first level in the +// inheritance chain +class Level1Direct { + function foo() {} +} + +// Trait Uses + +class Direct { + use ATrait; + function foo() {} +} + +class BaseL2 extends Level1Indirect { + use ATrait; +} + +class BaseL1 extends Level1Direct { + use ATrait; +} + +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 11:06:35 UTC (rev 314942) +++ php/php-src/branches/PHP_5_4/Zend/zend_compile.c 2011-08-15 11:16:18 UTC (rev 314943) @@ -3645,6 +3645,14 @@ zend_function* parent_function; if (ce->parent && zend_hash_quick_find(&ce->parent->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &parent_function) != FAILURE) { prototype = parent_function; /* ->common.fn_flags |= ZEND_ACC_ABSTRACT; */ + + /* we got that method in the parent class, and are going to override it, + except, if the trait is just asking to have an abstract method implemented. */ + if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { + /* then we clean up an skip this method */ + zend_function_dtor(fn); + return ZEND_HASH_APPLY_REMOVE; + } } fn->common.scope = ce; Added: php/php-src/trunk/Zend/tests/traits/bug55355.phpt =================================================================== --- php/php-src/trunk/Zend/tests/traits/bug55355.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/traits/bug55355.phpt 2011-08-15 11:16:18 UTC (rev 314943) @@ -0,0 +1,46 @@ +--TEST-- +Bug #55355 (Abstract functions required by a trait are not correctly found when implemented in an ancestor class) +--FILE-- +<?php + +// A trait that has a abstract function +trait ATrait { + function bar() { + $this->foo(); + } + abstract function foo(); +} + +// A class on the second level in the +// inheritance chain +class Level2Impl { + function foo() {} +} + +class Level1Indirect extends Level2Impl {} + +// A class on the first level in the +// inheritance chain +class Level1Direct { + function foo() {} +} + +// Trait Uses + +class Direct { + use ATrait; + function foo() {} +} + +class BaseL2 extends Level1Indirect { + use ATrait; +} + +class BaseL1 extends Level1Direct { + use ATrait; +} + +echo 'DONE'; +?> +--EXPECT-- +DONE Modified: php/php-src/trunk/Zend/zend_compile.c =================================================================== --- php/php-src/trunk/Zend/zend_compile.c 2011-08-15 11:06:35 UTC (rev 314942) +++ php/php-src/trunk/Zend/zend_compile.c 2011-08-15 11:16:18 UTC (rev 314943) @@ -3645,6 +3645,14 @@ zend_function* parent_function; if (ce->parent && zend_hash_quick_find(&ce->parent->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &parent_function) != FAILURE) { prototype = parent_function; /* ->common.fn_flags |= ZEND_ACC_ABSTRACT; */ + + /* we got that method in the parent class, and are going to override it, + except, if the trait is just asking to have an abstract method implemented. */ + if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { + /* then we clean up an skip this method */ + zend_function_dtor(fn); + return ZEND_HASH_APPLY_REMOVE; + } } fn->common.scope = ce;
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php