Print location on class redeclaration

Fixes GH-13950
Closes GH-13999
This commit is contained in:
Ilija Tovilo 2024-04-18 23:48:45 +02:00
parent d52605db15
commit 1c30c5e707
No known key found for this signature in database
GPG key ID: A4F5D403F118200A
30 changed files with 67 additions and 43 deletions

View file

@ -9,4 +9,4 @@ class_alias('foo', 'FOO');
?>
--EXPECTF--
Warning: Cannot declare class FOO, because the name is already in use in %s on line %d
Warning: Cannot redeclare class FOO (previously declared in %s:%d) in %s on line %d

View file

@ -12,4 +12,4 @@ class_alias('foo', 'test');
?>
--EXPECTF--
Warning: Cannot declare class test, because the name is already in use in %s on line %d
Warning: Cannot redeclare class test (previously declared in %s:%d) in %s on line %d

View file

@ -11,4 +11,4 @@ class b { }
?>
--EXPECTF--
Warning: Cannot declare interface b, because the name is already in use in %s on line %d
Warning: Cannot redeclare interface b (previously declared in %s:%d) in %s on line %d

View file

@ -14,4 +14,4 @@ class_alias('\foo', 'foo');
?>
--EXPECTF--
Warning: Cannot declare class foo, because the name is already in use in %s on line %d
Warning: Cannot redeclare class foo (previously declared in %s:%d) in %s on line %d

View file

@ -1,5 +1,5 @@
--TEST--
Cannot declare class, because the name is already in use
Cannot redeclare class
--FILE--
<?php
@ -11,4 +11,4 @@ test();
?>
--EXPECTF--
Fatal error: Cannot declare class A, because the name is already in use in %s on line %d
Fatal error: Cannot redeclare class A (previously declared in %s:%d) in %s on line %d

View file

@ -10,4 +10,4 @@ include __DIR__ . '/delayed_early_binding_redeclaration-2.inc';
var_dump(class_exists(Bar::class));
?>
--EXPECTF--
Fatal error: Cannot declare class Bar, because the name is already in use in %sdelayed_early_binding_redeclaration-2.inc on line %d
Fatal error: Cannot redeclare class Bar (previously declared in %sdelayed_early_binding_redeclaration-1.inc:2) in %sdelayed_early_binding_redeclaration-2.inc on line %d

View file

@ -9,4 +9,4 @@ class stdclass {
echo "Done\n";
?>
--EXPECTF--
Fatal error: Cannot declare class stdclass, because the name is already in use in %s on line %d
Fatal error: Cannot redeclare class stdClass in %s on line %d

View file

@ -6,4 +6,4 @@ function f() {}
function f() {}
?>
--EXPECTF--
Fatal error: Cannot redeclare f() (previously declared in %s:%d) in %s on line %d
Fatal error: Cannot redeclare function f() (previously declared in %s:%d) in %s on line %d

View file

@ -7,4 +7,4 @@ interface stdClass { }
?>
--EXPECTF--
Fatal error: Cannot declare interface stdClass, because the name is already in use in %s on line %d
Fatal error: Cannot redeclare class stdClass in %s on line %d

View file

@ -8,4 +8,4 @@ class A { }
?>
--EXPECTF--
Fatal error: Cannot declare class A, because the name is already in use in %s on line %d
Fatal error: Cannot redeclare class A (previously declared in %s:%d) in %s on line %d

View file

@ -8,4 +8,4 @@ interface A { }
?>
--EXPECTF--
Fatal error: Cannot declare interface A, because the name is already in use in %s on line %d
Fatal error: Cannot redeclare class A (previously declared in %s:%d) in %s on line %d

View file

@ -8,4 +8,4 @@ trait A { }
?>
--EXPECTF--
Fatal error: Cannot declare trait A, because the name is already in use in %s on line %d
Fatal error: Cannot redeclare class A (previously declared in %s:%d) in %s on line %d

View file

@ -8,4 +8,4 @@ interface A { }
?>
--EXPECTF--
Fatal error: Cannot declare interface A, because the name is already in use in %s on line %d
Fatal error: Cannot redeclare interface A (previously declared in %s:%d) in %s on line %d

View file

@ -8,4 +8,4 @@ trait A { }
?>
--EXPECTF--
Fatal error: Cannot declare trait A, because the name is already in use in %s on line %d
Fatal error: Cannot redeclare interface A (previously declared in %s:%d) in %s on line %d

View file

@ -8,4 +8,4 @@ trait A { }
?>
--EXPECTF--
Fatal error: Cannot declare trait A, because the name is already in use in %s on line %d
Fatal error: Cannot redeclare trait A (previously declared in %s:%d) in %s on line %d

View file

@ -13,4 +13,4 @@ namespace Bazzle {
}
?>
--EXPECTF--
Fatal error: Cannot declare class Bazzle\Bar because the name is already in use in %s on line %d
Fatal error: Cannot redeclare class Bazzle\Bar (previously declared as local import) in %s on line %d

View file

@ -13,4 +13,4 @@ namespace Bazzle {
}
?>
--EXPECTF--
Fatal error: Cannot declare function Bazzle\bar because the name is already in use in %s on line %d
Fatal error: Cannot redeclare function Bazzle\bar() (previously declared as local import) in %s on line %d

View file

@ -10,4 +10,4 @@ class Foo {
new Foo();
?>
--EXPECTF--
Fatal error: Cannot declare class Foo because the name is already in use in %sns_029.php on line 4
Fatal error: Cannot redeclare class Foo (previously declared as local import) in %sns_029.php on line 4

View file

@ -11,4 +11,4 @@ namespace {
?>
--EXPECTF--
Fatal error: Cannot declare function bar because the name is already in use in %s on line %d
Fatal error: Cannot redeclare function bar() (previously declared as local import) in %s on line %d

View file

@ -438,6 +438,26 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *
}
/* }}} */
ZEND_API ZEND_COLD void zend_class_redeclaration_error_ex(int type, zend_string *new_name, zend_class_entry *old_ce)
{
if (old_ce->type == ZEND_INTERNAL_CLASS) {
zend_error(type, "Cannot redeclare %s %s",
zend_get_object_type(old_ce),
ZSTR_VAL(new_name));
} else {
zend_error(type, "Cannot redeclare %s %s (previously declared in %s:%d)",
zend_get_object_type(old_ce),
ZSTR_VAL(new_name),
ZSTR_VAL(old_ce->info.user.filename),
old_ce->info.user.line_start);
}
}
ZEND_API ZEND_COLD void zend_class_redeclaration_error(int type, zend_class_entry *old_ce)
{
zend_class_redeclaration_error_ex(type, old_ce->name, old_ce);
}
ZEND_API bool ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, uint32_t num, bool check_null) /* {{{ */
{
zend_class_entry *ce_base = *pce;

View file

@ -1563,6 +1563,8 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_en
ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...);
ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format, ...);
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format, ...);
ZEND_API ZEND_COLD void zend_class_redeclaration_error(int type, zend_class_entry *old_ce);
ZEND_API ZEND_COLD void zend_class_redeclaration_error_ex(int type, zend_string *new_name, zend_class_entry *old_ce);
#define ZPP_ERROR_OK 0
#define ZPP_ERROR_FAILURE 1

