summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-02-06 11:13:13 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-02-17 12:21:33 +0100
commit72bd55902d1908857f47555ad69458861e1acd94 (patch)
tree3e54bf617776657ae9a7ae9a8b357798dfab2cb0
parent43443857b74503246ee4ca25859b302ed0ebc078 (diff)
downloadphp-git-72bd55902d1908857f47555ad69458861e1acd94.tar.gz
Improve generated names for anonymous classes
In order of preference, the generated name will be: new class extends ParentClass {}; // -> ParentClass@anonymous new class implements FirstInterface, SecondInterface {}; // -> FirstInterface@anonymous new class {}; // -> class@anonymous This is intended to display a more useful class name in error messages and stack traces, and thus make debugging easier. Closes GH-5153.
-rw-r--r--UPGRADING13
-rw-r--r--Zend/tests/anon_class_name.phpt30
-rw-r--r--Zend/tests/object_types/return_type_in_class.phpt4
-rw-r--r--Zend/tests/object_types/return_type_inheritance_in_class.phpt4
-rw-r--r--Zend/tests/object_types/return_type_inheritance_in_interface.phpt4
-rw-r--r--Zend/tests/temporary_cleaning_013.phpt4
-rw-r--r--Zend/tests/type_declarations/typed_properties_065.phpt8
-rw-r--r--Zend/zend_compile.c21
-rw-r--r--ext/opcache/tests/bug78937_1.phpt2
-rw-r--r--ext/opcache/tests/bug78937_2.phpt4
-rw-r--r--ext/opcache/tests/bug78937_3.phpt2
-rw-r--r--ext/opcache/tests/bug78937_4.phpt2
-rw-r--r--ext/opcache/tests/bug78937_5.phpt2
-rw-r--r--ext/opcache/tests/bug78937_6.phpt2
-rw-r--r--ext/reflection/tests/ReflectionClass_isSubclassOf_error2.phpt4
-rw-r--r--ext/standard/tests/class_object/bug78638.phpt2
-rw-r--r--ext/standard/tests/class_object/get_object_vars_variation_004.phptbin741 -> 763 bytes
17 files changed, 80 insertions, 28 deletions
diff --git a/UPGRADING b/UPGRADING
index 30611b1013..5174a2e52f 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -130,6 +130,18 @@ PHP 8.0 UPGRADE NOTES
exception.
. Some "Only variables should be passed by reference" notices have been converted
to "Cannot pass parameter by reference" exception.
+ . The generated name for anonymous classes has changed. It will now include
+ the name of the first parent or interface:
+
+ new class extends ParentClass {};
+ // -> ParentClass@anonymous
+ new class implements FirstInterface, SecondInterface {};
+ // -> FirstInterface@anonymous
+ new class {};
+ // -> class@anonymous
+
+ The name shown above is still followed by a null byte and and a unique
+ suffix.
- COM:
. Removed the ability to import case-insensitive constants from type
@@ -386,7 +398,6 @@ PHP 8.0 UPGRADE NOTES
writing `Foo::BAR::$baz` is now allowed.
RFC: https://wiki.php.net/rfc/variable_syntax_tweaks
-
- Date:
. Added DateTime::createFromInterface() and
DateTimeImmutable::createFromInterface().
diff --git a/Zend/tests/anon_class_name.phpt b/Zend/tests/anon_class_name.phpt
new file mode 100644
index 0000000000..36f613d707
--- /dev/null
+++ b/Zend/tests/anon_class_name.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Generated names for anonymous classes
+--FILE--
+<?php
+
+namespace DeclaringNS {
+ class Test1 {}
+ interface Test2 {}
+ interface Test3 {}
+}
+
+namespace UsingNS {
+ function print_name(object $obj) {
+ echo strstr(get_class($obj), "\0", true), "\n";
+ }
+
+ print_name(new class {});
+ print_name(new class extends \DeclaringNS\Test1 {});
+ print_name(new class extends \DeclaringNS\Test1 implements \DeclaringNS\Test2 {});
+ print_name(new class implements \DeclaringNS\Test2 {});
+ print_name(new class implements \DeclaringNS\Test2, \DeclaringNS\Test3 {});
+}
+
+?>
+--EXPECT--
+class@anonymous
+DeclaringNS\Test1@anonymous
+DeclaringNS\Test1@anonymous
+DeclaringNS\Test2@anonymous
+DeclaringNS\Test2@anonymous
diff --git a/Zend/tests/object_types/return_type_in_class.phpt b/Zend/tests/object_types/return_type_in_class.phpt
index c4c1dc0516..3edb015df7 100644
--- a/Zend/tests/object_types/return_type_in_class.phpt
+++ b/Zend/tests/object_types/return_type_in_class.phpt
@@ -18,8 +18,8 @@ $three = new class extends Two {
};
$three->a();
--EXPECTF--
-Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, int returned in %s:13
+Fatal error: Uncaught TypeError: Return value of Two@anonymous::a() must be an object, int returned in %s:%d
Stack trace:
-#0 %s(16): class@anonymous->a()
+#0 %s(%d): Two@anonymous->a()
#1 {main}
thrown in %s on line 13
diff --git a/Zend/tests/object_types/return_type_inheritance_in_class.phpt b/Zend/tests/object_types/return_type_inheritance_in_class.phpt
index a7316136fb..23528531ec 100644
--- a/Zend/tests/object_types/return_type_inheritance_in_class.phpt
+++ b/Zend/tests/object_types/return_type_inheritance_in_class.phpt
@@ -18,8 +18,8 @@ $three = new class extends Two {
};
$three->a();
--EXPECTF--
-Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, int returned in %s:13
+Fatal error: Uncaught TypeError: Return value of Two@anonymous::a() must be an object, int returned in %s:%d
Stack trace:
-#0 %s(16): class@anonymous->a()
+#0 %s(%d): Two@anonymous->a()
#1 {main}
thrown in %s on line 13
diff --git a/Zend/tests/object_types/return_type_inheritance_in_interface.phpt b/Zend/tests/object_types/return_type_inheritance_in_interface.phpt
index 4c8f6c08af..793cc980aa 100644
--- a/Zend/tests/object_types/return_type_inheritance_in_interface.phpt
+++ b/Zend/tests/object_types/return_type_inheritance_in_interface.phpt
@@ -18,8 +18,8 @@ $three = new class implements Two {
};
$three->a();
--EXPECTF--
-Fatal error: Uncaught TypeError: Return value of class@anonymous::a() must be an object, int returned in %s:13
+Fatal error: Uncaught TypeError: Return value of Two@anonymous::a() must be an object, int returned in %s:%d
Stack trace:
-#0 %s(16): class@anonymous->a()
+#0 %s(%d): Two@anonymous->a()
#1 {main}
thrown in %s on line 13
diff --git a/Zend/tests/temporary_cleaning_013.phpt b/Zend/tests/temporary_cleaning_013.phpt
index d9e7dd82f5..401edb512b 100644
--- a/Zend/tests/temporary_cleaning_013.phpt
+++ b/Zend/tests/temporary_cleaning_013.phpt
@@ -288,10 +288,10 @@ caught Exception 12
caught Exception 13
caught Exception 14
-Notice: Indirect modification of overloaded element of class@anonymous has no effect in %s on line %d
+Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d
caught Exception 15
-Notice: Indirect modification of overloaded element of class@anonymous has no effect in %s on line %d
+Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d
caught Exception 16
caught Exception 17
caught Exception 18
diff --git a/Zend/tests/type_declarations/typed_properties_065.phpt b/Zend/tests/type_declarations/typed_properties_065.phpt
index d81b51d049..7a1dd54894 100644
--- a/Zend/tests/type_declarations/typed_properties_065.phpt
+++ b/Zend/tests/type_declarations/typed_properties_065.phpt
@@ -61,11 +61,11 @@ offsetSet(1e50)
int(1)
int(0)
int(-1)
-Cannot decrement a reference held by property class@anonymous::$foo of type int past its minimal value
+Cannot decrement a reference held by property ArrayAccess@anonymous::$foo of type int past its minimal value
integer
-Cannot decrement a reference held by property class@anonymous::$foo of type int past its minimal value
+Cannot decrement a reference held by property ArrayAccess@anonymous::$foo of type int past its minimal value
integer
-Cannot increment a reference held by property class@anonymous::$foo of type int past its maximal value
+Cannot increment a reference held by property ArrayAccess@anonymous::$foo of type int past its maximal value
integer
-Cannot increment a reference held by property class@anonymous::$foo of type int past its maximal value
+Cannot increment a reference held by property ArrayAccess@anonymous::$foo of type int past its maximal value
integer
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 58fb3377d2..bc0a7dfdae 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -6569,14 +6569,25 @@ void zend_compile_implements(zend_ast *ast) /* {{{ */
}
/* }}} */
-static zend_string *zend_generate_anon_class_name(uint32_t start_lineno) /* {{{ */
+static zend_string *zend_generate_anon_class_name(zend_ast_decl *decl)
{
zend_string *filename = CG(active_op_array)->filename;
- zend_string *result = zend_strpprintf(0, "class@anonymous%c%s:%" PRIu32 "$%" PRIx32,
- '\0', ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
+ uint32_t start_lineno = decl->start_lineno;
+
+ /* Use parent or first interface as prefix. */
+ zend_string *prefix = ZSTR_KNOWN(ZEND_STR_CLASS);
+ if (decl->child[0]) {
+ prefix = zend_resolve_const_class_name_reference(decl->child[0], "class name");
+ } else if (decl->child[1]) {
+ zend_ast_list *list = zend_ast_get_list(decl->child[1]);
+ prefix = zend_resolve_const_class_name_reference(list->child[0], "interface name");
+ }
+
+ zend_string *result = zend_strpprintf(0, "%s@anonymous%c%s:%" PRIu32 "$%" PRIx32,
+ ZSTR_VAL(prefix), '\0', ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
+ zend_string_release(prefix);
return zend_new_interned_string(result);
}
-/* }}} */
zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
{
@@ -6613,7 +6624,7 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
zend_register_seen_symbol(lcname, ZEND_SYMBOL_CLASS);
} else {
- name = zend_generate_anon_class_name(decl->start_lineno);
+ name = zend_generate_anon_class_name(decl);
lcname = zend_string_tolower(name);
}
lcname = zend_new_interned_string(lcname);
diff --git a/ext/opcache/tests/bug78937_1.phpt b/ext/opcache/tests/bug78937_1.phpt
index bc285f107b..0572e521aa 100644
--- a/ext/opcache/tests/bug78937_1.phpt
+++ b/ext/opcache/tests/bug78937_1.phpt
@@ -19,7 +19,7 @@ var_dump(foo());
--EXPECTF--
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
-Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
+Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
Fatal error: Anonymous class wasn't preloaded in %spreload_bug78937.inc on line 3
diff --git a/ext/opcache/tests/bug78937_2.phpt b/ext/opcache/tests/bug78937_2.phpt
index a20c07d231..90aaa43883 100644
--- a/ext/opcache/tests/bug78937_2.phpt
+++ b/ext/opcache/tests/bug78937_2.phpt
@@ -20,6 +20,6 @@ var_dump(foo());
--EXPECTF--
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
-Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
-object(class@anonymous)#%d (0) {
+Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
+object(Bar@anonymous)#%d (0) {
}
diff --git a/ext/opcache/tests/bug78937_3.phpt b/ext/opcache/tests/bug78937_3.phpt
index 16f7b80a40..81821e3109 100644
--- a/ext/opcache/tests/bug78937_3.phpt
+++ b/ext/opcache/tests/bug78937_3.phpt
@@ -18,7 +18,7 @@ var_dump(foo());
--EXPECTF--
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
-Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
+Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
Fatal error: Uncaught Error: Class 'Bar' not found in %spreload_bug78937.inc:3
Stack trace:
diff --git a/ext/opcache/tests/bug78937_4.phpt b/ext/opcache/tests/bug78937_4.phpt
index 2ad86870de..86c38a6d98 100644
--- a/ext/opcache/tests/bug78937_4.phpt
+++ b/ext/opcache/tests/bug78937_4.phpt
@@ -20,6 +20,6 @@ var_dump(new Foo);
--EXPECTF--
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
-Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
+Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
Fatal error: Class foo wasn't preloaded in %spreload_bug78937.inc on line 6
diff --git a/ext/opcache/tests/bug78937_5.phpt b/ext/opcache/tests/bug78937_5.phpt
index 3502699750..bb83408d90 100644
--- a/ext/opcache/tests/bug78937_5.phpt
+++ b/ext/opcache/tests/bug78937_5.phpt
@@ -21,6 +21,6 @@ var_dump(new Foo);
--EXPECTF--
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
-Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
+Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
object(Foo)#%d (0) {
}
diff --git a/ext/opcache/tests/bug78937_6.phpt b/ext/opcache/tests/bug78937_6.phpt
index ec1cc2d277..6e4d7060b3 100644
--- a/ext/opcache/tests/bug78937_6.phpt
+++ b/ext/opcache/tests/bug78937_6.phpt
@@ -19,7 +19,7 @@ var_dump(new Foo);
--EXPECTF--
Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78937.inc on line 6
-Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
+Warning: Can't preload unlinked class Bar@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
Fatal error: Uncaught Error: Class 'Bar' not found in %spreload_bug78937.inc:6
Stack trace:
diff --git a/ext/reflection/tests/ReflectionClass_isSubclassOf_error2.phpt b/ext/reflection/tests/ReflectionClass_isSubclassOf_error2.phpt
index 8671c2500b..df7fb42073 100644
--- a/ext/reflection/tests/ReflectionClass_isSubclassOf_error2.phpt
+++ b/ext/reflection/tests/ReflectionClass_isSubclassOf_error2.phpt
@@ -11,7 +11,7 @@ class Base {}
$check = function () {
$base = Base::class;
foreach (get_declared_classes() as $class) {
- if (strpos($class, 'class@anonymous') === false) {
+ if (strpos($class, '@anonymous') === false) {
continue;
}
echo "Checking for $class\n";
@@ -30,6 +30,6 @@ echo "Done\n";
?>
--EXPECTF--
After first check
-Checking for class@%s
+Checking for Base@%s
true
Done
diff --git a/ext/standard/tests/class_object/bug78638.phpt b/ext/standard/tests/class_object/bug78638.phpt
index 088e7c4c1f..76315ee1c5 100644
--- a/ext/standard/tests/class_object/bug78638.phpt
+++ b/ext/standard/tests/class_object/bug78638.phpt
@@ -6,4 +6,4 @@ $c = new class('bar') extends __PHP_Incomplete_Class {
};
?>
--EXPECTF--
-Fatal error: Class class@anonymous may not inherit from final class (__PHP_Incomplete_Class) in %sbug78638.php on line %d
+Fatal error: Class __PHP_Incomplete_Class@anonymous may not inherit from final class (__PHP_Incomplete_Class) in %s on line %d
diff --git a/ext/standard/tests/class_object/get_object_vars_variation_004.phpt b/ext/standard/tests/class_object/get_object_vars_variation_004.phpt
index f52b3fed78..902149ea0a 100644
--- a/ext/standard/tests/class_object/get_object_vars_variation_004.phpt
+++ b/ext/standard/tests/class_object/get_object_vars_variation_004.phpt
Binary files differ