]> granicus.if.org Git - php/commitdiff
Bug #55424 Fatal error when calling a method from a trait that is defined in parent...
authorStefan Marr <gron@php.net>
Mon, 15 Aug 2011 22:16:58 +0000 (22:16 +0000)
committerStefan Marr <gron@php.net>
Mon, 15 Aug 2011 22:16:58 +0000 (22:16 +0000)
# 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.

Zend/tests/traits/bug55424.phpt [new file with mode: 0644]
Zend/zend_compile.c

diff --git a/Zend/tests/traits/bug55424.phpt b/Zend/tests/traits/bug55424.phpt
new file mode 100644 (file)
index 0000000..b6c3b54
--- /dev/null
@@ -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
index 59e0193194856f22e0c0211256c8a952c9043b33..cd883cbe6ff15035ea11bbaadc50887f5909eb21 100644 (file)
@@ -3635,10 +3635,13 @@ static int zend_traits_merge_functions_to_class(zend_function *fn TSRMLS_DC, int
        } 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) {