mirror of
https://github.com/php/php-src.git
synced 2026-04-28 02:33:17 +02:00
Implemented internal function return types
This commit is contained in:
@@ -2002,6 +2002,10 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
|
||||
internal_function->num_args--;
|
||||
}
|
||||
if (info->type_hint) {
|
||||
if (info->type_hint == IS_OBJECT) {
|
||||
ZEND_ASSERT(info->class_name);
|
||||
}
|
||||
|
||||
internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -105,6 +105,13 @@ typedef struct _zend_fcall_info_cache {
|
||||
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, NULL, type_hint, pass_by_ref, allow_null, 0 },
|
||||
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) { #name, NULL, 0, pass_by_ref, 0, 1 },
|
||||
|
||||
|
||||
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, class_name, allow_null) \
|
||||
static const zend_internal_arg_info name[] = { \
|
||||
{ (const char*)(zend_uintptr_t)(required_num_args), class_name, type, return_reference, allow_null, 0 },
|
||||
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(name, type, class_name, allow_null) \
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, 0, -1, type, class_name, allow_null)
|
||||
|
||||
#define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \
|
||||
static const zend_internal_arg_info name[] = { \
|
||||
{ (const char*)(zend_uintptr_t)(required_num_args), NULL, 0, return_reference, 0, 0 },
|
||||
|
||||
+2
-2
@@ -780,12 +780,12 @@ static void zend_verify_return_type(zend_function *zf, zval *ret)
|
||||
char *class_name;
|
||||
|
||||
if (Z_TYPE_P(ret) == IS_OBJECT) {
|
||||
need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
|
||||
need_msg = zf->type == ZEND_INTERNAL_FUNCTION ? zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce) : zend_verify_arg_class_kind(ret_info, &class_name, &ce);
|
||||
if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) {
|
||||
zend_verify_return_error(E_RECOVERABLE_ERROR, zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val);
|
||||
}
|
||||
} else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) {
|
||||
need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
|
||||
need_msg = zf->type == ZEND_INTERNAL_FUNCTION ? zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce) : zend_verify_arg_class_kind(ret_info, &class_name, &ce);
|
||||
zend_verify_return_error(E_RECOVERABLE_ERROR, zf, need_msg, class_name, zend_zval_type_name(ret), "");
|
||||
}
|
||||
} else if (ret_info->type_hint) {
|
||||
|
||||
@@ -2875,6 +2875,10 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
|
||||
zend_vm_stack_free_args(call);
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
|
||||
zend_verify_return_type(fbc, EX_VAR(opline->result.var));
|
||||
}
|
||||
|
||||
if (!RETURN_VALUE_USED(opline)) {
|
||||
zval_ptr_dtor(EX_VAR(opline->result.var));
|
||||
}
|
||||
|
||||
@@ -601,6 +601,10 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
zend_vm_stack_free_args(call);
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
|
||||
zend_verify_return_type(fbc, EX_VAR(opline->result.var));
|
||||
}
|
||||
|
||||
if (!RETURN_VALUE_USED(opline)) {
|
||||
zval_ptr_dtor(EX_VAR(opline->result.var));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user