From: Felipe Pena Date: Fri, 7 May 2010 16:29:15 +0000 (+0000) Subject: - Fixed ZEND_VERIFY_ABSTRACT_CLASS order when using traits X-Git-Tag: php-5.4.0alpha1~191^2~1534 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c95b4ace40e61ed2422612125a8f5ff0c465e49a;p=php - Fixed ZEND_VERIFY_ABSTRACT_CLASS order when using traits # It's the last one now, thus the traits can be used to implement interfaces --- diff --git a/Zend/tests/traits/interface_001.phpt b/Zend/tests/traits/interface_001.phpt new file mode 100644 index 0000000000..a14f78efc8 --- /dev/null +++ b/Zend/tests/traits/interface_001.phpt @@ -0,0 +1,25 @@ +--TEST-- +Using traits to implement interface +--FILE-- + +--EXPECT-- +OK diff --git a/Zend/tests/traits/interface_002.phpt b/Zend/tests/traits/interface_002.phpt new file mode 100644 index 0000000000..462d73fbd6 --- /dev/null +++ b/Zend/tests/traits/interface_002.phpt @@ -0,0 +1,24 @@ +--TEST-- +Checking error message when the trait doesn't implements the interface +--FILE-- + +--EXPECTF-- +Fatal error: Class bar contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (baz::abc) in %s on line %d diff --git a/Zend/tests/traits/interface_003.phpt b/Zend/tests/traits/interface_003.phpt new file mode 100644 index 0000000000..aa13bd8b59 --- /dev/null +++ b/Zend/tests/traits/interface_003.phpt @@ -0,0 +1,27 @@ +--TEST-- +Testing to implement Serializable interface by traits +--FILE-- + +--EXPECTF-- +string(20) "C:3:"bar":6:{foobar}" +string(6) "foobar" +object(bar)#%d (0) { +} diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 5d3865fbae..20b75ad09b 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4461,6 +4461,22 @@ void zend_do_end_class_declaration(const znode *class_token, const znode *parent } ce->line_end = zend_get_compiled_lineno(TSRMLS_C); + + /* Check for traits and proceed like with interfaces. + * The only difference will be a combined handling of them in the end. + * Thus, we need another opcode here. */ + if (ce->num_traits > 0) { + zend_op *opline; + + ce->traits = NULL; + ce->num_traits = 0; + ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS; + + /* opcode generation: */ + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_BIND_TRAITS; + SET_NODE(opline->op1, &CG(implementing_class)); + } if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) && ((parent_token->op_type != IS_UNUSED) || (ce->num_interfaces > 0))) { @@ -4479,22 +4495,6 @@ void zend_do_end_class_declaration(const znode *class_token, const znode *parent ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES; } - /* Check for traits and proceed like with interfaces. - * The only difference will be a combined handling of them in the end. - * Thus, we need another opcode here. */ - if (ce->num_traits > 0) { - zend_op *opline; - - ce->traits = NULL; - ce->num_traits = 0; - ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS; - - /* opcode generation: */ - opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_BIND_TRAITS; - SET_NODE(opline->op1, &CG(implementing_class)); - } - CG(active_class_entry) = NULL; } /* }}} */