From 9b3fda43424bb9044afcbf8490e38906c46851a3 Mon Sep 17 00:00:00 2001 From: Nikita Popov <nikita.ppv@gmail.com> Date: Fri, 4 Jan 2019 11:16:59 +0100 Subject: [PATCH] Don't replace self::class with __CLASS__ during const eval Instead delay this until const expression compilation. Otherwise self::class and [self::class] have different behavior... --- .../tests/class_name_as_scalar_error_007.phpt | 19 +++++++---- Zend/zend_compile.c | 32 ++++++++----------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Zend/tests/class_name_as_scalar_error_007.phpt b/Zend/tests/class_name_as_scalar_error_007.phpt index 22099f6104..cbaf518ea8 100644 --- a/Zend/tests/class_name_as_scalar_error_007.phpt +++ b/Zend/tests/class_name_as_scalar_error_007.phpt @@ -3,11 +3,18 @@ Cannot access self::class when no class scope is active --FILE-- <?php -var_dump(self::class); +try { + var_dump(self::class); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump([self::class]); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTF-- -Fatal error: Uncaught Error: Cannot use "self" when no class scope is active in %s:3 -Stack trace: -#0 {main} - thrown in %s on line 3 +--EXPECT-- +Cannot use "self" when no class scope is active +Cannot use "self" when no class scope is active diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index a12de01990..f3f12ddbf1 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1366,7 +1366,7 @@ static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */ } /* }}} */ -static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast, zend_bool constant) /* {{{ */ +static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast) /* {{{ */ { uint32_t fetch_type; @@ -1386,12 +1386,6 @@ static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_a return 0; case ZEND_FETCH_CLASS_STATIC: case ZEND_FETCH_CLASS_PARENT: - 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" - ); - } return 0; case ZEND_FETCH_CLASS_DEFAULT: ZVAL_STR(zv, zend_resolve_class_name_ast(class_ast)); @@ -7712,7 +7706,7 @@ void zend_compile_class_name(znode *result, zend_ast *ast) /* {{{ */ zend_ast *class_ast = ast->child[0]; zend_op *opline; - if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast, 0)) { + if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast)) { result->op_type = IS_CONST; return; } @@ -7962,8 +7956,14 @@ void zend_compile_const_expr_class_name(zend_ast **ast_ptr) /* {{{ */ zend_ast *class_ast = (*ast_ptr)->child[0]; uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(class_ast)); - /* If we reach here, ::class should have either been constant evaluated or replaced - * by a AST_MAGIC_CONST, so only the error case is left here. */ + /* TODO We should not use AST_CONSTANT_CLASS for this, because the semantics are slightly + * different. */ + if (fetch_type == ZEND_FETCH_CLASS_SELF) { + zend_ast_destroy(*ast_ptr); + *ast_ptr = zend_ast_create(ZEND_AST_CONSTANT_CLASS); + return; + } + 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" @@ -8635,16 +8635,10 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ case ZEND_AST_CLASS_NAME: { zend_ast *class_ast = ast->child[0]; - if (zend_try_compile_const_expr_resolve_class_name(&result, class_ast, 0)) { - break; - } - /* TODO We should not use AST_MAGIC_CONST for this, because the semantics are slightly - * different. */ - if (zend_get_class_fetch_type(zend_ast_get_str(class_ast)) == ZEND_FETCH_CLASS_SELF) { - zend_ast_destroy(ast); - *ast_ptr = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_CLASS_C); + if (!zend_try_compile_const_expr_resolve_class_name(&result, class_ast)) { + return; } - return; + break; } default: return; -- 2.40.0