@@ -316,6 +316,54 @@ static inline bool can_elide_return_type_check(
316316 return false;
317317}
318318
319+ static inline bool can_return_value_safely_be_coerced (
320+ const zend_op_array * op_array , const zend_ssa * ssa , const zend_ssa_op * ssa_op , zend_op * opline
321+ ) {
322+ const uint32_t return_type_mask = ZEND_TYPE_FULL_MASK (op_array -> arg_info [-1 ].type );
323+ const zend_ssa_var_info * use_info = & ssa -> var_info [ssa_op -> op1_use ];
324+
325+ /* Type preference order: int -> float -> string -> bool */
326+ /* Can always safely cast booleans to inter */
327+ if (return_type_mask & MAY_BE_LONG ) {
328+ if (use_info -> type & MAY_BE_BOOL ) {
329+ opline -> opcode = ZEND_CAST_VALUE_FOR_RETURN_TYPE ;
330+ opline -> extended_value = IS_LONG ;
331+ return true;
332+ }
333+ return false;
334+ }
335+ if (return_type_mask & MAY_BE_DOUBLE ) {
336+ /* Can always safely cast booleans, and integers to float */
337+ if (use_info -> type & (MAY_BE_LONG |MAY_BE_BOOL )) {
338+ opline -> opcode = ZEND_CAST_VALUE_FOR_RETURN_TYPE ;
339+ opline -> extended_value = IS_DOUBLE ;
340+ return true;
341+ }
342+ return false;
343+ }
344+ /* Can always safely cast booleans, and integers to string,
345+ * float value must not be NAN */
346+ if (return_type_mask & MAY_BE_STRING ) {
347+ if (use_info -> type & (MAY_BE_LONG |MAY_BE_BOOL )) {
348+ opline -> opcode = ZEND_CAST_VALUE_FOR_RETURN_TYPE ;
349+ opline -> extended_value = IS_STRING ;
350+ return true;
351+ }
352+ return false;
353+ }
354+ return false;
355+ if ((return_type_mask & MAY_BE_BOOL ) == MAY_BE_BOOL ) {
356+ /* Can always safely cast integers and strings to bool,
357+ * float value must not be NAN */
358+ if (use_info -> type & (MAY_BE_LONG |MAY_BE_STRING )) {
359+ opline -> opcode = ZEND_CAST_VALUE_FOR_RETURN_TYPE ;
360+ opline -> extended_value = IS_FALSE ;
361+ return true;
362+ }
363+ return false;
364+ }
365+ }
366+
319367static bool opline_supports_assign_contraction (
320368 zend_op_array * op_array , zend_ssa * ssa , zend_op * opline , int src_var , uint32_t cv_var ) {
321369 if (opline -> opcode == ZEND_NEW ) {
@@ -1287,6 +1335,8 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
12871335
12881336 MAKE_NOP (opline );
12891337 remove_nops = 1 ;
1338+ } else if (can_return_value_safely_be_coerced (op_array , ssa , & ssa -> ops [op_1 ], opline )) {
1339+ continue ;
12901340 }
12911341 }
12921342 }
0 commit comments