Skip to content

Commit f58846a

Browse files
committed
Handle self::class separately from __CLASS__ in const eval
1 parent 71ffae9 commit f58846a

File tree

3 files changed

+23
-10
lines changed

3 files changed

+23
-10
lines changed

Zend/tests/self_class_const_in_unknown_scope.phpt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ class Test {
1313
}
1414
(new Test)->foobar();
1515

16-
// This should error, but doesn't
1716
const BAR = self::class;
1817
var_dump(BAR);
1918

2019
?>
21-
--EXPECT--
20+
--EXPECTF--
2221
string(4) "Test"
23-
string(0) ""
22+
23+
Fatal error: Uncaught Error: Cannot use "self" when no class scope is active in %s:%d
24+
Stack trace:
25+
#0 {main}
26+
thrown in %s on line %d

Zend/zend_ast.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,13 +511,21 @@ ZEND_API int ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_c
511511
break;
512512
}
513513
case ZEND_AST_CONSTANT_CLASS:
514-
ZEND_ASSERT(EG(current_execute_data));
515514
if (scope && scope->name) {
516515
ZVAL_STR_COPY(result, scope->name);
517516
} else {
518517
ZVAL_EMPTY_STRING(result);
519518
}
520519
break;
520+
case ZEND_AST_CLASS_NAME:
521+
ZEND_ASSERT(ast->attr == ZEND_FETCH_CLASS_SELF);
522+
if (scope && scope->name) {
523+
ZVAL_STR_COPY(result, scope->name);
524+
} else {
525+
zend_throw_error(NULL, "Cannot use \"self\" when no class scope is active");
526+
ret = FAILURE;
527+
}
528+
break;
521529
case ZEND_AST_AND:
522530
if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
523531
ret = FAILURE;

Zend/zend_compile.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7953,14 +7953,16 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
79537953

79547954
void zend_compile_const_expr_class_name(zend_ast **ast_ptr) /* {{{ */
79557955
{
7956-
zend_ast *class_ast = (*ast_ptr)->child[0];
7957-
uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
7956+
zend_ast *ast = *ast_ptr;
7957+
zend_ast *class_ast = ast->child[0];
7958+
zend_string *class_name = zend_ast_get_str(class_ast);
7959+
uint32_t fetch_type = zend_get_class_fetch_type(class_name);
79587960

7959-
/* TODO We should not use AST_CONSTANT_CLASS for this, because the semantics are slightly
7960-
* different. */
7961+
/* For the const-eval representation store the fetch type instead of the name. */
79617962
if (fetch_type == ZEND_FETCH_CLASS_SELF) {
7962-
zend_ast_destroy(*ast_ptr);
7963-
*ast_ptr = zend_ast_create(ZEND_AST_CONSTANT_CLASS);
7963+
zend_string_release(class_name);
7964+
ast->child[0] = NULL;
7965+
ast->attr = fetch_type;
79647966
return;
79657967
}
79667968

0 commit comments

Comments
 (0)