diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-01-07 12:28:51 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-01-11 15:49:06 +0100 |
commit | e219ec144ef6682b71e135fd18654ee1bb4676b4 (patch) | |
tree | e4a3ae2b619cdc9fe50ee8e1fa5adb99d804dddf /Zend/zend_API.h | |
parent | fe8fdfa3bd588d80ce60f6b3848058239e0a760f (diff) | |
download | php-git-e219ec144ef6682b71e135fd18654ee1bb4676b4.tar.gz |
Implement typed properties
RFC: https://wiki.php.net/rfc/typed_properties_v2
This is a squash of PR #3734, which is a squash of PR #3313.
Co-authored-by: Bob Weinand <bobwei9@hotmail.com>
Co-authored-by: Joe Watkins <krakjoe@php.net>
Co-authored-by: Dmitry Stogov <dmitry@zend.com>
Diffstat (limited to 'Zend/zend_API.h')
-rw-r--r-- | Zend/zend_API.h | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 2357a1a49d..27fc6cb011 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -309,6 +309,9 @@ ZEND_API zend_bool zend_is_callable(zval *callable, uint32_t check_flags, zend_s ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_name); ZEND_API const char *zend_get_module_version(const char *module_name); ZEND_API int zend_get_module_started(const char *module_name); + +ZEND_API int zend_declare_typed_property(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment, zend_type type); + ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment); ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type); ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type); @@ -653,6 +656,134 @@ END_EXTERN_C() #define ZEND_GINIT_FUNCTION ZEND_MODULE_GLOBALS_CTOR_D #define ZEND_GSHUTDOWN_FUNCTION ZEND_MODULE_GLOBALS_DTOR_D +/* May modify arg in-place. Will free arg in failure case (and take ownership in success case). + * Prefer using the ZEND_TRY_ASSIGN_* macros over these APIs. */ +static zend_always_inline int zend_try_assign_ex(zval *zv, zval *arg, zend_bool strict) { + if (EXPECTED(Z_ISREF_P(zv))) { + zend_reference *ref = Z_REF_P(zv); + zv = Z_REFVAL_P(zv); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref)) && + UNEXPECTED(!zend_verify_ref_assignable_zval(ref, arg, strict)) + ) { + zval_ptr_dtor(arg); + return FAILURE; + } + } + + zval_ptr_dtor(zv); + ZVAL_COPY_VALUE(zv, arg); + return SUCCESS; +} + +static zend_always_inline int zend_try_assign(zval *zv, zval *arg) { + return zend_try_assign_ex(zv, arg, ZEND_ARG_USES_STRICT_TYPES()); +} + +#define ZEND_TRY_ASSIGN_NULL(zv) do { \ + zval _zv; \ + ZVAL_NULL(&_zv); \ + zend_try_assign(zv, &_zv); \ +} while (0) + +#define ZEND_TRY_ASSIGN_FALSE(zv) do { \ + zval _zv; \ + ZVAL_FALSE(&_zv); \ + zend_try_assign(zv, &_zv); \ +} while (0) + +#define ZEND_TRY_ASSIGN_TRUE(zv) do { \ + zval _zv; \ + ZVAL_TRUE(&_zv); \ + zend_try_assign(zv, &_zv); \ +} while (0) + +#define ZEND_TRY_ASSIGN_LONG(zv, lval) do { \ + zval _zv; \ + ZVAL_LONG(&_zv, lval); \ + zend_try_assign(zv, &_zv); \ +} while (0) + +#define ZEND_TRY_ASSIGN_DOUBLE(zv, dval) do { \ + zval _zv; \ + ZVAL_DOUBLE(&_zv, dval); \ + zend_try_assign(zv, &_zv); \ +} while (0) + +#define ZEND_TRY_ASSIGN_EMPTY_STRING(zv) do { \ + zval _zv; \ + ZVAL_EMPTY_STRING(&_zv); \ + zend_try_assign(zv, &_zv); \ +} while (0) + +#define ZEND_TRY_ASSIGN_STR(zv, str) do { \ + zval _zv; \ + ZVAL_STR(&_zv, str); \ + zend_try_assign(zv, &_zv); \ +} while (0) + +#define ZEND_TRY_ASSIGN_NEW_STR(zv, str) do { \ + zval _zv; \ + ZVAL_NEW_STR(&_zv, str); \ + zend_try_assign(zv, &_zv); \ +} while (0) + +#define ZEND_TRY_ASSIGN_STRING(zv, string) do { \ + zval _zv; \ + ZVAL_STRING(&_zv, string); \ + zend_try_assign(zv, &_zv); \ +} while (0) + +#define ZEND_TRY_ASSIGN_STRINGL(zv, string, len) do { \ + zval _zv; \ + ZVAL_STRINGL(&_zv, string, len); \ + zend_try_assign(zv, &_zv); \ +} while (0) + +#define ZEND_TRY_ASSIGN_RES(zv, res) do { \ + zval _zv; \ + ZVAL_RES(&_zv, res); \ + zend_try_assign(zv, &_zv); \ +} while (0) + +#define ZEND_TRY_ASSIGN_VALUE_EX(zv, other_zv, strict) do { \ + zval _zv; \ + ZVAL_COPY_VALUE(&_zv, other_zv); \ + zend_try_assign_ex(zv, &_zv, strict); \ +} while (0) + +#define ZEND_TRY_ASSIGN_COPY_EX(zv, other_zv, strict) do { \ + zval _zv; \ + ZVAL_COPY(&_zv, other_zv); \ + zend_try_assign_ex(zv, &_zv, strict); \ +} while (0) + +#define ZEND_TRY_ASSIGN_VALUE(zv, other_zv) \ + ZEND_TRY_ASSIGN_VALUE_EX(zv, other_zv, ZEND_ARG_USES_STRICT_TYPES()) +#define ZEND_TRY_ASSIGN_COPY(zv, other_zv) \ + ZEND_TRY_ASSIGN_COPY_EX(zv, other_zv, ZEND_ARG_USES_STRICT_TYPES()) + +/* Initializes a reference to an empty array and returns dereferenced zval, + * or NULL if the initialization failed. */ +static zend_always_inline zval *zend_try_array_init(zval *zv) { + zval tmp; + ZVAL_ARR(&tmp, zend_new_array(0)); + if (UNEXPECTED(zend_try_assign(zv, &tmp) == FAILURE)) { + return NULL; + } + ZVAL_DEREF(zv); + return zv; +} + +static zend_always_inline zval *zend_try_array_init_size(zval *zv, size_t size) { + zval tmp; + ZVAL_ARR(&tmp, zend_new_array(size)); + if (UNEXPECTED(zend_try_assign(zv, &tmp) == FAILURE)) { + return NULL; + } + ZVAL_DEREF(zv); + return zv; +} + /* Fast parameter parsing API */ /* Fast ZPP is always enabled now; this define is left in for compatibility |