diff options
Diffstat (limited to 'Zend/zend_ast.c')
-rw-r--r-- | Zend/zend_ast.c | 286 |
1 files changed, 231 insertions, 55 deletions
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 338ff09f76..cb61bec5d7 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -114,7 +114,7 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast * ZEND_API zend_ast *zend_ast_create_decl( zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, - zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3 + zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4 ) { zend_ast_decl *ast; @@ -131,6 +131,7 @@ ZEND_API zend_ast *zend_ast_create_decl( ast->child[1] = child1; ast->child[2] = child2; ast->child[3] = child3; + ast->child[4] = child4; return (zend_ast *) ast; } @@ -163,7 +164,6 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_1(zend_ast_kind kind, zend_ast lineno = CG(zend_lineno); } ast->lineno = lineno; - ast->lineno = lineno; return ast; } @@ -243,6 +243,37 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_4(zend_ast_kind kind, zend_ast return ast; } +ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_5(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4, zend_ast *child5) { + zend_ast *ast; + uint32_t lineno; + + ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 5); + ast = zend_ast_alloc(zend_ast_size(5)); + ast->kind = kind; + ast->attr = 0; + ast->child[0] = child1; + ast->child[1] = child2; + ast->child[2] = child3; + ast->child[3] = child4; + ast->child[4] = child5; + if (child1) { + lineno = zend_ast_get_lineno(child1); + } else if (child2) { + lineno = zend_ast_get_lineno(child2); + } else if (child3) { + lineno = zend_ast_get_lineno(child3); + } else if (child4) { + lineno = zend_ast_get_lineno(child4); + } else if (child5) { + lineno = zend_ast_get_lineno(child5); + } else { + lineno = CG(zend_lineno); + } + ast->lineno = lineno; + + return ast; +} + ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_kind kind) { zend_ast *ast; zend_ast_list *list; @@ -406,14 +437,14 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) return (zend_ast *) list; } -static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr) +static zend_result zend_ast_add_array_element(zval *result, zval *offset, zval *expr) { switch (Z_TYPE_P(offset)) { case IS_UNDEF: if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), expr)) { - zend_error(E_WARNING, + zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied"); - zval_ptr_dtor_nogc(expr); + return FAILURE; } break; case IS_STRING: @@ -436,17 +467,17 @@ 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; case IS_RESOURCE: - zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset)); + zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset)); zend_hash_index_update(Z_ARRVAL_P(result), Z_RES_HANDLE_P(offset), expr); break; default: - zend_throw_error(NULL, "Illegal offset type"); + zend_type_error("Illegal offset type"); return FAILURE; } return SUCCESS; } -static int zend_ast_add_unpacked_element(zval *result, zval *expr) { +static zend_result zend_ast_add_unpacked_element(zval *result, zval *expr) { if (EXPECTED(Z_TYPE_P(expr) == IS_ARRAY)) { HashTable *ht = Z_ARRVAL_P(expr); zval *val; @@ -458,8 +489,9 @@ static int zend_ast_add_unpacked_element(zval *result, zval *expr) { return FAILURE; } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) { - zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - break; + zend_throw_error(NULL, + "Cannot add element to the array as the next element is already occupied"); + return FAILURE; } Z_TRY_ADDREF_P(val); } @@ -472,10 +504,10 @@ static int zend_ast_add_unpacked_element(zval *result, zval *expr) { return FAILURE; } -ZEND_API int ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope) +ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope) { zval op1, op2; - int ret = SUCCESS; + zend_result ret = SUCCESS; switch (ast->kind) { case ZEND_AST_BINARY_OP: @@ -530,8 +562,7 @@ ZEND_API int ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_c if (UNEXPECTED(zv == NULL)) { ZVAL_UNDEF(result); - ret = zend_use_undefined_constant(name, ast->attr, result); - break; + return FAILURE; } ZVAL_COPY_OR_DUP(result, zv); break; @@ -718,6 +749,9 @@ ZEND_API int ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_c zval_ptr_dtor_nogc(&op1); zval_ptr_dtor_nogc(&op2); + if (UNEXPECTED(EG(exception))) { + return FAILURE; + } } break; default: @@ -814,7 +848,7 @@ ZEND_API zend_ast_ref * ZEND_FASTCALL zend_ast_copy(zend_ast *ast) ref = emalloc(tree_size); zend_ast_tree_copy(ast, GC_AST(ref)); GC_SET_REFCOUNT(ref, 1); - GC_TYPE_INFO(ref) = IS_CONSTANT_AST; + GC_TYPE_INFO(ref) = GC_CONSTANT_AST; return ref; } @@ -860,7 +894,8 @@ tail_call: zend_ast_destroy(decl->child[0]); zend_ast_destroy(decl->child[1]); zend_ast_destroy(decl->child[2]); - ast = decl->child[3]; + zend_ast_destroy(decl->child[3]); + ast = decl->child[4]; goto tail_call; } } @@ -910,8 +945,9 @@ ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn) { * 160 left & * 170 non-associative == != === !== * 180 non-associative < <= > >= <=> + * 185 left . * 190 left << >> - * 200 left + - . + * 200 left + - * 210 left * / % * 220 right ! * 230 non-associative instanceof @@ -1022,7 +1058,7 @@ static ZEND_COLD void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int zend_ast_export_ex(str, ast, priority, indent); } -static ZEND_COLD int zend_ast_valid_var_char(char ch) +static ZEND_COLD bool zend_ast_valid_var_char(char ch) { unsigned char c = (unsigned char)ch; @@ -1035,7 +1071,7 @@ static ZEND_COLD int zend_ast_valid_var_char(char ch) return 1; } -static ZEND_COLD int zend_ast_valid_var_name(const char *s, size_t len) +static ZEND_COLD bool zend_ast_valid_var_name(const char *s, size_t len) { unsigned char c; size_t i; @@ -1061,7 +1097,7 @@ static ZEND_COLD int zend_ast_valid_var_name(const char *s, size_t len) return 1; } -static ZEND_COLD int zend_ast_var_needs_braces(char ch) +static ZEND_COLD bool zend_ast_var_needs_braces(char ch) { return ch == '[' || zend_ast_valid_var_char(ch); } @@ -1084,7 +1120,7 @@ static ZEND_COLD void zend_ast_export_var(smart_str *str, zend_ast *ast, int pri smart_str_appendc(str, '}'); } -static ZEND_COLD void zend_ast_export_list(smart_str *str, zend_ast_list *list, int separator, int priority, int indent) +static ZEND_COLD void zend_ast_export_list(smart_str *str, zend_ast_list *list, bool separator, int priority, int indent) { uint32_t i = 0; @@ -1312,6 +1348,78 @@ static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, zend_ast_d smart_str_appends(str, "}"); } +static ZEND_COLD void zend_ast_export_attribute_group(smart_str *str, zend_ast *ast, int indent) { + zend_ast_list *list = zend_ast_get_list(ast); + uint32_t i, j; + + for (i = 0; i < list->children; i++) { + zend_ast *attr = list->child[i]; + + if (i) { + smart_str_appends(str, ", "); + } + zend_ast_export_ns_name(str, attr->child[0], 0, indent); + + if (attr->child[1]) { + zend_ast_list *args = zend_ast_get_list(attr->child[1]); + + smart_str_appendc(str, '('); + for (j = 0; j < args->children; j++) { + if (j) { + smart_str_appends(str, ", "); + } + zend_ast_export_ex(str, args->child[j], 0, indent); + } + smart_str_appendc(str, ')'); + } + } +} + +static ZEND_COLD void zend_ast_export_attributes(smart_str *str, zend_ast *ast, int indent, zend_bool newlines) { + zend_ast_list *list = zend_ast_get_list(ast); + uint32_t i; + + for (i = 0; i < list->children; i++) { + smart_str_appends(str, "#["); + zend_ast_export_attribute_group(str, list->child[i], indent); + smart_str_appends(str, "]"); + + if (newlines) { + smart_str_appendc(str, '\n'); + zend_ast_export_indent(str, indent); + } else { + smart_str_appendc(str, ' '); + } + } +} + +static ZEND_COLD void zend_ast_export_visibility(smart_str *str, uint32_t flags) { + if (flags & ZEND_ACC_PUBLIC) { + smart_str_appends(str, "public "); + } else if (flags & ZEND_ACC_PROTECTED) { + smart_str_appends(str, "protected "); + } else if (flags & ZEND_ACC_PRIVATE) { + smart_str_appends(str, "private "); + } +} + +static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int indent) { + if (ast->kind == ZEND_AST_TYPE_UNION) { + zend_ast_list *list = zend_ast_get_list(ast); + for (uint32_t i = 0; i < list->children; i++) { + if (i != 0) { + smart_str_appendc(str, '|'); + } + zend_ast_export_type(str, list->child[i], indent); + } + return; + } + if (ast->attr & ZEND_TYPE_NULLABLE) { + smart_str_appendc(str, '?'); + } + zend_ast_export_ns_name(str, ast, 0, indent); +} + #define BINARY_OP(_op, _p, _pl, _pr) do { \ op = _op; \ p = _p; \ @@ -1379,7 +1487,7 @@ tail_call: break; case ZEND_AST_ZNODE: /* This AST kind is only used for temporary nodes during compilation */ - ZEND_ASSERT(0); + ZEND_UNREACHABLE(); break; /* declaration nodes */ @@ -1388,13 +1496,13 @@ tail_call: case ZEND_AST_ARROW_FUNC: case ZEND_AST_METHOD: decl = (zend_ast_decl *) ast; - if (decl->flags & ZEND_ACC_PUBLIC) { - smart_str_appends(str, "public "); - } else if (decl->flags & ZEND_ACC_PROTECTED) { - smart_str_appends(str, "protected "); - } else if (decl->flags & ZEND_ACC_PRIVATE) { - smart_str_appends(str, "private "); + if (decl->child[4]) { + zend_bool newlines = !(ast->kind == ZEND_AST_CLOSURE || ast->kind == ZEND_AST_ARROW_FUNC); + zend_ast_export_attributes(str, decl->child[4], indent, newlines); } + + zend_ast_export_visibility(str, decl->flags); + if (decl->flags & ZEND_ACC_STATIC) { smart_str_appends(str, "static "); } @@ -1421,10 +1529,7 @@ tail_call: zend_ast_export_ex(str, decl->child[1], 0, indent); if (decl->child[3]) { smart_str_appends(str, ": "); - if (decl->child[3]->attr & ZEND_TYPE_NULLABLE) { - smart_str_appendc(str, '?'); - } - zend_ast_export_ns_name(str, decl->child[3], 0, indent); + zend_ast_export_type(str, decl->child[3], indent); } if (decl->child[2]) { if (decl->kind == ZEND_AST_ARROW_FUNC) { @@ -1447,6 +1552,9 @@ tail_call: break; case ZEND_AST_CLASS: decl = (zend_ast_decl *) ast; + if (decl->child[3]) { + zend_ast_export_attributes(str, decl->child[3], indent, 1); + } if (decl->flags & ZEND_ACC_INTERFACE) { smart_str_appends(str, "interface "); } else if (decl->flags & ZEND_ACC_TRAIT) { @@ -1491,6 +1599,7 @@ simple_list: break; case ZEND_AST_SWITCH_LIST: case ZEND_AST_CATCH_LIST: + case ZEND_AST_MATCH_ARM_LIST: zend_ast_export_list(str, (zend_ast_list*)ast, 0, 0, indent); break; case ZEND_AST_CLOSURE_USES: @@ -1502,23 +1611,18 @@ simple_list: zend_ast *type_ast = ast->child[0]; zend_ast *prop_ast = ast->child[1]; - if (ast->attr & ZEND_ACC_PUBLIC) { - smart_str_appends(str, "public "); - } else if (ast->attr & ZEND_ACC_PROTECTED) { - smart_str_appends(str, "protected "); - } else if (ast->attr & ZEND_ACC_PRIVATE) { - smart_str_appends(str, "private "); + if (ast->child[2]) { + zend_ast_export_attributes(str, ast->child[2], indent, 1); } + + zend_ast_export_visibility(str, ast->attr); + if (ast->attr & ZEND_ACC_STATIC) { smart_str_appends(str, "static "); } if (type_ast) { - if (type_ast->attr & ZEND_TYPE_NULLABLE) { - smart_str_appendc(str, '?'); - } - zend_ast_export_ns_name( - str, type_ast, 0, indent); + zend_ast_export_type(str, type_ast, indent); smart_str_appendc(str, ' '); } @@ -1527,9 +1631,19 @@ simple_list: } case ZEND_AST_CONST_DECL: - case ZEND_AST_CLASS_CONST_DECL: smart_str_appends(str, "const "); goto simple_list; + case ZEND_AST_CLASS_CONST_GROUP: + if (ast->child[1]) { + zend_ast_export_attributes(str, ast->child[1], indent, 1); + } + + zend_ast_export_visibility(str, ast->attr); + smart_str_appends(str, "const "); + + ast = ast->child[0]; + + goto simple_list; case ZEND_AST_NAME_LIST: zend_ast_export_name_list(str, (zend_ast_list*)ast, indent); break; @@ -1560,6 +1674,8 @@ simple_list: switch (ast->attr & ~ZEND_TYPE_NULLABLE) { case IS_ARRAY: APPEND_STR("array"); case IS_CALLABLE: APPEND_STR("callable"); + case IS_STATIC: APPEND_STR("static"); + case IS_MIXED: APPEND_STR("mixed"); EMPTY_SWITCH_DEFAULT_CASE(); } break; @@ -1685,8 +1801,9 @@ simple_list: smart_str_appendc(str, ']'); break; case ZEND_AST_PROP: + case ZEND_AST_NULLSAFE_PROP: zend_ast_export_ex(str, ast->child[0], 0, indent); - smart_str_appends(str, "->"); + smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_PROP ? "?->" : "->"); zend_ast_export_var(str, ast->child[1], 0, indent); break; case ZEND_AST_STATIC_PROP: @@ -1738,8 +1855,7 @@ simple_list: case ZEND_MOD: BINARY_OP(" % ", 210, 210, 211); case ZEND_SL: BINARY_OP(" << ", 190, 190, 191); case ZEND_SR: BINARY_OP(" >> ", 190, 190, 191); - case ZEND_PARENTHESIZED_CONCAT: /* fallthrough */ - case ZEND_CONCAT: BINARY_OP(" . ", 200, 200, 201); + case ZEND_CONCAT: BINARY_OP(" . ", 185, 185, 186); case ZEND_BW_OR: BINARY_OP(" | ", 140, 140, 141); case ZEND_BW_AND: BINARY_OP(" & ", 160, 160, 161); case ZEND_BW_XOR: BINARY_OP(" ^ ", 150, 150, 151); @@ -1771,13 +1887,17 @@ simple_list: case ZEND_AST_NEW: smart_str_appends(str, "new "); if (ast->child[0]->kind == ZEND_AST_CLASS) { + zend_ast_decl *decl = (zend_ast_decl *) ast->child[0]; + if (decl->child[3]) { + zend_ast_export_attributes(str, decl->child[3], indent, 0); + } 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); + zend_ast_export_class_no_header(str, decl, indent); } else { zend_ast_export_ns_name(str, ast->child[0], 0, indent); smart_str_appendc(str, '('); @@ -1858,6 +1978,25 @@ simple_list: } zend_ast_export_stmt(str, ast->child[1], indent + 1); break; + case ZEND_AST_MATCH: + smart_str_appends(str, "match ("); + zend_ast_export_ex(str, ast->child[0], 0, indent); + smart_str_appends(str, ") {\n"); + zend_ast_export_ex(str, ast->child[1], 0, indent + 1); + zend_ast_export_indent(str, indent); + smart_str_appendc(str, '}'); + break; + case ZEND_AST_MATCH_ARM: + zend_ast_export_indent(str, indent); + if (ast->child[0]) { + zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent); + smart_str_appends(str, " => "); + } else { + smart_str_appends(str, "default => "); + } + zend_ast_export_ex(str, ast->child[1], 0, 0); + smart_str_appends(str, ",\n"); + break; case ZEND_AST_DECLARE: smart_str_appends(str, "declare("); ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL); @@ -1934,11 +2073,17 @@ simple_list: zend_ast_export_name(str, ast->child[1], 0, indent); } break; + case ZEND_AST_NAMED_ARG: + smart_str_append(str, zend_ast_get_str(ast->child[0])); + smart_str_appends(str, ": "); + ast = ast->child[1]; + goto tail_call; /* 3 child nodes */ case ZEND_AST_METHOD_CALL: + case ZEND_AST_NULLSAFE_METHOD_CALL: zend_ast_export_ex(str, ast->child[0], 0, indent); - smart_str_appends(str, "->"); + smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL ? "?->" : "->"); zend_ast_export_var(str, ast->child[1], 0, indent); smart_str_appendc(str, '('); zend_ast_export_ex(str, ast->child[2], 0, indent); @@ -1981,18 +2126,20 @@ simple_list: 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); break; case ZEND_AST_PARAM: + if (ast->child[3]) { + zend_ast_export_attributes(str, ast->child[3], indent, 0); + } if (ast->child[0]) { - if (ast->child[0]->attr & ZEND_TYPE_NULLABLE) { - smart_str_appendc(str, '?'); - } - zend_ast_export_ns_name(str, ast->child[0], 0, indent); + zend_ast_export_type(str, ast->child[0], indent); smart_str_appendc(str, ' '); } if (ast->attr & ZEND_PARAM_REF) { @@ -2103,3 +2250,32 @@ ZEND_API ZEND_COLD zend_string *zend_ast_export(const char *prefix, zend_ast *as smart_str_0(&str); return str.s; } + +zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr) +{ + ZEND_ASSERT(attr->kind == ZEND_AST_ATTRIBUTE_LIST); + + switch (ast->kind) { + case ZEND_AST_FUNC_DECL: + case ZEND_AST_CLOSURE: + case ZEND_AST_METHOD: + case ZEND_AST_ARROW_FUNC: + ((zend_ast_decl *) ast)->child[4] = attr; + break; + case ZEND_AST_CLASS: + ((zend_ast_decl *) ast)->child[3] = attr; + break; + case ZEND_AST_PROP_GROUP: + ast->child[2] = attr; + break; + case ZEND_AST_PARAM: + ast->child[3] = attr; + break; + case ZEND_AST_CLASS_CONST_GROUP: + ast->child[1] = attr; + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + + return ast; +} |