{$action . 'JsonAction'}(); } switch (true) { case 1: return foo( function () { $foo = $bar; // when this is removed it works ok return false; // from here on it reports unreachable } ); } for($i=0,$j=50; $i<100; $i++) { while($j--) { if($j==17) { goto end; echo 'unreachable'; } } } switch ($var) { case '1': goto end; echo 'hi'; case '2': case '3': if ($something === true) { goto end; echo 'hi'; } break; default: goto end; if ($something === true) { goto end; echo 'hi'; } } end: echo 'j hit 17'; // Issue 2512. class TestAlternativeControlStructures { public function alternative_switch_in_function( $var ) { switch ( $var ) : case 'value1': do_something(); break; default: case 'value2': do_something_else(); break; endswitch; } public function various_alternative_control_structures() { $_while = 1; for ( $a = 0; $a++ < 1; ) : foreach ( [ 1 ] as $b ) : while ( $_while-- ) : if ( 1 ) : switch ( 1 ) : default: echo 'yay, we made it!'; break; endswitch; endif; endwhile; endforeach; endfor; } } $var_after_class_in_global_space = 1; do_something_else(); // These are parse errors, but that's not the concern of the sniff. function parseError1() { defined('FOO') or return 'foo'; echo 'unreachable'; } function parseError2() { defined('FOO') || continue; echo 'unreachable'; } // All logical operators are allowed with inline expressions (but this was not correctly handled by the sniff). function exitExpressionsWithLogicalOperators() { $condition = false; $condition || \exit(); $condition or die(); $condition = true; $condition && die(); $condition and exit; $condition xor die(); echo 'still executable as exit, in all of the above cases, is used as part of an expression'; } // Inline expressions are allowed in ternaries. function exitExpressionsInTernary() { $value = $myValue ? $myValue : exit(); $value = $myValue ?: exit(); $value = $var == 'foo' ? 'bar' : \die( 'world' ); $value = (!$myValue ) ? exit() : $myValue; $value = $var != 'foo' ? die( 'world' ) : 'bar'; echo 'still executable'; } // Inline expressions are allowed with null coalesce and null coalesce equals. function exitExpressionsWithNullCoalesce() { $value = $nullableValue ?? exit(); $value ??= die(); echo 'still executable'; } // Inline expressions are allowed in arrow functions. function exitExpressionsInArrowFunction() { $callable = fn() => die(); echo 'still executable'; } // PHP 8.0+: throw expressions which don't stop execution. function nonStoppingThrowExpressions() { $callable = fn() => throw new Exception(); $value = $myValue ? 'something' : throw new Exception(); $value = $myValue ?: throw new Exception(); $value = $myValue ? throw new Exception() : 'something'; $value = $nullableValue ?? throw new Exception(); $value ??= throw new Exception(); $condition && throw new Exception(); $condition || throw new Exception(); $condition and throw new Exception(); $condition or throw new Exception(); echo 'still executable as throw, in all of the above cases, is used as part of an expression'; throw new Exception(); echo 'non-executable'; } // PHP 8.0+: throw expressions which do stop execution. function executionStoppingThrowExpressionsA() { $condition xor throw new Exception(); echo 'non-executable'; } function executionStoppingThrowExpressionsB() { throw $userIsAuthorized ? new ForbiddenException() : new UnauthorizedException(); echo 'non-executable'; } function executionStoppingThrowExpressionsC() { throw $condition1 && $condition2 ? new Exception1() : new Exception2(); echo 'non-executable'; } function executionStoppingThrowExpressionsD() { throw $exception ??= new Exception(); echo 'non-executable'; } function executionStoppingThrowExpressionsE() { throw $maybeNullException ?? new Exception(); echo 'non-executable'; } function returnNotRequiredIgnoreCommentsA() { if ($something === TRUE) { return /*comment*/; } echo 'foo'; return /*comment*/; } function returnNotRequiredIgnoreCommentsB() { echo 'foo'; return; /*comment*/ } $closure = function () { echo 'foo'; return; // This return should be flagged as not required. }; function fqnExitWithCodeAfter() { do_something(); exit(); do_something_else(); } function fqnExitInControlStructureWithCodeAfter() { if(do_something()) { die(); do_something_else(); } do_something_else(); }