Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

- Change exception handling to use the Java-like catch(MyException $e…

…xception)

- semantics. Example:
<?php

	class MyException {
		function __construct($exception)
		{
			$this->exception = $exception;
		}

		function Display()
		{
			print "MyException: $this->exception\n";
		}

	}
	class MyExceptionFoo extends MyException {
		function __construct($exception)
		{
			$this->exception = $exception;
		}
		function Display()
		{
			print "MyException: $this->exception\n";
		}
	}

	try {
		throw  new MyExceptionFoo("Hello");
	} catch (MyException $exception) {
		$exception->Display();
	}
?>
  • Loading branch information...
commit f1e8815c26cae7cdc6ce7975688866e8dba1dbc6 1 parent 4cfbd67
@andigutmans andigutmans authored
View
18 Zend/zend_compile.c
@@ -958,13 +958,18 @@ void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC)
void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_DC)
{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ long fetch_class_op_number;
+ zend_op *opline;
+
+ fetch_class_op_number = get_next_op_number(CG(active_op_array));
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_FETCH_CLASS;
if (class_entry) {
opline->op1 = *class_entry;
} else {
SET_UNUSED(opline->op1);
+ CG(catch_begin) = fetch_class_op_number;
}
zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
if ((class_name->u.constant.value.str.len == (sizeof("self") - 1)) &&
@@ -1261,17 +1266,18 @@ static void throw_list_applier(long *opline_num, long *catch_opline)
}
}
-void zend_do_begin_catch(znode *try_token, znode *catch_var TSRMLS_DC)
+void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var TSRMLS_DC)
{
long catch_op_number = get_next_op_number(CG(active_op_array));
zend_op *opline;
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_CATCH;
- opline->op1 = *catch_var;
- SET_UNUSED(opline->op2);
+ opline->op1 = *catch_class;
+ SET_UNUSED(opline->op1); /* FIXME: Define IS_CLASS or something like that */
+ opline->op2 = *catch_var;
- zend_llist_apply_with_argument(CG(throw_list), (llist_apply_with_arg_func_t) throw_list_applier, &catch_op_number TSRMLS_CC);
+ zend_llist_apply_with_argument(CG(throw_list), (llist_apply_with_arg_func_t) throw_list_applier, &CG(catch_begin) TSRMLS_CC);
zend_llist_destroy(CG(throw_list));
efree(CG(throw_list));
CG(throw_list) = (void *) try_token->throw_list;
@@ -1281,7 +1287,7 @@ void zend_do_begin_catch(znode *try_token, znode *catch_var TSRMLS_DC)
void zend_do_end_catch(znode *try_token TSRMLS_DC)
{
- CG(active_op_array)->opcodes[try_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->opcodes[try_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
}
void zend_do_throw(znode *expr TSRMLS_DC)
View
2  Zend/zend_compile.h
@@ -281,7 +281,7 @@ void zend_do_end_function_call(znode *function_name, znode *result, znode *argum
void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
void zend_do_try(znode *try_token TSRMLS_DC);
-void zend_do_begin_catch(znode *try_token, znode *catch_var TSRMLS_DC);
+void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var TSRMLS_DC);
void zend_do_end_catch(znode *try_token TSRMLS_DC);
void zend_do_throw(znode *expr TSRMLS_DC);
View
35 Zend/zend_execute.c
@@ -1937,7 +1937,10 @@ binary_assign_op_addr: {
zval *exception;
value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
-
+
+ if (value->type != IS_OBJECT) {
+ zend_error(E_ERROR, "Can only throw objects");
+ }
/* Not sure if a complete copy is what we want here */
MAKE_STD_ZVAL(exception);
*exception = *value;
@@ -1956,15 +1959,31 @@ binary_assign_op_addr: {
}
NEXT_OPCODE();
case ZEND_CATCH:
- /* Check if this is really an exception, if not, jump over code */
- if (EG(exception) == NULL) {
- EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num];
+ {
+ zend_class_entry *ce;
+
+ /* Check if this is really an exception, if not, jump over code */
+ if (EG(exception) == NULL) {
+ EX(opline) = &op_array->opcodes[EX(opline)->extended_value];
continue;
+ }
+ ce = Z_OBJCE_P(EG(exception));
+ if (ce != EX(Ts)[EX(opline)->op1.u.var].EA.class_entry) {
+ while (ce->parent) {
+ if (ce->parent == EX(Ts)[EX(opline)->op1.u.var].EA.class_entry) {
+ goto exception_should_be_taken;
+ }
+ ce = ce->parent;
+ }
+ EX(opline) = &op_array->opcodes[EX(opline)->extended_value];
+ continue;
+ }
+exception_should_be_taken:
+ zend_hash_update(EG(active_symbol_table), EX(opline)->op2.u.constant.value.str.val,
+ EX(opline)->op2.u.constant.value.str.len+1, &EG(exception), sizeof(zval *), (void **) NULL);
+ EG(exception) = NULL;
+ NEXT_OPCODE();
}
- zend_hash_update(EG(active_symbol_table), EX(opline)->op1.u.constant.value.str.val,
- EX(opline)->op1.u.constant.value.str.len+1, &EG(exception), sizeof(zval *), (void **) NULL);
- EG(exception) = NULL;
- NEXT_OPCODE();
case ZEND_NAMESPACE:
{
#if 0
View
1  Zend/zend_globals.h
@@ -111,6 +111,7 @@ struct _zend_compiler_globals {
zend_llist open_files;
zend_llist *throw_list;
+ long catch_begin;
struct _zend_ini_parser_param *ini_parser_param;
View
6 Zend/zend_language_parser.y
@@ -206,11 +206,9 @@ unticked_statement:
| T_DECLARE { zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(TSRMLS_C); }
| ';' /* empty statement */
| T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
- T_CATCH '(' T_VARIABLE ')' { zend_do_begin_catch(&$1, &$8 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
+ T_CATCH '(' catch_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$8, &$9 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
| T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); }
| T_DELETE cvar ';' { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1, ZEND_UNSET_OBJ TSRMLS_CC); }
- | T_NAMESPACE namespace_class_entry ';' { do_namespace(&$2 TSRMLS_CC); }
- | T_NAMESPACE ';' { do_namespace(NULL TSRMLS_CC); }
;
unset_variables:
@@ -531,7 +529,7 @@ parse_class_name_entry:
| T_STRING T_PAAMAYIM_NEKUDOTAYIM { $$ = $1; zend_str_tolower($$.u.constant.value.str.val, $$.u.constant.value.str.len); }
;
-namespace_class_entry:
+catch_class_entry:
parse_class_entry T_STRING { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); }
| T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
;
Please sign in to comment.
Something went wrong with that request. Please try again.