Skip to content

Commit 1c6df2d

Browse files
committed
Fixed bug #81192
Normally the filename is the current filename, but when traits are involved, it might be a different one.
1 parent e539cb9 commit 1c6df2d

File tree

4 files changed

+41
-8
lines changed

4 files changed

+41
-8
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ PHP NEWS
77
(Nikita)
88
. Fixed bug #81280 (Unicode characters in cli.prompt causes segfault).
99
(krakjoe)
10+
. Fixed bug #81192 ("Declaration should be compatible with" gives incorrect
11+
line number with traits). (Nikita)
1012

1113
- Date:
1214
. Fixed bug #79580 (date_create_from_format misses leap year). (Derick)

Zend/tests/bug81192.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Bug #81192: "Declaration should be compatible with" gives incorrect line number with traits
3+
--FILE--
4+
<?php
5+
6+
require __DIR__ . '/bug81192_trait.inc';
7+
8+
class A {
9+
public function foo(): int {
10+
return 2;
11+
}
12+
}
13+
14+
class B extends A {
15+
use T;
16+
}
17+
18+
?>
19+
--EXPECTF--
20+
Fatal error: Declaration of T::foo(): string must be compatible with A::foo(): int in %sbug81192_trait.inc on line 4

Zend/tests/bug81192_trait.inc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
trait T {
4+
public function foo(): string {
5+
return "oops";
6+
}
7+
}

Zend/zend_inheritance.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,10 @@ static ZEND_COLD zend_string *zend_get_function_declaration(
961961
}
962962
/* }}} */
963963

964+
static zend_always_inline zend_string *func_filename(const zend_function *fn) {
965+
return fn->common.type == ZEND_USER_FUNCTION ? fn->op_array.filename : NULL;
966+
}
967+
964968
static zend_always_inline uint32_t func_lineno(const zend_function *fn) {
965969
return fn->common.type == ZEND_USER_FUNCTION ? fn->op_array.line_start : 0;
966970
}
@@ -979,7 +983,7 @@ static void ZEND_COLD emit_incompatible_method_error(
979983
} ZEND_HASH_FOREACH_END();
980984
ZEND_ASSERT(unresolved_class);
981985

982-
zend_error_at(E_COMPILE_ERROR, NULL, func_lineno(child),
986+
zend_error_at(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
983987
"Could not check compatibility between %s and %s, because class %s is not available",
984988
ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype), ZSTR_VAL(unresolved_class));
985989
} else if (status == INHERITANCE_WARNING) {
@@ -990,7 +994,7 @@ static void ZEND_COLD emit_incompatible_method_error(
990994
);
991995

992996
if (!return_type_will_change_attribute) {
993-
zend_error_at(E_DEPRECATED, NULL, func_lineno(child),
997+
zend_error_at(E_DEPRECATED, func_filename(child), func_lineno(child),
994998
"Return type of %s should either be compatible with %s, "
995999
"or the #[ReturnTypeWillChange] attribute should be used to temporarily suppress the notice",
9961000
ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype));
@@ -1000,7 +1004,7 @@ static void ZEND_COLD emit_incompatible_method_error(
10001004
}
10011005
}
10021006
} else {
1003-
zend_error_at(E_COMPILE_ERROR, NULL, func_lineno(child),
1007+
zend_error_at(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
10041008
"Declaration of %s must be compatible with %s",
10051009
ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype));
10061010
}
@@ -1047,7 +1051,7 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
10471051
if (check_only) {
10481052
return INHERITANCE_ERROR;
10491053
}
1050-
zend_error_at_noreturn(E_COMPILE_ERROR, NULL, func_lineno(child),
1054+
zend_error_at_noreturn(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
10511055
"Cannot override final method %s::%s()",
10521056
ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name));
10531057
}
@@ -1060,11 +1064,11 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
10601064
return INHERITANCE_ERROR;
10611065
}
10621066
if (child_flags & ZEND_ACC_STATIC) {
1063-
zend_error_at_noreturn(E_COMPILE_ERROR, NULL, func_lineno(child),
1067+
zend_error_at_noreturn(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
10641068
"Cannot make non static method %s::%s() static in class %s",
10651069
ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
10661070
} else {
1067-
zend_error_at_noreturn(E_COMPILE_ERROR, NULL, func_lineno(child),
1071+
zend_error_at_noreturn(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
10681072
"Cannot make static method %s::%s() non static in class %s",
10691073
ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
10701074
}
@@ -1075,7 +1079,7 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
10751079
if (check_only) {
10761080
return INHERITANCE_ERROR;
10771081
}
1078-
zend_error_at_noreturn(E_COMPILE_ERROR, NULL, func_lineno(child),
1082+
zend_error_at_noreturn(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
10791083
"Cannot make non abstract method %s::%s() abstract in class %s",
10801084
ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
10811085
}
@@ -1119,7 +1123,7 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
11191123
if (check_only) {
11201124
return INHERITANCE_ERROR;
11211125
}
1122-
zend_error_at_noreturn(E_COMPILE_ERROR, NULL, func_lineno(child),
1126+
zend_error_at_noreturn(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
11231127
"Access level to %s::%s() must be %s (as in class %s)%s",
11241128
ZEND_FN_SCOPE_NAME(child), ZSTR_VAL(child->common.function_name), zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
11251129
}

0 commit comments

Comments
 (0)