@@ -4542,7 +4542,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
45424542 zend_ast_list * catches = zend_ast_get_list (ast -> child [1 ]);
45434543 zend_ast * finally_ast = ast -> child [2 ];
45444544
4545- uint32_t i ;
4545+ uint32_t i , j ;
45464546 zend_op * opline ;
45474547 uint32_t try_catch_offset ;
45484548 uint32_t * jmp_opnums = safe_emalloc (sizeof (uint32_t ), catches -> children , 0 );
@@ -4587,34 +4587,53 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
45874587
45884588 for (i = 0 ; i < catches -> children ; ++ i ) {
45894589 zend_ast * catch_ast = catches -> child [i ];
4590- zend_ast * class_ast = catch_ast -> child [0 ];
4590+ zend_ast_list * classes = zend_ast_get_list ( catch_ast -> child [0 ]) ;
45914591 zend_ast * var_ast = catch_ast -> child [1 ];
45924592 zend_ast * stmt_ast = catch_ast -> child [2 ];
45934593 zval * var_name = zend_ast_get_zval (var_ast );
45944594 zend_bool is_last_catch = (i + 1 == catches -> children );
45954595
4596+ uint32_t * jmp_multicatch = safe_emalloc (sizeof (uint32_t ), classes -> children - 1 , 0 );
45964597 uint32_t opnum_catch ;
45974598
4598- if (!zend_is_const_default_class_ref (class_ast )) {
4599- zend_error_noreturn (E_COMPILE_ERROR , "Bad class name in the catch statement" );
4600- }
4599+ CG (zend_lineno ) = catch_ast -> lineno ;
46014600
4602- opnum_catch = get_next_op_number (CG (active_op_array ));
4603- if (i == 0 ) {
4604- CG (active_op_array )-> try_catch_array [try_catch_offset ].catch_op = opnum_catch ;
4605- }
4601+ for (j = 0 ; j < classes -> children ; j ++ ) {
46064602
4607- CG (zend_lineno ) = catch_ast -> lineno ;
4603+ zend_ast * class_ast = classes -> child [j ];
4604+ zend_bool is_last_class = (j + 1 == classes -> children );
46084605
4609- opline = get_next_op (CG (active_op_array ));
4610- opline -> opcode = ZEND_CATCH ;
4611- opline -> op1_type = IS_CONST ;
4612- opline -> op1 .constant = zend_add_class_name_literal (CG (active_op_array ),
4613- zend_resolve_class_name_ast (class_ast ));
4606+ if (!zend_is_const_default_class_ref (class_ast )) {
4607+ zend_error_noreturn (E_COMPILE_ERROR , "Bad class name in the catch statement" );
4608+ }
46144609
4615- opline -> op2_type = IS_CV ;
4616- opline -> op2 .var = lookup_cv (CG (active_op_array ), zend_string_copy (Z_STR_P (var_name )));
4617- opline -> result .num = is_last_catch ;
4610+ opnum_catch = get_next_op_number (CG (active_op_array ));
4611+ if (i == 0 && j == 0 ) {
4612+ CG (active_op_array )-> try_catch_array [try_catch_offset ].catch_op = opnum_catch ;
4613+ }
4614+
4615+ opline = get_next_op (CG (active_op_array ));
4616+ opline -> opcode = ZEND_CATCH ;
4617+ opline -> op1_type = IS_CONST ;
4618+ opline -> op1 .constant = zend_add_class_name_literal (CG (active_op_array ),
4619+ zend_resolve_class_name_ast (class_ast ));
4620+
4621+ opline -> op2_type = IS_CV ;
4622+ opline -> op2 .var = lookup_cv (CG (active_op_array ), zend_string_copy (Z_STR_P (var_name )));
4623+
4624+ opline -> result .num = is_last_catch && is_last_class ;
4625+
4626+ if (!is_last_class ) {
4627+ jmp_multicatch [j ] = zend_emit_jump (0 );
4628+ opline -> extended_value = get_next_op_number (CG (active_op_array ));
4629+ }
4630+ }
4631+
4632+ for (j = 0 ; j < classes -> children - 1 ; j ++ ) {
4633+ zend_update_jump_target_to_next (jmp_multicatch [j ]);
4634+ }
4635+
4636+ efree (jmp_multicatch );
46184637
46194638 zend_compile_stmt (stmt_ast );
46204639
0 commit comments