mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-8.3'
* PHP-8.3: Fix GH-12854: 8.3 - as final trait-used method does not correctly report visibility in Reflection
This commit is contained in:
commit
bfb678a266
2 changed files with 86 additions and 4 deletions
74
Zend/tests/traits/gh12854.phpt
Normal file
74
Zend/tests/traits/gh12854.phpt
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
--TEST--
|
||||||
|
GH-12854 (8.3 - as final trait-used method does not correctly report visibility in Reflection)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
trait SimpleTrait
|
||||||
|
{
|
||||||
|
public function pub() {}
|
||||||
|
protected function prot() {}
|
||||||
|
private function priv() {}
|
||||||
|
|
||||||
|
public final function final1() {}
|
||||||
|
public final function final2() {}
|
||||||
|
public final function final3() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Test
|
||||||
|
{
|
||||||
|
use SimpleTrait {
|
||||||
|
pub as final;
|
||||||
|
prot as final;
|
||||||
|
priv as final;
|
||||||
|
|
||||||
|
final1 as private;
|
||||||
|
final2 as protected;
|
||||||
|
final3 as public;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (['pub', 'prot', 'priv', 'final1', 'final2', 'final3'] as $method) {
|
||||||
|
echo "--- Method: $method ---\n";
|
||||||
|
$rm = new ReflectionMethod(Test::class, $method);
|
||||||
|
var_dump($rm->isFinal());
|
||||||
|
var_dump($rm->isPublic());
|
||||||
|
var_dump($rm->isProtected());
|
||||||
|
var_dump($rm->isPrivate());
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Warning: Private methods cannot be final as they are never overridden by other classes in %s on line %d
|
||||||
|
|
||||||
|
Warning: Private methods cannot be final as they are never overridden by other classes in %s on line %d
|
||||||
|
--- Method: pub ---
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
||||||
|
--- Method: prot ---
|
||||||
|
bool(true)
|
||||||
|
bool(false)
|
||||||
|
bool(true)
|
||||||
|
bool(false)
|
||||||
|
--- Method: priv ---
|
||||||
|
bool(true)
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
||||||
|
bool(true)
|
||||||
|
--- Method: final1 ---
|
||||||
|
bool(true)
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
||||||
|
bool(true)
|
||||||
|
--- Method: final2 ---
|
||||||
|
bool(true)
|
||||||
|
bool(false)
|
||||||
|
bool(true)
|
||||||
|
bool(false)
|
||||||
|
--- Method: final3 ---
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
|
@ -1952,6 +1952,10 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_
|
||||||
zend_function *new_fn;
|
zend_function *new_fn;
|
||||||
bool check_inheritance = false;
|
bool check_inheritance = false;
|
||||||
|
|
||||||
|
if ((fn->common.fn_flags & (ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)) == (ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)) {
|
||||||
|
zend_error(E_COMPILE_WARNING, "Private methods cannot be final as they are never overridden by other classes");
|
||||||
|
}
|
||||||
|
|
||||||
if ((existing_fn = zend_hash_find_ptr(&ce->function_table, key)) != NULL) {
|
if ((existing_fn = zend_hash_find_ptr(&ce->function_table, key)) != NULL) {
|
||||||
/* if it is the same function with the same visibility and has not been assigned a class scope yet, regardless
|
/* if it is the same function with the same visibility and has not been assigned a class scope yet, regardless
|
||||||
* of where it is coming from there is no conflict and we do not need to add it again */
|
* of where it is coming from there is no conflict and we do not need to add it again */
|
||||||
|
@ -2051,10 +2055,10 @@ static void zend_traits_copy_functions(zend_string *fnname, zend_function *fn, z
|
||||||
&& zend_string_equals_ci(alias->trait_method.method_name, fnname)
|
&& zend_string_equals_ci(alias->trait_method.method_name, fnname)
|
||||||
) {
|
) {
|
||||||
fn_copy = *fn;
|
fn_copy = *fn;
|
||||||
|
if (alias->modifiers & ZEND_ACC_PPP_MASK) {
|
||||||
/* if it is 0, no modifiers have been changed */
|
|
||||||
if (alias->modifiers) {
|
|
||||||
fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags & ~ZEND_ACC_PPP_MASK);
|
fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags & ~ZEND_ACC_PPP_MASK);
|
||||||
|
} else {
|
||||||
|
fn_copy.common.fn_flags = alias->modifiers | fn->common.fn_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcname = zend_string_tolower(alias->alias);
|
lcname = zend_string_tolower(alias->alias);
|
||||||
|
@ -2082,7 +2086,11 @@ static void zend_traits_copy_functions(zend_string *fnname, zend_function *fn, z
|
||||||
&& fn->common.scope == aliases[i]
|
&& fn->common.scope == aliases[i]
|
||||||
&& zend_string_equals_ci(alias->trait_method.method_name, fnname)
|
&& zend_string_equals_ci(alias->trait_method.method_name, fnname)
|
||||||
) {
|
) {
|
||||||
fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags & ~ZEND_ACC_PPP_MASK);
|
if (alias->modifiers & ZEND_ACC_PPP_MASK) {
|
||||||
|
fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags & ~ZEND_ACC_PPP_MASK);
|
||||||
|
} else {
|
||||||
|
fn_copy.common.fn_flags = alias->modifiers | fn->common.fn_flags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
alias_ptr++;
|
alias_ptr++;
|
||||||
alias = *alias_ptr;
|
alias = *alias_ptr;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue