]> granicus.if.org Git - php/commitdiff
Fixed return type hint handling for constants
authorDmitry Stogov <dmitry@zend.com>
Fri, 20 Mar 2015 15:36:43 +0000 (18:36 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 20 Mar 2015 15:36:43 +0000 (18:36 +0300)
Zend/zend_compile.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index d0c7264eec0a9319da944f03bfff357a4fd44319..64d96e452d8d50845e4ee03599de9b1a6d001ec7 100644 (file)
@@ -1929,11 +1929,12 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
 
 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));
+               }
        }
 }
 /* }}} */
@@ -3405,21 +3406,7 @@ void zend_compile_return(zend_ast *ast) /* {{{ */
 
        /* 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);
index fd586e79cb71986f9ef16bcf894959130923f851..9065221b39c03f181cd9f7187d55c9f45ea5f0ee 100644 (file)
@@ -3589,12 +3589,13 @@ ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED)
 #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;
@@ -3606,7 +3607,7 @@ ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED)
                        && !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 {
@@ -3614,8 +3615,10 @@ ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED)
                                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();
index ebc21017ac0372cefa97ea2e90a7f44caef66a27..df01a3bb4bf04b45fa39e0656e95117f184fcae4 100644 (file)
@@ -6969,12 +6969,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_
 #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;
@@ -6986,7 +6987,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_
                        && !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 {
@@ -6994,8 +6995,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_
                                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();
@@ -11930,12 +11933,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN
 #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;
@@ -11947,7 +11951,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN
                        && !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 {
@@ -11955,8 +11959,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN
                                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();
@@ -17291,12 +17297,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN
 #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;
@@ -17308,7 +17315,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN
                        && !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 {
@@ -17316,8 +17323,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN
                                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();
@@ -22909,12 +22918,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED
 #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;
@@ -22926,7 +22936,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED
                        && !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 {
@@ -22934,8 +22944,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED
                                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();
@@ -31863,12 +31875,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU
 #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;
@@ -31880,7 +31893,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU
                        && !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 {
@@ -31888,8 +31901,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU
                                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();