}
/* }}} */
-void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{{ */
+void zend_compile_class_const(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- char *lcname;
- zval *name, *ns, tmp;
- zend_bool warn = 0;
- zend_class_entry **pce;
+ zend_ast *class_ast = ast->child[0];
+ zend_ast *const_ast = ast->child[1];
- if (!CG(current_import)) {
- CG(current_import) = emalloc(sizeof(HashTable));
- zend_hash_init(CG(current_import), 0, NULL, ZVAL_PTR_DTOR, 0);
- }
+ znode class_node, const_node;
+ zend_op *opline;
- MAKE_STD_ZVAL(ns);
- ZVAL_ZVAL(ns, &ns_name->u.constant, 0, 0);
- if (new_name) {
- name = &new_name->u.constant;
+ if (zend_is_const_default_class_ref(class_ast)) {
+ class_node.op_type = IS_CONST;
+ ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast TSRMLS_CC));
} else {
- const char *p;
-
- /* The form "use A\B" is eqivalent to "use A\B as B".
- So we extract the last part of compound name to use as a new_name */
- name = &tmp;
- p = zend_memrchr(Z_STRVAL_P(ns), '\\', Z_STRLEN_P(ns));
- if (p) {
- ZVAL_STRING(name, p+1, 1);
- } else {
- ZVAL_ZVAL(name, ns, 1, 0);
- warn = !is_global && !CG(current_namespace);
- }
+ zend_compile_class_ref(&class_node, class_ast TSRMLS_CC);
}
- lcname = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+ zend_compile_expr(&const_node, const_ast TSRMLS_CC);
- if (((Z_STRLEN_P(name) == sizeof("self")-1) &&
- !memcmp(lcname, "self", sizeof("self")-1)) ||
- ((Z_STRLEN_P(name) == sizeof("parent")-1) &&
- !memcmp(lcname, "parent", sizeof("parent")-1))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name));
+ opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, &const_node TSRMLS_CC);
+
+ zend_set_class_name_op1(opline, &class_node TSRMLS_CC);
+
+ if (opline->op1_type == IS_CONST) {
+ zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC);
+ } else {
+ zend_alloc_polymorphic_cache_slot(opline->op2.constant TSRMLS_CC);
}
+}
+/* }}} */
- if (CG(current_namespace)) {
- /* Prefix import name with current namespace name to avoid conflicts with classes */
- char *c_ns_name = emalloc(Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) + 1);
-
- zend_str_tolower_copy(c_ns_name, Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
- c_ns_name[Z_STRLEN_P(CG(current_namespace))] = '\\';
- memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lcname, Z_STRLEN_P(name)+1);
- if (zend_hash_exists(CG(class_table), c_ns_name, Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name)+1)) {
- char *tmp2 = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
-
- if (Z_STRLEN_P(ns) != Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
- memcmp(tmp2, c_ns_name, Z_STRLEN_P(ns))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
+void zend_compile_resolve_class_name(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
+{
+ zend_ast *name_ast = ast->child[0];
+ uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
+
+ 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");
}
- result->op_type = IS_CONST;
- ZVAL_STR_COPY(&result->u.constant, CG(active_class_entry)->name);
- efree(tmp2);
- }
- efree(c_ns_name);
- } else if (zend_hash_find(CG(class_table), lcname, Z_STRLEN_P(name)+1, (void**)&pce) == SUCCESS &&
- (*pce)->type == ZEND_USER_CLASS &&
- (*pce)->info.user.filename == CG(compiled_filename)) {
- char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
++ if (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) {
++ zval class_str_zv;
++ zend_ast *class_str_ast, *class_const_ast;
+
- if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
- memcmp(c_tmp, lcname, Z_STRLEN_P(ns))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
- }
- efree(c_tmp);
- }
++ ZVAL_STRING(&class_str_zv, "class");
++ class_str_ast = zend_ast_create_zval(&class_str_zv);
++ class_const_ast = zend_ast_create(ZEND_AST_CLASS_CONST, name_ast, class_str_ast);
+
- if (zend_hash_add(CG(current_import), lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
- }
- if (warn) {
- if (!strcmp(Z_STRVAL_P(name), "strict")) {
- zend_error_noreturn(E_COMPILE_ERROR, "You seem to be trying to use a different language...");
- }
- zend_error(E_WARNING, "The use statement with non-compound name '%s' has no effect", Z_STRVAL_P(name));
++ zend_compile_expr(result, class_const_ast TSRMLS_CC);
++
++ zval_ptr_dtor(&class_str_zv);
++ } else {
++ result->op_type = IS_CONST;
++ ZVAL_STR_COPY(&result->u.constant, CG(active_class_entry)->name);
++ }
+ 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;
+
+ ZVAL_STRING(&class_str_zv, "class");
+ class_str_ast = zend_ast_create_zval(&class_str_zv);
+ class_const_ast = zend_ast_create(
+ ZEND_AST_CLASS_CONST, name_ast, class_str_ast);
+
+ zend_compile_expr(result, class_const_ast TSRMLS_CC);
+
+ zval_ptr_dtor(&class_str_zv);
+ }
+ break;
+ case ZEND_FETCH_CLASS_DEFAULT:
+ result->op_type = IS_CONST;
+ ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast TSRMLS_CC));
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
}
- efree(lcname);
- zval_dtor(name);
}
/* }}} */