Attributes may themselves contain elements which can have a doc comment on
their own (namely Closures). A doc comment before the attribute list is
generally understood as belonging to the symbol having the attributes.
Fixesphp/php-src#20895.
Avoid initializing the same string content multiple times and make use of the
fact that the strings created to initialize attribute values are not freed by
simply making use of an existing zend_string with the same content if one is
available.
This function always returned SUCCESS unconditionally; removing the return type
revealed some impossible code for handling FAILURE that could also be removed.
Instead of
* adding a zval on the stack
* initializing it
* copying the value to the attribute
Just initialize the value directly in the zend_attribute_arg
Only covers constants declared via stub files, others will be handled
separately in a later commit.
Does not include the intl extension, since that had some errors relating to the
cpp code; that extension will be updated separately.
Update to PHP-Parser 5.5.0 and add support for attributes on constants in
stubs. For now, I have only migrated over E_STRICT, once the support is in
place I'll do a larger migration of the existing deprecated constants.
In the process, fix the logic in `copy_zend_constant()` for copying attributes
when a constant is copied; just increase the reference count for the attributes
table rather than trying to duplicate the contents.
This is in preparation for the possible future transformation of `clone` into a
function call, but also meaningful on its own, since the purpose of the tests
is not to test the stack trace generation, but rather that an exception was
thrown. It also cleans up some unreachable code in the tests.
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