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; +}  | 
