diff options
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r-- | Zend/zend_compile.c | 67 |
1 files changed, 36 insertions, 31 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d4a9df36aa..c92a25a705 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1612,6 +1612,27 @@ uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */ } /* }}} */ +static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */ +{ + /* Fully qualified names are always default refs */ + if (name_ast->attr == ZEND_NAME_FQ) { + return ZEND_FETCH_CLASS_DEFAULT; + } + + return zend_get_class_fetch_type(zend_ast_get_str(name_ast)); +} +/* }}} */ + +void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */ +{ + if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active", + fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : + fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); + } +} +/* }}} */ + ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var) /* {{{ */ { return op_array->vars[EX_VAR_TO_NUM(var)]; @@ -2018,19 +2039,11 @@ static inline zend_bool zend_can_write_to_variable(zend_ast *ast) /* {{{ */ static inline zend_bool zend_is_const_default_class_ref(zend_ast *name_ast) /* {{{ */ { - zend_string *name; - if (name_ast->kind != ZEND_AST_ZVAL) { return 0; } - /* Fully qualified names are always default refs */ - if (!name_ast->attr) { - return 1; - } - - name = zend_ast_get_str(name_ast); - return ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(name); + return ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type_ast(name_ast); } /* }}} */ @@ -2077,6 +2090,8 @@ static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast, int th opline->op2_type = IS_CONST; opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), zend_resolve_class_name(name, type)); + } else { + zend_ensure_valid_class_fetch_type(fetch_type); } zend_string_release(name); @@ -4147,7 +4162,7 @@ ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */ } /* }}} */ -void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, zend_bool is_method) /* {{{ */ +void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); uint32_t i; @@ -4173,15 +4188,13 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, zend_bool is_ if (type != 0) { arg_infos->type_hint = type; } else { - if (zend_is_const_default_class_ref(return_type_ast)) { + uint32_t fetch_type = zend_get_class_fetch_type_ast(return_type_ast); + if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) { class_name = zend_resolve_class_name_ast(return_type_ast); zend_assert_valid_class_name(class_name); } else { + zend_ensure_valid_class_fetch_type(fetch_type); zend_string_addref(class_name); - if (!is_method) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare a return type of %s outside of a class scope", class_name->val); - return; - } } arg_infos->type_hint = IS_OBJECT; @@ -4302,10 +4315,12 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, zend_bool is_ if (type != 0) { arg_info->type_hint = type; } else { - if (zend_is_const_default_class_ref(type_ast)) { + uint32_t fetch_type = zend_get_class_fetch_type_ast(type_ast); + if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) { class_name = zend_resolve_class_name_ast(type_ast); zend_assert_valid_class_name(class_name); } else { + zend_ensure_valid_class_fetch_type(fetch_type); zend_string_addref(class_name); } @@ -4626,7 +4641,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */ zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var); } - zend_compile_params(params_ast, return_type_ast, is_method); + zend_compile_params(params_ast, return_type_ast); if (uses_ast) { zend_compile_closure_uses(uses_ast); } @@ -6329,13 +6344,10 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast) /* {{{ */ { zend_ast *name_ast = ast->child[0]; uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast)); + zend_ensure_valid_class_fetch_type(fetch_type); switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: - if (!CG(active_class_entry)) { - zend_error_noreturn(E_COMPILE_ERROR, - "Cannot access self::class when no class scope is active"); - } if (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) { zval class_str_zv; zend_ast *class_str_ast, *class_const_ast; @@ -6354,11 +6366,7 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast) /* {{{ */ break; case ZEND_FETCH_CLASS_STATIC: case ZEND_FETCH_CLASS_PARENT: - if (!CG(active_class_entry)) { - zend_error_noreturn(E_COMPILE_ERROR, - "Cannot access %s::class when no class scope is active", - fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"); - } else { + { zval class_str_zv; zend_ast *class_str_ast, *class_const_ast; @@ -6611,15 +6619,12 @@ void zend_compile_const_expr_resolve_class_name(zend_ast **ast_ptr) /* {{{ */ { zend_ast *ast = *ast_ptr; zend_ast *name_ast = ast->child[0]; - uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast)); zval result; + uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast)); + zend_ensure_valid_class_fetch_type(fetch_type); switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: - if (!CG(active_class_entry)) { - zend_error_noreturn(E_COMPILE_ERROR, - "Cannot access self::class when no class scope is active"); - } ZVAL_STR_COPY(&result, CG(active_class_entry)->name); break; case ZEND_FETCH_CLASS_STATIC: |