|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2020-10-04 12:58 UTC] jelly dot legend at gmail dot com
Description:
------------
If a use a complex expression as an if condition or while condition, it incorrectly resolves to false. While it correctly evaluates it if passed to a variable and printed.
PHP version:
PHP 8.0.0rc1 (cli) (built: Oct 4 2020 13:58:56) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies
with Zend OPcache v8.0.0rc1, Copyright (c), by Zend Technologies
php.development-ini changes:
zend_extension=opcache
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
If I disable opcache I get the correct results.
PHP was built from source. With following configuration.
./configure \
--prefix=.../php-8.0.0rc1 \
--with-config-file-path=.../php-8.0.0rc1/etc \
--enable-mbstring \
--enable-sockets \
--enable-opcache \
--with-openssl=/usr/local/openssl \
--with-curl \
--with-sodium \
--with-bz2 \
--with-zlib \
--with-zip
I was first noticed the bug on beta-4 but decided to try it out in rc-1 instead.
Test script:
---------------
$factory = function (string $msg): Closure {
return function () use ($msg): void {
echo $msg;
};
};
$callbacks = [
$factory('First item!'),
$factory('Second item!'),
$factory('Third item!'),
$factory('Fourth item!'),
];
$nl = function (): void {
echo PHP_EOL;
};
while ((null !== $callback = array_shift($callbacks)) && ($callback() || $nl() || true))
/**/; // exists after first item, should iterate thought all
// Full test at: https://pastebin.com/br54nGvM
Expected result:
----------------
First item!
Second item!
Third item!
Fourth item!
Actual result:
--------------
First item!
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Oct 27 03:00:02 2025 UTC |
Also happens with opcache.jit=0, so generic optimization issue. Slightly reduced by Dharman: <?php $callbacks = [ function () { echo "First item!\n"; }, function () { echo "Second item!\n"; }, function () { echo "Third item!\n"; }, function () { echo "Fourth item!\n"; }, ]; while ($callback = array_shift($callbacks) and $callback() || true); This iterates once instead of multiple times.Culprit is the block pass: $_main: ; (lines=22, args=0, vars=2, tmps=10) ; (before block pass) ; /home/nikic/php/php-src/t170.php:1-11 ; return [] RANGE[0..0] BB0: ; start lines=[0-9] ; to=(BB1) 0000 T2 = DECLARE_LAMBDA_FUNCTION string("") 0001 T3 = INIT_ARRAY 4 (packed) T2 NEXT 0002 T4 = DECLARE_LAMBDA_FUNCTION string("") 0003 T3 = ADD_ARRAY_ELEMENT T4 NEXT 0004 T5 = DECLARE_LAMBDA_FUNCTION string("") 0005 T3 = ADD_ARRAY_ELEMENT T5 NEXT 0006 T6 = DECLARE_LAMBDA_FUNCTION string("") 0007 T3 = ADD_ARRAY_ELEMENT T6 NEXT 0008 ASSIGN CV0($callbacks) T3 0009 NOP BB1: ; follow target lines=[10-14] ; to=(BB4, BB2) 0010 INIT_FCALL 1 96 string("array_shift") 0011 SEND_REF CV0($callbacks) 1 0012 V8 = DO_ICALL 0013 T9 = ASSIGN CV1($callback) V8 0014 T9 = JMPZ_EX T9 BB4 BB2: ; follow lines=[15-17] ; to=(BB1, BB3) 0015 INIT_DYNAMIC_CALL 0 CV1($callback) 0016 V10 = DO_FCALL 0017 T9 = JMPNZ_EX V10 BB1 BB3: ; follow lines=[18-20] ; to=(BB1, BB4) 0018 T11 = BOOL bool(true) 0019 T9 = BOOL T11 0020 JMPNZ T9 BB1 BB4: ; follow target exit lines=[21-21] 0021 RETURN int(1) $_main: ; (lines=17, args=0, vars=2, tmps=10) ; (after block pass) ; /home/nikic/php/php-src/t170.php:1-11 ; return [] RANGE[0..0] BB0: ; start lines=[0-13] ; to=(BB4, BB2) 0000 T2 = DECLARE_LAMBDA_FUNCTION string("") 0001 T3 = INIT_ARRAY 4 (packed) T2 NEXT 0002 T4 = DECLARE_LAMBDA_FUNCTION string("") 0003 T3 = ADD_ARRAY_ELEMENT T4 NEXT 0004 T5 = DECLARE_LAMBDA_FUNCTION string("") 0005 T3 = ADD_ARRAY_ELEMENT T5 NEXT 0006 T6 = DECLARE_LAMBDA_FUNCTION string("") 0007 T3 = ADD_ARRAY_ELEMENT T6 NEXT 0008 ASSIGN CV0($callbacks) T3 0009 INIT_FCALL 1 96 string("array_shift") 0010 SEND_REF CV0($callbacks) 1 0011 V8 = DO_ICALL 0012 T9 = ASSIGN CV1($callback) V8 0013 JMPZ T9 BB4 BB1: ; follow exit empty BB2: ; follow lines=[14-15] ; to=(BB1) 0014 INIT_DYNAMIC_CALL 0 CV1($callback) 0015 DO_FCALL BB4: ; target exit lines=[16-16] 0016 RETURN int(1) These are clearly not the same.