summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorBob Weinand <bobwei9@hotmail.com>2015-05-25 22:58:30 +0200
committerBob Weinand <bobwei9@hotmail.com>2015-05-25 22:58:30 +0200
commit69b54ba926b714dff0f8b54bea385e9a278c5849 (patch)
tree01ef4054445e77256c543e7dd2d55c37e870ed2a /Zend
parent36c3c4743428a57c3d1621bb74649d4d91538f7c (diff)
downloadphp-git-69b54ba926b714dff0f8b54bea385e9a278c5849.tar.gz
Also unreserve T_CLASS
Diffstat (limited to 'Zend')
-rw-r--r--Zend/tests/grammar/regression_003.phpt3
-rw-r--r--Zend/zend_ast.c3
-rw-r--r--Zend/zend_ast.h1
-rw-r--r--Zend/zend_compile.c188
-rw-r--r--Zend/zend_language_parser.y18
5 files changed, 120 insertions, 93 deletions
diff --git a/Zend/tests/grammar/regression_003.phpt b/Zend/tests/grammar/regression_003.phpt
index 7213ca3e07..e475754ccd 100644
--- a/Zend/tests/grammar/regression_003.phpt
+++ b/Zend/tests/grammar/regression_003.phpt
@@ -8,5 +8,6 @@ class Obj
const CLASS = 'class';
}
+?>
--EXPECTF--
-Parse error: syntax error, unexpected 'CLASS' (T_CLASS) in %s on line 5
+Fatal error: A class constant must not be called 'class'; it is reserved for class name fetching in %s on line %d
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index 34a2e132f9..aad9b64ffc 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -1149,9 +1149,6 @@ simple_list:
case ZEND_AST_CONST:
zend_ast_export_ns_name(str, ast->child[0], 0, indent);
break;
- case ZEND_AST_RESOLVE_CLASS_NAME:
- zend_ast_export_ns_name(str, ast->child[0], 0, indent);
- APPEND_STR("::class");
case ZEND_AST_UNPACK:
smart_str_appends(str, "...");
ast = ast->child[0];
diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h
index 33aa292fb7..2b8d4d37b8 100644
--- a/Zend/zend_ast.h
+++ b/Zend/zend_ast.h
@@ -66,7 +66,6 @@ enum _zend_ast_kind {
/* 1 child node */
ZEND_AST_VAR = 1 << ZEND_AST_NUM_CHILDREN_SHIFT,
ZEND_AST_CONST,
- ZEND_AST_RESOLVE_CLASS_NAME,
ZEND_AST_UNPACK,
ZEND_AST_UNARY_PLUS,
ZEND_AST_UNARY_MINUS,
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 458b571e5d..36652c646c 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -1347,6 +1347,88 @@ static inline zend_bool class_name_refers_to_active_ce(zend_string *class_name,
}
/* }}} */
+uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
+{
+ if (zend_string_equals_literal_ci(name, "self")) {
+ return ZEND_FETCH_CLASS_SELF;
+ } else if (zend_string_equals_literal_ci(name, "parent")) {
+ return ZEND_FETCH_CLASS_PARENT;
+ } else if (zend_string_equals_literal_ci(name, "static")) {
+ return ZEND_FETCH_CLASS_STATIC;
+ } else {
+ return ZEND_FETCH_CLASS_DEFAULT;
+ }
+}
+/* }}} */
+
+static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */
+{
+ /* Fully qualified names are always default refs */
+ if (name_ast->attr == ZEND_NAME_FQ) {
+ return ZEND_FETCH_CLASS_DEFAULT;
+ }
+
+ return zend_get_class_fetch_type(zend_ast_get_str(name_ast));
+}
+/* }}} */
+
+static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
+{
+ if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry) && zend_is_scope_known()) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active",
+ fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
+ fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
+ }
+}
+/* }}} */
+
+static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast, zend_ast *name_ast, zend_bool constant) /* {{{ */
+{
+ uint32_t fetch_type;
+
+ if (name_ast->kind != ZEND_AST_ZVAL) {
+ return 0;
+ }
+
+ if (!zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "class")) {
+ return 0;
+ }
+
+ if (class_ast->kind != ZEND_AST_ZVAL) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Dynamic class names are not allowed in compile-time ::class fetch");
+ }
+
+ fetch_type = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
+ zend_ensure_valid_class_fetch_type(fetch_type);
+
+ switch (fetch_type) {
+ case ZEND_FETCH_CLASS_SELF:
+ if (constant || (CG(active_class_entry) && zend_is_scope_known())) {
+ ZVAL_STR_COPY(zv, CG(active_class_entry)->name);
+ } else {
+ ZVAL_NULL(zv);
+ }
+ return 1;
+ case ZEND_FETCH_CLASS_STATIC:
+ case ZEND_FETCH_CLASS_PARENT:
+ if (constant) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "%s::class cannot be used for compile-time class name resolution",
+ fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
+ );
+ } else {
+ ZVAL_NULL(zv);
+ }
+ return 1;
+ case ZEND_FETCH_CLASS_DEFAULT:
+ ZVAL_STR(zv, zend_resolve_class_name_ast(class_ast));
+ return 1;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+}
+/* }}} */
+
static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
{
uint32_t fetch_type = zend_get_class_fetch_type(class_name);
@@ -1627,41 +1709,6 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
}
/* }}} */
-uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
-{
- if (zend_string_equals_literal_ci(name, "self")) {
- return ZEND_FETCH_CLASS_SELF;
- } else if (zend_string_equals_literal_ci(name, "parent")) {
- return ZEND_FETCH_CLASS_PARENT;
- } else if (zend_string_equals_literal_ci(name, "static")) {
- return ZEND_FETCH_CLASS_STATIC;
- } else {
- return ZEND_FETCH_CLASS_DEFAULT;
- }
-}
-/* }}} */
-
-static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */
-{
- /* Fully qualified names are always default refs */
- if (name_ast->attr == ZEND_NAME_FQ) {
- return ZEND_FETCH_CLASS_DEFAULT;
- }
-
- return zend_get_class_fetch_type(zend_ast_get_str(name_ast));
-}
-/* }}} */
-
-static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
-{
- if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry) && zend_is_scope_known()) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active",
- fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
- fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
- }
-}
-/* }}} */
-
ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var) /* {{{ */
{
return op_array->vars[EX_VAR_TO_NUM(var)];
@@ -4749,6 +4796,11 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */
zend_string *name = zend_ast_get_str(name_ast);
zval value_zv;
+ if (zend_string_equals_literal_ci(name, "class")) {
+ zend_error(E_COMPILE_ERROR,
+ "A class constant must not be called 'class'; it is reserved for class name fetching");
+ }
+
zend_const_expr_to_zval(&value_zv, value_ast);
name = zend_new_interned_string_safe(name);
@@ -6315,6 +6367,16 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
zend_op *opline;
zend_string *resolved_name;
+ if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast, const_ast, 0)) {
+ if (Z_TYPE(result->u.constant) == IS_NULL) {
+ zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
+ opline->extended_value = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
+ } else {
+ result->op_type = IS_CONST;
+ }
+ return;
+ }
+
zend_eval_const_expr(&class_ast);
zend_eval_const_expr(&const_ast);
@@ -6326,6 +6388,10 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
return;
}
}
+ if (const_ast->kind == ZEND_AST_ZVAL && zend_string_equals_literal_ci(zend_ast_get_str(const_ast), "class")) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Dynamic class names are not allowed in compile-time ::class fetch");
+ }
if (zend_is_const_default_class_ref(class_ast)) {
class_node.op_type = IS_CONST;
@@ -6538,7 +6604,7 @@ zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
|| kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_DIM
|| kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM
|| kind == ZEND_AST_CONST || kind == ZEND_AST_CLASS_CONST
- || kind == ZEND_AST_RESOLVE_CLASS_NAME || kind == ZEND_AST_MAGIC_CONST;
+ || kind == ZEND_AST_MAGIC_CONST;
}
/* }}} */
@@ -6557,6 +6623,11 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
"Dynamic class names are not allowed in compile-time class constant references");
}
+ if (zend_try_compile_const_expr_resolve_class_name(&result, class_ast, const_ast, 1)) {
+ *ast_ptr = zend_ast_create_zval(&result);
+ return;
+ }
+
class_name = zend_ast_get_str(class_ast);
fetch_type = zend_get_class_fetch_type(class_name);
@@ -6612,36 +6683,6 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */
}
/* }}} */
-void zend_compile_const_expr_resolve_class_name(zend_ast **ast_ptr) /* {{{ */
-{
- zend_ast *ast = *ast_ptr;
- zend_ast *name_ast = ast->child[0];
- zval result;
- uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
- zend_ensure_valid_class_fetch_type(fetch_type);
-
- switch (fetch_type) {
- case ZEND_FETCH_CLASS_SELF:
- ZVAL_STR_COPY(&result, CG(active_class_entry)->name);
- break;
- case ZEND_FETCH_CLASS_STATIC:
- case ZEND_FETCH_CLASS_PARENT:
- zend_error_noreturn(E_COMPILE_ERROR,
- "%s::class cannot be used for compile-time class name resolution",
- fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
- );
- break;
- case ZEND_FETCH_CLASS_DEFAULT:
- ZVAL_STR(&result, zend_resolve_class_name_ast(name_ast));
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
-
- zend_ast_destroy(ast);
- *ast_ptr = zend_ast_create_zval(&result);
-}
-/* }}} */
-
void zend_compile_const_expr_magic_const(zend_ast **ast_ptr) /* {{{ */
{
zend_ast *ast = *ast_ptr;
@@ -6680,9 +6721,6 @@ void zend_compile_const_expr(zend_ast **ast_ptr) /* {{{ */
case ZEND_AST_CONST:
zend_compile_const_expr_const(ast_ptr);
break;
- case ZEND_AST_RESOLVE_CLASS_NAME:
- zend_compile_const_expr_resolve_class_name(ast_ptr);
- break;
case ZEND_AST_MAGIC_CONST:
zend_compile_const_expr_magic_const(ast_ptr);
break;
@@ -6957,9 +6995,6 @@ void zend_compile_expr(znode *result, zend_ast *ast) /* {{{ */
case ZEND_AST_CLASS_CONST:
zend_compile_class_const(result, ast);
return;
- case ZEND_AST_RESOLVE_CLASS_NAME:
- zend_compile_resolve_class_name(result, ast);
- return;
case ZEND_AST_ENCAPS_LIST:
zend_compile_encaps_list(result, ast);
return;
@@ -7129,9 +7164,18 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
zend_ast *name_ast = ast->child[1];
zend_string *resolved_name;
+ if (zend_try_compile_const_expr_resolve_class_name(&result, class_ast, name_ast, 1)) {
+ break;
+ }
+
zend_eval_const_expr(&class_ast);
zend_eval_const_expr(&name_ast);
+ if (name_ast->kind == ZEND_AST_ZVAL && zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "class")) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Dynamic class names are not allowed in compile-time ::class fetch");
+ }
+
if (class_ast->kind != ZEND_AST_ZVAL || name_ast->kind != ZEND_AST_ZVAL) {
return;
}
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 72506c089c..e9a77c3399 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -21,14 +21,6 @@
/* $Id$ */
-/*
- * LALR shift/reduce conflicts and how they are resolved:
- *
- * - 2 shift/reduce conflicts due to the dangling elseif/else ambiguity. Solved by shift.
- *
- */
-
-
#include "zend_compile.h"
#include "zend.h"
#include "zend_list.h"
@@ -246,7 +238,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%type <ast> new_expr anonymous_class class_name class_name_reference simple_variable
%type <ast> internal_functions_in_yacc
%type <ast> exit_expr scalar backticks_expr lexical_var function_call member_name property_name
-%type <ast> variable_class_name dereferencable_scalar class_name_scalar constant dereferencable
+%type <ast> variable_class_name dereferencable_scalar constant dereferencable
%type <ast> callable_expr callable_variable static_member new_variable
%type <ast> assignment_list_element array_pair encaps_var encaps_var_offset isset_variables
%type <ast> top_statement_list use_declarations const_list inner_statement_list if_stmt
@@ -279,7 +271,7 @@ reserved_non_modifiers:
| T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
| T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK
| T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE
-// | T_CLASS
+ | T_CLASS
;
semi_reserved:
@@ -1058,7 +1050,6 @@ scalar:
| '"' encaps_list '"' { $$ = $2; }
| T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; }
| dereferencable_scalar { $$ = $1; }
- | class_name_scalar { $$ = $1; }
| constant { $$ = $1; }
;
@@ -1262,11 +1253,6 @@ isset_variable:
expr { $$ = zend_ast_create(ZEND_AST_ISSET, $1); }
;
-class_name_scalar:
- class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS
- { $$ = zend_ast_create(ZEND_AST_RESOLVE_CLASS_NAME, $1); }
-;
-
%%
/* Copy to YYRES the contents of YYSTR after stripping away unnecessary