View file

@ -1152,7 +1152,7 @@ ZEND_FUNCTION(class_alias)
if (zend_register_class_alias_ex(ZSTR_VAL(alias_name), ZSTR_LEN(alias_name), ce, false) == SUCCESS) {
RETURN_TRUE;
} else {
zend_error(E_WARNING, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(alias_name));
zend_class_redeclaration_error_ex(E_WARNING, alias_name, ce);
RETURN_FALSE;
}
} else {

View file

@ -1217,12 +1217,12 @@ static zend_never_inline ZEND_COLD ZEND_NORETURN void do_bind_function_error(zen
old_function = (zend_function*)Z_PTR_P(zv);
if (old_function->type == ZEND_USER_FUNCTION
&& old_function->op_array.last > 0) {
zend_error_noreturn(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
zend_error_noreturn(error_level, "Cannot redeclare function %s() (previously declared in %s:%d)",
op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name),
ZSTR_VAL(old_function->op_array.filename),
old_function->op_array.opcodes[0].lineno);
} else {
zend_error_noreturn(error_level, "Cannot redeclare %s()",
zend_error_noreturn(error_level, "Cannot redeclare function %s()",
op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name));
}
}
@ -1260,7 +1260,9 @@ ZEND_API zend_class_entry *zend_bind_class_in_slot(
success = zend_hash_add_ptr(EG(class_table), Z_STR_P(lcname), ce) != NULL;
}
if (UNEXPECTED(!success)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
zend_class_entry *old_class = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname));
ZEND_ASSERT(old_class);
zend_class_redeclaration_error(E_COMPILE_ERROR, old_class);
return NULL;
}
@ -1298,7 +1300,7 @@ ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /*
if (UNEXPECTED(!zv)) {
ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname));
ZEND_ASSERT(ce);
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
zend_class_redeclaration_error(E_COMPILE_ERROR, ce);
return FAILURE;
}
@ -7752,8 +7754,8 @@ static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array,
zend_string *import_name =
zend_hash_find_ptr_lc(FC(imports_function), unqualified_name);
if (import_name && !zend_string_equals_ci(lcname, import_name)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare function %s "
"because the name is already in use", ZSTR_VAL(name));
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare function %s() (previously declared as local import)",
ZSTR_VAL(name));
}
}
@ -8318,8 +8320,8 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
zend_string *import_name =
zend_hash_find_ptr_lc(FC(imports), unqualified_name);
if (import_name && !zend_string_equals_ci(lcname, import_name)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s "
"because the name is already in use", ZSTR_VAL(name));
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s "
"(previously declared as local import)", ZSTR_VAL(name));
}
}

View file

@ -3331,7 +3331,9 @@ static zend_always_inline bool register_early_bound_ce(zval *delayed_early_bindi
return true;
}
}
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
zend_class_entry *old_ce = zend_hash_find_ptr(EG(class_table), lcname);
ZEND_ASSERT(old_ce);
zend_class_redeclaration_error(E_COMPILE_ERROR, old_ce);
return false;
}
if (zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL) {

View file

@ -25,4 +25,4 @@ unlink($file_c);
unlink($file_p);
?>
--EXPECTF--
Fatal error: Cannot declare class p, because the name is already in use in %sbug67215.p.php on line %d
Fatal error: Cannot redeclare class p (previously declared in %sbug67215.p.php:%d) in %sbug67215.p.php on line %d

View file

@ -16,4 +16,4 @@ if (true) {
}
?>
--EXPECTF--
Fatal error: Cannot redeclare A() (previously declared in %sbug73583.php:4) in %sbug73583.php on line 5
Fatal error: Cannot redeclare function A() (previously declared in %sbug73583.php:4) in %sbug73583.php on line 5

View file

@ -33,7 +33,7 @@ echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/gh8846-index.php?s
--EXPECTF--
bool(true)
<br />
<b>Fatal error</b>: Cannot declare class Foo, because the name is already in use in <b>%sgh8846-2.inc</b> on line <b>%d</b><br />
<b>Fatal error</b>: Cannot redeclare class Foo (previously declared in %sgh8846-1.inc:2) in <b>%sgh8846-2.inc</b> on line <b>%d</b><br />
bool(true)
Ok

View file

@ -178,12 +178,12 @@ failure:
CG(zend_lineno) = function1->op_array.opcodes[0].lineno;
if (function2->type == ZEND_USER_FUNCTION
&& function2->op_array.last > 0) {
zend_error_noreturn(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)",
zend_error_noreturn(E_ERROR, "Cannot redeclare function %s() (previously declared in %s:%d)",
ZSTR_VAL(function1->common.function_name),
ZSTR_VAL(function2->op_array.filename),
(int)function2->op_array.opcodes[0].lineno);
} else {
zend_error_noreturn(E_ERROR, "Cannot redeclare %s()", ZSTR_VAL(function1->common.function_name));
zend_error_noreturn(E_ERROR, "Cannot redeclare function %s()", ZSTR_VAL(function1->common.function_name));
}
}
@ -227,9 +227,7 @@ static zend_always_inline void _zend_accel_class_hash_copy(HashTable *target, Ha
CG(in_compilation) = 1;
zend_set_compiled_filename(ce1->info.user.filename);
CG(zend_lineno) = ce1->info.user.line_start;
zend_error_noreturn(E_ERROR,
"Cannot declare %s %s, because the name is already in use",
zend_get_object_type(ce1), ZSTR_VAL(ce1->name));
zend_class_redeclaration_error(E_ERROR, Z_PTR_P(t));
return;
}
continue;

View file

@ -15,4 +15,4 @@ preg_replace_callback('/a/', function($matches) {
?>
--EXPECTF--
Fatal error: Cannot redeclare test() (previously declared in %s on line %d
Fatal error: Cannot redeclare function test() (previously declared in %s:%d) in %s on line %d

View file

@ -62,11 +62,11 @@ function getFiles(array $dirsOrFiles): \Iterator {
}
function normalizeOutput(string $out): string {
$out = preg_replace('/in (\/|[A-Z]:\\\\).+ on line \d+/m', 'in %s on line %d', $out);
$out = preg_replace('/in (\/|[A-Z]:\\\\).+:\d+$/m', 'in %s:%d', $out);
$out = preg_replace('/\{closure:(\/|[A-Z]:\\\\).+:\d+\}/', '{closure:%s:%d}', $out);
$out = preg_replace('/in (\/|[A-Z]:\\\\)\S+ on line \d+/m', 'in %s on line %d', $out);
$out = preg_replace('/in (\/|[A-Z]:\\\\)\S+:\d+/m', 'in %s:%d', $out);
$out = preg_replace('/\{closure:(\/|[A-Z]:\\\\)\S+:\d+\}/', '{closure:%s:%d}', $out);
$out = preg_replace('/object\(([A-Za-z0-9]*)\)#\d+/', 'object($1)#%d', $out);
$out = preg_replace('/^#(\d+) (\/|[A-Z]:\\\\).+\(\d+\):/m', '#$1 %s(%d):', $out);
$out = preg_replace('/^#(\d+) (\/|[A-Z]:\\\\)\S+\(\d+\):/m', '#$1 %s(%d):', $out);
$out = preg_replace('/Resource id #\d+/', 'Resource id #%d', $out);
$out = preg_replace('/resource\(\d+\) of type/', 'resource(%d) of type', $out);
$out = preg_replace(