Skip to content

Commit 9b3fda4

Browse files
committed
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...
1 parent 6aa55a2 commit 9b3fda4

File tree

2 files changed

+26
-25
lines changed

2 files changed

+26
-25
lines changed

Zend/tests/class_name_as_scalar_error_007.phpt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@ Cannot access self::class when no class scope is active
33
--FILE--
44
<?php
55

6-
var_dump(self::class);
6+
try {
7+
var_dump(self::class);
8+
} catch (Error $e) {
9+
echo $e->getMessage(), "\n";
10+
}
11+
try {
12+
var_dump([self::class]);
13+
} catch (Error $e) {
14+
echo $e->getMessage(), "\n";
15+
}
716

817
?>
9-
--EXPECTF--
10-
Fatal error: Uncaught Error: Cannot use "self" when no class scope is active in %s:3
11-
Stack trace:
12-
#0 {main}
13-
thrown in %s on line 3
18+
--EXPECT--
19+
Cannot use "self" when no class scope is active
20+
Cannot use "self" when no class scope is active

Zend/zend_compile.c

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,7 +1366,7 @@ static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
13661366
}
13671367
/* }}} */
13681368

1369-
static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast, zend_bool constant) /* {{{ */
1369+
static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast) /* {{{ */
13701370
{
13711371
uint32_t fetch_type;
13721372

@@ -1386,12 +1386,6 @@ static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_a
13861386
return 0;
13871387
case ZEND_FETCH_CLASS_STATIC:
13881388
case ZEND_FETCH_CLASS_PARENT:
1389-
if (constant) {
1390-
zend_error_noreturn(E_COMPILE_ERROR,
1391-
"%s::class cannot be used for compile-time class name resolution",
1392-
fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
1393-
);
1394-
}
13951389
return 0;
13961390
case ZEND_FETCH_CLASS_DEFAULT:
13971391
ZVAL_STR(zv, zend_resolve_class_name_ast(class_ast));
@@ -7712,7 +7706,7 @@ void zend_compile_class_name(znode *result, zend_ast *ast) /* {{{ */
77127706
zend_ast *class_ast = ast->child[0];
77137707
zend_op *opline;
77147708

7715-
if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast, 0)) {
7709+
if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast)) {
77167710
result->op_type = IS_CONST;
77177711
return;
77187712
}
@@ -7962,8 +7956,14 @@ void zend_compile_const_expr_class_name(zend_ast **ast_ptr) /* {{{ */
79627956
zend_ast *class_ast = (*ast_ptr)->child[0];
79637957
uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
79647958

7965-
/* If we reach here, ::class should have either been constant evaluated or replaced
7966-
* by a AST_MAGIC_CONST, so only the error case is left here. */
7959+
/* TODO We should not use AST_CONSTANT_CLASS for this, because the semantics are slightly
7960+
* different. */
7961+
if (fetch_type == ZEND_FETCH_CLASS_SELF) {
7962+
zend_ast_destroy(*ast_ptr);
7963+
*ast_ptr = zend_ast_create(ZEND_AST_CONSTANT_CLASS);
7964+
return;
7965+
}
7966+
79677967
zend_error_noreturn(E_COMPILE_ERROR,
79687968
"%s::class cannot be used for compile-time class name resolution",
79697969
fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
@@ -8635,16 +8635,10 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
86358635
case ZEND_AST_CLASS_NAME:
86368636
{
86378637
zend_ast *class_ast = ast->child[0];
8638-
if (zend_try_compile_const_expr_resolve_class_name(&result, class_ast, 0)) {
8639-
break;
8640-
}
8641-
/* TODO We should not use AST_MAGIC_CONST for this, because the semantics are slightly
8642-
* different. */
8643-
if (zend_get_class_fetch_type(zend_ast_get_str(class_ast)) == ZEND_FETCH_CLASS_SELF) {
8644-
zend_ast_destroy(ast);
8645-
*ast_ptr = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_CLASS_C);
8638+
if (!zend_try_compile_const_expr_resolve_class_name(&result, class_ast)) {
8639+
return;
86468640
}
8647-
return;
8641+
break;
86488642
}
86498643
default:
86508644
return;

0 commit comments

Comments
 (0)