diff --git a/Zend/tests/class_alias_002.phpt b/Zend/tests/class_alias_002.phpt index 7a6eb126a920e..16d2d60e3791b 100644 --- a/Zend/tests/class_alias_002.phpt +++ b/Zend/tests/class_alias_002.phpt @@ -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 diff --git a/Zend/tests/class_alias_004.phpt b/Zend/tests/class_alias_004.phpt index ea3501ed57ff1..df0d1e537d8b7 100644 --- a/Zend/tests/class_alias_004.phpt +++ b/Zend/tests/class_alias_004.phpt @@ -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 diff --git a/Zend/tests/class_alias_010.phpt b/Zend/tests/class_alias_010.phpt index 3e52f5ffc5c46..6dcf9eee63d98 100644 --- a/Zend/tests/class_alias_010.phpt +++ b/Zend/tests/class_alias_010.phpt @@ -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 diff --git a/Zend/tests/class_alias_019.phpt b/Zend/tests/class_alias_019.phpt index ace349e9bdd9a..4e229f511b12a 100644 --- a/Zend/tests/class_alias_019.phpt +++ b/Zend/tests/class_alias_019.phpt @@ -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 diff --git a/Zend/tests/declare_already_in_use.phpt b/Zend/tests/declare_already_in_use.phpt index c7e4ce8d677b7..85395160c5e76 100644 --- a/Zend/tests/declare_already_in_use.phpt +++ b/Zend/tests/declare_already_in_use.phpt @@ -1,5 +1,5 @@ --TEST-- -Cannot declare class, because the name is already in use +Cannot redeclare class --FILE-- --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 diff --git a/Zend/tests/delayed_early_binding_redeclaration.phpt b/Zend/tests/delayed_early_binding_redeclaration.phpt index 5370b45f52bcc..48fab510c0277 100644 --- a/Zend/tests/delayed_early_binding_redeclaration.phpt +++ b/Zend/tests/delayed_early_binding_redeclaration.phpt @@ -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 diff --git a/Zend/tests/errmsg_026.phpt b/Zend/tests/errmsg_026.phpt index 2144a0707b231..911b4f811d6cc 100644 --- a/Zend/tests/errmsg_026.phpt +++ b/Zend/tests/errmsg_026.phpt @@ -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 diff --git a/Zend/tests/function_redecl.phpt b/Zend/tests/function_redecl.phpt index 4c1395472fc6a..1bb683c6859fd 100644 --- a/Zend/tests/function_redecl.phpt +++ b/Zend/tests/function_redecl.phpt @@ -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 diff --git a/Zend/tests/inter_06.phpt b/Zend/tests/inter_06.phpt index aba8ba4fb4976..1987c24a8b96a 100644 --- a/Zend/tests/inter_06.phpt +++ b/Zend/tests/inter_06.phpt @@ -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 diff --git a/Zend/tests/name_collision_01.phpt b/Zend/tests/name_collision_01.phpt index d6d4ae35db1e6..07d36dd13b255 100644 --- a/Zend/tests/name_collision_01.phpt +++ b/Zend/tests/name_collision_01.phpt @@ -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 diff --git a/Zend/tests/name_collision_02.phpt b/Zend/tests/name_collision_02.phpt index 3baeb45e6f8fe..f740961d55bd1 100644 --- a/Zend/tests/name_collision_02.phpt +++ b/Zend/tests/name_collision_02.phpt @@ -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 diff --git a/Zend/tests/name_collision_03.phpt b/Zend/tests/name_collision_03.phpt index 6be45204a55b2..3785b04ce7829 100644 --- a/Zend/tests/name_collision_03.phpt +++ b/Zend/tests/name_collision_03.phpt @@ -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 diff --git a/Zend/tests/name_collision_04.phpt b/Zend/tests/name_collision_04.phpt index b391a96744342..a3d5c2995f1bd 100644 --- a/Zend/tests/name_collision_04.phpt +++ b/Zend/tests/name_collision_04.phpt @@ -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 diff --git a/Zend/tests/name_collision_05.phpt b/Zend/tests/name_collision_05.phpt index 87af1f0df9941..00cd046e3be3d 100644 --- a/Zend/tests/name_collision_05.phpt +++ b/Zend/tests/name_collision_05.phpt @@ -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 diff --git a/Zend/tests/name_collision_06.phpt b/Zend/tests/name_collision_06.phpt index cfeeed4a4340b..19dee2eaee4d2 100644 --- a/Zend/tests/name_collision_06.phpt +++ b/Zend/tests/name_collision_06.phpt @@ -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 diff --git a/Zend/tests/name_collision_07.phpt b/Zend/tests/name_collision_07.phpt index cb35e88db69cf..6988633b613dd 100644 --- a/Zend/tests/name_collision_07.phpt +++ b/Zend/tests/name_collision_07.phpt @@ -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 diff --git a/Zend/tests/name_collision_08.phpt b/Zend/tests/name_collision_08.phpt index 652fa3dbf15ed..8876431a669cc 100644 --- a/Zend/tests/name_collision_08.phpt +++ b/Zend/tests/name_collision_08.phpt @@ -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 diff --git a/Zend/tests/ns_029.phpt b/Zend/tests/ns_029.phpt index d053a9a33724a..75ee13ad4ce10 100644 --- a/Zend/tests/ns_029.phpt +++ b/Zend/tests/ns_029.phpt @@ -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 diff --git a/Zend/tests/use_function/define_imported.phpt b/Zend/tests/use_function/define_imported.phpt index c542a4d5494b9..abfc1cef5f117 100644 --- a/Zend/tests/use_function/define_imported.phpt +++ b/Zend/tests/use_function/define_imported.phpt @@ -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 diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 2a16f24250ebe..ae7a06f011761 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -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; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 8e82950e959cf..c61b27f3f52e9 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -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 diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index c92f507a1b2a5..337e5483613d1 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -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 { diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 3cbb0c4f7a1ed..ae2247b29e30d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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)); } } diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 491d68714b3c2..9df235a1853be 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -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) { diff --git a/ext/opcache/tests/bug67215.phpt b/ext/opcache/tests/bug67215.phpt index 133efaf435b1d..e4c65470897c9 100644 --- a/ext/opcache/tests/bug67215.phpt +++ b/ext/opcache/tests/bug67215.phpt @@ -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 diff --git a/ext/opcache/tests/bug73583.phpt b/ext/opcache/tests/bug73583.phpt index 9fb98faf80b90..419734188b37b 100644 --- a/ext/opcache/tests/bug73583.phpt +++ b/ext/opcache/tests/bug73583.phpt @@ -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 diff --git a/ext/opcache/tests/gh8846.phpt b/ext/opcache/tests/gh8846.phpt index dcfac1918de3b..98e94a401cb7a 100644 --- a/ext/opcache/tests/gh8846.phpt +++ b/ext/opcache/tests/gh8846.phpt @@ -33,7 +33,7 @@ echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/gh8846-index.php?s --EXPECTF-- bool(true)
-Fatal error: Cannot declare class Foo, because the name is already in use in %sgh8846-2.inc on line %d
+Fatal error: Cannot redeclare class Foo (previously declared in %sgh8846-1.inc:2) in %sgh8846-2.inc on line %d
bool(true) Ok diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 74161688ea443..a8eefad60c2fe 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -178,12 +178,12 @@ static zend_always_inline void _zend_accel_function_hash_copy(HashTable *target, 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; diff --git a/ext/pcre/tests/preg_replace_callback_fatal_error_leak.phpt b/ext/pcre/tests/preg_replace_callback_fatal_error_leak.phpt index 5ea3d4081e688..6bbcab49d99f5 100644 --- a/ext/pcre/tests/preg_replace_callback_fatal_error_leak.phpt +++ b/ext/pcre/tests/preg_replace_callback_fatal_error_leak.phpt @@ -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 diff --git a/scripts/dev/bless_tests.php b/scripts/dev/bless_tests.php index baf07d61f9e51..9ca37d77b8b43 100755 --- a/scripts/dev/bless_tests.php +++ b/scripts/dev/bless_tests.php @@ -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(