static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) /* {{{ */
{
- zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
-
if (return_info->type_hint != IS_UNDEF) {
zend_op *opline = zend_emit_op(NULL, ZEND_VERIFY_RETURN_TYPE, expr, NULL);
- opline->extended_value = (returns_reference ? ZEND_RETURN_REF : 0);
+ if (expr && expr->op_type == IS_CONST) {
+ opline->result_type = expr->op_type = IS_TMP_VAR;
+ opline->result.var = expr->u.op.var = get_temporary_variable(CG(active_op_array));
+ }
}
}
/* }}} */
/* Generator return types are handled separately */
if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
- 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(active_op_array)->fn_flags & ZEND_ACC_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) {
- zval_copy_ctor(&expr_node.u.constant);
- }
+ zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1);
}
opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
&expr_node, NULL);
#if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
USE_OPLINE
#endif
+
SAVE_OPLINE();
if (OP1_TYPE == IS_UNUSED) {
zend_verify_missing_return_type(EX(func));
} else {
/* prevents "undefined variable opline" errors */
-#if OP1_TYPE != IS_UNUSED
+#if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
zval *retval_ptr;
zend_free_op free_op1;
zend_arg_info *ret_info = EX(func)->common.arg_info - 1;
&& !ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(retval_ptr)))) {
/* A cast or an error will happen, so separate the zval to prevent overwriting it */
- if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
+ if (EXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
}
-
zend_verify_return_type(EX(func), retval_ptr);
+ if (OP1_TYPE == IS_CONST) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr);
+ }
#endif
}
CHECK_EXCEPTION();
#if 0 || (IS_CONST != IS_UNUSED)
USE_OPLINE
#endif
+
SAVE_OPLINE();
if (IS_CONST == IS_UNUSED) {
zend_verify_missing_return_type(EX(func));
} else {
/* prevents "undefined variable opline" errors */
-#if IS_CONST != IS_UNUSED
+#if 0 || (IS_CONST != IS_UNUSED)
zval *retval_ptr;
zend_arg_info *ret_info = EX(func)->common.arg_info - 1;
&& !ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(retval_ptr)))) {
/* A cast or an error will happen, so separate the zval to prevent overwriting it */
- if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
+ if (EXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
}
-
zend_verify_return_type(EX(func), retval_ptr);
+ if (IS_CONST == IS_CONST) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr);
+ }
#endif
}
CHECK_EXCEPTION();
#if 0 || (IS_TMP_VAR != IS_UNUSED)
USE_OPLINE
#endif
+
SAVE_OPLINE();
if (IS_TMP_VAR == IS_UNUSED) {
zend_verify_missing_return_type(EX(func));
} else {
/* prevents "undefined variable opline" errors */
-#if IS_TMP_VAR != IS_UNUSED
+#if 0 || (IS_TMP_VAR != IS_UNUSED)
zval *retval_ptr;
zend_free_op free_op1;
zend_arg_info *ret_info = EX(func)->common.arg_info - 1;
&& !ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(retval_ptr)))) {
/* A cast or an error will happen, so separate the zval to prevent overwriting it */
- if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
+ if (EXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
}
-
zend_verify_return_type(EX(func), retval_ptr);
+ if (IS_TMP_VAR == IS_CONST) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr);
+ }
#endif
}
CHECK_EXCEPTION();
#if 0 || (IS_VAR != IS_UNUSED)
USE_OPLINE
#endif
+
SAVE_OPLINE();
if (IS_VAR == IS_UNUSED) {
zend_verify_missing_return_type(EX(func));
} else {
/* prevents "undefined variable opline" errors */
-#if IS_VAR != IS_UNUSED
+#if 0 || (IS_VAR != IS_UNUSED)
zval *retval_ptr;
zend_free_op free_op1;
zend_arg_info *ret_info = EX(func)->common.arg_info - 1;
&& !ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(retval_ptr)))) {
/* A cast or an error will happen, so separate the zval to prevent overwriting it */
- if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
+ if (EXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
}
-
zend_verify_return_type(EX(func), retval_ptr);
+ if (IS_VAR == IS_CONST) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr);
+ }
#endif
}
CHECK_EXCEPTION();
#if 0 || (IS_UNUSED != IS_UNUSED)
USE_OPLINE
#endif
+
SAVE_OPLINE();
if (IS_UNUSED == IS_UNUSED) {
zend_verify_missing_return_type(EX(func));
} else {
/* prevents "undefined variable opline" errors */
-#if IS_UNUSED != IS_UNUSED
+#if 0 || (IS_UNUSED != IS_UNUSED)
zval *retval_ptr;
zend_arg_info *ret_info = EX(func)->common.arg_info - 1;
&& !ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(retval_ptr)))) {
/* A cast or an error will happen, so separate the zval to prevent overwriting it */
- if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
+ if (EXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
}
-
zend_verify_return_type(EX(func), retval_ptr);
+ if (IS_UNUSED == IS_CONST) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr);
+ }
#endif
}
CHECK_EXCEPTION();
#if 0 || (IS_CV != IS_UNUSED)
USE_OPLINE
#endif
+
SAVE_OPLINE();
if (IS_CV == IS_UNUSED) {
zend_verify_missing_return_type(EX(func));
} else {
/* prevents "undefined variable opline" errors */
-#if IS_CV != IS_UNUSED
+#if 0 || (IS_CV != IS_UNUSED)
zval *retval_ptr;
zend_arg_info *ret_info = EX(func)->common.arg_info - 1;
&& !ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(retval_ptr)))) {
/* A cast or an error will happen, so separate the zval to prevent overwriting it */
- if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
+ if (EXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
}
-
zend_verify_return_type(EX(func), retval_ptr);
+ if (IS_CV == IS_CONST) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr);
+ }
#endif
}
CHECK_EXCEPTION();