Commit: ec061a93c53c8cde10237741e98e992c1a05d148 Author: Nikita Popov <ni...@php.net> Thu, 12 Apr 2012 11:54:52 +0200 Parents: 5852e5f48d7b013108b98b9c57c18383765d21ea Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=ec061a93c53c8cde10237741e98e992c1a05d148 Log: Allow arbitrary expressions for empty() This change is as per RFC https://wiki.php.net/rfc/empty_isset_exprs. The change allows passing the result of function calls and other expressions to the empty() language construct. This is accomplished by simply rewriting empty(expr) to !expr. The change does not affect the suppression of errors when using empty() on variables. empty($undefinedVar) will continue not to throw errors. When an expression is used inside empty() on the other hand, errors will not be suppressed. Thus empty($undefinedVar + $somethingElse) *will* throw a notice. The change also does not make empty() into a real function, so using 'empty' as a callback is still not possible. In addition to the empty() changes the commit adds nicer error messages when isset() is used on function call results or other expressions. Changed paths: M NEWS M UPGRADING A Zend/tests/empty_with_expr.phpt A Zend/tests/isset_expr_error.phpt A Zend/tests/isset_func_error.phpt M Zend/zend_compile.c M Zend/zend_language_parser.y Diff: diff --git a/NEWS b/NEWS index 42c2f83..87ecf08 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,9 @@ PHP NEWS . World domination . Improve set_exception_handler while doing reset.(Laruence) . Support constant array/string dereferencing. (Laruence) + . Add support for using empty() on the result of function calls and + other expressions (https://wiki.php.net/rfc/empty_isset_exprs). + (Nikita Popov) - Core: . Fixed bug #61681 (Malformed grammar). (Nikita Popov, Etienne, Laruence). diff --git a/UPGRADING b/UPGRADING index 27d01cb..0fae614 100755 --- a/UPGRADING +++ b/UPGRADING @@ -28,6 +28,9 @@ PHP X.Y UPGRADE NOTES - Support constant array/string dereferencing. (Laruence) (https://wiki.php.net/rfc/constdereference) +- Add support for using empty() on the result of function calls and + other expressions. Thus it is now possible to write empty(getArray()), + for example. (https://wiki.php.net/rfc/empty_isset_exprs) ======================================== 2. Changes in SAPI modules @@ -51,7 +54,7 @@ PHP X.Y UPGRADE NOTES - Implemented format character "Z": NUL-padded string - "a" now does not remove trailing NUL characters on unpack() anymore - "A" will now strip all trailing ASCII whitespace on unpack() (it used to - remove only trailing spaces. + remove only trailing spaces) ======================================== 5. New Functions diff --git a/Zend/tests/empty_with_expr.phpt b/Zend/tests/empty_with_expr.phpt new file mode 100644 index 0000000..582eb3d --- /dev/null +++ b/Zend/tests/empty_with_expr.phpt @@ -0,0 +1,32 @@ +--TEST-- +empty() with arbitrary expressions +--FILE-- +<?php + +function getEmptyArray() { return []; } +function getNonEmptyArray() { return [1, 2, 3]; } + +var_dump(empty([])); +var_dump(empty([1, 2, 3])); + +var_dump(empty(getEmptyArray())); +var_dump(empty(getNonEmptyArray())); + +var_dump(empty([] + [])); +var_dump(empty([1, 2, 3] + [])); + +var_dump(empty("string")); +var_dump(empty("")); +var_dump(empty(true)); +var_dump(empty(false)); +--EXPECT-- +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) diff --git a/Zend/tests/isset_expr_error.phpt b/Zend/tests/isset_expr_error.phpt new file mode 100644 index 0000000..27fc6cd --- /dev/null +++ b/Zend/tests/isset_expr_error.phpt @@ -0,0 +1,8 @@ +--TEST-- +Error message for isset(func()) +--FILE-- +<?php +isset(1 + 1); +?> +--EXPECTF-- +Fatal error: Cannot use isset() on the result of an expression (you can use "null !== expression" instead) in %s on line %d diff --git a/Zend/tests/isset_func_error.phpt b/Zend/tests/isset_func_error.phpt new file mode 100644 index 0000000..7d1036d --- /dev/null +++ b/Zend/tests/isset_func_error.phpt @@ -0,0 +1,8 @@ +--TEST-- +Error message for isset(func()) +--FILE-- +<?php +isset(abc()); +?> +--EXPECTF-- +Fatal error: Cannot use isset() on the result of a function call (you can use "null !== func()" instead) in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 602b600..37f2dc2 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6089,7 +6089,16 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC zend_do_end_variable_parse(variable, BP_VAR_IS, 0 TSRMLS_CC); - zend_check_writable_variable(variable); + if (zend_is_function_or_method_call(variable)) { + if (type == ZEND_ISEMPTY) { + /* empty(func()) can be transformed to !func() */ + zend_do_unary_op(ZEND_BOOL_NOT, result, variable TSRMLS_CC); + } else { + zend_error(E_COMPILE_ERROR, "Cannot use isset() on the result of a function call (you can use \"null !== func()\" instead)"); + } + + return; + } if (variable->op_type == IS_CV) { last_op = get_next_op(CG(active_op_array) TSRMLS_CC); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 893e013..5a5bb60 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -1158,6 +1158,7 @@ encaps_var_offset: 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_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); } @@ -1166,8 +1167,13 @@ internal_functions_in_yacc: ; isset_variables: - variable { zend_do_isset_or_isempty(ZEND_ISSET, &$$, &$1 TSRMLS_CC); } - | isset_variables ',' { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } variable { znode tmp; zend_do_isset_or_isempty(ZEND_ISSET, &tmp, &$4 TSRMLS_CC); zend_do_boolean_and_end(&$$, &$1, &tmp, &$2 TSRMLS_CC); } + isset_variable { $$ = $1; } + | isset_variables ',' { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } isset_variable { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); } +; + +isset_variable: + variable { zend_do_isset_or_isempty(ZEND_ISSET, &$$, &$1 TSRMLS_CC); } + | expr_without_variable { zend_error(E_COMPILE_ERROR, "Cannot use isset() on the result of an expression (you can use \"null !== expression\" instead)"); } ; class_constant: -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php