Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: add a page about zend_attribute #18122

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/source/core/data-structures/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
reference-counting
zend_string
zend_constant
zend_attribute

This section provides an overview of the core data structures used in php-src.
88 changes: 88 additions & 0 deletions docs/source/core/data-structures/zend_attribute.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
################
zend_attribute
################

PHP attributes are stored in a dedicated structure ``zend_attribute``, which holds details of
attributes.

************
definition
************

.. code:: c

typedef struct _zend_attribute {
zend_string *name;
zend_string *lcname;
uint32_t flags;
uint32_t lineno;
/* Parameter offsets start at 1, everything else uses 0. */
uint32_t offset;
uint32_t argc;
zend_attribute_arg args[1];
} zend_attribute;

Broadly, the attribute holds

- the name of the attribute (``name``, ``lcname``)
- metadata about the attribute (``flags``)
- metadata about the attribute usage (``lineno``, ``offset``)
- details of arguments (``argc``, ``args``)

******
name
******

The name of the attribute is stored in the :doc:`./zend_string` ``name``. To make case-insensitive
comparisons easier, a lowercase version of the name is also saved in the :doc:`./zend_string`
``lcname``.

*******
flags
*******

The ``flags`` field holds metadata about the internal details of how the attribute should be used.
The flags are made from

.. code:: c

#define ZEND_ATTRIBUTE_PERSISTENT (1<<0)
#define ZEND_ATTRIBUTE_STRICT_TYPES (1<<1)

And are *not* the same as the flags in ``Attribute::$flags``.

**********
metadata
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The metadata and filename titles look wrong.

**********

The ``name`` holds a :doc:`zend_string` with the name of the constant, to allow searching for
constants that have already been defined. This string is released when the constant itself is freed.

**********
filename
**********

The ``lineno`` field holds the line number that the attribute is used on, for use in error messages.

The ``offset`` field is only used for attributes on parameters, and indicates *which* parameter the
attribute is applied to (since the attributes for a function's parameters are all stored together).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe mention that function attributes have offset 0, while args have offset 1+.


***********
arguments
***********

The number of arguments that are passed to the attribute is stored in the ``argc`` field. But, since
attributes support the use of named parameters, storing just the parameters that were used is not
enough, the parameter names need to be stored too.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe mention that value may contain constant expressions that are evaluated when creating an instance of the attribute. Meaning if you have #[MyAttr(new Foo)], new Foo will be performed for every $reflectionAttr->newInstance().


Those are stored in ``zend_attribute_arg`` objects:

.. code:: c

typedef struct {
zend_string *name;
zval value;
} zend_attribute_arg;

Where the ``name`` field stores the name used, and the :doc:`./zval` ``value`` field stores the
value.