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

Reply via email to