diff --git a/NEWS b/NEWS index 1984a4a81dc52..a9426d9a22b6e 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Destructing non-array values (other than NULL) using [] or list() now emits a warning. (Girgias) + . Fixed bug GH-19637 (Incorrect Closure scope for FCC in constant + expression). (timwolla) - Opcache: . Fixed bug GH-19486 (Incorrect opline after deoptimization). (Arnaud) diff --git a/Zend/tests/first_class_callable/constexpr/autoload.phpt b/Zend/tests/first_class_callable/constexpr/autoload.phpt index 2dd2561f9a369..c962b77f12b61 100644 --- a/Zend/tests/first_class_callable/constexpr/autoload.phpt +++ b/Zend/tests/first_class_callable/constexpr/autoload.phpt @@ -26,6 +26,6 @@ var_dump(Closure); Autoloading AutoloadedClass object(Closure)#%d (1) { ["function"]=> - string(16) "withStaticMethod" + string(33) "AutoloadedClass::withStaticMethod" } Called AutoloadedClass::withStaticMethod diff --git a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt index efffa4a1d366a..54c96c915635d 100644 --- a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt +++ b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt @@ -1,5 +1,5 @@ --TEST-- -FCC in initializer errors for static reference to instance method. +FCC in initializer warns for static reference to trait method. --FILE-- - string(8) "myMethod" + string(13) "Foo::myMethod" ["parameter"]=> array(1) { ["$foo"]=> diff --git a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt index d36f7c97651e0..97831a8d65f0e 100644 --- a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt +++ b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt @@ -1,5 +1,5 @@ --TEST-- -FCC in initializer errors for static reference to instance method (Exception). +FCC in initializer emits deprecation for static reference to trait method (Exception). --FILE-- getClosureCalledClass()); + var_dump($r->getClosureScopeClass()); + } + } +} + +foreach ((new ReflectionClass(C::class))->getAttributes() as $reflectionAttribute) { + foreach ($reflectionAttribute->newInstance()->value as $fn) { + $r = new \ReflectionFunction($fn); + var_dump($r->getClosureCalledClass()); + var_dump($r->getClosureScopeClass()); + } +} +echo "=======\n"; +C::foo(); + +?> +--EXPECTF-- +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "G" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +NULL +NULL +======= +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "G" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +NULL +NULL diff --git a/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt b/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt index 3959efbd16a05..1776cd8f319de 100644 --- a/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt +++ b/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt @@ -23,7 +23,7 @@ var_dump(($c->d)("abc")); --EXPECTF-- object(Closure)#%d (2) { ["function"]=> - string(11) "C::myMethod" + string(11) "P::myMethod" ["parameter"]=> array(1) { ["$foo"]=> diff --git a/Zend/tests/first_class_callable/constexpr/static_call.phpt b/Zend/tests/first_class_callable/constexpr/static_call.phpt index 26761a041a4cc..2c6d3aa92b52f 100644 --- a/Zend/tests/first_class_callable/constexpr/static_call.phpt +++ b/Zend/tests/first_class_callable/constexpr/static_call.phpt @@ -19,7 +19,7 @@ var_dump(Closure); --EXPECTF-- object(Closure)#%d (2) { ["function"]=> - string(8) "myMethod" + string(13) "Foo::myMethod" ["parameter"]=> array(1) { ["$foo"]=> diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 2f66d8d5cd2b1..9cb3c7aae4a1f 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1055,6 +1055,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( case ZEND_AST_STATIC_CALL: { zend_function *fptr; + zend_class_entry *called_scope = NULL; switch (ast->kind) { case ZEND_AST_CALL: { ZEND_ASSERT(ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT); @@ -1086,13 +1087,15 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( ZEND_ASSERT(ast->child[2]->kind == ZEND_AST_CALLABLE_CONVERT); zend_ast_fcc *fcc_ast = (zend_ast_fcc*)ast->child[2]; + zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope); + if (!ce) { + return FAILURE; + } + called_scope = ce; + fptr = ZEND_MAP_PTR_GET(fcc_ast->fptr); if (!fptr) { - zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope); - if (!ce) { - return FAILURE; - } zend_string *method_name = zend_ast_get_str(ast->child[1]); if (ce->get_static_method) { fptr = ce->get_static_method(ce, method_name); @@ -1145,7 +1148,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( } } - zend_create_fake_closure(result, fptr, scope, scope, NULL); + zend_create_fake_closure(result, fptr, fptr->common.scope, called_scope, NULL); return SUCCESS; }