summaryrefslogtreecommitdiff
path: root/Zend/zend_ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_ast.c')
-rw-r--r--Zend/zend_ast.c132
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");