summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorMáté Kocsis <kocsismate@woohoolabs.com>2020-04-06 11:02:13 +0200
committerMáté Kocsis <kocsismate@woohoolabs.com>2020-04-08 18:37:51 +0200
commit3709e74b5e495e210ada8039ed81fafa9cbadcdb (patch)
treeb7347572b1e22a2a27a45260b4f4773bf916b158 /Zend
parentb0d8f012f95ba1f2d8dba238c93baf3afb73b78e (diff)
downloadphp-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')
-rw-r--r--Zend/tests/argument_restriction_001.phpt2
-rw-r--r--Zend/tests/argument_restriction_003.phpt2
-rw-r--r--Zend/tests/argument_restriction_006.phpt2
-rw-r--r--Zend/tests/bug64988.phpt2
-rw-r--r--Zend/tests/bug70957.phpt2
-rw-r--r--Zend/tests/bug71428.1.phpt2
-rw-r--r--Zend/tests/bug73987.phpt2
-rw-r--r--Zend/tests/bug73987_2.phpt2
-rw-r--r--Zend/tests/closures/closure_from_callable_basic.phpt4
-rw-r--r--Zend/tests/parameter_default_values/internal_declaration_error_class_const.phpt12
-rw-r--r--Zend/tests/parameter_default_values/internal_declaration_error_const.phpt12
-rw-r--r--Zend/tests/parameter_default_values/internal_declaration_error_false.phpt11
-rw-r--r--Zend/tests/parameter_default_values/internal_declaration_error_int.phpt12
-rw-r--r--Zend/tests/parameter_default_values/internal_declaration_error_null.phpt12
-rw-r--r--Zend/tests/parameter_default_values/userland_declaration_error_class_const.phpt25
-rw-r--r--Zend/tests/parameter_default_values/userland_declaration_error_const.phpt25
-rw-r--r--Zend/tests/type_declarations/variance/internal_parent.phpt2
-rw-r--r--Zend/zend_API.h49
-rw-r--r--Zend/zend_builtin_functions_arginfo.h34
-rw-r--r--Zend/zend_compile.h7
-rw-r--r--Zend/zend_exceptions_arginfo.h12
-rw-r--r--Zend/zend_inheritance.c11
-rw-r--r--Zend/zend_language_scanner.l36
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)
{