]> granicus.if.org Git - php/commitdiff
Fixed bug #42802 (Namespace not supported in typehints)
authorDmitry Stogov <dmitry@php.net>
Mon, 1 Oct 2007 10:37:36 +0000 (10:37 +0000)
committerDmitry Stogov <dmitry@php.net>
Mon, 1 Oct 2007 10:37:36 +0000 (10:37 +0000)
Zend/tests/bug42802.phpt [new file with mode: 0755]
Zend/zend_compile.c
Zend/zend_execute.c
Zend/zend_language_parser.y
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/bug42802.phpt b/Zend/tests/bug42802.phpt
new file mode 100755 (executable)
index 0000000..80ae02b
--- /dev/null
@@ -0,0 +1,45 @@
+--TEST--
+Bug #42802 (Namespace not supported in typehints)
+--FILE--
+<?php
+namespace foo;
+
+class bar {
+}
+
+function test1(bar $bar) {
+       echo "ok\n";
+}
+
+function test2(foo::bar $bar) {
+        echo "ok\n";
+}
+function test3(::foo::bar $bar) {
+        echo "ok\n";
+}
+function test4(::Exception $e) {
+       echo "ok\n";
+}
+function test5(Exception $e) {
+       echo "ok\n";
+}
+function test6(::bar $bar) {
+        echo "bug\n";
+}
+
+$x = new bar();
+$y = new Exception();
+test1($x);
+test2($x);
+test3($x);
+test4($y);
+test5($y);
+test6($x);
+--EXPECTF--
+ok
+ok
+ok
+ok
+ok
+
+Catchable fatal error: Argument 1 passed to foo::test6() must be an instance of bar, instance of foo::bar given, called in %sbug42802.php on line 23
index bda7271ed653e99d1b4a424ca28111f3c2008a84..750b38f884eab8c891322e46eecdd84eaab8deef 100644 (file)
@@ -29,6 +29,8 @@
 ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
 ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
 
+void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_name TSRMLS_DC);
+
 #ifndef ZTS
 ZEND_API zend_compiler_globals compiler_globals;
 ZEND_API zend_executor_globals executor_globals;
@@ -1412,6 +1414,7 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
        if (class_type->op_type != IS_UNUSED) {
                cur_arg_info->allow_null = 0;
                if (Z_TYPE(class_type->u.constant) == IS_STRING || Z_TYPE(class_type->u.constant) == IS_UNICODE) {
+                       zend_resolve_class_name(class_type, &opline->extended_value, 1 TSRMLS_CC);
                        cur_arg_info->class_name = Z_UNIVAL(class_type->u.constant);
                        cur_arg_info->class_name_len = Z_UNILEN(class_type->u.constant);
                        if (op == ZEND_RECV_INIT) {
index 3663199b8e2b385c6dee70ee83ef34388d840dc3..4df2fe9d36970edec730724dc8eca7739f7900d5 100644 (file)
@@ -497,9 +497,9 @@ static inline void make_real_object(zval **object_ptr TSRMLS_DC) /* {{{ */
 }
 /* }}} */
 
-static inline char * zend_verify_arg_class_kind(zend_arg_info *cur_arg_info, zstr *class_name, zend_class_entry **pce TSRMLS_DC) /* {{{ */
+static inline char * zend_verify_arg_class_kind(zend_arg_info *cur_arg_info, ulong fetch_type, zstr *class_name, zend_class_entry **pce TSRMLS_DC) /* {{{ */
 {
-       *pce = zend_u_fetch_class(UG(unicode) ? IS_UNICODE : IS_STRING, cur_arg_info->class_name, cur_arg_info->class_name_len, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC);
+       *pce = zend_u_fetch_class(UG(unicode) ? IS_UNICODE : IS_STRING, cur_arg_info->class_name, cur_arg_info->class_name_len, (fetch_type | ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC);
 
        *class_name = (*pce) ? (*pce)->name: cur_arg_info->class_name;
        if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
@@ -534,7 +534,7 @@ static inline int zend_verify_arg_error(zend_function *zf, zend_uint arg_num, ze
 }
 /* }}} */
 
-static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg TSRMLS_DC) /* {{{ */
+static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC) /* {{{ */
 {
        zend_arg_info *cur_arg_info;
        char *need_msg;
@@ -550,16 +550,16 @@ static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zva
         zstr class_name;
 
         if (!arg) {
-            need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC);
+            need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
             return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "none", EMPTY_ZSTR TSRMLS_CC);
         }
         if (Z_TYPE_P(arg) == IS_OBJECT) {
-            need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC);
+            need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
             if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
                 return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name TSRMLS_CC);
             }
         } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
