From: Nikita Popov Date: Mon, 13 Jan 2020 10:34:04 +0000 (+0100) Subject: Make class name references use the class_name production X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5d869df75329530a28860a3c2399ab32414fe5bc;p=php Make class name references use the class_name production Throw a compile error for "static" references instead, where it isn't already the case. Also extract the code that does that -- we have quite a few places where we get a const class ref and require it to be default. --- diff --git a/Zend/tests/catch_static.phpt b/Zend/tests/catch_static.phpt new file mode 100644 index 0000000000..283aef9181 --- /dev/null +++ b/Zend/tests/catch_static.phpt @@ -0,0 +1,17 @@ +--TEST-- +Cannot catch "static" +--FILE-- + +--EXPECTF-- +Fatal error: Bad class name in the catch statement in %s on line %d diff --git a/Zend/tests/class_uses_static.phpt b/Zend/tests/class_uses_static.phpt new file mode 100644 index 0000000000..96a913272e --- /dev/null +++ b/Zend/tests/class_uses_static.phpt @@ -0,0 +1,12 @@ +--TEST-- +Class cannot use static as a trait, as it is reserved +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use 'static' as trait name as it is reserved in %s on line %d diff --git a/Zend/tests/errmsg_030.phpt b/Zend/tests/errmsg_030.phpt index c0d42263c3..589965cf08 100644 --- a/Zend/tests/errmsg_030.phpt +++ b/Zend/tests/errmsg_030.phpt @@ -9,4 +9,4 @@ class test extends self { echo "Done\n"; ?> --EXPECTF-- -Fatal error: Cannot use 'self' as class name as it is reserved in %s on line %d +Fatal error: Cannot use 'self' as class name, as it is reserved in %s on line %d diff --git a/Zend/tests/errmsg_031.phpt b/Zend/tests/errmsg_031.phpt index c847a26e64..ed1d0bec2d 100644 --- a/Zend/tests/errmsg_031.phpt +++ b/Zend/tests/errmsg_031.phpt @@ -9,4 +9,4 @@ class test extends parent { echo "Done\n"; ?> --EXPECTF-- -Fatal error: Cannot use 'parent' as class name as it is reserved in %s on line %d +Fatal error: Cannot use 'parent' as class name, as it is reserved in %s on line %d diff --git a/Zend/tests/errmsg_035.phpt b/Zend/tests/errmsg_035.phpt index e8fa8da8e8..140e3e9cf4 100644 --- a/Zend/tests/errmsg_035.phpt +++ b/Zend/tests/errmsg_035.phpt @@ -9,4 +9,4 @@ class test implements self { echo "Done\n"; ?> --EXPECTF-- -Fatal error: Cannot use 'self' as interface name as it is reserved in %s on line %d +Fatal error: Cannot use 'self' as interface name, as it is reserved in %s on line %d diff --git a/Zend/tests/errmsg_036.phpt b/Zend/tests/errmsg_036.phpt index 4f98f384d7..33c6bca1d6 100644 --- a/Zend/tests/errmsg_036.phpt +++ b/Zend/tests/errmsg_036.phpt @@ -9,4 +9,4 @@ class test implements parent { echo "Done\n"; ?> --EXPECTF-- -Fatal error: Cannot use 'parent' as interface name as it is reserved in %s on line %d +Fatal error: Cannot use 'parent' as interface name, as it is reserved in %s on line %d diff --git a/Zend/tests/interface_extends_static.phpt b/Zend/tests/interface_extends_static.phpt new file mode 100644 index 0000000000..3d12070ec8 --- /dev/null +++ b/Zend/tests/interface_extends_static.phpt @@ -0,0 +1,10 @@ +--TEST-- +Interface cannot extend static, as it is reserved +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use 'static' as interface name, as it is reserved in %s on line %d diff --git a/Zend/tests/lsb_007.phpt b/Zend/tests/lsb_007.phpt index c28e815be0..970044eab2 100644 --- a/Zend/tests/lsb_007.phpt +++ b/Zend/tests/lsb_007.phpt @@ -9,4 +9,4 @@ class Foo implements static { ?> ==DONE== --EXPECTF-- -Parse error: %s error,%sexpecting %s in %s on line %d +Fatal error: Cannot use 'static' as interface name, as it is reserved in %s on line %d diff --git a/Zend/tests/static_in_trait_insteadof_list.phpt b/Zend/tests/static_in_trait_insteadof_list.phpt new file mode 100644 index 0000000000..77ecf1e42b --- /dev/null +++ b/Zend/tests/static_in_trait_insteadof_list.phpt @@ -0,0 +1,18 @@ +--TEST-- +Cannot use static in trait insteadof list +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use 'static' as trait name, as it is reserved in %s on line %d diff --git a/Zend/tests/static_in_trait_insteadof_reference.phpt b/Zend/tests/static_in_trait_insteadof_reference.phpt new file mode 100644 index 0000000000..95a6b3c170 --- /dev/null +++ b/Zend/tests/static_in_trait_insteadof_reference.phpt @@ -0,0 +1,18 @@ +--TEST-- +Cannot use static in trait insteadof method reference +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use 'static' as trait name, as it is reserved in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 7cd71426f5..6b26630869 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1498,6 +1498,17 @@ static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */ } /* }}} */ +static zend_string *zend_resolve_const_class_name_reference(zend_ast *ast, const char *type) +{ + zend_string *class_name = zend_ast_get_str(ast); + if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type_ast(ast)) { + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot use '%s' as %s, as it is reserved", + ZSTR_VAL(class_name), type); + } + return zend_resolve_class_name(class_name, ast->attr); +} + static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */ { if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && zend_is_scope_known()) { @@ -6399,7 +6410,7 @@ static void zend_compile_method_ref(zend_ast *ast, zend_trait_method_reference * method_ref->method_name = zend_string_copy(zend_ast_get_str(method_ast)); if (class_ast) { - method_ref->class_name = zend_resolve_class_name_ast(class_ast); + method_ref->class_name = zend_resolve_const_class_name_reference(class_ast, "trait name"); } else { method_ref->class_name = NULL; } @@ -6419,7 +6430,8 @@ static void zend_compile_trait_precedence(zend_ast *ast) /* {{{ */ for (i = 0; i < insteadof_list->children; ++i) { zend_ast *name_ast = insteadof_list->child[i]; - precedence->exclude_class_names[i] = zend_resolve_class_name_ast(name_ast); + precedence->exclude_class_names[i] = + zend_resolve_const_class_name_reference(name_ast, "trait name"); } zend_add_to_list(&CG(active_class_entry)->trait_precedences, precedence); @@ -6513,15 +6525,8 @@ void zend_compile_implements(zend_ast *ast) /* {{{ */ for (i = 0; i < list->children; ++i) { zend_ast *class_ast = list->child[i]; - zend_string *name = zend_ast_get_str(class_ast); - - if (!zend_is_const_default_class_ref(class_ast)) { - efree(interface_names); - zend_error_noreturn(E_COMPILE_ERROR, - "Cannot use '%s' as interface name as it is reserved", ZSTR_VAL(name)); - } - - interface_names[i].name = zend_resolve_class_name_ast(class_ast); + interface_names[i].name = + zend_resolve_const_class_name_reference(class_ast, "interface name"); interface_names[i].lc_name = zend_string_tolower(interface_names[i].name); } @@ -6605,23 +6610,8 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ } if (extends_ast) { - znode extends_node; - zend_string *extends_name; - - if (!zend_is_const_default_class_ref(extends_ast)) { - extends_name = zend_ast_get_str(extends_ast); - zend_error_noreturn(E_COMPILE_ERROR, - "Cannot use '%s' as class name as it is reserved", ZSTR_VAL(extends_name)); - } - - zend_compile_expr(&extends_node, extends_ast); - if (extends_node.op_type != IS_CONST || Z_TYPE(extends_node.u.constant) != IS_STRING) { - zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name"); - } - extends_name = Z_STR(extends_node.u.constant); - ce->parent_name = zend_resolve_class_name(extends_name, - extends_ast->kind == ZEND_AST_ZVAL ? extends_ast->attr : ZEND_NAME_FQ); - zend_string_release_ex(extends_name, 0); + ce->parent_name = + zend_resolve_const_class_name_reference(extends_ast, "class name"); ce->ce_flags |= ZEND_ACC_INHERITED; } diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index f501527740..3d31ce03fe 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -249,7 +249,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %type echo_expr_list unset_variables catch_name_list catch_list parameter_list class_statement_list %type implements_list case_list if_stmt_without_else %type non_empty_parameter_list argument_list non_empty_argument_list property_list -%type class_const_list class_const_decl name_list trait_adaptations method_body non_empty_for_exprs +%type class_const_list class_const_decl class_name_list trait_adaptations method_body non_empty_for_exprs %type ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars %type lexical_var_list encaps_list %type array_pair non_empty_array_pair_list array_pair_list possible_array_pair @@ -469,8 +469,8 @@ catch_list: ; catch_name_list: - name { $$ = zend_ast_create_list(1, ZEND_AST_NAME_LIST, $1); } - | catch_name_list '|' name { $$ = zend_ast_list_add($1, $3); } + class_name { $$ = zend_ast_create_list(1, ZEND_AST_NAME_LIST, $1); } + | catch_name_list '|' class_name { $$ = zend_ast_list_add($1, $3); } ; finally_statement: @@ -542,13 +542,13 @@ extends_from: ; interface_extends_list: - /* empty */ { $$ = NULL; } - | T_EXTENDS name_list { $$ = $2; } + /* empty */ { $$ = NULL; } + | T_EXTENDS class_name_list { $$ = $2; } ; implements_list: - /* empty */ { $$ = NULL; } - | T_IMPLEMENTS name_list { $$ = $2; } + /* empty */ { $$ = NULL; } + | T_IMPLEMENTS class_name_list { $$ = $2; } ; foreach_variable: @@ -732,7 +732,7 @@ class_statement: $$->attr = $1; } | method_modifiers T_CONST class_const_list ';' { $$ = $3; $$->attr = $1; } - | T_USE name_list trait_adaptations + | T_USE class_name_list trait_adaptations { $$ = zend_ast_create(ZEND_AST_USE_TRAIT, $2, $3); } | method_modifiers function returns_ref identifier backup_doc_comment '(' parameter_list ')' return_type backup_fn_flags method_body backup_fn_flags @@ -740,9 +740,9 @@ class_statement: zend_ast_get_str($4), $7, NULL, $11, $9); CG(extra_fn_flags) = $10; } ; -name_list: - name { $$ = zend_ast_create_list(1, ZEND_AST_NAME_LIST, $1); } - | name_list ',' name { $$ = zend_ast_list_add($1, $3); } +class_name_list: + class_name { $$ = zend_ast_create_list(1, ZEND_AST_NAME_LIST, $1); } + | class_name_list ',' class_name { $$ = zend_ast_list_add($1, $3); } ; trait_adaptations: @@ -764,7 +764,7 @@ trait_adaptation: ; trait_precedence: - absolute_trait_method_reference T_INSTEADOF name_list + absolute_trait_method_reference T_INSTEADOF class_name_list { $$ = zend_ast_create(ZEND_AST_TRAIT_PRECEDENCE, $1, $3); } ; @@ -786,7 +786,7 @@ trait_method_reference: ; absolute_trait_method_reference: - name T_PAAMAYIM_NEKUDOTAYIM identifier + class_name T_PAAMAYIM_NEKUDOTAYIM identifier { $$ = zend_ast_create(ZEND_AST_METHOD_REFERENCE, $1, $3); } ;