Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Allow arbitrary expressions for empty() #54

Merged
merged 1 commit into from

3 participants

Nikita Popov Linus Unnebäck Account for PHP Pull Requests
Linus Unnebäck

I think that this is a great idea, thank you for taking the time to implement it!

Nikita Popov nikic 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.
ec061a9
Account for PHP Pull Requests php-pulls merged commit ec061a9 into from
Account for PHP Pull Requests
Collaborator

Comment on behalf of stas at php.net:

merged to master, thanks

Account for PHP Pull Requests
Collaborator

Comment on behalf of stas at php.net:

merged to master, thanks

Account for PHP Pull Requests php-pulls referenced this pull request from a commit
Dmitry Stogov dstogov Merge branch 'PHP-5.5'
* PHP-5.5: (101 commits)
  Renamed ZendOptimizerPlus.so into opcache.so
  "ZendOptimizerPlus" is renamed to "opcache" to de merged into PHP-5.5 under ext/opcache (the product name is still "Zend Optimizer+")
  More accurate restart scheduling
  Autogolobal $GLOBALS has to be pinged even if auto_globals_jit=0
  Allow only shared O+ build
  Fixed typos
  add tests into package
  Add test script for #57 (segfaults in drupal7)
  fixed memory leaks
  Fixed Issue #57 (segfaults in drupal7)
  Fixed issue #58 (PHP-5.2 compatibility)
  Allows exclusion of large files from being cached
  Add maintainers inot package.xml
  fix ANSI C90 compat
  Fixed test
  Fixed uninitialized variable
  Fixed bug #64353 (Built-in classes can be unavailable with dynamic includes and Optimizer+)
  Save a stat() call by calling sapi_module.get_stat()
  Fixed #54 (PECL install adds extension= instead of zend_extension= to php.ini)
  release 7.0.0
  ...
29a9e13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 13, 2012
  1. Nikita Popov

    Allow arbitrary expressions for empty()

    nikic authored
    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.
This page is out of date. Refresh to see the latest.
3  NEWS
View
@@ -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).
5 UPGRADING
View
@@ -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
32 Zend/tests/empty_with_expr.phpt
View
@@ -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)
8 Zend/tests/isset_expr_error.phpt
View
@@ -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
8 Zend/tests/isset_func_error.phpt
View
@@ -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
11 Zend/zend_compile.c
View
@@ -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);
10 Zend/zend_language_parser.y
View
@@ -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:
Something went wrong with that request. Please try again.