mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
gen_stub: Intern the parameter name string for named arguments in internal attributes (#14595)
This is necessary because `zend_get_attribute_object()` will use the persistent string with the parameter name as the index for a newly created non-persistent HashTable, which is not legal. As parameter names are expected to be short-ish, reasonably common terms and need to sit around in memory anyways, we might as well make them an interned string, circumstepping the issue without needing to duplicate the parameter name into a non-persistent string.
This commit is contained in:
@@ -3124,7 +3124,7 @@ class AttributeInfo {
|
||||
$code .= $value->initializeZval($zvalName);
|
||||
$code .= "\tZVAL_COPY_VALUE(&attribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].value, &$zvalName);\n";
|
||||
if ($arg->name) {
|
||||
$code .= "\tattribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].name = zend_string_init(\"{$arg->name->name}\", sizeof(\"{$arg->name->name}\") - 1, 1);\n";
|
||||
$code .= "\tattribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].name = zend_string_init_interned(\"{$arg->name->name}\", sizeof(\"{$arg->name->name}\") - 1, 1);\n";
|
||||
}
|
||||
}
|
||||
return $code;
|
||||
|
||||
@@ -58,6 +58,7 @@ static zend_class_entry *zend_test_attribute;
|
||||
static zend_class_entry *zend_test_repeatable_attribute;
|
||||
static zend_class_entry *zend_test_parameter_attribute;
|
||||
static zend_class_entry *zend_test_property_attribute;
|
||||
static zend_class_entry *zend_test_attribute_with_arguments;
|
||||
static zend_class_entry *zend_test_class_with_method_with_parameter_attribute;
|
||||
static zend_class_entry *zend_test_child_class_with_method_with_parameter_attribute;
|
||||
static zend_class_entry *zend_test_class_with_property_attribute;
|
||||
@@ -575,6 +576,11 @@ static ZEND_FUNCTION(zend_test_parameter_with_attribute)
|
||||
RETURN_LONG(1);
|
||||
}
|
||||
|
||||
static ZEND_FUNCTION(zend_test_attribute_with_named_argument)
|
||||
{
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
}
|
||||
|
||||
#ifdef ZEND_CHECK_STACK_LIMIT
|
||||
static ZEND_FUNCTION(zend_test_zend_call_stack_get)
|
||||
{
|
||||
@@ -989,6 +995,19 @@ static ZEND_METHOD(ZendTestPropertyAttribute, __construct)
|
||||
ZVAL_STR_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), parameter);
|
||||
}
|
||||
|
||||
static ZEND_METHOD(ZendTestAttributeWithArguments, __construct)
|
||||
{
|
||||
zval *arg;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
Z_PARAM_ZVAL(arg)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
zend_string *property_name = zend_string_init("arg", strlen("arg"), 0);
|
||||
zend_update_property_ex(zend_test_attribute_with_arguments, Z_OBJ_P(ZEND_THIS), property_name, arg);
|
||||
zend_string_release(property_name);
|
||||
}
|
||||
|
||||
static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, no_override)
|
||||
{
|
||||
zend_string *parameter;
|
||||
@@ -1217,6 +1236,9 @@ PHP_MINIT_FUNCTION(zend_test)
|
||||
zend_test_property_attribute = register_class_ZendTestPropertyAttribute();
|
||||
zend_mark_internal_attribute(zend_test_property_attribute);
|
||||
|
||||
zend_test_attribute_with_arguments = register_class_ZendTestAttributeWithArguments();
|
||||
zend_mark_internal_attribute(zend_test_attribute_with_arguments);
|
||||
|
||||
zend_test_class_with_method_with_parameter_attribute = register_class_ZendTestClassWithMethodWithParameterAttribute();
|
||||
zend_test_child_class_with_method_with_parameter_attribute = register_class_ZendTestChildClassWithMethodWithParameterAttribute(zend_test_class_with_method_with_parameter_attribute);
|
||||
|
||||
|
||||
@@ -104,6 +104,13 @@ namespace {
|
||||
final class ZendTestAttribute {
|
||||
}
|
||||
|
||||
#[Attribute(Attribute::TARGET_ALL)]
|
||||
final class ZendTestAttributeWithArguments {
|
||||
public readonly mixed $arg;
|
||||
|
||||
public function __construct(mixed $arg) {}
|
||||
}
|
||||
|
||||
#[Attribute(Attribute::TARGET_ALL|Attribute::IS_REPEATABLE)]
|
||||
final class ZendTestRepeatableAttribute {
|
||||
}
|
||||
@@ -243,6 +250,9 @@ namespace {
|
||||
string $parameter
|
||||
): int {}
|
||||
|
||||
#[ZendTestAttributeWithArguments(arg: "foo")]
|
||||
function zend_test_attribute_with_named_argument(): void {}
|
||||
|
||||
function zend_get_current_func_name(): string {}
|
||||
|
||||
function zend_call_method(object|string $obj_or_class, string $method, mixed $arg1 = UNKNOWN, mixed $arg2 = UNKNOWN): mixed {}
|
||||
|
||||
53
ext/zend_test/test_arginfo.h
generated
53
ext/zend_test/test_arginfo.h
generated
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 810a94e09724a27d46c99495593da999cfc46243 */
|
||||
* Stub hash: b7e8a9c27def16e8691883bea7837def1f717ab8 */
|
||||
|
||||
ZEND_STATIC_ASSERT(PHP_VERSION_ID >= 80000, "test_arginfo.h only supports PHP version ID 80000 or newer, "
|
||||
"but it is included on an older PHP version");
|
||||
@@ -90,6 +90,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_parameter_with_attribu
|
||||
ZEND_ARG_TYPE_INFO(0, parameter, IS_STRING, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_zend_test_attribute_with_named_argument arginfo_zend_test_void_return
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_get_current_func_name, 0, 0, IS_STRING, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
@@ -208,6 +210,10 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class__ZendTestTrait_testMethod arginfo_zend_test_is_pcre_bundled
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZendTestAttributeWithArguments___construct, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, arg, IS_MIXED, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZendTestParameterAttribute___construct, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, parameter, IS_STRING, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
@@ -262,6 +268,7 @@ static ZEND_FUNCTION(zend_weakmap_remove);
|
||||
static ZEND_FUNCTION(zend_weakmap_dump);
|
||||
static ZEND_FUNCTION(zend_get_unit_enum);
|
||||
static ZEND_FUNCTION(zend_test_parameter_with_attribute);
|
||||
static ZEND_FUNCTION(zend_test_attribute_with_named_argument);
|
||||
static ZEND_FUNCTION(zend_get_current_func_name);
|
||||
static ZEND_FUNCTION(zend_call_method);
|
||||
static ZEND_FUNCTION(zend_object_init_with_constructor);
|
||||
@@ -302,6 +309,7 @@ static ZEND_METHOD(_ZendTestMagicCall, __call);
|
||||
static ZEND_METHOD(_ZendTestChildClass, returnsThrowable);
|
||||
static ZEND_METHOD(ZendAttributeTest, testMethod);
|
||||
static ZEND_METHOD(_ZendTestTrait, testMethod);
|
||||
static ZEND_METHOD(ZendTestAttributeWithArguments, __construct);
|
||||
static ZEND_METHOD(ZendTestParameterAttribute, __construct);
|
||||
static ZEND_METHOD(ZendTestPropertyAttribute, __construct);
|
||||
static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, no_override);
|
||||
@@ -359,6 +367,7 @@ static const zend_function_entry ext_functions[] = {
|
||||
ZEND_FE(zend_weakmap_dump, arginfo_zend_weakmap_dump)
|
||||
ZEND_FE(zend_get_unit_enum, arginfo_zend_get_unit_enum)
|
||||
ZEND_FE(zend_test_parameter_with_attribute, arginfo_zend_test_parameter_with_attribute)
|
||||
ZEND_FE(zend_test_attribute_with_named_argument, arginfo_zend_test_attribute_with_named_argument)
|
||||
ZEND_FE(zend_get_current_func_name, arginfo_zend_get_current_func_name)
|
||||
ZEND_FE(zend_call_method, arginfo_zend_call_method)
|
||||
ZEND_FE(zend_object_init_with_constructor, arginfo_zend_object_init_with_constructor)
|
||||
@@ -466,6 +475,11 @@ static const zend_function_entry class_ZendTestAttribute_methods[] = {
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
static const zend_function_entry class_ZendTestAttributeWithArguments_methods[] = {
|
||||
ZEND_ME(ZendTestAttributeWithArguments, __construct, arginfo_class_ZendTestAttributeWithArguments___construct, ZEND_ACC_PUBLIC)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
static const zend_function_entry class_ZendTestRepeatableAttribute_methods[] = {
|
||||
ZEND_FE_END
|
||||
};
|
||||
@@ -553,6 +567,15 @@ static void register_test_symbols(int module_number)
|
||||
zend_string *attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0_str = zend_string_init("value1", strlen("value1"), 1);
|
||||
ZVAL_STR(&attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0, attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0_str);
|
||||
ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0->args[0].value, &attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0);
|
||||
|
||||
zend_string *attribute_name_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0 = zend_string_init_interned("ZendTestAttributeWithArguments", sizeof("ZendTestAttributeWithArguments") - 1, 1);
|
||||
zend_attribute *attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_attribute_with_named_argument", sizeof("zend_test_attribute_with_named_argument") - 1), attribute_name_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0, 1);
|
||||
zend_string_release(attribute_name_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0);
|
||||
zval attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0;
|
||||
zend_string *attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0_str = zend_string_init("foo", strlen("foo"), 1);
|
||||
ZVAL_STR(&attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0, attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0_str);
|
||||
ZVAL_COPY_VALUE(&attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0->args[0].value, &attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0);
|
||||
attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0->args[0].name = zend_string_init_interned("arg", sizeof("arg") - 1, 1);
|
||||
}
|
||||
|
||||
static zend_class_entry *register_class__ZendTestInterface(void)
|
||||
@@ -802,6 +825,34 @@ static zend_class_entry *register_class_ZendTestAttribute(void)
|
||||
return class_entry;
|
||||
}
|
||||
|
||||
static zend_class_entry *register_class_ZendTestAttributeWithArguments(void)
|
||||
{
|
||||
zend_class_entry ce, *class_entry;
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "ZendTestAttributeWithArguments", class_ZendTestAttributeWithArguments_methods);
|
||||
class_entry = zend_register_internal_class_ex(&ce, NULL);
|
||||
class_entry->ce_flags |= ZEND_ACC_FINAL;
|
||||
|
||||
zval property_arg_default_value;
|
||||
ZVAL_UNDEF(&property_arg_default_value);
|
||||
zend_string *property_arg_name = zend_string_init("arg", sizeof("arg") - 1, 1);
|
||||
#if (PHP_VERSION_ID >= 80100)
|
||||
zend_declare_typed_property(class_entry, property_arg_name, &property_arg_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY));
|
||||
#elif (PHP_VERSION_ID >= 80000)
|
||||
zend_declare_typed_property(class_entry, property_arg_name, &property_arg_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY));
|
||||
#endif
|
||||
zend_string_release(property_arg_name);
|
||||
|
||||
zend_string *attribute_name_Attribute_class_ZendTestAttributeWithArguments_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1);
|
||||
zend_attribute *attribute_Attribute_class_ZendTestAttributeWithArguments_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestAttributeWithArguments_0, 1);
|
||||
zend_string_release(attribute_name_Attribute_class_ZendTestAttributeWithArguments_0);
|
||||
zval attribute_Attribute_class_ZendTestAttributeWithArguments_0_arg0;
|
||||
ZVAL_LONG(&attribute_Attribute_class_ZendTestAttributeWithArguments_0_arg0, ZEND_ATTRIBUTE_TARGET_ALL);
|
||||
ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestAttributeWithArguments_0->args[0].value, &attribute_Attribute_class_ZendTestAttributeWithArguments_0_arg0);
|
||||
|
||||
return class_entry;
|
||||
}
|
||||
|
||||
static zend_class_entry *register_class_ZendTestRepeatableAttribute(void)
|
||||
{
|
||||
zend_class_entry ce, *class_entry;
|
||||
|
||||
22
ext/zend_test/tests/attribute-named-parameter.phpt
Normal file
22
ext/zend_test/tests/attribute-named-parameter.phpt
Normal file
@@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Verify that attributes for internal functions correctly support named arguments.
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$reflection = new ReflectionFunction("zend_test_attribute_with_named_argument");
|
||||
$attribute = $reflection->getAttributes()[0];
|
||||
var_dump($attribute->getArguments());
|
||||
var_dump($attribute->newInstance());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(1) {
|
||||
["arg"]=>
|
||||
string(3) "foo"
|
||||
}
|
||||
object(ZendTestAttributeWithArguments)#3 (1) {
|
||||
["arg"]=>
|
||||
string(3) "foo"
|
||||
}
|
||||
Reference in New Issue
Block a user