-            need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC);
+            need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
             return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, zend_zval_type_name(arg), EMPTY_ZSTR TSRMLS_CC);
         }
        } else if (cur_arg_info->array_type_hint) {
index bf6b472d2413773ef6cfed9042b3ccefaaa5b790..0150d30e96ecd24bd3c5665005340278e2b038ea 100644 (file)
@@ -455,9 +455,9 @@ non_empty_parameter_list:
 
 
 optional_class_type:
-               /* empty */             { $$.op_type = IS_UNUSED; }
-       |       T_STRING                { $$ = $1; }
-       |       T_ARRAY         { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_NULL;}
+               /* empty */                                     { $$.op_type = IS_UNUSED; }
+       |       fully_qualified_class_name      { $$ = $1; }
+       |       T_ARRAY                                         { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_NULL;}
 ;
 
 
index 20383041b1a879f3a4c0f251c96e580994656126..8fa69d1f6b2aeaa15eff8959e1d22df7d6d97f20 100644 (file)
@@ -2025,7 +2025,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
                        arg_count = (ulong)(zend_uintptr_t) *p;
 
                        while (arg_count>0) {
-                               zend_verify_arg_type(EX(function_state).function, ++i, *(p-arg_count) TSRMLS_CC);
+                               zend_verify_arg_type(EX(function_state).function, ++i, *(p-arg_count), 0 TSRMLS_CC);
                                arg_count--;
                        }
                }
@@ -2440,7 +2440,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
                zstr class_name = get_active_class_name(&space TSRMLS_CC);
                zend_execute_data *ptr = EX(prev_execute_data);
 
-               if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC)) {
+               if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL, opline->extended_value TSRMLS_CC)) {
                        if(ptr && ptr->op_array) {
                                zend_error(E_WARNING, "Missing argument %ld for %v%s%v(), called in %s on line %d and defined", Z_LVAL(opline->op1.u.constant), class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
                        } else {
@@ -2454,7 +2454,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
                zend_free_op free_res;
                zval **var_ptr;
 
-               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param TSRMLS_CC);
+               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param, opline->extended_value TSRMLS_CC);
                var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W);
                if (PZVAL_IS_REF(*param)) {
                        zend_assign_to_variable_reference(var_ptr, param TSRMLS_CC);
@@ -2492,13 +2492,13 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
                        param = NULL;
                        assignment_value = &opline->op2.u.constant;
                }
-               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value TSRMLS_CC);
+               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC);
                zend_assign_to_variable(NULL, &opline->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC);
        } else {
                zval **var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W);
 
                assignment_value = *param;
-               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value TSRMLS_CC);
+               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC);
                if (PZVAL_IS_REF(assignment_value)) {
                        zend_assign_to_variable_reference(var_ptr, param TSRMLS_CC);
                } else {
index 89a484e41f5ac969471be694427deebd4622fef2..6fc4f2910a75db304b92be439a8aa1a3f69745f6 100644 (file)
@@ -192,7 +192,7 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                        arg_count = (ulong)(zend_uintptr_t) *p;
 
                        while (arg_count>0) {
-                               zend_verify_arg_type(EX(function_state).function, ++i, *(p-arg_count) TSRMLS_CC);
+                               zend_verify_arg_type(EX(function_state).function, ++i, *(p-arg_count), 0 TSRMLS_CC);
                                arg_count--;
                        }
                }
@@ -366,7 +366,7 @@ static int ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                zstr class_name = get_active_class_name(&space TSRMLS_CC);
                zend_execute_data *ptr = EX(prev_execute_data);
 
-               if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC)) {
+               if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL, opline->extended_value TSRMLS_CC)) {
                        if(ptr && ptr->op_array) {
                                zend_error(E_WARNING, "Missing argument %ld for %v%s%v(), called in %s on line %d and defined", Z_LVAL(opline->op1.u.constant), class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
                        } else {
@@ -380,7 +380,7 @@ static int ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                zend_free_op free_res;
                zval **var_ptr;
 
-               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param TSRMLS_CC);
+               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param, opline->extended_value TSRMLS_CC);
                var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W);
                if (PZVAL_IS_REF(*param)) {
                        zend_assign_to_variable_reference(var_ptr, param TSRMLS_CC);
@@ -772,13 +772,13 @@ static int ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        param = NULL;
                        assignment_value = &opline->op2.u.constant;
                }
-               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value TSRMLS_CC);
+               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC);
                zend_assign_to_variable(NULL, &opline->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC);
        } else {
                zval **var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W);
 
                assignment_value = *param;
-               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value TSRMLS_CC);
+               zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC);
                if (PZVAL_IS_REF(assignment_value)) {
                        zend_assign_to_variable_reference(var_ptr, param TSRMLS_CC);
                } else {