]> granicus.if.org Git - php/commitdiff
- Fixed ZEND_VERIFY_ABSTRACT_CLASS order when using traits
authorFelipe Pena <felipe@php.net>
Fri, 7 May 2010 16:29:15 +0000 (16:29 +0000)
committerFelipe Pena <felipe@php.net>
Fri, 7 May 2010 16:29:15 +0000 (16:29 +0000)
# It's the last one now, thus the traits can be used to implement interfaces

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

diff --git a/Zend/tests/traits/interface_001.phpt b/Zend/tests/traits/interface_001.phpt
new file mode 100644 (file)
index 0000000..a14f78e
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+Using traits to implement interface
+--FILE--
+<?php
+
+trait foo {
+       public function abc() {
+       }
+}
+
+interface baz {
+       public function abc();
+}
+
+class bar implements baz {
+       use foo;
+
+}
+
+new bar;
+print "OK\n";
+
+?>
+--EXPECT--
+OK
diff --git a/Zend/tests/traits/interface_002.phpt b/Zend/tests/traits/interface_002.phpt
new file mode 100644 (file)
index 0000000..462d73f
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+Checking error message when the trait doesn't implements the interface
+--FILE--
+<?php
+
+trait foo {
+       public function a() {
+       }
+}
+
+interface baz {
+       public function abc();
+}
+
+class bar implements baz {
+       use foo;
+
+}
+
+new bar;
+
+?>
+--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 (file)
index 0000000..aa13bd8
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Testing to implement Serializable interface by traits
+--FILE--
+<?php
+
+trait foo {
+       public function serialize() {
+               return 'foobar';
+       }
+       public function unserialize($x) {
+               var_dump($x);
+       }
+}
+
+class bar implements Serializable {
+       use foo;
+}
+
+var_dump($o = serialize(new bar));
+var_dump(unserialize($o));
+
+?>
+--EXPECTF--
+string(20) "C:3:"bar":6:{foobar}"
+string(6) "foobar"
+object(bar)#%d (0) {
+}
index 5d3865fbaee225f3455b841876603a786253373d..20b75ad09be9dbe68b808a5e716c1f58b22a8e1f 100644 (file)
@@ -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;
 }
 /* }}} */