Skip to content

Commit 447b347

Browse files
committed
Support parent::class inside constexpr contexts
1 parent f58846a commit 447b347

File tree

4 files changed

+40
-21
lines changed

4 files changed

+40
-21
lines changed

Zend/tests/class_name_as_scalar_error_002.phpt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ namespace Foo\Bar {
77
class One {
88
const Baz = parent::class;
99
}
10+
var_dump(One::Baz);
1011
}
1112
?>
1213
--EXPECTF--
13-
Fatal error: parent::class cannot be used for compile-time class name resolution in %s on line %d
14+
Fatal error: Uncaught Error: Cannot use "parent" when current class scope has no parent in %s:%d
15+
Stack trace:
16+
#0 {main}
17+
thrown in %s on line %d

Zend/tests/class_name_as_scalar_error_004.phpt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ class name as scalar from ::class keyword error using parent in method signature
44
<?php
55

66
namespace Foo\Bar {
7-
class One {
8-
public function baz($x = parent::class) {}
7+
class One {}
8+
class Two extends One {
9+
public function baz($x = parent::class) {
10+
var_dump($x);
11+
}
912
}
13+
(new Two)->baz();
1014
}
1115
?>
12-
--EXPECTF--
13-
Fatal error: parent::class cannot be used for compile-time class name resolution in %s on line %d
16+
--EXPECT--
17+
string(11) "Foo\Bar\One"

Zend/zend_ast.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -511,19 +511,28 @@ 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-
if (scope && scope->name) {
514+
if (scope) {
515515
ZVAL_STR_COPY(result, scope->name);
516516
} else {
517517
ZVAL_EMPTY_STRING(result);
518518
}
519519
break;
520520
case ZEND_AST_CLASS_NAME:
521-
ZEND_ASSERT(ast->attr == ZEND_FETCH_CLASS_SELF);
522-
if (scope && scope->name) {
521+
if (!scope) {
522+
zend_throw_error(NULL, "Cannot use \"self\" when no class scope is active");
523+
return FAILURE;
524+
}
525+
if (ast->attr == ZEND_FETCH_CLASS_SELF) {
523526
ZVAL_STR_COPY(result, scope->name);
527+
} else if (ast->attr == ZEND_FETCH_CLASS_PARENT) {
528+
if (!scope->parent) {
529+
zend_throw_error(NULL,
530+
"Cannot use \"parent\" when current class scope has no parent");
531+
return FAILURE;
532+
}
533+
ZVAL_STR_COPY(result, scope->parent->name);
524534
} else {
525-
zend_throw_error(NULL, "Cannot use \"self\" when no class scope is active");
526-
ret = FAILURE;
535+
ZEND_ASSERT(0 && "Should have errored during compilation");
527536
}
528537
break;
529538
case ZEND_AST_AND:

Zend/zend_compile.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7958,18 +7958,20 @@ void zend_compile_const_expr_class_name(zend_ast **ast_ptr) /* {{{ */
79587958
zend_string *class_name = zend_ast_get_str(class_ast);
79597959
uint32_t fetch_type = zend_get_class_fetch_type(class_name);
79607960

7961-
/* For the const-eval representation store the fetch type instead of the name. */
7962-
if (fetch_type == ZEND_FETCH_CLASS_SELF) {
7963-
zend_string_release(class_name);
7964-
ast->child[0] = NULL;
7965-
ast->attr = fetch_type;
7966-
return;
7961+
switch (fetch_type) {
7962+
case ZEND_FETCH_CLASS_SELF:
7963+
case ZEND_FETCH_CLASS_PARENT:
7964+
/* For the const-eval representation store the fetch type instead of the name. */
7965+
zend_string_release(class_name);
7966+
ast->child[0] = NULL;
7967+
ast->attr = fetch_type;
7968+
return;
7969+
case ZEND_FETCH_CLASS_STATIC:
7970+
zend_error_noreturn(E_COMPILE_ERROR,
7971+
"static::class cannot be used for compile-time class name resolution");
7972+
return;
7973+
EMPTY_SWITCH_DEFAULT_CASE()
79677974
}
7968-
7969-
zend_error_noreturn(E_COMPILE_ERROR,
7970-
"%s::class cannot be used for compile-time class name resolution",
7971-
fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
7972-
);
79737975
}
79747976

79757977
void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */

0 commit comments

Comments
 (0)