}
/* }}} */
-void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
- int doing_inheritance = 0;
- zend_class_entry *new_class_entry;
- zend_string *lcname;
- int error = 0;
- zend_string *ns_name;
- zval key;
-
- if (CG(active_class_entry)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
- return;
- }
-
- 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 (!(strcmp(lcname->val, "self") && strcmp(lcname->val, "parent"))) {
- STR_FREE(lcname);
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", Z_STRVAL(class_name->u.constant));
- }
-
- /* Class name must not conflict with import names */
- if (CG(current_import) &&
- (ns_name = zend_hash_find_ptr(CG(current_import), lcname)) != NULL) {
- error = 1;
- }
-
- if (Z_TYPE(CG(current_namespace)) != IS_UNDEF) {
- /* Prefix class name with name of current namespace */
- znode tmp;
-
- 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);
- 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 (error) {
- char *tmp = zend_str_tolower_dup(ns_name->val, ns_name->len);
-
- if (ns_name->len != Z_STRLEN(class_name->u.constant) ||
- memcmp(tmp, lcname->val, Z_STRLEN(class_name->u.constant))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s because the name is already in use", Z_STRVAL(class_name->u.constant));
- }
- efree(tmp);
- }
-
- new_class_entry = emalloc(sizeof(zend_class_entry));
- new_class_entry->type = ZEND_USER_CLASS;
- new_class_entry->name = zend_new_interned_string(Z_STR(class_name->u.constant) TSRMLS_CC);
-
- zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
- new_class_entry->info.user.filename = zend_get_compiled_filename(TSRMLS_C);
- new_class_entry->info.user.line_start = class_token->u.op.opline_num;
- new_class_entry->ce_flags |= class_token->EA;
-
- if (parent_class_name && parent_class_name->op_type != IS_UNUSED) {
- switch (parent_class_name->EA) {
- case ZEND_FETCH_CLASS_SELF:
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'self' as class name as it is reserved");
- break;
- case ZEND_FETCH_CLASS_PARENT:
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved");
- break;
- case ZEND_FETCH_CLASS_STATIC:
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as class name as it is reserved");
- break;
- default:
- break;
- }
- doing_inheritance = 1;
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->op1_type = IS_CONST;
- build_runtime_defined_function_key(&key, lcname, LANG_SCNG(yy_text) TSRMLS_CC);
- opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
-
- opline->op2_type = IS_CONST;
-
- if (doing_inheritance) {
- /* Make sure a trait does not try to extend a class */
- if ((new_class_entry->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
- zend_error_noreturn(E_COMPILE_ERROR, "A trait (%s) cannot extend a class. Traits can only be composed from other traits with the 'use' keyword. Error", new_class_entry->name->val);
- }
-
- opline->extended_value = parent_class_name->u.op.var;
- opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
- } else {
- opline->opcode = ZEND_DECLARE_CLASS;
- }
-
- LITERAL_STR(opline->op2, lcname);
-
- zend_hash_update_ptr(CG(class_table), Z_STR(key), new_class_entry);
- CG(active_class_entry) = new_class_entry;
-
- opline->result.var = get_temporary_variable(CG(active_op_array));
- opline->result_type = IS_VAR;
- GET_NODE(&CG(implementing_class), opline->result);
-
- if (CG(doc_comment)) {
- CG(active_class_entry)->info.user.doc_comment = CG(doc_comment);
- CG(doc_comment) = NULL;
- }
-}
-/* }}} */
-
static void do_verify_abstract_class(TSRMLS_D) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
}
/* }}} */
-void zend_do_end_class_declaration(const znode *class_token, const znode *parent_token TSRMLS_DC) /* {{{ */
-{
- zend_class_entry *ce = CG(active_class_entry);
-
- if (ce->constructor) {
- ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
- if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error_noreturn(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static", ce->name->val, ce->constructor->common.function_name->val);
- }
- }
- if (ce->destructor) {
- ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
- if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error_noreturn(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static", ce->name->val, ce->destructor->common.function_name->val);
- }
- }
- if (ce->clone) {
- ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
- if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error_noreturn(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static", ce->name->val, ce->clone->common.function_name->val);
- }
- }
-
- ce->info.user.line_end = zend_get_compiled_lineno(TSRMLS_C);
-
- /* Check for traits and proceed like with interfaces.
- * The only difference will be a combined handling of them in the end.
- * Thus, we need another opcode here. */
- if (ce->num_traits > 0) {
- zend_op *opline;
-
- ce->traits = NULL;
- ce->num_traits = 0;
- ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
-
- /* opcode generation: */
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_BIND_TRAITS;
- SET_NODE(opline->op1, &CG(implementing_class));
- }
-
- if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
- && (parent_token || (ce->num_interfaces > 0))) {
- zend_verify_abstract_class(ce TSRMLS_CC);
- if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
- do_verify_abstract_class(TSRMLS_C);
- }
- }
- /* Inherit interfaces; reset number to zero, we need it for above check and
- * will restore it during actual implementation.
- * The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
- * zend_verify_abstract_class() */
- if (ce->num_interfaces > 0) {
- ce->interfaces = NULL;
- ce->num_interfaces = 0;
- ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
- }
-
- CG(active_class_entry) = NULL;
-}
-/* }}} */
-
-void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
-
- /* Traits can not implement interfaces */
- if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as interface on '%s' since it is a Trait",
- Z_STRVAL(interface_name->u.constant),
- CG(active_class_entry)->name->val);
- }
-
- switch (zend_get_class_fetch_type(Z_STRVAL(interface_name->u.constant), Z_STRLEN(interface_name->u.constant))) {
- case ZEND_FETCH_CLASS_SELF:
- case ZEND_FETCH_CLASS_PARENT:
- case ZEND_FETCH_CLASS_STATIC:
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as interface name as it is reserved", Z_STRVAL(interface_name->u.constant));
- break;
- default:
- break;
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_ADD_INTERFACE;
- SET_NODE(opline->op1, &CG(implementing_class));
- 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), Z_STR(interface_name->u.constant) TSRMLS_CC);
- CG(active_class_entry)->num_interfaces++;
-}
-/* }}} */
-
ZEND_API zend_string *zend_mangle_property_name(const char *src1, int src1_length, const char *src2, int src2_length, int internal) /* {{{ */
{
zend_string *prop_name;
}
/* }}} */
-void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC) /* {{{ */
-{
- zval property;
- zend_property_info *existing_property_info;
- zend_string *comment = NULL;
-
- if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
- zend_error_noreturn(E_COMPILE_ERROR, "Interfaces may not include member variables");
- }
-
- if (access_type & ZEND_ACC_ABSTRACT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract");
- }
-
- if (access_type & ZEND_ACC_FINAL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, the final modifier is allowed only for methods and classes",
- CG(active_class_entry)->name->val, Z_STRVAL(var_name->u.constant));
- }
-
- if ((existing_property_info = zend_hash_find_ptr(&CG(active_class_entry)->properties_info, Z_STR(var_name->u.constant))) != NULL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name->val, Z_STRVAL(var_name->u.constant));
- }
-
- if (value) {
- ZVAL_COPY_VALUE(&property, &value->u.constant);
- } else {
- ZVAL_NULL(&property);
- }
-
- if (CG(doc_comment)) {
- comment = CG(doc_comment);
- CG(doc_comment) = NULL;
- }
-
- Z_STR(var_name->u.constant) = zend_new_interned_string(Z_STR(var_name->u.constant) TSRMLS_CC);
- if (IS_INTERNED(Z_STR(var_name->u.constant))) {
- Z_TYPE_FLAGS(var_name->u.constant) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
- }
- zend_declare_property_ex(CG(active_class_entry), Z_STR(var_name->u.constant), &property, access_type, comment TSRMLS_CC);
- STR_RELEASE(Z_STR(var_name->u.constant));
-}
-/* }}} */
-
-void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC) /* {{{ */
-{
- zval property;
-
- if ((Z_TYPE(value->u.constant) == IS_ARRAY) ||
- (Z_TYPE(value->u.constant) == IS_CONSTANT_AST &&
- Z_ASTVAL(value->u.constant)->kind == ZEND_INIT_ARRAY)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Arrays are not allowed in class constants");
- return;
- }
- if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants");
- return;
- }
-
- ZVAL_COPY_VALUE(&property, &value->u.constant);
-
- Z_STR(var_name->u.constant) = zend_new_interned_string(Z_STR(var_name->u.constant) TSRMLS_CC);
- if (IS_INTERNED(Z_STR(var_name->u.constant))) {
- Z_TYPE_FLAGS(var_name->u.constant) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
- }
- if (zend_hash_add(&CG(active_class_entry)->constants_table, Z_STR(var_name->u.constant), &property) == NULL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name->val, Z_STRVAL(var_name->u.constant));
- }
- FREE_PNODE(var_name);
-
- if (CG(doc_comment)) {
- STR_RELEASE(CG(doc_comment));
- CG(doc_comment) = NULL;
- }
-}
-/* }}} */
-
void zend_do_halt_compiler_register(TSRMLS_D) /* {{{ */
{
zend_string *name;