Permalink
Browse files

unset() now returns a boolean

The __unset() magic method may return a value which is, casted to boolean, returned by unset()
The class functions unset_dimension and unset_property are now changed to return an int: the return value should be SUCCESS or FAILURE
1 parent 7e5f761 commit 787d71eed0c5e0140048b8fbacf799029b322661 @bwoebi committed Mar 6, 2013
View
@@ -509,7 +509,7 @@ ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci
ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...);
-ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, const char *name, int name_len, ulong hash_value TSRMLS_DC);
+ZEND_API int zend_delete_variable(zend_execute_data *ex, HashTable *ht, const char *name, int name_len, ulong hash_value TSRMLS_DC);
ZEND_API int zend_delete_global_variable(const char *name, int name_len TSRMLS_DC);
View
@@ -228,9 +228,10 @@ static int zend_closure_has_property(zval *object, zval *member, int has_set_exi
}
/* }}} */
-static void zend_closure_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
+static int zend_closure_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
ZEND_CLOSURE_PROPERTY_ERROR();
+ return FAILURE;
}
/* }}} */
View
@@ -6100,37 +6100,39 @@ void zend_do_indirect_references(znode *result, const znode *num_references, zno
}
/* }}} */
-void zend_do_unset(const znode *variable TSRMLS_DC) /* {{{ */
+void zend_do_unset(znode *result, const znode *variable TSRMLS_DC) /* {{{ */
{
zend_op *last_op;
- zend_check_writable_variable(variable);
+// zend_check_writable_variable(variable);
+ zend_do_end_variable_parse(variable, BP_VAR_UNSET, 0 TSRMLS_CC);
if (variable->op_type == IS_CV) {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_UNSET_VAR;
SET_NODE(opline->op1, variable);
SET_UNUSED(opline->op2);
- SET_UNUSED(opline->result);
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_TMP_VAR;
opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
+ GET_NODE(result, opline->result);
} else {
last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
+ last_op->result_type = IS_TMP_VAR;
switch (last_op->opcode) {
case ZEND_FETCH_UNSET:
last_op->opcode = ZEND_UNSET_VAR;
- SET_UNUSED(last_op->result);
break;
case ZEND_FETCH_DIM_UNSET:
last_op->opcode = ZEND_UNSET_DIM;
- SET_UNUSED(last_op->result);
break;
case ZEND_FETCH_OBJ_UNSET:
last_op->opcode = ZEND_UNSET_OBJ;
- SET_UNUSED(last_op->result);
break;
}
+ GET_NODE(result, last_op->result);
}
}
/* }}} */
View
@@ -74,7 +74,7 @@ typedef struct _zend_literal {
#define Z_HASH_P(zv) \
(((zend_literal*)(zv))->hash_value)
-typedef union _znode_op {
+typedef union _znode_op {
zend_uint constant;
zend_uint var;
zend_uint num;
@@ -86,7 +86,7 @@ typedef union _znode_op {
void *ptr; /* Used for passing pointers from the compile to execution phase, currently used for traits */
} znode_op;
-typedef struct _znode { /* used only during compilation */
+typedef struct _znode { /* used only during compilation */
int op_type;
union {
znode_op op;
@@ -597,7 +597,7 @@ void zend_add_to_list(void *result, void *item TSRMLS_DC);
void zend_do_cast(znode *result, const znode *expr, int type TSRMLS_DC);
void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC);
-void zend_do_unset(const znode *variable TSRMLS_DC);
+void zend_do_unset(znode *result, const znode *variable TSRMLS_DC);
void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC);
void zend_do_instanceof(znode *result, const znode *expr, const znode *class_znode, int type TSRMLS_DC);
View
@@ -1676,7 +1676,7 @@ ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC) /* {{{ */
}
/* }}} */
-ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, const char *name, int name_len, ulong hash_value TSRMLS_DC) /* {{{ */
+ZEND_API int zend_delete_variable(zend_execute_data *ex, HashTable *ht, const char *name, int name_len, ulong hash_value TSRMLS_DC) /* {{{ */
{
if (zend_hash_quick_del(ht, name, name_len, hash_value) == SUCCESS) {
name_len--;
@@ -1695,7 +1695,9 @@ ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, const c
}
ex = ex->prev_execute_data;
}
+ return SUCCESS;
}
+ return FAILURE;
}
/* }}} */
@@ -306,7 +306,6 @@ unticked_statement:
| T_ECHO echo_expr_list ';'
| T_INLINE_HTML { zend_do_echo(&$1 TSRMLS_CC); }
| expr ';' { zend_do_free(&$1 TSRMLS_CC); }
- | T_UNSET '(' unset_variables ')' ';'
| T_FOREACH '(' variable T_AS
{ zend_do_foreach_begin(&$1, &$2, &$3, &$4, 1 TSRMLS_CC); }
foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
@@ -352,12 +351,13 @@ additional_catch:
;
unset_variables:
- unset_variable
- | unset_variables ',' unset_variable
+ unset_variable { $$ = $1; }
+ | unset_variables ',' { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } unset_variable { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
;
unset_variable:
- variable { zend_do_end_variable_parse(&$1, BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); }
+ variable { zend_do_unset(&$$, &$1 TSRMLS_CC); }
+ | expr_without_variable { zend_error(E_COMPILE_ERROR, "Cannot use unset() on the result of an expression, only on variables"); }
;
function_declaration_statement:
@@ -1180,6 +1180,7 @@ internal_functions_in_yacc:
T_ISSET '(' isset_variables ')' { $$ = $3; }
| T_EMPTY '(' variable ')' { zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); }
| T_EMPTY '(' expr_without_variable ')' { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$3 TSRMLS_CC); }
+ | T_UNSET '(' unset_variables ')' { $$ = $3; }
| T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); }
| T_INCLUDE_ONCE expr { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); }
| T_EVAL '(' expr ')' { zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); }
@@ -197,7 +197,7 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D
}
/* }}} */
-static void zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static int zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC) /* {{{ */
{
zend_class_entry *ce = Z_OBJCE_P(object);
@@ -207,9 +207,12 @@ static void zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC) /* {{{
SEPARATE_ARG_IF_REF(member);
- zend_call_method_with_1_params(&object, ce, &ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member);
+ zval *ret_zval = zend_call_method_with_1_params(&object, ce, &ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member);
zval_ptr_dtor(&member);
+
+ convert_to_boolean(ret_zval);
+ return Z_LVAL_P(ret_zval)?SUCCESS:FAILURE;
}
/* }}} */
@@ -786,11 +789,12 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, const ze
}
/* }}} */
-static void zend_std_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
+static int zend_std_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
zend_object *zobj;
zval *tmp_member = NULL;
zend_property_info *property_info;
+ int result = FAILURE;
zobj = Z_OBJ_P(object);
@@ -813,9 +817,10 @@ static void zend_std_unset_property(zval *object, zval *member, const zend_liter
EXPECTED(zobj->properties_table[property_info->offset] != NULL)) {
zval_ptr_dtor(&zobj->properties_table[property_info->offset]);
zobj->properties_table[property_info->offset] = NULL;
+ result = SUCCESS;
} else if (UNEXPECTED(!property_info) ||
!zobj->properties ||
- UNEXPECTED(zend_hash_quick_del(zobj->properties, property_info->name, property_info->name_length+1, property_info->h) == FAILURE)) {
+ UNEXPECTED((result = zend_hash_quick_del(zobj->properties, property_info->name, property_info->name_length+1, property_info->h)) == FAILURE)) {
zend_guard *guard = NULL;
if (zobj->ce->__unset &&
@@ -827,7 +832,7 @@ static void zend_std_unset_property(zval *object, zval *member, const zend_liter
SEPARATE_ZVAL(&object);
}
guard->in_unset = 1; /* prevent circular unsetting */
- zend_std_call_unsetter(object, member TSRMLS_CC);
+ result = zend_std_call_unsetter(object, member TSRMLS_CC);
guard->in_unset = 0;
zval_ptr_dtor(&object);
} else if (zobj->ce->__unset && guard && guard->in_unset == 1) {
@@ -838,30 +843,37 @@ static void zend_std_unset_property(zval *object, zval *member, const zend_liter
zend_error(E_ERROR, "Cannot access property started with '\\0'");
}
}
+ result = FAILURE;
}
} else if (EXPECTED(property_info != NULL) &&
EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
property_info->offset >= 0) {
zobj->properties_table[property_info->offset] = NULL;
+ result = SUCCESS;
}
if (UNEXPECTED(tmp_member != NULL)) {
zval_ptr_dtor(&tmp_member);
}
+
+ return result;
}
/* }}} */
-static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{{ */
+static int zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{{ */
{
zend_class_entry *ce = Z_OBJCE_P(object);
if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
SEPARATE_ARG_IF_REF(offset);
- zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", NULL, offset);
+ zval *ret_zval = zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", NULL, offset);
zval_ptr_dtor(&offset);
- } else {
- zend_error_noreturn(E_ERROR, "Cannot use object of type %s as array", ce->name);
+ convert_to_boolean(ret_zval);
+ return Z_LVAL_P(ret_zval)?SUCCESS:FAILURE;
}
+
+ zend_error_noreturn(E_ERROR, "Cannot use object of type %s as array", ce->name);
+ return FAILURE;
}
/* }}} */
@@ -73,10 +73,10 @@ typedef int (*zend_object_has_property_t)(zval *object, zval *member, int has_se
typedef int (*zend_object_has_dimension_t)(zval *object, zval *member, int check_empty TSRMLS_DC);
/* Used to remove a property of the object */
-typedef void (*zend_object_unset_property_t)(zval *object, zval *member, const struct _zend_literal *key TSRMLS_DC);
+typedef int (*zend_object_unset_property_t)(zval *object, zval *member, const struct _zend_literal *key TSRMLS_DC);
/* Used to remove a dimension of the object */
-typedef void (*zend_object_unset_dimension_t)(zval *object, zval *offset TSRMLS_DC);
+typedef int (*zend_object_unset_dimension_t)(zval *object, zval *offset TSRMLS_DC);
/* Used to get hash of the properties of the object, as hash of zval's */
typedef HashTable *(*zend_object_get_properties_t)(zval *object TSRMLS_DC);
Oops, something went wrong.

0 comments on commit 787d71e

Please sign in to comment.