diff options
Diffstat (limited to 'Zend/zend_ast.c')
-rw-r--r-- | Zend/zend_ast.c | 132 |
1 files changed, 91 insertions, 41 deletions
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 58119c2598..236d0783fc 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -203,7 +203,7 @@ static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr) zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr); break; default: - zend_throw_error(zend_ce_error, "Illegal offset type"); + zend_throw_error(NULL, "Illegal offset type"); return FAILURE; } return SUCCESS; @@ -256,23 +256,23 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc case ZEND_AST_ZVAL: { zval *zv = zend_ast_get_zval(ast); - if (scope) { - /* class constants may be updated in-place */ - if (Z_OPT_CONSTANT_P(zv)) { - if (UNEXPECTED(zval_update_constant_ex(zv, 1, scope) != SUCCESS)) { + + if (Z_OPT_CONSTANT_P(zv)) { + if (!(Z_TYPE_FLAGS_P(zv) & IS_TYPE_IMMUTABLE)) { + if (UNEXPECTED(zval_update_constant_ex(zv, scope) != SUCCESS)) { ret = FAILURE; break; } - } - ZVAL_DUP(result, zv); - } else { - ZVAL_DUP(result, zv); - if (Z_OPT_CONSTANT_P(result)) { - if (UNEXPECTED(zval_update_constant_ex(result, 1, scope) != SUCCESS)) { + ZVAL_COPY(result, zv); + } else { + ZVAL_COPY_VALUE(result, zv); + if (UNEXPECTED(zval_update_constant_ex(result, scope) != SUCCESS)) { ret = FAILURE; break; } } + } else { + ZVAL_COPY(result, zv); } break; } @@ -337,6 +337,22 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc zval_dtor(&op1); } break; + case ZEND_AST_COALESCE: + if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) { + ret = FAILURE; + break; + } + if (Z_TYPE(op1) > IS_NULL) { + *result = op1; + } else { + if (UNEXPECTED(zend_ast_evaluate(result, ast->child[1], scope) != SUCCESS)) { + zval_dtor(&op1); + ret = FAILURE; + break; + } + zval_dtor(&op1); + } + break; case ZEND_AST_UNARY_PLUS: if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) { ret = FAILURE; @@ -385,6 +401,10 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc } break; case ZEND_AST_DIM: + if (ast->child[1] == NULL) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading"); + } + if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) { ret = FAILURE; } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) { @@ -393,7 +413,12 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc } else { zval tmp; - zend_fetch_dimension_by_zval(&tmp, &op1, &op2); + if (ast->attr == ZEND_DIM_IS) { + zend_fetch_dimension_by_zval_is(&tmp, &op1, &op2, IS_CONST); + } else { + zend_fetch_dimension_by_zval(&tmp, &op1, &op2); + } + if (UNEXPECTED(Z_ISREF(tmp))) { ZVAL_DUP(result, Z_REFVAL(tmp)); } else { @@ -405,7 +430,7 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc } break; default: - zend_throw_error(zend_ce_error, "Unsupported constant expression"); + zend_throw_error(NULL, "Unsupported constant expression"); ret = FAILURE; } return ret; @@ -591,7 +616,7 @@ static void zend_ast_export_qstr(smart_str *str, char quote, zend_string *s) case '\v': smart_str_appends(str, "\\v"); break; -#ifdef PHP_WIN32 +#ifdef ZEND_WIN32 case VK_ESCAPE: #else case '\e': @@ -751,19 +776,22 @@ static void zend_ast_export_encaps_list(smart_str *str, char quote, zend_ast_lis } } -static void zend_ast_export_name_list(smart_str *str, zend_ast_list *list, int indent) +static void zend_ast_export_name_list_ex(smart_str *str, zend_ast_list *list, int indent, const char *separator) { uint32_t i = 0; while (i < list->children) { if (i != 0) { - smart_str_appends(str, ", "); + smart_str_appends(str, separator); } zend_ast_export_name(str, list->child[i], 0, indent); i++; } } +#define zend_ast_export_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, ", ") +#define zend_ast_export_catch_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, "|") + static void zend_ast_export_var_list(smart_str *str, zend_ast_list *list, int indent) { uint32_t i = 0; @@ -783,6 +811,10 @@ static void zend_ast_export_var_list(smart_str *str, zend_ast_list *list, int in static void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int indent) { + if (!ast) { + return; + } + if (ast->kind == ZEND_AST_STMT_LIST || ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) { zend_ast_list *list = (zend_ast_list*)ast; @@ -918,6 +950,21 @@ static void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int ind } } +static void zend_ast_export_class_no_header(smart_str *str, zend_ast_decl *decl, int indent) { + if (decl->child[0]) { + smart_str_appends(str, " extends "); + zend_ast_export_ns_name(str, decl->child[0], 0, indent); + } + if (decl->child[1]) { + smart_str_appends(str, " implements "); + zend_ast_export_ex(str, decl->child[1], 0, indent); + } + smart_str_appends(str, " {\n"); + zend_ast_export_stmt(str, decl->child[2], indent + 1); + zend_ast_export_indent(str, indent); + smart_str_appends(str, "}"); +} + #define BINARY_OP(_op, _p, _pl, _pr) do { \ op = _op; \ p = _p; \ @@ -1044,18 +1091,8 @@ tail_call: smart_str_appends(str, "class "); } smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name)); - if (decl->child[0]) { - smart_str_appends(str, " extends "); - zend_ast_export_ns_name(str, decl->child[0], 0, indent); - } - if (decl->child[1]) { - smart_str_appends(str, " implements "); - zend_ast_export_ex(str, decl->child[1], 0, indent); - } - smart_str_appends(str, " {\n"); - zend_ast_export_stmt(str, decl->child[2], indent + 1); - zend_ast_export_indent(str, indent); - smart_str_appends(str, "}\n"); + zend_ast_export_class_no_header(str, decl, indent); + smart_str_appendc(str, '\n'); break; /* list nodes */ @@ -1065,11 +1102,6 @@ tail_call: simple_list: zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent); break; - case ZEND_AST_LIST: - smart_str_appends(str, "list("); - zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent); - smart_str_appendc(str, ')'); - break; case ZEND_AST_ARRAY: smart_str_appendc(str, '['); zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent); @@ -1183,7 +1215,11 @@ simple_list: if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) { zend_ast_export_encaps_list(str, '`', (zend_ast_list*)ast->child[0], indent); } else { - zend_ast_export_ex(str, ast->child[0], 0, indent); + zval *zv; + ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_ZVAL); + zv = zend_ast_get_zval(ast->child[0]); + ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING); + zend_ast_export_qstr(str, '`', Z_STR_P(zv)); } smart_str_appendc(str, '`'); break; @@ -1340,12 +1376,26 @@ simple_list: break; case ZEND_AST_NEW: smart_str_appends(str, "new "); - zend_ast_export_ns_name(str, ast->child[0], 0, indent); - smart_str_appendc(str, '('); - zend_ast_export_ex(str, ast->child[1], 0, indent); - smart_str_appendc(str, ')'); + if (ast->child[0]->kind == ZEND_AST_CLASS) { + smart_str_appends(str, "class"); + if (zend_ast_get_list(ast->child[1])->children) { + smart_str_appendc(str, '('); + zend_ast_export_ex(str, ast->child[1], 0, indent); + smart_str_appendc(str, ')'); + } + zend_ast_export_class_no_header(str, (zend_ast_decl *) ast->child[0], indent); + } else { + zend_ast_export_ns_name(str, ast->child[0], 0, indent); + smart_str_appendc(str, '('); + zend_ast_export_ex(str, ast->child[1], 0, indent); + smart_str_appendc(str, ')'); + } + break; + case ZEND_AST_INSTANCEOF: + zend_ast_export_ex(str, ast->child[0], 0, indent); + smart_str_appends(str, " instanceof "); + zend_ast_export_ns_name(str, ast->child[1], 0, indent); break; - case ZEND_AST_INSTANCEOF: BINARY_OP(" instanceof ", 230, 231, 231); case ZEND_AST_YIELD: if (priority > 70) smart_str_appendc(str, '('); smart_str_appends(str, "yield "); @@ -1536,7 +1586,7 @@ simple_list: break; case ZEND_AST_CATCH: smart_str_appends(str, "} catch ("); - zend_ast_export_ns_name(str, ast->child[0], 0, indent); + 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); smart_str_appends(str, ") {\n"); |