Fixed bug #42802 (Namespace not supported in typehints)

This commit is contained in:
Dmitry Stogov 2007-10-01 10:37:14 +00:00
parent 3a3a7e7441
commit 41e9b6b61c
7 changed files with 67 additions and 19 deletions

1
NEWS
View File

@ -32,6 +32,7 @@ PHP NEWS
- Improved and cleaned CGI code. FastCGI is now always enabled and can not be
disabled. See sapi/cgi/CHANGES for more details. (Dmitry)
- Fixed bug #42802 (Namespace not supported in typehints). (Dmitry)
- Fixed bug #42798 (__autoload() not triggered for classes used in method
signature). (Dmitry)
- Fixed bug #42657 (ini_get() returns incorrect value when default is NULL).

45
Zend/tests/bug42802.phpt Executable file
View File

@ -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

View File

@ -34,6 +34,7 @@
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;
@ -1318,6 +1319,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 (class_type->u.constant.type == IS_STRING) {
zend_resolve_class_name(class_type, &opline->extended_value, 1 TSRMLS_CC);
cur_arg_info->class_name = class_type->u.constant.value.str.val;
cur_arg_info->class_name_len = class_type->u.constant.value.str.len;
if (op == ZEND_RECV_INIT) {

View File

@ -456,9 +456,9 @@ static inline void make_real_object(zval **object_ptr TSRMLS_DC)
}
}
static inline char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, const char **class_name, zend_class_entry **pce TSRMLS_DC)
static inline char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, const char **class_name, zend_class_entry **pce TSRMLS_DC)
{
*pce = zend_fetch_class(cur_arg_info->class_name, cur_arg_info->class_name_len, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC);
*pce = zend_fetch_class(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) {
@ -491,7 +491,7 @@ static inline int zend_verify_arg_error(zend_function *zf, zend_uint arg_num, co
return 0;
}
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;
@ -508,16 +508,16 @@ static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zva
const char *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", "" 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), "" TSRMLS_CC);
}
} else if (cur_arg_info->array_type_hint) {

View File

@ -450,9 +450,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;}
;

View File

@ -1950,7 +1950,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--;
}
}
@ -2381,7 +2381,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
char *class_name = get_active_class_name(&space TSRMLS_CC);
zend_execute_data *ptr = EX(prev_execute_data);
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC);
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 %s%s%s(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
} else {
@ -2394,7 +2394,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);
@ -2432,13 +2432,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 {

View File

@ -184,7 +184,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--;
}
}
@ -358,7 +358,7 @@ static int ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *class_name = get_active_class_name(&space TSRMLS_CC);
zend_execute_data *ptr = EX(prev_execute_data);
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC);
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 %s%s%s(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
} else {
@ -371,7 +371,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);
@ -742,13 +742,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 {