]> granicus.if.org Git - php/commitdiff
Fix #76773 - Methods with a concrete scope need to be added again
authorChris Wright <daverandom@php.net>
Tue, 21 Aug 2018 16:40:06 +0000 (17:40 +0100)
committerChristoph M. Becker <cmbecker69@gmx.de>
Wed, 22 Aug 2018 12:08:15 +0000 (14:08 +0200)
NEWS
Zend/tests/traits/bug76773.phpt [new file with mode: 0644]
Zend/zend_inheritance.c

diff --git a/NEWS b/NEWS
index 0b3c7ce0d7f35409f0c5d2a335a92921ae65da48..bc69712105bb5588eead2afc7d7ef2c306dfd93c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ PHP                                                                        NEWS
 ?? ??? ????, PHP 7.3.0beta3
 
 - Core:
+  . Fixed #76773 (Traits used on the parent are ignored for child classes).
+    (daverandom)
   . Fixed #76767 (‘asm’ operand has impossible constraints in zend_operators.h).
     (ondrej)
   . Fixed bug #76754 (parent private constant in extends class memory leak).
diff --git a/Zend/tests/traits/bug76773.phpt b/Zend/tests/traits/bug76773.phpt
new file mode 100644 (file)
index 0000000..2601d1c
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Bug #76773 (Traits used on the parent are ignored for child classes)
+--FILE--
+<?php
+
+trait MyTrait
+{
+    public function hello()
+    {
+        echo __CLASS__, "\n";
+
+        if (\is_callable(array('parent', __FUNCTION__))) {
+            parent::hello();
+        }
+    }
+}
+
+class ParentClass
+{
+    use MyTrait;
+}
+
+class ChildClass extends ParentClass
+{
+    use MyTrait;
+}
+
+$c = new ChildClass();
+$c->hello();
+
+--EXPECT--
+ChildClass
+ParentClass
index 8af409f1919e2a5463f603059d32d7331123e03b..d692f3410c7ccd63ea53f5751891266dd8df73ef 100644 (file)
@@ -1178,10 +1178,11 @@ static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_s
        zend_function *new_fn;
 
        if ((existing_fn = zend_hash_find_ptr(&ce->function_table, key)) != NULL) {
-               /* if it is the same function with the same visibility regardless of where it is coming from */
-               /* there is no conflict and we do not need to add it again */
+               /* if it is the same function with the same visibility and has not been assigned a class scope yet, regardless
+                * of where it is coming from there is no conflict and we do not need to add it again */
                if (existing_fn->op_array.opcodes == fn->op_array.opcodes &&
-                       (existing_fn->common.fn_flags & ZEND_ACC_PPP_MASK) == (fn->common.fn_flags & ZEND_ACC_PPP_MASK)) {
+                       (existing_fn->common.fn_flags & ZEND_ACC_PPP_MASK) == (fn->common.fn_flags & ZEND_ACC_PPP_MASK) &&
+                       (existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
                        return;
                }