1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

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.
This commit is contained in:
Nikita Popov
2020-01-13 11:34:04 +01:00
parent 2a3e37a496
commit 5d869df753
12 changed files with 111 additions and 46 deletions

View File

@@ -0,0 +1,17 @@
--TEST--
Cannot catch "static"
--FILE--
<?php
// This could in principle be supported, but isn't right now.
class Test {
public function method() {
try {
foo();
} catch (static $e) {}
}
}
?>
--EXPECTF--
Fatal error: Bad class name in the catch statement in %s on line %d

View File

@@ -0,0 +1,12 @@
--TEST--
Class cannot use static as a trait, as it is reserved
--FILE--
<?php
class Test {
use static;
}
?>
--EXPECTF--
Fatal error: Cannot use 'static' as trait name as it is reserved in %s on line %d

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,10 @@
--TEST--
Interface cannot extend static, as it is reserved
--FILE--
<?php
interface Foo extends static {}
?>
--EXPECTF--
Fatal error: Cannot use 'static' as interface name, as it is reserved in %s on line %d

View File

@@ -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

View File

@@ -0,0 +1,18 @@
--TEST--
Cannot use static in trait insteadof list
--FILE--
<?php
trait SomeTrait {
public function foobar() {}
}
class Test {
use SomeTrait {
SomeTrait::foobar insteadof static;
}
}
?>
--EXPECTF--
Fatal error: Cannot use 'static' as trait name, as it is reserved in %s on line %d

View File

@@ -0,0 +1,18 @@
--TEST--
Cannot use static in trait insteadof method reference
--FILE--
<?php
trait SomeTrait {
public function foobar() {}
}
class Test {
use SomeTrait {
static::foobar insteadof SomeTrait;
}
}
?>
--EXPECTF--
Fatal error: Cannot use 'static' as trait name, as it is reserved in %s on line %d

View File

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

View File

@@ -249,7 +249,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%type <ast> echo_expr_list unset_variables catch_name_list catch_list parameter_list class_statement_list
%type <ast> implements_list case_list if_stmt_without_else
%type <ast> non_empty_parameter_list argument_list non_empty_argument_list property_list
%type <ast> class_const_list class_const_decl name_list trait_adaptations method_body non_empty_for_exprs
%type <ast> class_const_list class_const_decl class_name_list trait_adaptations method_body non_empty_for_exprs
%type <ast> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars
%type <ast> lexical_var_list encaps_list
%type <ast> 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); }
;