Skip to content

Commit a1f4eba

Browse files
committed
Fix phpGH-13177: PHP 8.3.2: final private constructor not allowed when used in trait
zend_compile has an exception to this rule for constructors using `zend_is_constructor`, which compares the function name to `__construct`. Sadly, `zend_is_constructor` is not a public API, but we can just do the string compare ourselves.
1 parent 1c7dc0f commit a1f4eba

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

Zend/tests/traits/bugs/gh13177.phpt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
GH-13177 (PHP 8.3.2: final private constructor not allowed when used in trait)
3+
--FILE--
4+
<?php
5+
6+
trait Bar {
7+
final private function __construct() {}
8+
}
9+
10+
final class Foo1 {
11+
use Bar;
12+
}
13+
14+
final class Foo2 {
15+
use Bar {
16+
__construct as final;
17+
}
18+
}
19+
20+
class Foo3 {
21+
use Bar {
22+
__construct as final;
23+
}
24+
}
25+
26+
for ($i = 1; $i <= 3; $i++) {
27+
$rc = new ReflectionClass("Foo$i");
28+
echo $rc->getMethod("__construct"), "\n";
29+
}
30+
31+
class Foo4 extends Foo3 {
32+
private function __construct() {}
33+
}
34+
35+
?>
36+
--EXPECTF--
37+
Method [ <user, ctor> final private method __construct ] {
38+
@@ %sgh13177.php 4 - 4
39+
}
40+
41+
Method [ <user, ctor> final private method __construct ] {
42+
@@ %sgh13177.php 4 - 4
43+
}
44+
45+
Method [ <user, ctor> final private method __construct ] {
46+
@@ %sgh13177.php 4 - 4
47+
}
48+
49+
50+
Fatal error: Cannot override final method Foo3::__construct() in %s on line %d

Zend/zend_inheritance.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1949,7 +1949,7 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_
19491949
zend_function *new_fn;
19501950
bool check_inheritance = false;
19511951

1952-
if ((fn->common.fn_flags & (ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)) == (ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)) {
1952+
if ((fn->common.fn_flags & (ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)) == (ZEND_ACC_PRIVATE | ZEND_ACC_FINAL) && !zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME)) {
19531953
zend_error(E_COMPILE_WARNING, "Private methods cannot be final as they are never overridden by other classes");
19541954
}
19551955

0 commit comments

Comments
 (0)