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
writing `Foo::BAR::$baz` is now allowed.
RFC: https://wiki.php.net/rfc/variable_syntax_tweaks
-
- Date:
. Added DateTime::createFromInterface() and
DateTimeImmutable::createFromInterface().
--- /dev/null
+--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
};
$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
};
$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
};
$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
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
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
}
/* }}} */
-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) /* {{{ */
{
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);
--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
--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) {
}
--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:
--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
--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) {
}
--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:
$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";
?>
--EXPECTF--
After first check
-Checking for class@%s
+Checking for Base@%s
true
Done
};
?>
--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