diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 50e6e5f5fff..1c5c951a4b3 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -7795,7 +7795,8 @@ zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) { || kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS || kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM - || kind == ZEND_AST_CONST || kind == ZEND_AST_CLASS_CONST; + || kind == ZEND_AST_CONST || kind == ZEND_AST_CLASS_CONST + || kind == ZEND_AST_RESOLVE_CLASS_NAME; } void zend_compile_const_expr_class_const(zend_ast **ast_ptr TSRMLS_DC) { @@ -7868,6 +7869,39 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr TSRMLS_DC) { *ast_ptr = zend_ast_create_constant(&result.u.constant); } +void zend_compile_const_expr_resolve_class_name(zend_ast **ast_ptr TSRMLS_DC) { + zend_ast *ast = *ast_ptr; + 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; + + 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"); + } + ZVAL_STR(&result.u.constant, STR_COPY(CG(active_class_entry)->name)); + break; + case ZEND_FETCH_CLASS_STATIC: + case ZEND_FETCH_CLASS_PARENT: + 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" + ); + break; + case ZEND_FETCH_CLASS_DEFAULT: + zend_compile_expr(&result, name_ast TSRMLS_CC); + zend_resolve_class_name(&result TSRMLS_CC); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + + zend_ast_destroy(ast); + *ast_ptr = zend_ast_create_constant(&result.u.constant); +} + void zend_compile_const_expr(zend_ast **ast_ptr TSRMLS_DC) { zend_ast *ast = *ast_ptr; if (ast == NULL || ast->kind == ZEND_CONST) { @@ -7892,6 +7926,9 @@ void zend_compile_const_expr(zend_ast **ast_ptr TSRMLS_DC) { case ZEND_AST_CONST: zend_compile_const_expr_const(ast_ptr TSRMLS_CC); break; + case ZEND_AST_RESOLVE_CLASS_NAME: + zend_compile_const_expr_resolve_class_name(ast_ptr TSRMLS_CC); + break; } } diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 6de001a5702..3dbb27675c6 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -978,7 +978,8 @@ static_scalar: /* compile-time evaluated scalars */ static_scalar_value: T_CONSTANT_ENCAPSED_STRING { $$.u.ast = AST_ZVAL(&$1); } - | static_class_name_scalar { $$.u.ast = AST_ZVAL(&$1); } + | class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS + { $$.u.ast = zend_ast_create_unary(ZEND_AST_RESOLVE_CLASS_NAME, AST_ZVAL(&$1)); } | class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { $$.u.ast = zend_ast_create_binary( ZEND_AST_CLASS_CONST, AST_ZVAL(&$1), AST_ZVAL(&$3)); } @@ -1329,10 +1330,6 @@ class_constant: ZEND_AST_CLASS_CONST, $1.u.ast, AST_ZVAL(&$3)); } ; -static_class_name_scalar: - class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS { zend_do_resolve_class_name(&$$, &$1, 1 TSRMLS_CC); } -; - class_name_scalar: class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS { $$.u.ast = zend_ast_create_unary(ZEND_AST_RESOLVE_CLASS_NAME, AST_ZVAL(&$1)); }