diff options
author | Máté Kocsis <kocsismate@woohoolabs.com> | 2020-04-06 11:02:13 +0200 |
---|---|---|
committer | Máté Kocsis <kocsismate@woohoolabs.com> | 2020-04-08 18:37:51 +0200 |
commit | 3709e74b5e495e210ada8039ed81fafa9cbadcdb (patch) | |
tree | b7347572b1e22a2a27a45260b4f4773bf916b158 /Zend | |
parent | b0d8f012f95ba1f2d8dba238c93baf3afb73b78e (diff) | |
download | php-git-3709e74b5e495e210ada8039ed81fafa9cbadcdb.tar.gz |
Store default parameter values of internal functions in arg info
Closes GH-5353. From now on, PHP will have reflection information
about default values of parameters of internal functions.
Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>
Diffstat (limited to 'Zend')
23 files changed, 226 insertions, 54 deletions
diff --git a/Zend/tests/argument_restriction_001.phpt b/Zend/tests/argument_restriction_001.phpt index c7deb760a0..47739dd29e 100644 --- a/Zend/tests/argument_restriction_001.phpt +++ b/Zend/tests/argument_restriction_001.phpt @@ -13,4 +13,4 @@ class Sub extends Base { } ?> --EXPECTF-- -Fatal error: Declaration of & Sub::test() must be compatible with & Base::test($foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %sargument_restriction_001.php on line %d +Fatal error: Declaration of & Sub::test() must be compatible with & Base::test($foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %s on line %d diff --git a/Zend/tests/argument_restriction_003.phpt b/Zend/tests/argument_restriction_003.phpt index 7857d377ae..2640be6ae0 100644 --- a/Zend/tests/argument_restriction_003.phpt +++ b/Zend/tests/argument_restriction_003.phpt @@ -16,4 +16,4 @@ class Sub extends Base { } ?> --EXPECTF-- -Fatal error: Declaration of Sub::test() must be compatible with Base::test(Foo $foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %sargument_restriction_003.php on line %d +Fatal error: Declaration of Sub::test() must be compatible with Base::test(Foo $foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %s on line %d diff --git a/Zend/tests/argument_restriction_006.phpt b/Zend/tests/argument_restriction_006.phpt index 5298c6959d..7c00281e99 100644 --- a/Zend/tests/argument_restriction_006.phpt +++ b/Zend/tests/argument_restriction_006.phpt @@ -13,4 +13,4 @@ class Sub extends Base { } ?> --EXPECTF-- -Fatal error: Declaration of Sub::test($foo, $extra) must be compatible with Base::test($foo, $extra = Array) in %sargument_restriction_006.php on line %d +Fatal error: Declaration of Sub::test($foo, $extra) must be compatible with Base::test($foo, $extra = Array) in %s on line %d diff --git a/Zend/tests/bug64988.phpt b/Zend/tests/bug64988.phpt index 490c47194b..bff388ca0f 100644 --- a/Zend/tests/bug64988.phpt +++ b/Zend/tests/bug64988.phpt @@ -26,4 +26,4 @@ $o = new Smooth1(); echo "okey"; ?> --EXPECTF-- -Fatal error: Declaration of Smooth1::insert(array $data) must be compatible with Noisy1::insert(array $data, $option1 = NULL) in %sbug64988.php on line 17 +Fatal error: Declaration of Smooth1::insert(array $data) must be compatible with Noisy1::insert(array $data, $option1 = NULL) in %s on line %d diff --git a/Zend/tests/bug70957.phpt b/Zend/tests/bug70957.phpt index ad2115e4a0..39970f9123 100644 --- a/Zend/tests/bug70957.phpt +++ b/Zend/tests/bug70957.phpt @@ -19,4 +19,4 @@ class B extends Foo } ?> --EXPECTF-- -Fatal error: Declaration of T::bar() must be compatible with Foo::bar($a = 'Foo') in %sbug70957.php on line %d +Fatal error: Declaration of T::bar() must be compatible with Foo::bar($a = 'Foo') in %s on line %d diff --git a/Zend/tests/bug71428.1.phpt b/Zend/tests/bug71428.1.phpt index acecd85fc5..7b20aa73b2 100644 --- a/Zend/tests/bug71428.1.phpt +++ b/Zend/tests/bug71428.1.phpt @@ -9,4 +9,4 @@ class B extends A { public function m(array $a = []) {} } --EXPECTF-- -Fatal error: Declaration of B::m(array $a = Array) must be compatible with A::m(?array $a = NULL) in %sbug71428.1.php on line 6 +Fatal error: Declaration of B::m(array $a = Array) must be compatible with A::m(?array $a = NULL) in %s on line %d diff --git a/Zend/tests/bug73987.phpt b/Zend/tests/bug73987.phpt index 610b594a64..b6e9e744aa 100644 --- a/Zend/tests/bug73987.phpt +++ b/Zend/tests/bug73987.phpt @@ -15,4 +15,4 @@ class B extends A { ?> --EXPECTF-- -Fatal error: Declaration of B::example($a, $b, $c = NULL) must be compatible with A::example($a, $b = NULL, $c = NULL) in %s +Fatal error: Declaration of B::example($a, $b, $c = NULL) must be compatible with A::example($a, $b = NULL, $c = NULL) in %s on line %d diff --git a/Zend/tests/bug73987_2.phpt b/Zend/tests/bug73987_2.phpt index a70f1455e8..976280be19 100644 --- a/Zend/tests/bug73987_2.phpt +++ b/Zend/tests/bug73987_2.phpt @@ -17,4 +17,4 @@ class C extends B { ?> --EXPECTF-- -Fatal error: Declaration of C::example($a, $b, $c = NULL) must be compatible with B::example($a, $b = NULL, $c = NULL) in %s +Fatal error: Declaration of C::example($a, $b, $c = NULL) must be compatible with B::example($a, $b = NULL, $c = NULL) in %s on line %d diff --git a/Zend/tests/closures/closure_from_callable_basic.phpt b/Zend/tests/closures/closure_from_callable_basic.phpt index 72cb5bc68c..88a27c7e70 100644 --- a/Zend/tests/closures/closure_from_callable_basic.phpt +++ b/Zend/tests/closures/closure_from_callable_basic.phpt @@ -81,7 +81,7 @@ $foo = new SubFoo; $fn = $foo->getSelfColonParentPublicInstanceMethod(); echo $fn(" OK".PHP_EOL); -echo 'Access proteced instance method of parent object through "self::" to parent method'; +echo 'Access protected instance method of parent object through "self::" to parent method'; $foo = new SubFoo; $fn = $foo->getSelfColonParentProtectedInstanceMethod(); echo $fn(" OK".PHP_EOL); @@ -114,6 +114,6 @@ Subclass closure over parent class static protected method OK Access public instance method of parent object through "parent::" OK Access public instance method of self object through "self::" OK Access public instance method of parent object through "self::" to parent method OK -Access proteced instance method of parent object through "self::" to parent method OK +Access protected instance method of parent object through "self::" to parent method OK MagicCall __call instance method __call,nonExistentMethod, OK MagicCall __callStatic static method __callStatic,nonExistentMethod, OK diff --git a/Zend/tests/parameter_default_values/internal_declaration_error_class_const.phpt b/Zend/tests/parameter_default_values/internal_declaration_error_class_const.phpt new file mode 100644 index 0000000000..2e0e6e2aea --- /dev/null +++ b/Zend/tests/parameter_default_values/internal_declaration_error_class_const.phpt @@ -0,0 +1,12 @@ +--TEST-- +The default value is a class constant in the parent class method's signature. +--FILE-- +<?php +class MyDateTimeZone extends DateTimeZone +{ + public static function listIdentifiers() + { + } +} +--EXPECTF-- +Fatal error: Declaration of MyDateTimeZone::listIdentifiers() must be compatible with DateTimeZone::listIdentifiers(int $what = DateTimeZone::ALL, ?string $country = null) in %s on line %d diff --git a/Zend/tests/parameter_default_values/internal_declaration_error_const.phpt b/Zend/tests/parameter_default_values/internal_declaration_error_const.phpt new file mode 100644 index 0000000000..58924076e3 --- /dev/null +++ b/Zend/tests/parameter_default_values/internal_declaration_error_const.phpt @@ -0,0 +1,12 @@ +--TEST-- +The default value is a constant in the parent class method's signature. +--FILE-- +<?php +class MyDateTimeZone extends DateTimeZone +{ + public function getTransitions() + { + } +} +--EXPECTF-- +Fatal error: Declaration of MyDateTimeZone::getTransitions() must be compatible with DateTimeZone::getTransitions(int $timestamp_begin = PHP_INT_MIN, int $timestamp_end = PHP_INT_MAX) in %s on line %d diff --git a/Zend/tests/parameter_default_values/internal_declaration_error_false.phpt b/Zend/tests/parameter_default_values/internal_declaration_error_false.phpt new file mode 100644 index 0000000000..e7cb522c54 --- /dev/null +++ b/Zend/tests/parameter_default_values/internal_declaration_error_false.phpt @@ -0,0 +1,11 @@ +--TEST-- +The default value is false in the parent class method's signature. +--FILE-- +<?php + +interface MyDateTimeInterface extends DateTimeInterface +{ + public function diff(); +} +--EXPECTF-- +Fatal error: Declaration of MyDateTimeInterface::diff() must be compatible with DateTimeInterface::diff(DateTimeInterface $object, bool $absolute = false) in %s on line %d diff --git a/Zend/tests/parameter_default_values/internal_declaration_error_int.phpt b/Zend/tests/parameter_default_values/internal_declaration_error_int.phpt new file mode 100644 index 0000000000..599ff6162a --- /dev/null +++ b/Zend/tests/parameter_default_values/internal_declaration_error_int.phpt @@ -0,0 +1,12 @@ +--TEST-- +The default value is an integer in the parent class method's signature. +--FILE-- +<?php +class MyDateTime extends DateTime +{ + public function setTime(int $hour, int $minute, int $second = 0, bool $microseconds = false) + { + } +} +--EXPECTF-- +Fatal error: Declaration of MyDateTime::setTime(int $hour, int $minute, int $second = 0, bool $microseconds = false) must be compatible with DateTime::setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0) in %s on line %d diff --git a/Zend/tests/parameter_default_values/internal_declaration_error_null.phpt b/Zend/tests/parameter_default_values/internal_declaration_error_null.phpt new file mode 100644 index 0000000000..e03e0394d6 --- /dev/null +++ b/Zend/tests/parameter_default_values/internal_declaration_error_null.phpt @@ -0,0 +1,12 @@ +--TEST-- +The default value is null in the parent class method's signature. +--FILE-- +<?php +class MyDateTime extends DateTime +{ + public static function createFromFormat() + { + } +} +--EXPECTF-- +Fatal error: Declaration of MyDateTime::createFromFormat() must be compatible with DateTime::createFromFormat(string $format, string $time, ?DateTimeZone $timezone = null) in %s on line %d diff --git a/Zend/tests/parameter_default_values/userland_declaration_error_class_const.phpt b/Zend/tests/parameter_default_values/userland_declaration_error_class_const.phpt new file mode 100644 index 0000000000..c65883229d --- /dev/null +++ b/Zend/tests/parameter_default_values/userland_declaration_error_class_const.phpt @@ -0,0 +1,25 @@ +--TEST-- +The default value is a constant in the parent class method's signature. +--FILE-- +<?php + +use Foo\Bar; + +class A +{ + public function foo( + $param1 = \Foo\Bar::CONSTANT, + $param2 = Foo\Bar::CONSTANT, + $param3 = Bar::CONSTANT + ) { + } +} + +class B extends A +{ + public function foo() + { + } +} +--EXPECTF-- +Fatal error: Declaration of B::foo() must be compatible with A::foo($param1 = Foo\Bar::CONSTANT, $param2 = Foo\Bar::CONSTANT, $param3 = Foo\Bar::CONSTANT) in %s on line %d diff --git a/Zend/tests/parameter_default_values/userland_declaration_error_const.phpt b/Zend/tests/parameter_default_values/userland_declaration_error_const.phpt new file mode 100644 index 0000000000..710494d0ac --- /dev/null +++ b/Zend/tests/parameter_default_values/userland_declaration_error_const.phpt @@ -0,0 +1,25 @@ +--TEST-- +The default value is a constant in the parent class method's signature. +--FILE-- +<?php + +use const Foo\CONSTANT; + +class A +{ + public function foo( + $param1 = \Foo\CONSTANT, + $param2 = Foo\CONSTANT, + $param3 = CONSTANT + ) { + } +} + +class B extends A +{ + public function foo() + { + } +} +--EXPECTF-- +Fatal error: Declaration of B::foo() must be compatible with A::foo($param1 = Foo\CONSTANT, $param2 = Foo\CONSTANT, $param3 = Foo\CONSTANT) in %s on line %d diff --git a/Zend/tests/type_declarations/variance/internal_parent.phpt b/Zend/tests/type_declarations/variance/internal_parent.phpt index d31dcb17a8..ae86a3bc3c 100644 --- a/Zend/tests/type_declarations/variance/internal_parent.phpt +++ b/Zend/tests/type_declarations/variance/internal_parent.phpt @@ -9,4 +9,4 @@ class Test extends DateTime { ?> --EXPECTF-- -Fatal error: Could not check compatibility between Test::createFromFormat($format, $time, ?Wrong $timezone = NULL) and DateTime::createFromFormat(string $format, string $time, ?DateTimeZone $timezone = NULL), because class Wrong is not available in %s on line %d +Fatal error: Could not check compatibility between Test::createFromFormat($format, $time, ?Wrong $timezone = NULL) and DateTime::createFromFormat(string $format, string $time, ?DateTimeZone $timezone = null), because class Wrong is not available in %s on line %d diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 77599ca814..afc2ad8a7d 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -105,50 +105,61 @@ typedef struct _zend_fcall_info_cache { #define _ZEND_ARG_INFO_FLAGS(pass_by_ref, is_variadic) \ (((pass_by_ref) << _ZEND_SEND_MODE_SHIFT) | ((is_variadic) ? _ZEND_IS_VARIADIC_BIT : 0)) +/* Arginfo structures without type information */ #define ZEND_ARG_INFO(pass_by_ref, name) \ - { #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0))}, -#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) \ - { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, -#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) \ - { #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, -#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) \ - { #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, -#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \ - { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, -#define ZEND_ARG_TYPE_MASK(pass_by_ref, name, type_mask) \ - { #name, ZEND_TYPE_INIT_MASK(type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, + { #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL }, +#define ZEND_ARG_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, default_value) \ + { #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value }, #define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) \ - { #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) }, + { #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL }, +/* Arginfo structures with simple type information */ +#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \ + { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL }, +#define ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, type_hint, allow_null, default_value) \ + { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value }, #define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \ - { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) }, + { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL }, +/* Arginfo structures with complex type information */ +#define ZEND_ARG_TYPE_MASK(pass_by_ref, name, type_mask, default_value) \ + { #name, ZEND_TYPE_INIT_MASK(type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value }, +/* Arginfo structures with object type information */ +#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) \ + { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL }, +#define ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, classname, allow_null, default_value) \ + { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), default_value }, #define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) \ - { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) }, + { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)), NULL }, +/* Legacy arginfo structures */ +#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) \ + { #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL }, +#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) \ + { #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)), NULL }, #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \ static const zend_internal_arg_info name[] = { \ { (const char*)(zend_uintptr_t)(required_num_args), \ - ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, + ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL }, #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO(name, class_name, allow_null) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, -1, class_name, allow_null) #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(name, return_reference, required_num_args, type) \ static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_MASK(type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, + { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_MASK(type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL }, #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(name, return_reference, required_num_args, class_name, type) \ static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, + { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CLASS_CONST_MASK(#class_name, type | _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL }, #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \ static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, + { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL }, #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(name, type, allow_null) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, 0, -1, type, allow_null) #define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \ static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, + { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0)), NULL }, #define ZEND_BEGIN_ARG_INFO(name, _unused) \ ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1) #define ZEND_END_ARG_INFO() }; diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index 78393d28ec..03315d185b 100644 --- a/Zend/zend_builtin_functions_arginfo.h +++ b/Zend/zend_builtin_functions_arginfo.h @@ -39,7 +39,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_define, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, constant_name, IS_STRING, 0) ZEND_ARG_INFO(0, value) - ZEND_ARG_TYPE_INFO(0, case_insensitive, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, case_insensitive, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_defined, 0, 1, _IS_BOOL, 0) @@ -59,10 +59,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_is_subclass_of, 0, 2, _IS_BOOL, 0) ZEND_ARG_INFO(0, object) ZEND_ARG_TYPE_INFO(0, class_name, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, allow_string, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, allow_string, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() -#define arginfo_is_a arginfo_is_subclass_of +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_is_a, 0, 2, _IS_BOOL, 0) + ZEND_ARG_INFO(0, object) + ZEND_ARG_TYPE_INFO(0, class_name, IS_STRING, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, allow_string, _IS_BOOL, 0, "false") +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_get_class_vars, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, class_name, IS_STRING, 0) @@ -90,14 +94,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_exists, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, classname, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, autoload, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, autoload, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() #define arginfo_interface_exists arginfo_class_exists ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_trait_exists, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, traitname, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, autoload, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, autoload, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_function_exists, 0, 1, _IS_BOOL, 0) @@ -107,7 +111,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_alias, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, user_class_name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, alias_name, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, autoload, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, autoload, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() #define arginfo_get_included_files arginfo_func_get_args @@ -116,14 +120,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_trigger_error, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, error_type, IS_LONG, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, error_type, IS_LONG, 0, "E_USER_NOTICE") ZEND_END_ARG_INFO() #define arginfo_user_error arginfo_trigger_error ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1) ZEND_ARG_INFO(0, error_handler) - ZEND_ARG_TYPE_INFO(0, error_types, IS_LONG, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, error_types, IS_LONG, 0, "E_ALL") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_restore_error_handler, 0, 0, _IS_BOOL, 0) @@ -142,7 +146,7 @@ ZEND_END_ARG_INFO() #define arginfo_get_declared_interfaces arginfo_func_get_args ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_defined_functions, 0, 0, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO(0, exclude_disabled, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, exclude_disabled, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() #define arginfo_get_defined_vars arginfo_func_get_args @@ -156,21 +160,21 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_resources, 0, 0, IS_ARRAY, 0 ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_loaded_extensions, 0, 0, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO(0, zend_extensions, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, zend_extensions, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_defined_constants, 0, 0, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO(0, categorize, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, categorize, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_debug_backtrace, 0, 0, IS_ARRAY, 0) - ZEND_ARG_TYPE_INFO(0, options, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, limit, IS_LONG, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_LONG, 0, "DEBUG_BACKTRACE_PROVIDE_OBJECT") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, limit, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_debug_print_backtrace, 0, 0, IS_VOID, 0) - ZEND_ARG_TYPE_INFO(0, options, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, limit, IS_LONG, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, limit, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_extension_loaded, 0, 1, _IS_BOOL, 0) diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index d6ddb0760f..5dd4c39d6a 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -374,12 +374,14 @@ typedef struct _zend_class_constant { typedef struct _zend_internal_arg_info { const char *name; zend_type type; + const char *default_value; } zend_internal_arg_info; /* arg_info for user functions */ typedef struct _zend_arg_info { zend_string *name; zend_type type; + zend_string *default_value; } zend_arg_info; /* the following structure repeats the layout of zend_internal_arg_info, @@ -390,6 +392,7 @@ typedef struct _zend_arg_info { typedef struct _zend_internal_function_info { zend_uintptr_t required_num_args; zend_type type; + const char *default_value; } zend_internal_function_info; struct _zend_op_array { @@ -765,9 +768,13 @@ ZEND_API void function_add_ref(zend_function *function); /* helper functions in zend_language_scanner.l */ +struct _zend_arena; + ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type); ZEND_API zend_op_array *compile_string(zval *source_string, const char *filename); ZEND_API zend_op_array *compile_filename(int type, zval *filename); +ZEND_API zend_ast *zend_compile_string_to_ast( + zend_string *code, struct _zend_arena **ast_arena, const char *filename); ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...); ZEND_API int open_file_for_scanning(zend_file_handle *file_handle); ZEND_API void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size); diff --git a/Zend/zend_exceptions_arginfo.h b/Zend/zend_exceptions_arginfo.h index 93badb6652..b264a925dd 100644 --- a/Zend/zend_exceptions_arginfo.h +++ b/Zend/zend_exceptions_arginfo.h @@ -19,8 +19,8 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Exception___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, code, IS_LONG, 0) - ZEND_ARG_OBJ_INFO(0, previous, Throwable, 1) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, code, IS_LONG, 0, "0") + ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, previous, Throwable, 1, "null") ZEND_END_ARG_INFO() #define arginfo_class_Exception___wakeup arginfo_class_Throwable_getMessage @@ -44,11 +44,11 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ErrorException___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, code, IS_LONG, 0) - ZEND_ARG_TYPE_INFO(0, severity, IS_LONG, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, code, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, severity, IS_LONG, 0, "E_ERROR") ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, lineno, IS_LONG, 0) - ZEND_ARG_OBJ_INFO(0, previous, Throwable, 1) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, lineno, IS_LONG, 0, "0") + ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, previous, Throwable, 1, "null") ZEND_END_ARG_INFO() #define arginfo_class_ErrorException_getSeverity arginfo_class_Throwable_getMessage diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 10e8552b69..5f7f115af4 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -678,7 +678,14 @@ static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function if (i >= required && !ZEND_ARG_IS_VARIADIC(arg_info)) { smart_str_appends(&str, " = "); - if (fptr->type == ZEND_USER_FUNCTION) { + + if (fptr->type == ZEND_INTERNAL_FUNCTION) { + if (((zend_internal_arg_info*)arg_info)->default_value) { + smart_str_appends(&str, ((zend_internal_arg_info*)arg_info)->default_value); + } else { + smart_str_appends(&str, "<default>"); + } + } else { zend_op *precv = NULL; { uint32_t idx = i; @@ -727,8 +734,6 @@ static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function zend_tmp_string_release(tmp_zv_str); } } - } else { - smart_str_appends(&str, "NULL"); } } diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 232ccdf8be..984d73474b 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -653,6 +653,42 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type) return op_array; } +ZEND_API zend_ast *zend_compile_string_to_ast( + zend_string *code, zend_arena **ast_arena, const char *filename) { + zval code_zv; + zend_bool original_in_compilation; + zend_lex_state original_lex_state; + zend_ast *ast; + + ZVAL_STR_COPY(&code_zv, code); + + original_in_compilation = CG(in_compilation); + CG(in_compilation) = 1; + + zend_save_lexical_state(&original_lex_state); + if (zend_prepare_string_for_scanning(&code_zv, filename) == SUCCESS) { + CG(ast) = NULL; + CG(ast_arena) = zend_arena_create(1024 * 32); + LANG_SCNG(yy_state) = yycINITIAL; + + if (zendparse() != 0) { + zend_ast_destroy(CG(ast)); + zend_arena_destroy(CG(ast_arena)); + CG(ast) = NULL; + } + } + + /* restore_lexical_state changes CG(ast) and CG(ast_arena) */ + ast = CG(ast); + *ast_arena = CG(ast_arena); + + zend_restore_lexical_state(&original_lex_state); + CG(in_compilation) = original_in_compilation; + + zval_dtor(&code_zv); + + return ast; +} zend_op_array *compile_filename(int type, zval *filename) { |