Implement per-file strictness for scalar return types

This commit is contained in:
Andrea Faulds 2015-02-01 23:20:39 +00:00
parent 44ed070a9a
commit 5a7ac0fade
4 changed files with 28 additions and 10 deletions

View File

@ -1902,7 +1902,8 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) /* {{{ */ static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) /* {{{ */
{ {
if (return_info->type_hint != IS_UNDEF) { if (return_info->type_hint != IS_UNDEF) {
zend_emit_op(NULL, ZEND_VERIFY_RETURN_TYPE, expr, NULL); zend_op *opline = zend_emit_op(NULL, ZEND_VERIFY_RETURN_TYPE, expr, NULL);
opline->extended_value = (CG(declarables).strict_types ? 1 : 0);
} }
} }
/* }}} */ /* }}} */
@ -3238,7 +3239,18 @@ void zend_compile_return(zend_ast *ast) /* {{{ */
} }
if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
zend_emit_return_type_check(&expr_node, CG(active_op_array)->arg_info - 1); zend_arg_info *arg_info = CG(active_op_array)->arg_info - 1;
/* for scalar, weak return types, the value may be casted
* thus, for constants, we need to store them in a tmp var
*/
if (expr_node.op_type == IS_CONST && !CG(declarables).strict_types) {
znode expr_node_copy = expr_node;
zend_emit_op_tmp(&expr_node, ZEND_QM_ASSIGN, &expr_node_copy, NULL);
}
zend_emit_return_type_check(&expr_node, arg_info);
if (expr_node.op_type == IS_CONST) { if (expr_node.op_type == IS_CONST) {
zval_copy_ctor(&expr_node.u.constant); zval_copy_ctor(&expr_node.u.constant);
} }

View File

@ -874,7 +874,7 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
} }
#endif #endif
static void zend_verify_return_type(zend_function *zf, zval *ret) static void zend_verify_return_type(zend_function *zf, zval *ret, zend_bool strict)
{ {
zend_arg_info *ret_info = zf->common.arg_info - 1; zend_arg_info *ret_info = zf->common.arg_info - 1;
char *need_msg; char *need_msg;
@ -909,7 +909,7 @@ failure:
} }
return; return;
} }
if (!zend_verify_scalar_type_hint(ret_info->type_hint, ret, 1)) { if (!zend_verify_scalar_type_hint(ret_info->type_hint, ret, strict)) {
goto failure; goto failure;
} }
} }

View File

@ -2962,7 +2962,8 @@ ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED)
zend_free_op free_op1; zend_free_op free_op1;
retval_ptr = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); retval_ptr = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
zend_verify_return_type(EX(func), retval_ptr); /* extended_value stores strictness flag */
zend_verify_return_type(EX(func), retval_ptr, opline->extended_value);
} }
CHECK_EXCEPTION(); CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); ZEND_VM_NEXT_OPCODE();

View File

@ -6113,7 +6113,8 @@ static int ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND
retval_ptr = EX_CONSTANT(opline->op1); retval_ptr = EX_CONSTANT(opline->op1);
zend_verify_return_type(EX(func), retval_ptr); /* extended_value stores strictness flag */
zend_verify_return_type(EX(func), retval_ptr, opline->extended_value);
} }
CHECK_EXCEPTION(); CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); ZEND_VM_NEXT_OPCODE();
@ -10131,7 +10132,8 @@ static int ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_O
zend_free_op free_op1; zend_free_op free_op1;
retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
zend_verify_return_type(EX(func), retval_ptr); /* extended_value stores strictness flag */
zend_verify_return_type(EX(func), retval_ptr, opline->extended_value);
} }
CHECK_EXCEPTION(); CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); ZEND_VM_NEXT_OPCODE();
@ -14972,7 +14974,8 @@ static int ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_O
zend_free_op free_op1; zend_free_op free_op1;
retval_ptr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); retval_ptr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
zend_verify_return_type(EX(func), retval_ptr); /* extended_value stores strictness flag */
zend_verify_return_type(EX(func), retval_ptr, opline->extended_value);
} }
CHECK_EXCEPTION(); CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); ZEND_VM_NEXT_OPCODE();
@ -20235,7 +20238,8 @@ static int ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED_HANDLER(ZEN
retval_ptr = NULL; retval_ptr = NULL;
zend_verify_return_type(EX(func), retval_ptr); /* extended_value stores strictness flag */
zend_verify_return_type(EX(func), retval_ptr, opline->extended_value);
} }
CHECK_EXCEPTION(); CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); ZEND_VM_NEXT_OPCODE();
@ -28419,7 +28423,8 @@ static int ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OP
retval_ptr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var); retval_ptr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
zend_verify_return_type(EX(func), retval_ptr); /* extended_value stores strictness flag */
zend_verify_return_type(EX(func), retval_ptr, opline->extended_value);
} }
CHECK_EXCEPTION(); CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); ZEND_VM_NEXT_OPCODE();