diff --git a/Zend/tests/bug75573.phpt b/Zend/tests/bug75573.phpt index 476ff6e6cfab9..f5e87f82838a2 100644 --- a/Zend/tests/bug75573.phpt +++ b/Zend/tests/bug75573.phpt @@ -6,10 +6,6 @@ Bug #75573 (Segmentation fault in 7.1.12 and 7.0.26) class A { var $_stdObject; - function initialize($properties = FALSE) { - $this->_stdObject = $properties ? (object) $properties : new stdClass(); - parent::initialize(); - } function &__get($property) { if (isset($this->_stdObject->{$property})) { @@ -31,10 +27,6 @@ class A class B extends A { - function initialize($properties = array()) - { - parent::initialize($properties); - } function &__get($property) { if (isset($this->settings) && isset($this->settings[$property])) { diff --git a/Zend/tests/class_name_as_scalar.phpt b/Zend/tests/class_name_as_scalar.phpt index 72a460abaae0f..a01ac45d81f39 100644 --- a/Zend/tests/class_name_as_scalar.phpt +++ b/Zend/tests/class_name_as_scalar.phpt @@ -8,8 +8,11 @@ namespace Foo\Bar { // compile time constants const A = self::class; const B = Two::class; + } class Two extends One { + const A = parent::class; + public static function run() { var_dump(self::class); // self compile time lookup var_dump(static::class); // runtime lookup @@ -18,6 +21,8 @@ namespace Foo\Bar { } } class Three extends Two { + const B = parent::class; + // compile time static lookups public static function checkCompileTime( $one = self::class, diff --git a/Zend/tests/class_name_as_scalar_error_002.phpt b/Zend/tests/class_name_as_scalar_error_002.phpt index 59b7a2edc9acc..11268fbf017ba 100644 --- a/Zend/tests/class_name_as_scalar_error_002.phpt +++ b/Zend/tests/class_name_as_scalar_error_002.phpt @@ -10,4 +10,6 @@ namespace Foo\Bar { } ?> --EXPECTF-- -Fatal error: parent::class cannot be used for compile-time class name resolution in %s on line %d +Deprecated: Cannot use "parent" without a parent class in %s on line %d + +Fatal error: Cannot use "parent" without a parent class in %s on line %d diff --git a/Zend/tests/class_name_as_scalar_error_004.phpt b/Zend/tests/class_name_as_scalar_error_004.phpt index c00037fca3e15..166e29466bd8a 100644 --- a/Zend/tests/class_name_as_scalar_error_004.phpt +++ b/Zend/tests/class_name_as_scalar_error_004.phpt @@ -10,4 +10,6 @@ namespace Foo\Bar { } ?> --EXPECTF-- -Fatal error: parent::class cannot be used for compile-time class name resolution in %s on line %d +Deprecated: Cannot use "parent" without a parent class in %s on line %d + +Fatal error: Cannot use "parent" without a parent class in %s on line %d diff --git a/Zend/tests/compile_time_parent_error_01.phpt b/Zend/tests/compile_time_parent_error_01.phpt new file mode 100644 index 0000000000000..41929c3fc1b9e --- /dev/null +++ b/Zend/tests/compile_time_parent_error_01.phpt @@ -0,0 +1,11 @@ +--TEST-- +Using "parent" in class without parent results in compile-time error +--FILE-- + +--EXPECTF-- +Deprecated: Cannot use "parent" without a parent class in %s on line %d diff --git a/Zend/tests/compile_time_parent_error_02.phpt b/Zend/tests/compile_time_parent_error_02.phpt new file mode 100644 index 0000000000000..47d8183706007 --- /dev/null +++ b/Zend/tests/compile_time_parent_error_02.phpt @@ -0,0 +1,11 @@ +--TEST-- +Using "parent" in class without parent results in compile-time error +--FILE-- + +--EXPECTF-- +Deprecated: Cannot use "parent" without a parent class in %s on line %d diff --git a/Zend/tests/compile_time_parent_error_03.phpt b/Zend/tests/compile_time_parent_error_03.phpt new file mode 100644 index 0000000000000..4c92e5edce2f9 --- /dev/null +++ b/Zend/tests/compile_time_parent_error_03.phpt @@ -0,0 +1,13 @@ +--TEST-- +Using "parent" in class without parent results in compile-time error +--FILE-- + +--EXPECTF-- +Deprecated: Cannot use "parent" without a parent class in %s on line %d diff --git a/Zend/tests/compile_time_parent_error_04.phpt b/Zend/tests/compile_time_parent_error_04.phpt new file mode 100644 index 0000000000000..a9703f0b4193c --- /dev/null +++ b/Zend/tests/compile_time_parent_error_04.phpt @@ -0,0 +1,13 @@ +--TEST-- +Using "parent" in class without parent results in compile-time error +--FILE-- + +--EXPECTF-- +Deprecated: Cannot use "parent" without a parent class in %s on line %d diff --git a/Zend/tests/compile_time_parent_error_05.phpt b/Zend/tests/compile_time_parent_error_05.phpt new file mode 100644 index 0000000000000..e002197fa4b7c --- /dev/null +++ b/Zend/tests/compile_time_parent_error_05.phpt @@ -0,0 +1,17 @@ +--TEST-- +Using "parent" in class without parent results in compile-time error +--FILE-- + +--EXPECTF-- +Deprecated: Cannot use "parent" without a parent class in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 7c63771fed9cd..da2514caf99e6 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -331,6 +331,7 @@ void zend_init_compiler_data_structures(void) /* {{{ */ zend_stack_init(&CG(loop_var_stack), sizeof(zend_loop_var)); zend_stack_init(&CG(delayed_oplines_stack), sizeof(zend_op)); CG(active_class_entry) = NULL; + CG(active_class_entry_parent_name) = NULL; CG(in_compilation) = 0; CG(start_lineno) = 0; @@ -1467,10 +1468,22 @@ static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */ static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */ { - if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry) && zend_is_scope_known()) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active", - fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : - fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); + if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && zend_is_scope_known()) { + if (!CG(active_class_entry)) { + zend_error_noreturn( + E_COMPILE_ERROR, + "Cannot use \"%s\" when no class scope is active", + fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : + fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static" + ); + } else if (fetch_type == ZEND_FETCH_CLASS_PARENT + && !CG(active_class_entry_parent_name)) + { + zend_error_noreturn( + E_DEPRECATED, + "Cannot use \"parent\" without a parent class" + ); + } } } /* }}} */ @@ -1493,23 +1506,39 @@ static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_a } fetch_type = zend_get_class_fetch_type(zend_ast_get_str(class_ast)); - zend_ensure_valid_class_fetch_type(fetch_type); switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: + zend_ensure_valid_class_fetch_type(fetch_type); if (constant || (CG(active_class_entry) && zend_is_scope_known())) { ZVAL_STR_COPY(zv, CG(active_class_entry)->name); } else { ZVAL_NULL(zv); } return 1; - case ZEND_FETCH_CLASS_STATIC: + case ZEND_FETCH_CLASS_PARENT: + if (zend_is_scope_known()) { + if (CG(active_class_entry_parent_name)) { + ZVAL_STR_COPY(zv, CG(active_class_entry_parent_name)); + return 1; + } + if (constant) { + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot use \"parent\" without a parent class"); + } else { + zend_error(E_DEPRECATED, + "Cannot use \"parent\" without a parent class"); + } + } + ZVAL_NULL(zv); + return 1; + + case ZEND_FETCH_CLASS_STATIC: + zend_ensure_valid_class_fetch_type(fetch_type); if (constant) { zend_error_noreturn(E_COMPILE_ERROR, - "%s::class cannot be used for compile-time class name resolution", - fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent" - ); + "static::class cannot be used for compile-time class name resolution"); } else { ZVAL_NULL(zv); } @@ -6307,6 +6336,7 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ int extends_const; zend_class_entry *original_ce = CG(active_class_entry); + zend_string *original_ce_parent_name = CG(active_class_entry_parent_name); znode original_implementing_class = FC(implementing_class); if (EXPECTED((decl->flags & ZEND_ACC_ANON_CLASS) == 0)) { @@ -6423,6 +6453,15 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ } CG(active_class_entry) = ce; + if (extends_ast) { + zend_string *extends_name = zend_ast_get_str(extends_ast); + CG(active_class_entry_parent_name) = zend_resolve_class_name( + extends_name, + extends_ast->kind == ZEND_AST_ZVAL ? extends_ast->attr : ZEND_NAME_FQ + ); + } else { + CG(active_class_entry_parent_name) = NULL; + } zend_compile_stmt(stmt_ast); @@ -6504,6 +6543,10 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ FC(implementing_class) = original_implementing_class; CG(active_class_entry) = original_ce; + if (CG(active_class_entry_parent_name)) { + zend_string_release(CG(active_class_entry_parent_name)); + } + CG(active_class_entry_parent_name) = original_ce_parent_name; } /* }}} */ diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 907349c173171..1cb2454954cfc 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -69,6 +69,7 @@ struct _zend_compiler_globals { zend_stack loop_var_stack; zend_class_entry *active_class_entry; + zend_string *active_class_entry_parent_name; zend_string *compiled_filename;