Skip to content

Commit

Permalink
Catch exceptions without capturing them to variables
Browse files Browse the repository at this point in the history
Work in progress, will be posted to RFC later.
  • Loading branch information
MaxSem committed Apr 3, 2020
1 parent 305b17e commit 1e412f9
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 8 deletions.
12 changes: 12 additions & 0 deletions Zend/tests/try/catch_novar.phpt
@@ -0,0 +1,12 @@
--TEST--
catch without capturing a variable
--FILE--
<?php

try {
throw new Exception()
} catch (Exception) {
echo "caught!\n";
}
--EXPECT--
caught!
6 changes: 4 additions & 2 deletions Zend/zend_ast.c
Expand Up @@ -1992,8 +1992,10 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
case ZEND_AST_CATCH:
smart_str_appends(str, "} catch (");
zend_ast_export_catch_name_list(str, zend_ast_get_list(ast->child[0]), indent);
smart_str_appends(str, " $");
zend_ast_export_var(str, ast->child[1], 0, indent);
if (ast->child[1]) {
smart_str_appends(str, " $");
zend_ast_export_var(str, ast->child[1], 0, indent);
}
smart_str_appends(str, ") {\n");
zend_ast_export_stmt(str, ast->child[2], indent + 1);
zend_ast_export_indent(str, indent);
Expand Down
8 changes: 4 additions & 4 deletions Zend/zend_compile.c
Expand Up @@ -5229,7 +5229,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
zend_ast_list *classes = zend_ast_get_list(catch_ast->child[0]);
zend_ast *var_ast = catch_ast->child[1];
zend_ast *stmt_ast = catch_ast->child[2];
zend_string *var_name = zval_make_interned_string(zend_ast_get_zval(var_ast));
zend_string *var_name = var_ast ? zval_make_interned_string(zend_ast_get_zval(var_ast)) : NULL;
zend_bool is_last_catch = (i + 1 == catches->children);

uint32_t *jmp_multicatch = safe_emalloc(sizeof(uint32_t), classes->children - 1, 0);
Expand Down Expand Up @@ -5257,12 +5257,12 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
zend_resolve_class_name_ast(class_ast));
opline->extended_value = zend_alloc_cache_slot();

if (zend_string_equals_literal(var_name, "this")) {
if (var_name && zend_string_equals_literal(var_name, "this")) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
}

opline->result_type = IS_CV;
opline->result.var = lookup_cv(var_name);
opline->result_type = var_name ? IS_CV : IS_UNUSED;
opline->result.var = var_name ? lookup_cv(var_name) : -1;

if (is_last_catch && is_last_class) {
opline->extended_value |= ZEND_LAST_CATCH;
Expand Down
9 changes: 7 additions & 2 deletions Zend/zend_language_parser.y
Expand Up @@ -247,7 +247,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%type <ast> encaps_var encaps_var_offset isset_variables
%type <ast> top_statement_list use_declarations const_list inner_statement_list if_stmt
%type <ast> alt_if_stmt for_exprs switch_case_list global_var_list static_var_list
%type <ast> echo_expr_list unset_variables catch_name_list catch_list parameter_list class_statement_list
%type <ast> echo_expr_list unset_variables catch_name_list catch_list optional_variable parameter_list class_statement_list
%type <ast> implements_list case_list if_stmt_without_else
%type <ast> non_empty_parameter_list argument_list non_empty_argument_list property_list
%type <ast> class_const_list class_const_decl class_name_list trait_adaptations method_body non_empty_for_exprs
Expand Down Expand Up @@ -465,7 +465,7 @@ statement:
catch_list:
%empty
{ $$ = zend_ast_create_list(0, ZEND_AST_CATCH_LIST); }
| catch_list T_CATCH '(' catch_name_list T_VARIABLE ')' '{' inner_statement_list '}'
| catch_list T_CATCH '(' catch_name_list optional_variable ')' '{' inner_statement_list '}'
{ $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_CATCH, $4, $5, $8)); }
;

Expand All @@ -474,6 +474,11 @@ catch_name_list:
| catch_name_list '|' class_name { $$ = zend_ast_list_add($1, $3); }
;

optional_variable:
%empty { $$ = NULL; }
| T_VARIABLE { $$ = $1; }
;

finally_statement:
%empty { $$ = NULL; }
| T_FINALLY '{' inner_statement_list '}' { $$ = $3; }
Expand Down

0 comments on commit 1e412f9

Please sign in to comment.