}
/* }}} */
-static int zend_add_class_name_literal(zend_op_array *op_array, zval *zv TSRMLS_DC) /* {{{ */
-{
+static int zend_add_class_name_literal(zend_op_array *op_array, zend_string *name TSRMLS_DC) {
int ret;
zend_string *lc_name;
- zval c;
- if (op_array->last_literal > 0 &&
- &op_array->literals[op_array->last_literal - 1] == zv &&
- Z_CACHE_SLOT(op_array->literals[op_array->last_literal - 1]) == -1) {
- /* we already have function name as last literal (do nothing) */
- ret = op_array->last_literal - 1;
- } else {
- ret = zend_add_literal(op_array, zv TSRMLS_CC);
- }
+ zval zv;
+ ZVAL_STR(&zv, name);
- if (Z_STRVAL_P(zv)[0] == '\\') {
- lc_name = STR_ALLOC(Z_STRLEN_P(zv) - 1, 0);
- zend_str_tolower_copy(lc_name->val, Z_STRVAL_P(zv) + 1, Z_STRLEN_P(zv) - 1);
+ ret = zend_add_literal(op_array, &zv TSRMLS_CC);
+
+ if (name->val[0] == '\\') {
+ lc_name = STR_ALLOC(name->len - 1, 0);
+ zend_str_tolower_copy(lc_name->val, name->val + 1, name->len - 1);
} else {
- lc_name = STR_ALLOC(Z_STRLEN_P(zv), 0);
- zend_str_tolower_copy(lc_name->val, Z_STRVAL_P(zv), Z_STRLEN_P(zv));
+ lc_name = STR_ALLOC(name->len, 0);
+ zend_str_tolower_copy(lc_name->val, name->val, name->len);
}
- ZVAL_NEW_STR(&c, lc_name);
- zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+
+ ZVAL_NEW_STR(&zv, lc_name);
+ zend_add_literal(CG(active_op_array), &zv TSRMLS_CC);
GET_CACHE_SLOT(ret);
zend_string *zend_resolve_class_name_ast(zend_ast *ast TSRMLS_DC) {
zend_string *name = Z_STR_P(zend_ast_get_zval(ast));
- zend_bool is_fully_qualified = ast->attr;
+ zend_bool is_fully_qualified = !ast->attr;
return zend_resolve_class_name(name, is_fully_qualified TSRMLS_CC);
}
zend_resolve_class_name_old(class_name TSRMLS_CC);
opline->op2_type = IS_CONST;
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), Z_STR(class_name->u.constant) TSRMLS_CC);
break;
}
} else {
zend_resolve_class_name_old(interface_name TSRMLS_CC);
opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;
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), Z_STR(interface_name->u.constant) TSRMLS_CC);
CG(active_class_entry)->num_interfaces++;
}
/* }}} */
static void zend_set_class_name_op1(zend_op *opline, znode *class_node TSRMLS_DC) {
if (class_node->op_type == IS_CONST) {
opline->op1_type = IS_CONST;
- opline->op1.constant =
- zend_add_class_name_literal(CG(active_op_array), &class_node->u.constant TSRMLS_CC);
+ opline->op1.constant = zend_add_class_name_literal(
+ CG(active_op_array), Z_STR(class_node->u.constant) TSRMLS_CC);
} else {
SET_NODE(opline->op1, class_node);
}
}
static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast TSRMLS_DC) {
- znode name_node;
zend_op *opline;
- zend_compile_expr(&name_node, name_ast TSRMLS_CC);
-
- if (name_node.op_type == IS_CONST) {
- zval *name = &name_node.u.constant;
+ if (name_ast->kind == ZEND_AST_ZVAL) {
+ zval *name = zend_ast_get_zval(name_ast);
int fetch_type = zend_get_class_fetch_type(Z_STRVAL_P(name), Z_STRLEN_P(name));
opline = emit_op(result, ZEND_FETCH_CLASS, NULL, NULL TSRMLS_CC);
opline->extended_value = fetch_type;
- switch (fetch_type) {
- case ZEND_FETCH_CLASS_SELF:
- case ZEND_FETCH_CLASS_PARENT:
- case ZEND_FETCH_CLASS_STATIC:
- zval_ptr_dtor(name);
- break;
- default:
- zend_resolve_class_name_old(&name_node TSRMLS_CC);
- opline->op2_type = IS_CONST;
- opline->op2.constant =
- zend_add_class_name_literal(CG(active_op_array), name TSRMLS_CC);
- break;
+ if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
+ zend_resolve_class_name_ast(name_ast TSRMLS_CC) TSRMLS_CC);
}
} else {
+ znode name_node;
+ zend_compile_expr(&name_node, name_ast TSRMLS_CC);
opline = emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node TSRMLS_CC);
opline->extended_value = ZEND_FETCH_CLASS_DEFAULT;
}
zend_op *opline;
if (zend_is_const_default_class_ref(class_ast)) {
- zend_compile_expr(&class_node, class_ast TSRMLS_CC);
- zend_resolve_class_name_old(&class_node TSRMLS_CC);
+ class_node.op_type = IS_CONST;
+ ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast TSRMLS_CC));
} else {
zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
}
}
if (class_node.op_type == IS_CONST) {
opline->op2_type = IS_CONST;
- opline->op2.constant =
- zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
+ opline->op2.constant = zend_add_class_name_literal(
+ CG(active_op_array), Z_STR(class_node.u.constant) TSRMLS_CC);
} else {
SET_NODE(opline->op2, &class_node);
}
zend_ulong extended_value = 0;
if (zend_is_const_default_class_ref(class_ast)) {
- zend_compile_expr(&class_node, class_ast TSRMLS_CC);
- zend_resolve_class_name_old(&class_node TSRMLS_CC);
+ class_node.op_type = IS_CONST;
+ ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast TSRMLS_CC));
} else {
opline = zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
extended_value = opline->extended_value;
zval *var_name = zend_ast_get_zval(var_ast);
zend_bool is_last_catch = (i + 1 == catches_ast->children);
- znode class_node;
zend_uint opnum_catch;
- if (zend_is_const_default_class_ref(class_ast)) {
- zend_compile_expr(&class_node, class_ast TSRMLS_CC);
- zend_resolve_class_name_old(&class_node TSRMLS_CC);
- } else {
+ if (!zend_is_const_default_class_ref(class_ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
}
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_CATCH;
opline->op1_type = IS_CONST;
- opline->op1.constant = zend_add_class_name_literal(
- CG(active_op_array), &class_node.u.constant TSRMLS_CC);
+ opline->op1.constant = zend_add_class_name_literal(CG(active_op_array),
+ zend_resolve_class_name_ast(class_ast TSRMLS_CC) TSRMLS_CC);
+
opline->op2_type = IS_CV;
opline->op2.var = lookup_cv(CG(active_op_array), STR_COPY(Z_STR_P(var_name)) TSRMLS_CC);
opline->result.num = is_last_catch;
zend_ast *trait_ast = traits_ast->child[i];
zend_string *name = Z_STR_P(zend_ast_get_zval(trait_ast));
- znode name_node;
-
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use traits inside of interfaces. "
"%s is used in %s", name->val, ce->name->val);
break;
}
- zend_compile_expr(&name_node, trait_ast TSRMLS_CC);
- zend_resolve_class_name_old(&name_node TSRMLS_CC);
-
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ADD_TRAIT;
SET_NODE(opline->op1, &CG(implementing_class));
opline->extended_value = ZEND_FETCH_CLASS_TRAIT;
opline->op2_type = IS_CONST;
- opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &name_node.u.constant TSRMLS_CC);
+ opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
+ zend_resolve_class_name_ast(trait_ast TSRMLS_CC) TSRMLS_CC);
+
ce->num_traits++;
}
zend_op *opline;
if (zend_is_const_default_class_ref(class_ast)) {
- zend_compile_expr(&class_node, class_ast TSRMLS_CC);
- zend_resolve_class_name_old(&class_node TSRMLS_CC);
+ class_node.op_type = IS_CONST;
+ ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast TSRMLS_CC));
} else {
zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
}
}
break;
case ZEND_FETCH_CLASS_DEFAULT:
- zend_compile_expr(result, name_ast TSRMLS_CC);
- zend_resolve_class_name_old(result TSRMLS_CC);
+ result->op_type = IS_CONST;
+ ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast TSRMLS_CC));
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
zend_ast *ast = *ast_ptr;
zend_ast *class_ast = ast->child[0];
zend_ast *const_ast = ast->child[1];
- znode class_name, const_name;
+ zend_string *class_name = Z_STR_P(zend_ast_get_zval(class_ast));
+ zend_string *const_name = Z_STR_P(zend_ast_get_zval(const_ast));
zval result;
int fetch_type;
"Dynamic class names are not allowed in compile-time class constant references");
}
- zend_compile_expr(&class_name, class_ast TSRMLS_CC);
- zend_compile_expr(&const_name, const_ast TSRMLS_CC);
- fetch_type = zend_get_class_fetch_type(
- Z_STRVAL(class_name.u.constant), Z_STRLEN(class_name.u.constant));
+ fetch_type = zend_get_class_fetch_type(class_name->val, class_name->len);
if (ZEND_FETCH_CLASS_STATIC == fetch_type) {
zend_error_noreturn(E_COMPILE_ERROR,
"\"static::\" is not allowed in compile-time constants");
- } else if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
- zend_resolve_class_name_old(&class_name TSRMLS_CC);
+ }
+
+ if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
+ class_name = zend_resolve_class_name_ast(class_ast TSRMLS_CC);
+ } else {
+ STR_ADDREF(class_name);
}
- zend_do_build_full_name(NULL, &class_name, &const_name, 1 TSRMLS_CC);
+ Z_STR(result) = zend_concat3(
+ class_name->val, class_name->len, "::", 2, const_name->val, const_name->len);
- ZVAL_COPY_VALUE(&result, &class_name.u.constant);
Z_TYPE_INFO(result) = IS_CONSTANT_EX;
if (IS_INTERNED(Z_STR(result))) {
Z_TYPE_FLAGS(result) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
Z_CONST_FLAGS(result) = fetch_type;
zend_ast_destroy(ast);
+ STR_RELEASE(class_name);
+
*ast_ptr = zend_ast_create_zval(&result);
}
zend_ast *name_ast = ast->child[0];
zval *name = zend_ast_get_zval(name_ast);
int fetch_type = zend_get_class_fetch_type(Z_STRVAL_P(name), Z_STRLEN_P(name));
- znode result;
+ zval result;
switch (fetch_type) {
case ZEND_FETCH_CLASS_SELF:
zend_error_noreturn(E_COMPILE_ERROR,
"Cannot access self::class when no class scope is active");
}
- ZVAL_STR(&result.u.constant, STR_COPY(CG(active_class_entry)->name));
+ ZVAL_STR(&result, STR_COPY(CG(active_class_entry)->name));
break;
case ZEND_FETCH_CLASS_STATIC:
case ZEND_FETCH_CLASS_PARENT:
);
break;
case ZEND_FETCH_CLASS_DEFAULT:
- zend_compile_expr(&result, name_ast TSRMLS_CC);
- zend_resolve_class_name_old(&result TSRMLS_CC);
+ ZVAL_STR(&result, zend_resolve_class_name_ast(name_ast TSRMLS_CC));
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
zend_ast_destroy(ast);
- *ast_ptr = zend_ast_create_zval(&result.u.constant);
+ *ast_ptr = zend_ast_create_zval(&result);
}
void zend_compile_const_expr(zend_ast **ast_ptr TSRMLS_DC) {
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_CALL, $1.u.ast, $2.u.ast); }
| class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
{ $$.u.ast = zend_ast_create_ternary(ZEND_AST_STATIC_CALL,
- AST_ZVAL(&$1), $3.u.ast, $4.u.ast); }
+ $1.u.ast, $3.u.ast, $4.u.ast); }
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
{ $$.u.ast = zend_ast_create_ternary(ZEND_AST_STATIC_CALL,
$1.u.ast, $3.u.ast, $4.u.ast); }
;
class_name:
- T_STATIC { $$.op_type = IS_CONST; ZVAL_STRINGL(&$$.u.constant, "static", sizeof("static")-1);}
- | namespace_name { $$ = $1; }
- | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); $$ = $2; }
+ T_STATIC
+ { zval zv; ZVAL_STRINGL(&zv, "static", sizeof("static")-1);
+ $$.u.ast = zend_ast_create_zval(&zv); }
+ | name { $$.u.ast = $1.u.ast; }
;
fully_qualified_class_name:
class_name_reference:
- class_name { $$.u.ast = AST_ZVAL(&$1); }
+ class_name { $$.u.ast = $1.u.ast; }
| new_variable { $$.u.ast = $1.u.ast; }
;
static_member:
class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
- { $$.u.ast = zend_ast_create_binary(ZEND_AST_STATIC_PROP, AST_ZVAL(&$1), $3.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_STATIC_PROP, $1.u.ast, $3.u.ast); }
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_STATIC_PROP, $1.u.ast, $3.u.ast); }
;
| new_variable T_OBJECT_OPERATOR member_name
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_PROP, $1.u.ast, $3.u.ast); }
| class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
- { $$.u.ast = zend_ast_create_binary(ZEND_AST_STATIC_PROP, AST_ZVAL(&$1), $3.u.ast); }
+ { $$.u.ast = zend_ast_create_binary(ZEND_AST_STATIC_PROP, $1.u.ast, $3.u.ast); }
| new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable
{ $$.u.ast = zend_ast_create_binary(ZEND_AST_STATIC_PROP, $1.u.ast, $3.u.ast); }
;
class_constant:
class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING
{ $$.u.ast = zend_ast_create_binary(
- ZEND_AST_CLASS_CONST, AST_ZVAL(&$1), AST_ZVAL(&$3)); }
+ ZEND_AST_CLASS_CONST, $1.u.ast, AST_ZVAL(&$3)); }
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING
{ $$.u.ast = zend_ast_create_binary(
ZEND_AST_CLASS_CONST, $1.u.ast, AST_ZVAL(&$3)); }
class_name_scalar:
class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS
- { $$.u.ast = zend_ast_create_unary(ZEND_AST_RESOLVE_CLASS_NAME, AST_ZVAL(&$1)); }
+ { $$.u.ast = zend_ast_create_unary(ZEND_AST_RESOLVE_CLASS_NAME, $1.u.ast); }
;
%%