From: moliata <7127204+moliata@users.noreply.github.com> Date: Mon, 6 Jul 2020 16:23:27 +0000 (+0300) Subject: refactor: class constants parsing X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4a0d6901bb00154e40237143a754234a266d2774;p=php refactor: class constants parsing As part of my work on typed class constants, I wanted to make a separate pull request for unrelated changes. These include: * Moving from ast->child[0]->attr to ast->attr * Making zend_ast_export_ex() export class constants' visibility * Extracting an additional zend_compile_class_const_group() function Closes GH-5812. --- diff --git a/Zend/tests/assert/expect_015.phpt b/Zend/tests/assert/expect_015.phpt index 21ff636f92..3414f52e1b 100644 --- a/Zend/tests/assert/expect_015.phpt +++ b/Zend/tests/assert/expect_015.phpt @@ -164,8 +164,8 @@ Warning: assert(): assert(0 && ($a = function () { Warning: assert(): assert(0 && ($a = function &(array &$a, ?X $b = null) use($c, &$d): ?X { abstract class A extends B implements C, D { - const X = 12; - const Y = self::X, Z = 'aaa'; + public const X = 12; + public const Y = self::X, Z = 'aaa'; public $a = 1, $b; protected $c; private static $d = null; diff --git a/Zend/tests/attributes/012_ast_export.phpt b/Zend/tests/attributes/012_ast_export.phpt index 47176b1b0d..fe3539c8a9 100644 --- a/Zend/tests/attributes/012_ast_export.phpt +++ b/Zend/tests/attributes/012_ast_export.phpt @@ -29,7 +29,7 @@ Warning: assert(): assert(0 && ($a = <> fn() => 1)) failed in % Warning: assert(): assert(0 && ($a = new <> class { <> <> - const FOO = 'foo'; + public const FOO = 'foo'; <> public $x; <> diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 5d7c98dad5..53c3be0de9 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1381,6 +1381,16 @@ static ZEND_COLD void zend_ast_export_attributes(smart_str *str, zend_ast *ast, } } +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); @@ -1478,13 +1488,9 @@ tail_call: zend_bool newlines = !(ast->kind == ZEND_AST_CLOSURE || ast->kind == ZEND_AST_ARROW_FUNC); zend_ast_export_attributes(str, decl->child[4], indent, newlines); } - 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 "); - } + + zend_ast_export_visibility(str, decl->flags); + if (decl->flags & ZEND_ACC_STATIC) { smart_str_appends(str, "static "); } @@ -1595,13 +1601,9 @@ simple_list: if (ast->child[2]) { zend_ast_export_attributes(str, ast->child[2], indent, 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 "); - } + + zend_ast_export_visibility(str, ast->attr); + if (ast->attr & ZEND_ACC_STATIC) { smart_str_appends(str, "static "); } @@ -1616,15 +1618,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_ex(str, ast->child[0], 0, indent); - break; + + 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; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 7ee7e8e9d3..ea5baf2a12 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6613,18 +6613,18 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags, z } /* }}} */ -void zend_compile_prop_group(zend_ast *list) /* {{{ */ +void zend_compile_prop_group(zend_ast *ast) /* {{{ */ { - zend_ast *type_ast = list->child[0]; - zend_ast *prop_ast = list->child[1]; - zend_ast *attr_ast = list->child[2]; + zend_ast *type_ast = ast->child[0]; + zend_ast *prop_ast = ast->child[1]; + zend_ast *attr_ast = ast->child[2]; if (attr_ast && zend_ast_get_list(prop_ast)->children > 1) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot apply attributes to a group of properties"); return; } - zend_compile_prop_decl(prop_ast, type_ast, list->attr, attr_ast); + zend_compile_prop_decl(prop_ast, type_ast, ast->attr, attr_ast); } /* }}} */ @@ -6640,23 +6640,18 @@ static void zend_check_const_and_trait_alias_attr(uint32_t attr, const char* ent } /* }}} */ -void zend_compile_class_const_decl(zend_ast *ast, zend_ast *attr_ast) /* {{{ */ +void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_ast *attr_ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); zend_class_entry *ce = CG(active_class_entry); - uint32_t i; + uint32_t i, children = list->children; if ((ce->ce_flags & ZEND_ACC_TRAIT) != 0) { zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants"); return; } - if (attr_ast && list->children > 1) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot apply attributes to a group of constants"); - return; - } - - for (i = 0; i < list->children; ++i) { + for (i = 0; i < children; ++i) { zend_class_constant *c; zend_ast *const_ast = list->child[i]; zend_ast *name_ast = const_ast->child[0]; @@ -6666,12 +6661,12 @@ void zend_compile_class_const_decl(zend_ast *ast, zend_ast *attr_ast) /* {{{ */ zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL; zval value_zv; - if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) { - zend_check_const_and_trait_alias_attr(ast->attr, "constant"); + if (UNEXPECTED(flags & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) { + zend_check_const_and_trait_alias_attr(flags, "constant"); } zend_const_expr_to_zval(&value_zv, value_ast); - c = zend_declare_class_constant_ex(ce, name, &value_zv, ast->attr, doc_comment); + c = zend_declare_class_constant_ex(ce, name, &value_zv, flags, doc_comment); if (attr_ast) { zend_compile_attributes(&c->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_CLASS_CONST); @@ -6680,6 +6675,21 @@ void zend_compile_class_const_decl(zend_ast *ast, zend_ast *attr_ast) /* {{{ */ } /* }}} */ +void zend_compile_class_const_group(zend_ast *ast) /* {{{ */ +{ + zend_ast *const_ast = ast->child[0]; + zend_ast *attr_ast = ast->child[1]; + + if (attr_ast && zend_ast_get_list(const_ast)->children > 1) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot apply attributes to a group of constants"); + + return; + } + + zend_compile_class_const_decl(const_ast, ast->attr, attr_ast); +} +/* }}} */ + static void zend_compile_method_ref(zend_ast *ast, zend_trait_method_reference *method_ref) /* {{{ */ { zend_ast *class_ast = ast->child[0]; @@ -8983,7 +8993,7 @@ void zend_compile_stmt(zend_ast *ast) /* {{{ */ zend_compile_prop_group(ast); break; case ZEND_AST_CLASS_CONST_GROUP: - zend_compile_class_const_decl(ast->child[0], ast->child[1]); + zend_compile_class_const_group(ast); break; case ZEND_AST_USE_TRAIT: zend_compile_use_trait(ast); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 88b159cc6e..7827a178f6 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -797,7 +797,8 @@ attributed_class_statement: { $$ = zend_ast_create(ZEND_AST_PROP_GROUP, $2, $3, NULL); $$->attr = $1; } | method_modifiers T_CONST class_const_list ';' - { $$ = zend_ast_create(ZEND_AST_CLASS_CONST_GROUP, $3, NULL); $3->attr = $1; } + { $$ = zend_ast_create(ZEND_AST_CLASS_CONST_GROUP, $3, NULL); + $$->attr = $1; } | method_modifiers function returns_ref identifier backup_doc_comment '(' parameter_list ')' return_type backup_fn_flags method_body backup_fn_flags { $$ = zend_ast_create_decl(ZEND_AST_METHOD, $3 | $1 | $12, $2, $5,