diff options
31 files changed, 223 insertions, 229 deletions
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 6fe98f0a45..ff56dfa655 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -13,7 +13,7 @@ PHP 7.2 INTERNALS UPGRADE NOTES j. Run-time constant operand addressing k. Array/Object recursion protection l. HASH_FLAG_PERSISTENT - m. zend_ast_ref + m. AST and IS_CONSTANT 2. Build system changes a. Unix build system changes @@ -94,6 +94,11 @@ PHP 7.2 INTERNALS UPGRADE NOTES zend_ast_destroy_and_free() is removed. ZVAL_NEW_AST() is replaced by ZVAL_AST(). + IS_CONSTANT type and Z_CONST_FLAGS() are removed. Now constants are always + represented using IS_CONSTANT_AST (ZEND_AST_CONSTANT kind). AST node + attributes are used instead of constant flags. IS_TYPE_CONSTANT flag is + removed, but Z_CONSTANT() macro is kept for compatibility. + ======================== 2. Build system changes ======================== diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 2e8a994000..b9467da710 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1150,7 +1150,7 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */ ZEND_HASH_FOREACH_PTR(&class_type->constants_table, c) { val = &c->value; - if (Z_CONSTANT_P(val)) { + if (Z_TYPE_P(val) == IS_CONSTANT_AST) { if (UNEXPECTED(zval_update_constant_ex(val, c->ce) != SUCCESS)) { return FAILURE; } @@ -1167,7 +1167,7 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */ val = (zval*)((char*)class_type->default_properties_table + prop_info->offset - OBJ_PROP_TO_OFFSET(0)); } ZVAL_DEREF(val); - if (Z_CONSTANT_P(val)) { + if (Z_TYPE_P(val) == IS_CONSTANT_AST) { if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) { return FAILURE; } @@ -3685,12 +3685,12 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z if (ce->type == ZEND_INTERNAL_CLASS) { property_info = pemalloc(sizeof(zend_property_info), 1); - if ((access_type & ZEND_ACC_STATIC) || Z_CONSTANT_P(property)) { + if ((access_type & ZEND_ACC_STATIC) || Z_TYPE_P(property) == IS_CONSTANT_AST) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } } else { property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info)); - if (Z_CONSTANT_P(property)) { + if (Z_TYPE_P(property) == IS_CONSTANT_AST) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } } @@ -3846,7 +3846,7 @@ ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *n Z_ACCESS_FLAGS(c->value) = access_type; c->doc_comment = doc_comment; c->ce = ce; - if (Z_CONSTANT_P(value)) { + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index defa535319..96bedb7b42 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -25,6 +25,7 @@ #include "zend_language_parser.h" #include "zend_smart_str.h" #include "zend_exceptions.h" +#include "zend_constants.h" ZEND_API zend_ast_process_t zend_ast_process = NULL; @@ -72,6 +73,17 @@ ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) { return zend_ast_create_zval_with_lineno(zv, attr, CG(zend_lineno)); } +ZEND_API zend_ast *zend_ast_create_constant(zend_string *name, zend_ast_attr attr) { + zend_ast_zval *ast; + + ast = zend_ast_alloc(sizeof(zend_ast_zval)); + ast->kind = ZEND_AST_CONSTANT; + ast->attr = attr; + ZVAL_STR(&ast->val, name); + ast->val.u2.lineno = CG(zend_lineno); + return (zend_ast *) ast; +} + ZEND_API zend_ast *zend_ast_create_decl( zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3 @@ -276,25 +288,30 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc { zval *zv = zend_ast_get_zval(ast); - if (Z_OPT_CONSTANT_P(zv)) { - if (Z_TYPE_FLAGS_P(zv) & IS_TYPE_REFCOUNTED) { - if (UNEXPECTED(zval_update_constant_ex(zv, scope) != SUCCESS)) { - ret = FAILURE; - break; - } - ZVAL_COPY(result, zv); - } else { - ZVAL_COPY_VALUE(result, zv); - if (UNEXPECTED(zval_update_constant_ex(result, scope) != SUCCESS)) { - ret = FAILURE; - break; - } - } - } else { - ZVAL_COPY(result, zv); + ZVAL_COPY(result, zv); + break; + } + case ZEND_AST_CONSTANT: + { + zend_string *name = zend_ast_get_constant_name(ast); + zval *zv = zend_get_constant_ex(name, scope, ast->attr); + + if (UNEXPECTED(zv == NULL)) { + ZVAL_UNDEF(result); + ret = zend_use_undefined_constant(name, ast->attr, result); + break; } + ZVAL_DUP(result, zv); break; } + case ZEND_AST_CONSTANT_CLASS: + ZEND_ASSERT(EG(current_execute_data)); + if (scope && scope->name) { + ZVAL_STR_COPY(result, scope->name); + } else { + ZVAL_EMPTY_STRING(result); + } + break; case ZEND_AST_AND: if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) { ret = FAILURE; @@ -455,7 +472,7 @@ static size_t zend_ast_tree_size(zend_ast *ast) { size_t size; - if (ast->kind == ZEND_AST_ZVAL) { + if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) { size = sizeof(zend_ast_zval); } else if (zend_ast_is_list(ast)) { uint32_t i; @@ -488,6 +505,12 @@ static void* zend_ast_tree_copy(zend_ast *ast, void *buf) new->attr = ast->attr; ZVAL_COPY(&new->val, zend_ast_get_zval(ast)); buf = (void*)((char*)buf + sizeof(zend_ast_zval)); + } else if (ast->kind == ZEND_AST_CONSTANT) { + zend_ast_zval *new = (zend_ast_zval*)buf; + new->kind = ZEND_AST_CONSTANT; + new->attr = ast->attr; + ZVAL_STR_COPY(&new->val, zend_ast_get_constant_name(ast)); + buf = (void*)((char*)buf + sizeof(zend_ast_zval)); } else if (zend_ast_is_list(ast)) { zend_ast_list *list = zend_ast_get_list(ast); zend_ast_list *new = (zend_ast_list*)buf; @@ -548,6 +571,9 @@ ZEND_API void zend_ast_destroy(zend_ast *ast) { * become invalid. GC would cause such a reference in the root buffer. */ zval_ptr_dtor_nogc(zend_ast_get_zval(ast)); break; + case ZEND_AST_CONSTANT: + zend_string_release(zend_ast_get_constant_name(ast)); + break; case ZEND_AST_FUNC_DECL: case ZEND_AST_CLOSURE: case ZEND_AST_METHOD: @@ -996,9 +1022,6 @@ static void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int ind } ZEND_HASH_FOREACH_END(); smart_str_appendc(str, ']'); break; - case IS_CONSTANT: - smart_str_appendl(str, Z_STRVAL_P(zv), Z_STRLEN_P(zv)); - break; case IS_CONSTANT_AST: zend_ast_export_ex(str, Z_ASTVAL_P(zv), priority, indent); break; @@ -1078,6 +1101,14 @@ tail_call: case ZEND_AST_ZVAL: zend_ast_export_zval(str, zend_ast_get_zval(ast), priority, indent); break; + case ZEND_AST_CONSTANT: { + zend_string *name = zend_ast_get_constant_name(ast); + smart_str_appendl(str, ZSTR_VAL(name), ZSTR_LEN(name)); + break; + } + case ZEND_AST_CONSTANT_CLASS: + smart_str_appendl(str, "__CLASS__", sizeof("__CLASS__")-1); + break; case ZEND_AST_ZNODE: /* This AST kind is only used for temporary nodes during compilation */ ZEND_ASSERT(0); diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 9e0aeeb545..99ad920ad6 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -32,6 +32,7 @@ enum _zend_ast_kind { /* special nodes */ ZEND_AST_ZVAL = 1 << ZEND_AST_SPECIAL_SHIFT, + ZEND_AST_CONSTANT, ZEND_AST_ZNODE, /* declaration nodes */ @@ -61,6 +62,7 @@ enum _zend_ast_kind { /* 0 child nodes */ ZEND_AST_MAGIC_CONST = 0 << ZEND_AST_NUM_CHILDREN_SHIFT, ZEND_AST_TYPE, + ZEND_AST_CONSTANT_CLASS, /* 1 child node */ ZEND_AST_VAR = 1 << ZEND_AST_NUM_CHILDREN_SHIFT, @@ -192,6 +194,8 @@ extern ZEND_API zend_ast_process_t zend_ast_process; ZEND_API zend_ast *zend_ast_create_zval_with_lineno(zval *zv, zend_ast_attr attr, uint32_t lineno); ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr); +ZEND_API zend_ast *zend_ast_create_constant(zend_string *name, zend_ast_attr attr); + ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...); ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...); @@ -230,6 +234,12 @@ static zend_always_inline zend_string *zend_ast_get_str(zend_ast *ast) { return Z_STR_P(zv); } +static zend_always_inline zend_string *zend_ast_get_constant_name(zend_ast *ast) { + ZEND_ASSERT(ast->kind == ZEND_AST_CONSTANT); + ZEND_ASSERT(Z_TYPE(((zend_ast_zval *) ast)->val) == IS_STRING); + return Z_STR(((zend_ast_zval *) ast)->val); +} + static zend_always_inline uint32_t zend_ast_get_num_children(zend_ast *ast) { ZEND_ASSERT(!zend_ast_is_list(ast)); return ast->kind >> ZEND_AST_NUM_CHILDREN_SHIFT; diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 73b1b64c82..5793ea3308 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1071,7 +1071,7 @@ static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, int st /* this is necessary to make it able to work with default array * properties, returned to user */ - if (Z_OPT_CONSTANT_P(prop)) { + if (Z_OPT_TYPE_P(prop) == IS_CONSTANT_AST) { if (UNEXPECTED(zval_update_constant_ex(prop, NULL) != SUCCESS)) { return; } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2f73afcf9e..8d353b8c0a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -460,7 +460,7 @@ void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */ /* Common part of zend_add_literal and zend_append_individual_literal */ static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int literal_position) /* {{{ */ { - if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) { + if (Z_TYPE_P(zv) == IS_STRING) { zend_string_hash_val(Z_STR_P(zv)); Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv)); if (ZSTR_IS_INTERNED(Z_STR_P(zv))) { @@ -5518,8 +5518,9 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ zend_bool allow_null; zend_bool has_null_default = default_ast && (Z_TYPE(default_node.u.constant) == IS_NULL - || (Z_TYPE(default_node.u.constant) == IS_CONSTANT - && strcasecmp(Z_STRVAL(default_node.u.constant), "NULL") == 0)); + || (Z_TYPE(default_node.u.constant) == IS_CONSTANT_AST + && Z_ASTVAL(default_node.u.constant)->kind == ZEND_AST_CONSTANT + && strcasecmp(ZSTR_VAL(zend_ast_get_constant_name(Z_ASTVAL(default_node.u.constant))), "NULL") == 0)); zend_bool is_explicitly_nullable = (type_ast->attr & ZEND_TYPE_NULLABLE) == ZEND_TYPE_NULLABLE; op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; @@ -5536,19 +5537,19 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ if (ZEND_TYPE_CODE(arg_info->type) == IS_ARRAY) { if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_ARRAY - && !Z_CONSTANT(default_node.u.constant) + && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST ) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with array type can only be an array or NULL"); } } else if (ZEND_TYPE_CODE(arg_info->type) == IS_CALLABLE && default_ast) { - if (!has_null_default && !Z_CONSTANT(default_node.u.constant)) { + if (!has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with callable type can only be NULL"); } } } else { - if (default_ast && !has_null_default && !Z_CONSTANT(default_node.u.constant)) { + if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { if (ZEND_TYPE_IS_CLASS(arg_info->type)) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with a class type can only be NULL"); @@ -7916,6 +7917,7 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */ zend_ast *const_ast = ast->child[1]; zend_string *class_name; zend_string *const_name = zend_ast_get_str(const_ast); + zend_string *name; zval result; int fetch_type; @@ -7943,16 +7945,13 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */ zend_string_addref(class_name); } - Z_STR(result) = zend_concat3( + name = zend_concat3( ZSTR_VAL(class_name), ZSTR_LEN(class_name), "::", 2, ZSTR_VAL(const_name), ZSTR_LEN(const_name)); - Z_TYPE_INFO(result) = IS_CONSTANT_EX; - Z_CONST_FLAGS(result) = fetch_type; - zend_ast_destroy(ast); zend_string_release(class_name); - *ast_ptr = zend_ast_create_zval(&result); + *ast_ptr = zend_ast_create_constant(name, fetch_type); } /* }}} */ @@ -7962,25 +7961,21 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */ zend_ast *name_ast = ast->child[0]; zend_string *orig_name = zend_ast_get_str(name_ast); zend_bool is_fully_qualified; + zval result; + zend_string *resolved_name; - zval result, resolved_name; - ZVAL_STR(&resolved_name, zend_resolve_const_name( - orig_name, name_ast->attr, &is_fully_qualified)); + resolved_name = zend_resolve_const_name( + orig_name, name_ast->attr, &is_fully_qualified); - if (zend_try_ct_eval_const(&result, Z_STR(resolved_name), is_fully_qualified)) { - zend_string_release(Z_STR(resolved_name)); + if (zend_try_ct_eval_const(&result, resolved_name, is_fully_qualified)) { + zend_string_release(resolved_name); zend_ast_destroy(ast); *ast_ptr = zend_ast_create_zval(&result); return; } - Z_TYPE_INFO(resolved_name) = IS_CONSTANT_EX; - if (!is_fully_qualified) { - Z_CONST_FLAGS(resolved_name) = IS_CONSTANT_UNQUALIFIED; - } - zend_ast_destroy(ast); - *ast_ptr = zend_ast_create_zval(&resolved_name); + *ast_ptr = zend_ast_create_constant(resolved_name, !is_fully_qualified ? IS_CONSTANT_UNQUALIFIED : 0); } /* }}} */ @@ -7993,14 +7988,8 @@ void zend_compile_const_expr_magic_const(zend_ast **ast_ptr) /* {{{ */ CG(active_class_entry) && (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != 0); - { - zval const_zv; - Z_STR(const_zv) = zend_string_init("__CLASS__", sizeof("__CLASS__")-1, 0); - Z_TYPE_INFO(const_zv) = IS_CONSTANT_EX | (IS_CONSTANT_CLASS << Z_CONST_FLAGS_SHIFT); - - zend_ast_destroy(ast); - *ast_ptr = zend_ast_create_zval(&const_zv); - } + zend_ast_destroy(ast); + *ast_ptr = zend_ast_create_ex(ZEND_AST_CONSTANT_CLASS, 0); } /* }}} */ diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 6c4a5b51f1..62fcdc9d8d 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -886,6 +886,10 @@ void zend_assert_valid_class_name(const zend_string *const_name); #define ZEND_DIM_IS 1 +#define IS_CONSTANT_UNQUALIFIED 0x010 +#define IS_CONSTANT_CLASS 0x080 /* __CLASS__ in trait */ +#define IS_CONSTANT_IN_NAMESPACE 0x100 + static zend_always_inline int zend_check_arg_send_type(const zend_function *zf, uint32_t arg_num, uint32_t mask) { arg_num--; diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index f5a71ac6cc..100d0a263b 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -348,7 +348,7 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, } } - if (ret_constant && Z_CONSTANT_P(ret_constant)) { + if (ret_constant && Z_TYPE_P(ret_constant) == IS_CONSTANT_AST) { if (Z_TYPE_P(ret_constant) == IS_CONSTANT_AST) { if (IS_CONSTANT_VISITED(ret_constant)) { zend_throw_error(NULL, "Cannot declare self-referencing constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name)); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index b608933996..b80e7f0af6 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -729,7 +729,7 @@ static ZEND_COLD void zend_verify_arg_error( static int is_null_constant(zend_class_entry *scope, zval *default_value) { - if (Z_CONSTANT_P(default_value)) { + if (Z_TYPE_P(default_value) == IS_CONSTANT_AST) { zval constant; ZVAL_COPY(&constant, default_value); diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index ae809ab224..39fce43ccc 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -131,6 +131,7 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval ZEND_API int zval_update_constant(zval *pp); ZEND_API int zval_update_constant_ex(zval *pp, zend_class_entry *scope); +ZEND_API int zend_use_undefined_constant(zend_string *name, zend_ast_attr attr, zval *result); /* dedicated Zend executor functions - do not use! */ struct _zend_vm_stack { diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index d5d03625e2..e69a84ba6b 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -542,90 +542,63 @@ ZEND_API void _zval_internal_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) /* {{{ * } /* }}} */ -ZEND_API int zval_update_constant_ex(zval *p, zend_class_entry *scope) /* {{{ */ +ZEND_API int zend_use_undefined_constant(zend_string *name, zend_ast_attr attr, zval *result) /* {{{ */ { - zval *const_value; char *colon; - zend_bool inline_change; - if (Z_TYPE_P(p) == IS_CONSTANT) { - if (IS_CONSTANT_VISITED(p)) { - zend_throw_error(NULL, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p)); + if (UNEXPECTED(EG(exception))) { + return FAILURE; + } else if ((colon = (char*)zend_memrchr(ZSTR_VAL(name), ':', ZSTR_LEN(name)))) { + zend_throw_error(NULL, "Undefined class constant '%s'", ZSTR_VAL(name)); + return FAILURE; + } else if ((attr & IS_CONSTANT_UNQUALIFIED) == 0) { + zend_throw_error(NULL, "Undefined constant '%s'", ZSTR_VAL(name)); + return FAILURE; + } else { + char *actual = ZSTR_VAL(name); + size_t actual_len = ZSTR_LEN(name); + char *slash = (char *) zend_memrchr(actual, '\\', actual_len); + + if (slash) { + actual = slash + 1; + actual_len -= (actual - ZSTR_VAL(name)); + } + + zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)", actual, actual); + if (EG(exception)) { return FAILURE; + } else { + zval_ptr_dtor_nogc(result); + ZVAL_STRINGL(result, actual, actual_len); } - inline_change = (Z_TYPE_FLAGS_P(p) & IS_TYPE_REFCOUNTED) != 0; - SEPARATE_ZVAL_NOREF(p); - MARK_CONSTANT_VISITED(p); - if (Z_CONST_FLAGS_P(p) & IS_CONSTANT_CLASS) { - ZEND_ASSERT(EG(current_execute_data)); - if (inline_change) { - zend_string_release(Z_STR_P(p)); - } - if (scope && scope->name) { - ZVAL_STR_COPY(p, scope->name); - } else { - ZVAL_EMPTY_STRING(p); - } - } else if (UNEXPECTED((const_value = zend_get_constant_ex(Z_STR_P(p), scope, Z_CONST_FLAGS_P(p))) == NULL)) { - if (UNEXPECTED(EG(exception))) { - RESET_CONSTANT_VISITED(p); - return FAILURE; - } else if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) { - zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(p)); - RESET_CONSTANT_VISITED(p); - return FAILURE; - } else { - if ((Z_CONST_FLAGS_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) { - zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(p)); - RESET_CONSTANT_VISITED(p); - return FAILURE; - } else { - zend_string *save = Z_STR_P(p); - char *actual = Z_STRVAL_P(p); - size_t actual_len = Z_STRLEN_P(p); - char *slash = (char *) zend_memrchr(actual, '\\', actual_len); - if (slash) { - actual = slash + 1; - actual_len -= (actual - Z_STRVAL_P(p)); - } + } + return SUCCESS; +} +/* }}} */ - zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)", actual, actual); - if (EG(exception)) { - RESET_CONSTANT_VISITED(p); - return FAILURE; - } +ZEND_API int zval_update_constant_ex(zval *p, zend_class_entry *scope) /* {{{ */ +{ + if (Z_TYPE_P(p) == IS_CONSTANT_AST) { + zend_ast *ast = Z_ASTVAL_P(p); - if (!inline_change) { - ZVAL_STRINGL(p, actual, actual_len); - } else { - if (slash) { - ZVAL_STRINGL(p, actual, actual_len); - zend_string_release(save); - } else { - Z_TYPE_INFO_P(p) = Z_REFCOUNTED_P(p) ? - IS_STRING_EX : IS_INTERNED_STRING_EX; - } - } - } + if (ast->kind == ZEND_AST_CONSTANT) { + zend_string *name = zend_ast_get_constant_name(ast); + zval *zv = zend_get_constant_ex(name, scope, ast->attr); + + if (UNEXPECTED(zv == NULL)) { + return zend_use_undefined_constant(name, ast->attr, p); } + zval_ptr_dtor_nogc(p); + ZVAL_DUP(p, zv); } else { - if (inline_change) { - zend_string_release(Z_STR_P(p)); - } - ZVAL_COPY_VALUE(p, const_value); - zval_opt_copy_ctor(p); - } - } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) { - zval tmp; + zval tmp; - inline_change = (Z_TYPE_FLAGS_P(p) & IS_TYPE_REFCOUNTED) != 0; - if (UNEXPECTED(zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope) != SUCCESS)) { - return FAILURE; - } - if (inline_change) { + if (UNEXPECTED(zend_ast_evaluate(&tmp, ast, scope) != SUCCESS)) { + return FAILURE; + } zval_ptr_dtor_nogc(p); + ZVAL_COPY_VALUE(p, &tmp); } - ZVAL_COPY_VALUE(p, &tmp); } return SUCCESS; } diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 3e57343c4c..b607efa5c9 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -497,9 +497,7 @@ static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) { zval *zv = RT_CONSTANT(precv, precv->op2); - if (Z_TYPE_P(zv) == IS_CONSTANT) { - smart_str_append(&str, Z_STR_P(zv)); - } else if (Z_TYPE_P(zv) == IS_FALSE) { + if (Z_TYPE_P(zv) == IS_FALSE) { smart_str_appends(&str, "false"); } else if (Z_TYPE_P(zv) == IS_TRUE) { smart_str_appends(&str, "true"); @@ -515,7 +513,12 @@ static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function } else if (Z_TYPE_P(zv) == IS_ARRAY) { smart_str_appends(&str, "Array"); } else if (Z_TYPE_P(zv) == IS_CONSTANT_AST) { - smart_str_appends(&str, "<expression>"); + zend_ast *ast = Z_ASTVAL_P(zv); + if (ast->kind == ZEND_AST_CONSTANT) { + smart_str_append(&str, zend_ast_get_constant_name(ast)); + } else { + smart_str_appends(&str, "<expression>"); + } } else { zend_string *zv_str = zval_get_string(zv); smart_str_append(&str, zv_str); @@ -769,7 +772,7 @@ static void do_inherit_class_constant(zend_string *name, zend_class_constant *pa ZSTR_VAL(ce->name), ZSTR_VAL(name), zend_visibility_string(Z_ACCESS_FLAGS(parent_const->value)), ZSTR_VAL(ce->parent->name), (Z_ACCESS_FLAGS(parent_const->value) & ZEND_ACC_PUBLIC) ? "" : " or weaker"); } } else if (!(Z_ACCESS_FLAGS(parent_const->value) & ZEND_ACC_PRIVATE)) { - if (Z_CONSTANT(parent_const->value)) { + if (Z_TYPE(parent_const->value) == IS_CONSTANT_AST) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } if (ce->type & ZEND_INTERNAL_CLASS) { @@ -845,7 +848,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent #ifdef ZTS if (parent_ce->type != ce->type) { ZVAL_DUP(dst, src); - if (Z_OPT_CONSTANT_P(dst)) { + if (Z_OPT_TYPE_P(dst) == IS_CONSTANT_AST) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } continue; @@ -853,7 +856,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent #endif ZVAL_COPY(dst, src); - if (Z_OPT_CONSTANT_P(dst)) { + if (Z_OPT_TYPE_P(dst) == IS_CONSTANT_AST) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } } while (dst != end); @@ -894,7 +897,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent } ZVAL_COPY_VALUE(dst, src); Z_ADDREF_P(dst); - if (Z_CONSTANT_P(Z_REFVAL_P(dst))) { + if (Z_TYPE_P(Z_REFVAL_P(dst)) == IS_CONSTANT_AST) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } } while (dst != end); @@ -982,7 +985,7 @@ static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c, { if (do_inherit_constant_check(&ce->constants_table, c, name, iface)) { zend_class_constant *ct; - if (Z_CONSTANT(c->value)) { + if (Z_TYPE(c->value) == IS_CONSTANT_AST) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } if (ce->type & ZEND_INTERNAL_CLASS) { diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 9ade3983be..c613dfbe1d 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -183,8 +183,8 @@ struct _zval_struct { ZEND_ENDIAN_LOHI_4( zend_uchar type, /* active type */ zend_uchar type_flags, - zend_uchar const_flags, - zend_uchar reserved) /* call info for EX(This) */ + zend_uchar _unused, + zend_uchar _reserved) /* call info for EX(This) */ } v; uint32_t type_info; } u1; @@ -372,7 +372,6 @@ struct _zend_ast_ref { #define IS_REFERENCE 10 /* constant expressions */ -#define IS_CONSTANT 11 #define IS_CONSTANT_AST 12 /* fake types */ @@ -402,9 +401,6 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define Z_TYPE_FLAGS(zval) (zval).u1.v.type_flags #define Z_TYPE_FLAGS_P(zval_p) Z_TYPE_FLAGS(*(zval_p)) -#define Z_CONST_FLAGS(zval) (zval).u1.v.const_flags -#define Z_CONST_FLAGS_P(zval_p) Z_CONST_FLAGS(*(zval_p)) - #define Z_TYPE_INFO(zval) (zval).u1.type_info #define Z_TYPE_INFO_P(zval_p) Z_TYPE_INFO(*(zval_p)) @@ -432,7 +428,6 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define Z_TYPE_MASK 0xff #define Z_TYPE_FLAGS_SHIFT 8 -#define Z_CONST_FLAGS_SHIFT 16 #define GC_REFCOUNT(p) (p)->gc.refcount #define GC_TYPE(p) (p)->gc.u.v.type @@ -465,31 +460,24 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define GC_OBJECT (IS_OBJECT | (GC_COLLECTABLE << GC_FLAGS_SHIFT)) /* zval.u1.v.type_flags */ -#define IS_TYPE_CONSTANT (1<<0) #define IS_TYPE_REFCOUNTED (1<<2) #define IS_TYPE_COPYABLE (1<<4) +#define IS_CONSTANT_VISITED_MARK (1<<5) /* extended types */ #define IS_INTERNED_STRING_EX IS_STRING -#define IS_STRING_EX (IS_STRING | (( IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) -#define IS_ARRAY_EX (IS_ARRAY | (( IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) -#define IS_OBJECT_EX (IS_OBJECT | (( IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT)) -#define IS_RESOURCE_EX (IS_RESOURCE | (( IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT)) -#define IS_REFERENCE_EX (IS_REFERENCE | (( IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT)) - -#define IS_CONSTANT_EX (IS_CONSTANT | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) -#define IS_CONSTANT_AST_EX (IS_CONSTANT_AST | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) +#define IS_STRING_EX (IS_STRING | ((IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) +#define IS_ARRAY_EX (IS_ARRAY | ((IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) +#define IS_OBJECT_EX (IS_OBJECT | ((IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT)) +#define IS_RESOURCE_EX (IS_RESOURCE | ((IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT)) +#define IS_REFERENCE_EX (IS_REFERENCE | ((IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT)) -/* zval.u1.v.const_flags */ -#define IS_CONSTANT_UNQUALIFIED 0x010 -#define IS_CONSTANT_VISITED_MARK 0x020 -#define IS_CONSTANT_CLASS 0x080 /* __CLASS__ in trait */ -#define IS_CONSTANT_IN_NAMESPACE 0x100 /* used only in opline->extended_value */ +#define IS_CONSTANT_AST_EX (IS_CONSTANT_AST | ((IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) -#define IS_CONSTANT_VISITED(p) (Z_CONST_FLAGS_P(p) & IS_CONSTANT_VISITED_MARK) -#define MARK_CONSTANT_VISITED(p) Z_CONST_FLAGS_P(p) |= IS_CONSTANT_VISITED_MARK -#define RESET_CONSTANT_VISITED(p) Z_CONST_FLAGS_P(p) &= ~IS_CONSTANT_VISITED_MARK +#define IS_CONSTANT_VISITED(p) (Z_TYPE_FLAGS_P(p) & IS_CONSTANT_VISITED_MARK) +#define MARK_CONSTANT_VISITED(p) Z_TYPE_FLAGS_P(p) |= IS_CONSTANT_VISITED_MARK +#define RESET_CONSTANT_VISITED(p) Z_TYPE_FLAGS_P(p) &= ~IS_CONSTANT_VISITED_MARK /* string flags (zval.value->gc.u.flags) */ #define IS_STR_INTERNED GC_IMMUTABLE /* interned string */ @@ -526,7 +514,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define Z_UNPROTECT_RECURSION_P(zv) Z_UNPROTECT_RECURSION(*(zv)) /* All data types < IS_STRING have their constructor/destructors skipped */ -#define Z_CONSTANT(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_CONSTANT) != 0) +#define Z_CONSTANT(zval) (Z_TYPE(zval) == IS_CONSTANT_AST) #define Z_CONSTANT_P(zval_p) Z_CONSTANT(*(zval_p)) #define Z_REFCOUNTED(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_REFCOUNTED) != 0) @@ -545,7 +533,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define Z_OPT_TYPE(zval) (Z_TYPE_INFO(zval) & Z_TYPE_MASK) #define Z_OPT_TYPE_P(zval_p) Z_OPT_TYPE(*(zval_p)) -#define Z_OPT_CONSTANT(zval) ((Z_TYPE_INFO(zval) & (IS_TYPE_CONSTANT << Z_TYPE_FLAGS_SHIFT)) != 0) +#define Z_OPT_CONSTANT(zval) (Z_OPT_TYPE(zval) == IS_CONSTANT_AST) #define Z_OPT_CONSTANT_P(zval_p) Z_OPT_CONSTANT(*(zval_p)) #define Z_OPT_REFCOUNTED(zval) ((Z_TYPE_INFO(zval) & (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT)) != 0) diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index 09338013b8..d7fd5239d7 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -31,8 +31,7 @@ ZEND_API void ZEND_FASTCALL _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC) { switch (GC_TYPE(p)) { - case IS_STRING: - case IS_CONSTANT: { + case IS_STRING: { zend_string *str = (zend_string*)p; CHECK_ZVAL_STRING_REL(str); zend_string_free(str); @@ -79,7 +78,6 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC) { switch (Z_TYPE_P(zvalue)) { case IS_STRING: - case IS_CONSTANT: CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue)); zend_string_release(Z_STR_P(zvalue)); break; @@ -110,7 +108,6 @@ ZEND_API void _zval_internal_dtor_for_ptr(zval *zvalue ZEND_FILE_LINE_DC) { switch (Z_TYPE_P(zvalue)) { case IS_STRING: - case IS_CONSTANT: CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue)); zend_string_free(Z_STR_P(zvalue)); break; @@ -170,9 +167,6 @@ ZEND_API void ZEND_FASTCALL _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC) } else if (EXPECTED(Z_TYPE_P(zvalue) == IS_STRING)) { CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue)); ZVAL_NEW_STR(zvalue, zend_string_dup(Z_STR_P(zvalue), 0)); - } else if (EXPECTED(Z_TYPE_P(zvalue) == IS_CONSTANT)) { - CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue)); - Z_STR_P(zvalue) = zend_string_dup(Z_STR_P(zvalue), 0); } else if (EXPECTED(Z_TYPE_P(zvalue) == IS_CONSTANT_AST)) { ZVAL_AST(zvalue, zend_ast_copy(Z_ASTVAL_P(zvalue))); } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index fff72782f7..b8f0aa1f34 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4676,7 +4676,7 @@ ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST) param = _get_zval_ptr_cv_undef_BP_VAR_W(opline->result.var EXECUTE_DATA_CC); if (arg_num > EX_NUM_ARGS()) { ZVAL_COPY(param, RT_CONSTANT(opline, opline->op2)); - if (Z_OPT_CONSTANT_P(param)) { + if (Z_OPT_TYPE_P(param) == IS_CONSTANT_AST) { SAVE_OPLINE(); if (UNEXPECTED(zval_update_constant_ex(param, EX(func)->op_array.scope) != SUCCESS)) { zval_ptr_dtor_nogc(param); @@ -5078,7 +5078,7 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO HANDLE_EXCEPTION(); } value = &c->value; - if (Z_CONSTANT_P(value)) { + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { zval_update_constant_ex(value, c->ce); if (UNEXPECTED(EG(exception) != NULL)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -7932,7 +7932,7 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, CONST, REF) value = zend_hash_find(ht, Z_STR_P(varname)); if (opline->extended_value) { - if (Z_CONSTANT_P(value)) { + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { SAVE_OPLINE(); if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) { ZVAL_NULL(variable_ptr); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b286868cd0..9d99daf986 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2292,7 +2292,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CON param = _get_zval_ptr_cv_undef_BP_VAR_W(opline->result.var EXECUTE_DATA_CC); if (arg_num > EX_NUM_ARGS()) { ZVAL_COPY(param, RT_CONSTANT(opline, opline->op2)); - if (Z_OPT_CONSTANT_P(param)) { + if (Z_OPT_TYPE_P(param) == IS_CONSTANT_AST) { SAVE_OPLINE(); if (UNEXPECTED(zval_update_constant_ex(param, EX(func)->op_array.scope) != SUCCESS)) { zval_ptr_dtor_nogc(param); @@ -5746,7 +5746,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS HANDLE_EXCEPTION(); } value = &c->value; - if (Z_CONSTANT_P(value)) { + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { zval_update_constant_ex(value, c->ce); if (UNEXPECTED(EG(exception) != NULL)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -19629,7 +19629,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ HANDLE_EXCEPTION(); } value = &c->value; - if (Z_CONSTANT_P(value)) { + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { zval_update_constant_ex(value, c->ce); if (UNEXPECTED(EG(exception) != NULL)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -28467,7 +28467,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS HANDLE_EXCEPTION(); } value = &c->value; - if (Z_CONSTANT_P(value)) { + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { zval_update_constant_ex(value, c->ce); if (UNEXPECTED(EG(exception) != NULL)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); @@ -38504,7 +38504,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_CONST_HAND value = zend_hash_find(ht, Z_STR_P(varname)); if (opline->extended_value) { - if (Z_CONSTANT_P(value)) { + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { SAVE_OPLINE(); if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) { ZVAL_NULL(variable_ptr); diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c index b74e977f0e..04c7d5f8c1 100644 --- a/ext/com_dotnet/com_variant.c +++ b/ext/com_dotnet/com_variant.c @@ -176,7 +176,6 @@ PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codep break; case IS_RESOURCE: - case IS_CONSTANT: case IS_CONSTANT_AST: default: V_VT(v) = VT_NULL; diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c index 0b98da054d..a8457c9405 100644 --- a/ext/opcache/Optimizer/compact_literals.c +++ b/ext/opcache/Optimizer/compact_literals.c @@ -422,7 +422,6 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx } break; case IS_STRING: - case IS_CONSTANT: if (info[i].flags & LITERAL_MAY_MERGE) { if (info[i].flags & LITERAL_EX_OBJ) { int key_len = sizeof("$this->") - 1 + Z_STRLEN(op_array->literals[i]); diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c index 1548260b60..81d62ca171 100644 --- a/ext/opcache/Optimizer/optimize_func_calls.c +++ b/ext/opcache/Optimizer/optimize_func_calls.c @@ -123,7 +123,7 @@ static void zend_try_inline_call(zend_op_array *op_array, zend_op *fcall, zend_o i = fcall->extended_value; do { - if (Z_CONSTANT_P(RT_CONSTANT(&func->op_array.opcodes[i], func->op_array.opcodes[i].op2))) { + if (Z_TYPE_P(RT_CONSTANT(&func->op_array.opcodes[i], func->op_array.opcodes[i].op2)) == IS_CONSTANT_AST) { return; } i++; diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c index 7697fb1943..9f28019013 100644 --- a/ext/opcache/Optimizer/pass1_5.c +++ b/ext/opcache/Optimizer/pass1_5.c @@ -35,8 +35,6 @@ #include "zend_execute.h" #include "zend_vm.h" -#define ZEND_IS_CONSTANT_TYPE(t) ((t) == IS_CONSTANT) - void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) { int i = 0; @@ -305,11 +303,10 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) (Z_ACCESS_FLAGS(cc->value) & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) { c = &cc->value; if (Z_TYPE_P(c) == IS_CONSTANT_AST) { - break; - } - if (ZEND_IS_CONSTANT_TYPE(Z_TYPE_P(c))) { - if (!zend_optimizer_get_persistent_constant(Z_STR_P(c), &t, 1) || - ZEND_IS_CONSTANT_TYPE(Z_TYPE(t))) { + zend_ast *ast = Z_ASTVAL_P(c); + if (ast->kind != ZEND_AST_CONSTANT + || !zend_optimizer_get_persistent_constant(zend_ast_get_constant_name(ast), &t, 1) + || Z_TYPE(t) == IS_CONSTANT_AST) { break; } } else { diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index 1b77eae74e..ac13187624 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -455,9 +455,6 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * if (opline->extended_value & IS_CONSTANT_UNQUALIFIED) { fprintf(stderr, " (unqualified)"); } - if (opline->extended_value & IS_CONSTANT_CLASS) { - fprintf(stderr, " (__class__)"); - } if (opline->extended_value & IS_CONSTANT_IN_NAMESPACE) { fprintf(stderr, " (in-namespace)"); } diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index 2e7b00a03a..7bb906d4a6 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -2748,7 +2748,7 @@ static int zend_update_type_info(const zend_op_array *op_array, if (arg_info) { tmp = zend_fetch_arg_info(script, arg_info, &ce); if (opline->opcode == ZEND_RECV_INIT && - Z_CONSTANT_P(CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants))) { + Z_TYPE_P(CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants)) == IS_CONSTANT_AST) { /* The constant may resolve to NULL */ tmp |= MAY_BE_NULL; } @@ -4260,7 +4260,7 @@ int zend_may_throw(const zend_op *opline, zend_op_array *op_array, zend_ssa *ssa case ZEND_COUNT: return (t1 & MAY_BE_ANY) != MAY_BE_ARRAY; case ZEND_RECV_INIT: - if (Z_CONSTANT_P(CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants))) { + if (Z_TYPE_P(CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants)) == IS_CONSTANT_AST) { return 1; } if (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { diff --git a/ext/opcache/Optimizer/zend_inference.h b/ext/opcache/Optimizer/zend_inference.h index d7a6f97901..6bd9706fa8 100644 --- a/ext/opcache/Optimizer/zend_inference.h +++ b/ext/opcache/Optimizer/zend_inference.h @@ -159,9 +159,7 @@ DEFINE_SSA_OP_RANGE_OVERFLOW(op2) #define OP2_RANGE_OVERFLOW() (_ssa_op2_range_overflow (op_array, ssa, opline)) static zend_always_inline uint32_t _const_op_type(const zval *zv) { - if (Z_TYPE_P(zv) == IS_CONSTANT) { - return MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY; - } else if (Z_TYPE_P(zv) == IS_CONSTANT_AST) { + if (Z_TYPE_P(zv) == IS_CONSTANT_AST) { return MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY; } else if (Z_TYPE_P(zv) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(zv); diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index a7758058de..0b95212693 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -278,7 +278,7 @@ static zend_ast *zend_file_cache_serialize_ast(zend_ast *ast, ret = ast; UNSERIALIZE_PTR(ast); - if (ast->kind == ZEND_AST_ZVAL) { + if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) { zend_file_cache_serialize_zval(&((zend_ast_zval*)ast)->val, script, info, buf); } else if (zend_ast_is_list(ast)) { zend_ast_list *list = zend_ast_get_list(ast); @@ -305,7 +305,6 @@ static void zend_file_cache_serialize_zval(zval *zv, { switch (Z_TYPE_P(zv)) { case IS_STRING: - case IS_CONSTANT: if (!IS_SERIALIZED(Z_STR_P(zv))) { SERIALIZE_STR(Z_STR_P(zv)); } @@ -893,7 +892,7 @@ static zend_ast *zend_file_cache_unserialize_ast(zend_ast *ast, UNSERIALIZE_PTR(ast); - if (ast->kind == ZEND_AST_ZVAL) { + if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) { zend_file_cache_unserialize_zval(&((zend_ast_zval*)ast)->val, script, buf); } else if (zend_ast_is_list(ast)) { zend_ast_list *list = zend_ast_get_list(ast); @@ -919,7 +918,6 @@ static void zend_file_cache_unserialize_zval(zval *zv, { switch (Z_TYPE_P(zv)) { case IS_STRING: - case IS_CONSTANT: if (!IS_UNSERIALIZED(Z_STR_P(zv))) { UNSERIALIZE_STR(Z_STR_P(zv)); } @@ -945,8 +943,6 @@ static void zend_file_cache_unserialize_zval(zval *zv, break; case IS_CONSTANT_AST: if (!IS_UNSERIALIZED(Z_AST_P(zv))) { - zend_ast_ref *ast; - UNSERIALIZE_PTR(Z_AST_P(zv)); zend_file_cache_unserialize_ast(Z_ASTVAL_P(zv), script, buf); } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index c21842b66f..8fb7f41e3e 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -249,7 +249,7 @@ static zend_ast *zend_persist_ast(zend_ast *ast) uint32_t i; zend_ast *node; - if (ast->kind == ZEND_AST_ZVAL) { + if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) { zend_ast_zval *copy = zend_accel_memdup(ast, sizeof(zend_ast_zval)); zend_persist_zval(©->val); node = (zend_ast *) copy; @@ -282,7 +282,6 @@ static void zend_persist_zval(zval *z) switch (Z_TYPE_P(z)) { case IS_STRING: - case IS_CONSTANT: zend_accel_store_interned_string(Z_STR_P(z)); Z_TYPE_FLAGS_P(z) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); break; @@ -320,12 +319,12 @@ static void zend_persist_zval(zval *z) new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z)); if (new_ptr) { Z_AST_P(z) = new_ptr; - Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_COPYABLE; + Z_TYPE_FLAGS_P(z) = IS_TYPE_COPYABLE; } else { zend_ast_ref *old_ref = Z_AST_P(z); Z_ARR_P(z) = zend_accel_memdup(Z_AST_P(z), sizeof(zend_ast_ref)); zend_persist_ast(GC_AST(old_ref)); - Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_COPYABLE; + Z_TYPE_FLAGS_P(z) = IS_TYPE_COPYABLE; GC_REFCOUNT(Z_COUNTED_P(z)) = 2; efree(old_ref); } diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index cb7eb11b7a..0c600daef5 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -94,9 +94,9 @@ static void zend_persist_ast_calc(zend_ast *ast) { uint32_t i; - if (ast->kind == ZEND_AST_ZVAL) { + if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) { ADD_SIZE(sizeof(zend_ast_zval)); - zend_persist_zval_calc(zend_ast_get_zval(ast)); + zend_persist_zval_calc(&((zend_ast_zval*)(ast))->val); } else if (zend_ast_is_list(ast)) { zend_ast_list *list = zend_ast_get_list(ast); ADD_SIZE(sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children); @@ -122,7 +122,6 @@ static void zend_persist_zval_calc(zval *z) switch (Z_TYPE_P(z)) { case IS_STRING: - case IS_CONSTANT: ADD_INTERNED_STRING(Z_STR_P(z), 0); if (ZSTR_IS_INTERNED(Z_STR_P(z))) { Z_TYPE_FLAGS_P(z) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index d42299f55d..6a19940686 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -2806,7 +2806,7 @@ ZEND_METHOD(reflection_parameter, getDefaultValue) } ZVAL_DUP(return_value, RT_CONSTANT(precv, precv->op2)); - if (Z_CONSTANT_P(return_value)) { + if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) { zval_update_constant_ex(return_value, param->fptr->common.scope); } } @@ -2829,8 +2829,13 @@ ZEND_METHOD(reflection_parameter, isDefaultValueConstant) } precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param); - if (precv && Z_TYPE_P(RT_CONSTANT(precv, precv->op2)) == IS_CONSTANT) { - RETURN_TRUE; + if (precv && Z_TYPE_P(RT_CONSTANT(precv, precv->op2)) == IS_CONSTANT_AST) { + zend_ast *ast = Z_ASTVAL_P(RT_CONSTANT(precv, precv->op2)); + + if (ast->kind == ZEND_AST_CONSTANT + || ast->kind == ZEND_AST_CONSTANT_CLASS) { + RETURN_TRUE; + } } RETURN_FALSE; @@ -2854,8 +2859,14 @@ ZEND_METHOD(reflection_parameter, getDefaultValueConstantName) } precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param); - if (precv && Z_TYPE_P(RT_CONSTANT(precv, precv->op2)) == IS_CONSTANT) { - RETURN_STR_COPY(Z_STR_P(RT_CONSTANT(precv, precv->op2))); + if (precv && Z_TYPE_P(RT_CONSTANT(precv, precv->op2)) == IS_CONSTANT_AST) { + zend_ast *ast = Z_ASTVAL_P(RT_CONSTANT(precv, precv->op2)); + + if (ast->kind == ZEND_AST_CONSTANT) { + RETURN_STR_COPY(zend_ast_get_constant_name(ast)); + } else if (ast->kind == ZEND_AST_CONSTANT_CLASS) { + RETURN_STRINGL("__CLASS__", sizeof("__CLASS__")-1); + } } } /* }}} */ @@ -3698,7 +3709,7 @@ ZEND_METHOD(reflection_class_constant, getValue) GET_REFLECTION_OBJECT_PTR(ref); ZVAL_DUP(return_value, &ref->value); - if (Z_CONSTANT_P(return_value)) { + if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) { zval_update_constant_ex(return_value, ref->ce); } } @@ -3834,7 +3845,7 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value /* this is necessary to make it able to work with default array * properties, returned to user */ - if (Z_CONSTANT(prop_copy)) { + if (Z_TYPE(prop_copy) == IS_CONSTANT_AST) { if (UNEXPECTED(zval_update_constant_ex(&prop_copy, NULL) != SUCCESS)) { return; } diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 6d69d81c33..16b15698c5 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -149,7 +149,6 @@ encode defaultEncoding[] = { {{IS_DOUBLE, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL, NULL}, to_zval_double, to_xml_double}, {{IS_FALSE, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL, NULL}, to_zval_bool, to_xml_bool}, {{IS_TRUE, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL, NULL}, to_zval_bool, to_xml_bool}, - {{IS_CONSTANT, XSD_STRING_STRING, XSD_NAMESPACE, NULL, NULL}, to_zval_string, to_xml_string}, {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL, NULL}, to_zval_array, guess_array_map}, {{IS_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_1_ENC_NAMESPACE, NULL, NULL}, to_zval_object, to_xml_object}, {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL, NULL}, to_zval_array, guess_array_map}, diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index fdcc50b860..93d469168b 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -3880,7 +3880,7 @@ PHP_FUNCTION(constant) c = zend_get_constant_ex(const_name, scope, ZEND_FETCH_CLASS_SILENT); if (c) { ZVAL_DUP(return_value, c); - if (Z_CONSTANT_P(return_value)) { + if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) { if (UNEXPECTED(zval_update_constant_ex(return_value, scope) != SUCCESS)) { return; } diff --git a/ext/xmlrpc/xmlrpc-epi-php.c b/ext/xmlrpc/xmlrpc-epi-php.c index e20b6d6872..88f52519d0 100644 --- a/ext/xmlrpc/xmlrpc-epi-php.c +++ b/ext/xmlrpc/xmlrpc-epi-php.c @@ -1339,9 +1339,6 @@ XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval* newvalue) /* {{{ */ case IS_DOUBLE: type = xmlrpc_double; break; - case IS_CONSTANT: - type = xmlrpc_string; - break; case IS_STRING: type = xmlrpc_string; break; diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c index bdcb173c24..fa27fa96a8 100644 --- a/sapi/phpdbg/phpdbg_utils.c +++ b/sapi/phpdbg/phpdbg_utils.c @@ -844,12 +844,17 @@ char *phpdbg_short_zval_print(zval *zv, int maxlen) /* {{{ */ ZSTR_VAL(str), ZSTR_LEN(str) <= maxlen ? 0 : '+'); break; } - case IS_CONSTANT: - decode = estrdup("<constant>"); - break; - case IS_CONSTANT_AST: - decode = estrdup("<ast>"); + case IS_CONSTANT_AST: { + zend_ast *ast = Z_ASTVAL_P(zv); + + if (ast->kind == ZEND_AST_CONSTANT + || ast->kind == ZEND_AST_CONSTANT_CLASS) { + decode = estrdup("<constant>"); + } else { + decode = estrdup("<ast>"); + } break; + } default: spprintf(&decode, 0, "unknown type: %d", Z_TYPE_P(zv)); break; |