Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve generated names for anonymous classes #5153

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 30 additions & 0 deletions 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
4 changes: 2 additions & 2 deletions Zend/tests/object_types/return_type_in_class.phpt
Expand Up @@ -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
Expand Up @@ -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
Expand Up @@ -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
4 changes: 2 additions & 2 deletions Zend/tests/temporary_cleaning_013.phpt
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions Zend/tests/type_declarations/typed_properties_065.phpt
Expand Up @@ -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
21 changes: 16 additions & 5 deletions Zend/zend_compile.c
Expand Up @@ -6555,14 +6555,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) /* {{{ */
{
Expand Down Expand Up @@ -6599,7 +6610,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);
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/tests/bug78937_1.phpt
Expand Up @@ -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

4 changes: 2 additions & 2 deletions ext/opcache/tests/bug78937_2.phpt
Expand Up @@ -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) {
}
2 changes: 1 addition & 1 deletion ext/opcache/tests/bug78937_3.phpt
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/tests/bug78937_4.phpt
Expand Up @@ -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
2 changes: 1 addition & 1 deletion ext/opcache/tests/bug78937_5.phpt
Expand Up @@ -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) {
}
2 changes: 1 addition & 1 deletion ext/opcache/tests/bug78937_6.phpt
Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions ext/reflection/tests/ReflectionClass_isSubclassOf_error2.phpt
Expand Up @@ -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";
Expand All @@ -30,6 +30,6 @@ echo "Done\n";
?>
--EXPECTF--
After first check
Checking for class@%s
Checking for Base@%s
true
Done
2 changes: 1 addition & 1 deletion ext/standard/tests/class_object/bug78638.phpt
Expand Up @@ -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
Binary file not shown.