Refactor class name resolution as well

This commit is contained in:
Nikita Popov 2014-07-04 23:45:20 +02:00
parent b3336270f6
commit 17c2d16d79
3 changed files with 72 additions and 77 deletions

View file

@ -1651,7 +1651,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization,
} else { } else {
cur_arg_info->type_hint = IS_OBJECT; cur_arg_info->type_hint = IS_OBJECT;
if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) { if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
zend_resolve_class_name(class_type TSRMLS_CC); zend_resolve_class_name_old(class_type TSRMLS_CC);
} }
Z_STR(class_type->u.constant) = zend_new_interned_string(Z_STR(class_type->u.constant) TSRMLS_CC); Z_STR(class_type->u.constant) = zend_new_interned_string(Z_STR(class_type->u.constant) TSRMLS_CC);
if (IS_INTERNED(Z_STR(class_type->u.constant))) { if (IS_INTERNED(Z_STR(class_type->u.constant))) {
@ -1777,77 +1777,70 @@ zend_string *zend_resolve_const_name(
name, is_fully_qualified, 1, CG(current_import_const) TSRMLS_CC); name, is_fully_qualified, 1, CG(current_import_const) TSRMLS_CC);
} }
void zend_resolve_class_name(znode *class_name TSRMLS_DC) /* {{{ */ zend_string *zend_resolve_class_name(
{ zend_string *name, zend_bool is_fully_qualified TSRMLS_DC
) {
char *compound; char *compound;
zend_string *lcname;
zval *ns; zval *ns;
znode tmp;
int len;
compound = memchr(Z_STRVAL(class_name->u.constant), '\\', Z_STRLEN(class_name->u.constant)); if (is_fully_qualified || name->val[0] == '\\') {
if (compound) { /* Remove \ prefix (only relevant if this is a string rather than a label) */
/* This is a compound class name that contains namespace prefix */ if (name->val[0] == '\\') {
if (Z_STRVAL(class_name->u.constant)[0] == '\\') { name = STR_INIT(name->val + 1, name->len - 1, 0);
/* The STRING name has "\" prefix */ } else {
memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant)); STR_ADDREF(name);
Z_STR(class_name->u.constant) = STR_REALLOC( }
Z_STR(class_name->u.constant), /* Ensure that \self, \parent and \static are not used */
Z_STRLEN(class_name->u.constant) - 1, 0); if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name->val, name->len)) {
Z_TYPE_FLAGS(class_name->u.constant) = IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE; zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", name->val);
}
return name;
}
if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) { if (CG(current_import)) {
zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", Z_STRVAL(class_name->u.constant)); compound = memchr(name->val, '\\', name->len);
if (compound) {
/* If the first part of a qualified name is an alias, substitute it. */
size_t len = compound - name->val;
zend_string *lcname = STR_ALLOC(len, 0);
zend_str_tolower_copy(lcname->val, name->val, len);
ns = zend_hash_find(CG(current_import), lcname);
STR_FREE(lcname);
if (ns) {
return zend_concat_names(
Z_STRVAL_P(ns), Z_STRLEN_P(ns), name->val + len + 1, name->len - len - 1);
} }
} else { } else {
if (CG(current_import)) { /* If an unqualified name is an alias, replace it. */
len = compound - Z_STRVAL(class_name->u.constant); zend_string *lcname = STR_ALLOC(name->len, 0);
lcname = STR_ALLOC(len, 0); zend_str_tolower_copy(lcname->val, name->val, name->len);
zend_str_tolower_copy(lcname->val, Z_STRVAL(class_name->u.constant), len);
/* Check if first part of compound name is an import name */
if ((ns = zend_hash_find(CG(current_import), lcname)) != NULL) {
/* Substitute import name */
tmp.op_type = IS_CONST;
ZVAL_DUP(&tmp.u.constant, ns);
len += 1;
Z_STRLEN(class_name->u.constant) -= len;
memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+len, Z_STRLEN(class_name->u.constant)+1);
zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
*class_name = tmp;
STR_FREE(lcname);
return;
}
STR_FREE(lcname);
}
/* Here name is not prefixed with \ and not imported */
if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
tmp.op_type = IS_CONST;
ZVAL_DUP(&tmp.u.constant, &CG(current_namespace));
zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
*class_name = tmp;
}
}
} else if (CG(current_import) || Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
/* this is a plain name (without \) */
lcname = STR_ALLOC(Z_STRLEN(class_name->u.constant), 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
if (CG(current_import) && ns = zend_hash_find(CG(current_import), lcname);
(ns = zend_hash_find(CG(current_import), lcname)) != NULL) { STR_FREE(lcname);
/* The given name is an import name. Substitute it. */
zval_dtor(&class_name->u.constant); if (ns) {
ZVAL_DUP(&class_name->u.constant, ns); return STR_COPY(Z_STR_P(ns));
} else if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) { }
/* plain name, no import - prepend current namespace to it */
tmp.op_type = IS_CONST;
ZVAL_DUP(&tmp.u.constant, &CG(current_namespace));
zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
*class_name = tmp;
} }
STR_FREE(lcname);
} }
/* If not fully qualified and not an alias, prepend the current namespace */
if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
return zend_concat_names(
Z_STRVAL(CG(current_namespace)), Z_STRLEN(CG(current_namespace)), name->val, name->len);
}
return STR_COPY(name);
}
void zend_resolve_class_name_old(znode *class_name TSRMLS_DC) {
zend_string *resolved_name = zend_resolve_class_name(
Z_STR(class_name->u.constant), 0 TSRMLS_CC);
zval_dtor(&class_name->u.constant);
ZVAL_STR(&class_name->u.constant, resolved_name);
} }
/* }}} */
void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
{ {
@ -1874,7 +1867,7 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
zval_dtor(&class_name->u.constant); zval_dtor(&class_name->u.constant);
break; break;
default: default:
zend_resolve_class_name(class_name TSRMLS_CC); zend_resolve_class_name_old(class_name TSRMLS_CC);
opline->op2_type = IS_CONST; opline->op2_type = IS_CONST;
opline->op2.constant = opline->op2.constant =
zend_add_class_name_literal(CG(active_op_array), &class_name->u.constant TSRMLS_CC); zend_add_class_name_literal(CG(active_op_array), &class_name->u.constant TSRMLS_CC);
@ -2280,7 +2273,7 @@ void zend_do_begin_catch(znode *catch_token, znode *class_name, znode *catch_var
if (class_name->op_type == IS_CONST && if (class_name->op_type == IS_CONST &&
ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) { ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
zend_resolve_class_name(class_name TSRMLS_CC); zend_resolve_class_name_old(class_name TSRMLS_CC);
catch_class = *class_name; catch_class = *class_name;
} else { } else {
zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement"); zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
@ -3952,7 +3945,7 @@ void zend_prepare_reference(znode *result, znode *class_name, znode *method_name
/* REM: There should not be a need for copying, /* REM: There should not be a need for copying,
zend_do_begin_class_declaration is also just using that string */ zend_do_begin_class_declaration is also just using that string */
if (class_name) { if (class_name) {
zend_resolve_class_name(class_name TSRMLS_CC); zend_resolve_class_name_old(class_name TSRMLS_CC);
method_ref->class_name = Z_STR(class_name->u.constant); method_ref->class_name = Z_STR(class_name->u.constant);
} else { } else {
method_ref->class_name = NULL; method_ref->class_name = NULL;
@ -4564,7 +4557,7 @@ void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ADD_INTERFACE; opline->opcode = ZEND_ADD_INTERFACE;
SET_NODE(opline->op1, &CG(implementing_class)); SET_NODE(opline->op1, &CG(implementing_class));
zend_resolve_class_name(interface_name TSRMLS_CC); zend_resolve_class_name_old(interface_name TSRMLS_CC);
opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE; opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;
opline->op2_type = IS_CONST; opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &interface_name->u.constant TSRMLS_CC); opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &interface_name->u.constant TSRMLS_CC);
@ -4596,7 +4589,7 @@ void zend_do_use_trait(znode *trait_name TSRMLS_DC) /* {{{ */
opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ADD_TRAIT; opline->opcode = ZEND_ADD_TRAIT;
SET_NODE(opline->op1, &CG(implementing_class)); SET_NODE(opline->op1, &CG(implementing_class));
zend_resolve_class_name(trait_name TSRMLS_CC); zend_resolve_class_name_old(trait_name TSRMLS_CC);
opline->extended_value = ZEND_FETCH_CLASS_TRAIT; opline->extended_value = ZEND_FETCH_CLASS_TRAIT;
opline->op2_type = IS_CONST; opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &trait_name->u.constant TSRMLS_CC); opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &trait_name->u.constant TSRMLS_CC);
@ -6147,7 +6140,7 @@ static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast TSRMLS_
zval_ptr_dtor(name); zval_ptr_dtor(name);
break; break;
default: default:
zend_resolve_class_name(&name_node TSRMLS_CC); zend_resolve_class_name_old(&name_node TSRMLS_CC);
opline->op2_type = IS_CONST; opline->op2_type = IS_CONST;
opline->op2.constant = opline->op2.constant =
zend_add_class_name_literal(CG(active_op_array), name TSRMLS_CC); zend_add_class_name_literal(CG(active_op_array), name TSRMLS_CC);
@ -6307,7 +6300,7 @@ zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, int type
if (zend_is_const_default_class_ref(class_ast)) { if (zend_is_const_default_class_ref(class_ast)) {
zend_compile_expr(&class_node, class_ast TSRMLS_CC); zend_compile_expr(&class_node, class_ast TSRMLS_CC);
zend_resolve_class_name(&class_node TSRMLS_CC); zend_resolve_class_name_old(&class_node TSRMLS_CC);
} else { } else {
zend_compile_class_ref(&class_node, class_ast TSRMLS_CC); zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
} }
@ -6828,7 +6821,7 @@ void zend_compile_static_call(znode *result, zend_ast *ast, int type TSRMLS_DC)
if (zend_is_const_default_class_ref(class_ast)) { if (zend_is_const_default_class_ref(class_ast)) {
zend_compile_expr(&class_node, class_ast TSRMLS_CC); zend_compile_expr(&class_node, class_ast TSRMLS_CC);
zend_resolve_class_name(&class_node TSRMLS_CC); zend_resolve_class_name_old(&class_node TSRMLS_CC);
} else { } else {
opline = zend_compile_class_ref(&class_node, class_ast TSRMLS_CC); opline = zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
extended_value = opline->extended_value; extended_value = opline->extended_value;
@ -7447,7 +7440,7 @@ void zend_compile_class_const(znode *result, zend_ast *ast TSRMLS_DC) {
if (zend_is_const_default_class_ref(class_ast)) { if (zend_is_const_default_class_ref(class_ast)) {
zend_compile_expr(&class_node, class_ast TSRMLS_CC); zend_compile_expr(&class_node, class_ast TSRMLS_CC);
zend_resolve_class_name(&class_node TSRMLS_CC); zend_resolve_class_name_old(&class_node TSRMLS_CC);
} else { } else {
zend_compile_class_ref(&class_node, class_ast TSRMLS_CC); zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
} }
@ -7502,7 +7495,7 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast TSRMLS_DC) {
break; break;
case ZEND_FETCH_CLASS_DEFAULT: case ZEND_FETCH_CLASS_DEFAULT:
zend_compile_expr(result, name_ast TSRMLS_CC); zend_compile_expr(result, name_ast TSRMLS_CC);
zend_resolve_class_name(result TSRMLS_CC); zend_resolve_class_name_old(result TSRMLS_CC);
break; break;
EMPTY_SWITCH_DEFAULT_CASE() EMPTY_SWITCH_DEFAULT_CASE()
} }
@ -7592,7 +7585,7 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr TSRMLS_DC) {
zend_error_noreturn(E_COMPILE_ERROR, zend_error_noreturn(E_COMPILE_ERROR,
"\"static::\" is not allowed in compile-time constants"); "\"static::\" is not allowed in compile-time constants");
} else if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) { } else if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
zend_resolve_class_name(&class_name TSRMLS_CC); zend_resolve_class_name_old(&class_name TSRMLS_CC);
} }
zend_do_build_full_name(NULL, &class_name, &const_name, 1 TSRMLS_CC); zend_do_build_full_name(NULL, &class_name, &const_name, 1 TSRMLS_CC);
@ -7659,7 +7652,7 @@ void zend_compile_const_expr_resolve_class_name(zend_ast **ast_ptr TSRMLS_DC) {
break; break;
case ZEND_FETCH_CLASS_DEFAULT: case ZEND_FETCH_CLASS_DEFAULT:
zend_compile_expr(&result, name_ast TSRMLS_CC); zend_compile_expr(&result, name_ast TSRMLS_CC);
zend_resolve_class_name(&result TSRMLS_CC); zend_resolve_class_name_old(&result TSRMLS_CC);
break; break;
EMPTY_SWITCH_DEFAULT_CASE() EMPTY_SWITCH_DEFAULT_CASE()
} }

