Update gen_stubs.php to generate C enums from internal enums, when the stub is annotated with @generate-c-enums. Enum values can be compared to the result of zend_enum_fetch_case_id(zend_object*).
The generated enums are added to separate files named {$extensionName}_decl.h, so that it's possible to include these from anywhere. _arginfo.h files would generate warnings if we tried to include them in a compilation unit that doesn't call the register_{$class} functions, for instance.
Introduce Z_PARAM_ENUM().
* Make ZEND_AST_CONST_ENUM_INIT a 4-children node
* Store enum case id in ZEND_AST_CONST_ENUM_INIT
* Store enum case id in instance
* Expose enum case_id internally
* Generate C enum for internal enums
* Introduce Z_PARAM_ENUM()
* Port extensions
The arg_info member of zend_function is now always a zend_arg_info*. Before,
it was a zend_internal_arg_info* on internal functions, unless the
ZEND_ACC_USER_ARG_INFO flag was set.
Closes GH-19022
Since the executor needs to be active at this point, the only way you
could get an UNDEF return value is by having an exception.
Therefore, `!EG(exception)` is always false.
The check doesn't make sense, remove it.
This function always returned SUCCESS unconditionally; removing the return type
revealed some impossible code for handling FAILURE that could also be removed.
The motivation for this is that types should be considered immutable.
The only times this is not valid is during compilation, optimizations (opcache), or destruction.
Therefore the "normal" type foreach macros are marked to take const arguments and we add mutable version that say so in the name.
Thus add various const qualifiers to communicate intent.
- When appending a single character to the string, use `smart_str_appendc()`
- When appending a C-string without printf use, use `smart_str_appends()`
- When appending just a `zend_string`, use `smart_str_append()`
While internally enums are mostly the same as classes, their output in
`ReflectionClass::__toString()` should show the enum as the developer wrote it,
rather than as the engine stored it. Accordingly
- Say that the enum is an enum, not a final class
- Include the backing type, if any, in the declaration line
- List enum cases separately from constants, and show the underlying values, if
any
GH-15766
Add "final" and "abstract" to the result of `_property_string()` when
outputting the string representation of a `ReflectionClass` or
`ReflectionProperty` instance
Closes GH-17827
When a property default is based on a global constant, show the type of the
default. Previously, `format_default_value()` assumed that non-scalar and
non-array defaults were always going to be `IS_CONSTANT_AST` pointers, and when
the AST expression had been evaluated and produced an object, depending on when
the `ReflectionClass` or `ReflectionProperty` instance had been created, the
default was shown as one of `callable` or `__CLASS__`.
Instead, if the default value is an object (`IS_OBJECT`), show the type of that
object.
Add test cases for both of the `callable` and `__CLASS__` cases to confirm that
they now properly show the type of the constant.
Closes GH-15902.
Closes GH-17781.
Apply the following changes to ReflectionProperty::getValue(), ::getRawValue(), ::isInitialized(), ::setValue(), ::setRawValue():
- Pass a cache slot to the property handler
- Inline the simple case of fetching a declared property
- Use the new parameter parsing API
This results in run time decrease of 12% to 59% in [micro benchmarks](https://gist.github.com/arnaud-lb/2de08142dcd0c7b49caed21398f44656), when executed with `hyperfine -L version base,opt "/tmp/{version}/sapi/cli/php -d opcache.enable_cli=1 $script"`:
```
get-raw-value.php: -58%
get-value-dyn.php: -50%
get-value-hook.php: -47%
get-value.php: -59%
is-initialized.php: -59%
set-value.php: -11%
```
And a 1.8% decrease in this Doctrine benchmark: 505825290d...reflection-property-get-value-opt
When the `zend_class_entry` has a `zend_function` entry for `clone`, the logic
is the same regardless of if the `reflection_object` entry has an object or
not; the determination is based solely on the flags of the `zend_function`.
`new Reflectionproperty($scope, $propName)` keeps a reference to the
zend_property_info of $propName declared in $scope. In getRawValue() and
related methods, we use this reference to check whether the property is hooked.
Calling `new ReflectionProperty($scope, $propName)->getRawValue($object)` is
equivalent to the expression $object->$propName from scope $scope (except that
it bypasses hooks), and thus may access an overridden property (unless the
original is private). This property may have hooks and different flags.
Here I fetch the effective property info before checking for hooks and
property flags.
Fixes GH-17713
Closes GH-17714
Normally, accesses to properties marked as lazy trigger the object's
initialization, or forward to a real instance if the object is an initialized
proxy.
The purpose of ReflectionProperty::setRawValueWithoutLazyInitialization() and
ReflectionProperty::skipLazyInitialization() is to bypass auto-initialization,
so that some properties can be initialized without triggering initialization.
However, when the object is an initialized proxy, these methods would
unexpectedly update the proxy.
Here I make sure that these methods have an effect on the real instance, when
the object is an initialized proxy.
Fixes GH-16344
Since the return value is never used, the only difference between using this
method and using `object_init_ex()` directly is the flipped order of
parameters, and the added level of indirection - remove that level of
indirection by replacing its uses.
Additionally fixes wrong behaviour in ReflectionParameter when you first
have a construction that uses an object and the subsequent doesn't.
Closes GH-16672.
Allow determining the name of the file that defined a constant, when the
constant was defined in userland code via const or define(). For constants
defined by PHP core or extensions, false is returned, matching the existing
getFileName() methods on other reflection classes.
Fixes GH-15723
Closes GH-15847