View file

@ -459,9 +459,11 @@ ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D);
zend_string *zend_resolve_non_class_name(zend_string *name, zend_bool *is_fully_qualified, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC); zend_string *zend_resolve_non_class_name(zend_string *name, zend_bool *is_fully_qualified, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC);
zend_string *zend_resolve_function_name(zend_string *name, zend_bool *is_fully_qualified TSRMLS_DC); zend_string *zend_resolve_function_name(zend_string *name, zend_bool *is_fully_qualified TSRMLS_DC);
zend_string *zend_resolve_const_name(zend_string *name, zend_bool *is_fully_qualified TSRMLS_DC); zend_string *zend_resolve_const_name(zend_string *name, zend_bool *is_fully_qualified TSRMLS_DC);
void zend_resolve_class_name(znode *class_name TSRMLS_DC); zend_string *zend_resolve_class_name(zend_string *name, zend_bool is_fully_qualified TSRMLS_DC);
ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var); ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var);
void zend_resolve_class_name_old(znode *class_name TSRMLS_DC);
#ifdef ZTS #ifdef ZTS
const char *zend_get_zendtext(TSRMLS_D); const char *zend_get_zendtext(TSRMLS_D);
int zend_get_zendleng(TSRMLS_D); int zend_get_zendleng(TSRMLS_D);

View file

@ -676,8 +676,8 @@ trait_precedence:
; ;
trait_reference_list: trait_reference_list:
fully_qualified_class_name { zend_resolve_class_name(&$1 TSRMLS_CC); zend_init_list(&$$.u.op.ptr, Z_STR($1.u.constant) TSRMLS_CC); } fully_qualified_class_name { zend_resolve_class_name_old(&$1 TSRMLS_CC); zend_init_list(&$$.u.op.ptr, Z_STR($1.u.constant) TSRMLS_CC); }
| trait_reference_list ',' fully_qualified_class_name { zend_resolve_class_name(&$3 TSRMLS_CC); zend_add_to_list(&$1.u.op.ptr, Z_STR($3.u.constant) TSRMLS_CC); $$ = $1; } | trait_reference_list ',' fully_qualified_class_name { zend_resolve_class_name_old(&$3 TSRMLS_CC); zend_add_to_list(&$1.u.op.ptr, Z_STR($3.u.constant) TSRMLS_CC); $$ = $1; }
; ;
trait_method_reference: trait_method_reference: