1
0
mirror of https://github.com/php/php-src.git synced 2026-04-27 18:23:26 +02:00

Working commit for constant scalar expressions (with constants).

Tests will follow.
This commit is contained in:
Bob Weinand
2013-10-31 08:57:12 +01:00
parent 4218e89f8d
commit 2361745806
19 changed files with 602 additions and 279 deletions
+2 -1
View File
@@ -18,7 +18,8 @@ libZend_la_SOURCES=\
zend_default_classes.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c \
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \
zend_generators.c
zend_generators.c \
zend_ast.c
libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
+4
View File
@@ -119,6 +119,10 @@ SOURCE=.\zend_API.c
# End Source File
# Begin Source File
SOURCE=.\zend_ast.c
# End Source File
# Begin Source File
SOURCE=.\zend_builtin_functions.c
# End Source File
# Begin Source File
+4
View File
@@ -140,6 +140,10 @@ SOURCE=.\zend_alloc.c
# End Source File
# Begin Source File
SOURCE=.\zend_ast.c
# End Source File
# Begin Source File
SOURCE=.\zend_API.c
# End Source File
# Begin Source File
+13 -10
View File
@@ -317,6 +317,7 @@ typedef struct _zend_object {
} zend_object;
#include "zend_object_handlers.h"
#include "zend_ast.h"
typedef union _zvalue_value {
long lval; /* long value */
@@ -327,6 +328,7 @@ typedef union _zvalue_value {
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
zend_ast *ast;
} zvalue_value;
struct _zval_struct {
@@ -577,17 +579,18 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
/* data types */
/* All data types <= IS_BOOL have their constructor/destructors skipped */
#define IS_NULL 0
#define IS_LONG 1
#define IS_DOUBLE 2
#define IS_BOOL 3
#define IS_ARRAY 4
#define IS_OBJECT 5
#define IS_STRING 6
#define IS_RESOURCE 7
#define IS_CONSTANT 8
#define IS_NULL 0
#define IS_LONG 1
#define IS_DOUBLE 2
#define IS_BOOL 3
#define IS_ARRAY 4
#define IS_OBJECT 5
#define IS_STRING 6
#define IS_RESOURCE 7
#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9
#define IS_CALLABLE 10
#define IS_CONSTANT_AST 10
#define IS_CALLABLE 11
/* Ugly hack to support constants as static array indices */
#define IS_CONSTANT_TYPE_MASK 0x00f
+28 -25
View File
@@ -1053,34 +1053,37 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro
static int zval_update_class_constant(zval **pp, int is_static, int offset TSRMLS_DC) /* {{{ */
{
if ((Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
(Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT_ARRAY) {
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
switch (Z_TYPE_PP(pp) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST: {
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
if ((*scope)->parent) {
zend_class_entry *ce = *scope;
HashPosition pos;
zend_property_info *prop_info;
if ((*scope)->parent) {
zend_class_entry *ce = *scope;
HashPosition pos;
zend_property_info *prop_info;
do {
for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS;
zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) &&
offset == prop_info->offset) {
int ret;
zend_class_entry *old_scope = *scope;
*scope = prop_info->ce;
ret = zval_update_constant(pp, (void*)1 TSRMLS_CC);
*scope = old_scope;
return ret;
}
}
ce = ce->parent;
} while (ce);
do {
for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS;
zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) &&
offset == prop_info->offset) {
int ret;
zend_class_entry *old_scope = *scope;
*scope = prop_info->ce;
ret = zval_update_constant(pp, (void*)1 TSRMLS_CC);
*scope = old_scope;
return ret;
}
}
ce = ce->parent;
} while (ce);
}
return zval_update_constant(pp, (void*)1 TSRMLS_CC);
}
return zval_update_constant(pp, (void*)1 TSRMLS_CC);
}
return 0;
}
+128
View File
@@ -0,0 +1,128 @@
/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Bob Weinand <bwoebi@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#include "zend_ast.h"
#include "zend_execute.h"
#define OP_IS_CONST_THEN(op, do_code) \
switch (Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK) { \
case IS_CONSTANT: \
case IS_CONSTANT_ARRAY: \
case IS_CONSTANT_AST: { \
do_code \
} \
}
#define OP_IS_NOT_CONST_THEN(op, do_code) \
switch (Z_TYPE_P(op) & IS_CONSTANT_TYPE_MASK) { \
case IS_CONSTANT: \
case IS_CONSTANT_ARRAY: \
case IS_CONSTANT_AST: \
break; \
\
default: { \
do_code \
} \
}
#define COPY_ZVAL_TO_OP(nr) \
Z_AST_P(result)->ops[nr] = emalloc(sizeof(zval)); \
*Z_AST_P(result)->ops[nr] = *op##nr;
void zend_ast_add(zval *result, intermediary_ast_function_type func, char op_count) {
zend_ast *ast = emalloc(sizeof(zend_ast));
ast->op_count = op_count;
ast->ops = emalloc(op_count * sizeof(zval *));
ast->refcount = 1;
ast->func = func;
Z_AST_P(result) = ast;
Z_TYPE_P(result) = IS_CONSTANT_AST;
}
/* Do operations on constant operators at compile time (AST building time) */
void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0) {
OP_IS_NOT_CONST_THEN(op0,
func(result, op0);
return;
)
zend_ast_add(result, (intermediary_ast_function_type)func, 1);
COPY_ZVAL_TO_OP(0)
}
void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1) {
OP_IS_NOT_CONST_THEN(op0, OP_IS_NOT_CONST_THEN(op1,
func(result, op0, op1);
return;
))
zend_ast_add(result, (intermediary_ast_function_type)func, 2);
COPY_ZVAL_TO_OP(0)
COPY_ZVAL_TO_OP(1)
}
void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2) {
OP_IS_NOT_CONST_THEN(op0, OP_IS_NOT_CONST_THEN(op1, OP_IS_NOT_CONST_THEN(op2,
func(result, op0, op1, op2);
return;
)))
zend_ast_add(result, (intermediary_ast_function_type)func, 3);
COPY_ZVAL_TO_OP(0)
COPY_ZVAL_TO_OP(1)
COPY_ZVAL_TO_OP(2)
}
void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC) {
int i;
for (i = ast->op_count; i--;) {
OP_IS_CONST_THEN(ast->ops[i],
zval_update_constant_ex(&ast->ops[i], (void *)1, NULL TSRMLS_CC);
)
}
switch (ast->op_count) {
case 1:
((unary_ast_func)ast->func)(result, ast->ops[0]);
break;
case 2:
((binary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1]);
break;
case 3:
((ternary_ast_func)ast->func)(result, ast->ops[0], ast->ops[1], ast->ops[2]);
break;
}
}
void zend_ast_destroy(zend_ast *ast TSRMLS_DC) {
int i;
for (i = ast->op_count; i--;) {
if (!Z_DELREF_P(ast->ops[i])) {
zval_dtor(ast->ops[i]);
efree(ast->ops[i]);
}
}
efree(ast->ops);
efree(ast);
}
+60
View File
@@ -0,0 +1,60 @@
/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Bob Weinand <bwoebi@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef ZEND_AST_H
#define ZEND_AST_H
typedef struct _zend_ast zend_ast;
#include "zend.h"
typedef void(*intermediary_ast_function_type)(zval *, ...);
typedef int(*unary_ast_func)(zval *result, zval *op0);
typedef int(*binary_ast_func)(zval *result, zval *op0, zval *op1);
typedef int(*ternary_ast_func)(zval *result, zval *op0, zval *op1, zval *op2);
struct _zend_ast {
char op_count;
zval **ops;
intermediary_ast_function_type func;
int refcount;
};
void zend_ast_add_unary(zval *result, unary_ast_func func, zval *op0);
void zend_ast_add_binary(zval *result, binary_ast_func func, zval *op0, zval *op1);
void zend_ast_add_ternary(zval *result, ternary_ast_func func, zval *op0, zval *op1, zval *op2);
void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC);
void zend_ast_destroy(zend_ast *ast TSRMLS_DC);
#define ZEND_AST_ADD_REF(ast) ++ast->refcount
static inline int ZEND_AST_DEL_REF(zend_ast *ast) {
if (ast->refcount == 1) {
TSRMLS_FETCH();
zend_ast_destroy(ast TSRMLS_CC);
return 0;
}
return --ast->refcount;
}
#endif
+5 -2
View File
@@ -946,8 +946,11 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
/* this is necessary to make it able to work with default array
* properties, returned to user */
if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
switch (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST:
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
}
add_assoc_zval(return_value, key, prop_copy);
+20 -5
View File
@@ -1891,7 +1891,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ
if (class_type->u.constant.type == IS_ARRAY) {
cur_arg_info->type_hint = IS_ARRAY;
if (op == ZEND_RECV_INIT) {
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
cur_arg_info->allow_null = 1;
} else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) {
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
@@ -1900,7 +1900,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ
} else if (class_type->u.constant.type == IS_CALLABLE) {
cur_arg_info->type_hint = IS_CALLABLE;
if (op == ZEND_RECV_INIT) {
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
cur_arg_info->allow_null = 1;
} else {
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with callable type hint can only be NULL");
@@ -1915,7 +1915,7 @@ void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initializ
cur_arg_info->class_name = Z_STRVAL(class_type->u.constant);
cur_arg_info->class_name_len = Z_STRLEN(class_type->u.constant);
if (op == ZEND_RECV_INIT) {
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
cur_arg_info->allow_null = 1;
} else {
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
@@ -5530,7 +5530,8 @@ static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal
(c->flags & CONST_PERSISTENT) &&
!(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
Z_TYPE(c->value) != IS_CONSTANT &&
Z_TYPE(c->value) != IS_CONSTANT_ARRAY) {
Z_TYPE(c->value) != IS_CONSTANT_ARRAY &&
Z_TYPE(c->value) != IS_CONSTANT_AST) {
return c;
}
return NULL;
@@ -5772,7 +5773,7 @@ void zend_do_add_static_array_element(znode *result, znode *offset, const znode
ALLOC_ZVAL(element);
*element = expr->u.constant;
if (offset) {
switch (offset->u.constant.type & IS_CONSTANT_TYPE_MASK) {
switch (Z_TYPE(offset->u.constant) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
/* Ugly hack to denote that this value has a constant index */
Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
@@ -5782,6 +5783,20 @@ void zend_do_add_static_array_element(znode *result, znode *offset, const znode
zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+3, &element, sizeof(zval *), NULL);
zval_dtor(&offset->u.constant);
break;
case IS_CONSTANT_AST: {
/* Another ugly hack to store the data about the AST in the array */
char* key;
int len = sizeof(zend_ast *);
Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
key = emalloc(len + 2);
*(zend_ast **)key = Z_AST(offset->u.constant);
key[len] = Z_TYPE(offset->u.constant);
key[len + 1] = 0;
zend_symtable_update(Z_ARRVAL(result->u.constant), key, len + 2, &element, sizeof(zval *), NULL);
efree(key);
}
break;
case IS_STRING:
zend_symtable_update(Z_ARRVAL(result->u.constant), Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+1, &element, sizeof(zval *), NULL);
zval_dtor(&offset->u.constant);
+1
View File
@@ -23,6 +23,7 @@
#define ZEND_COMPILE_H
#include "zend.h"
#include "zend_ast.h"
#ifdef HAVE_STDARG_H
# include <stdarg.h>
+184 -164
View File
@@ -478,188 +478,208 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
if (IS_CONSTANT_VISITED(p)) {
zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
} else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
int refcount;
zend_uchar is_ref;
return FAILURE;
}
switch (Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT: {
int refcount;
zend_uchar is_ref;
SEPARATE_ZVAL_IF_NOT_REF(pp);
p = *pp;
SEPARATE_ZVAL_IF_NOT_REF(pp);
p = *pp;
MARK_CONSTANT_VISITED(p);
MARK_CONSTANT_VISITED(p);
refcount = Z_REFCOUNT_P(p);
is_ref = Z_ISREF_P(p);
refcount = Z_REFCOUNT_P(p);
is_ref = Z_ISREF_P(p);
if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
char *actual = Z_STRVAL_P(p);
if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
char *actual = Z_STRVAL_P(p);
if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
if (inline_change) {
colon = estrndup(colon, Z_STRLEN_P(p));
str_efree(Z_STRVAL_P(p));
Z_STRVAL_P(p) = colon;
} else {
Z_STRVAL_P(p) = colon + 1;
}
} else {
char *save = actual, *slash;
int actual_len = Z_STRLEN_P(p);
if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
actual = slash + 1;
actual_len -= (actual - Z_STRVAL_P(p));
if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
if (inline_change) {
actual = estrndup(actual, actual_len);
Z_STRVAL_P(p) = actual;
Z_STRLEN_P(p) = actual_len;
}
}
if (actual[0] == '\\') {
if (inline_change) {
memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
--Z_STRLEN_P(p);
colon = estrndup(colon, Z_STRLEN_P(p));
str_efree(Z_STRVAL_P(p));
Z_STRVAL_P(p) = colon;
} else {
++actual;
Z_STRVAL_P(p) = colon + 1;
}
--actual_len;
}
if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
int fix_save = 0;
if (save[0] == '\\') {
save++;
fix_save = 1;
}
zend_error(E_ERROR, "Undefined constant '%s'", save);
if (fix_save) {
save--;
}
if (inline_change) {
str_efree(save);
}
save = NULL;
}
if (inline_change && save && save != actual) {
str_efree(save);
}
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
p->type = IS_STRING;
if (!inline_change) {
Z_STRVAL_P(p) = actual;
Z_STRLEN_P(p) = actual_len;
zval_copy_ctor(p);
}
}
} else {
if (inline_change) {
str_efree(Z_STRVAL_P(p));
}
*p = const_value;
}
Z_SET_REFCOUNT_P(p, refcount);
Z_SET_ISREF_TO_P(p, is_ref);
} else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) {
zval **element, *new_val;
char *str_index;
uint str_index_len;
ulong num_index;
int ret;
SEPARATE_ZVAL_IF_NOT_REF(pp);
p = *pp;
Z_TYPE_P(p) = IS_ARRAY;
if (!inline_change) {
zval *tmp;
HashTable *tmp_ht = NULL;
ALLOC_HASHTABLE(tmp_ht);
zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
Z_ARRVAL_P(p) = tmp_ht;
}
/* First go over the array and see if there are any constant indices */
zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
zend_hash_move_forward(Z_ARRVAL_P(p));
continue;
}
Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
zend_hash_move_forward(Z_ARRVAL_P(p));
continue;
}
if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
char *actual;
const char *save = str_index;
if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
str_index_len -= ((colon - str_index) + 1);
str_index = colon;
} else {
if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
actual++;
str_index_len -= (actual - str_index);
str_index = actual;
char *save = actual, *slash;
int actual_len = Z_STRLEN_P(p);
if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
actual = slash + 1;
actual_len -= (actual - Z_STRVAL_P(p));
if (inline_change) {
actual = estrndup(actual, actual_len);
Z_STRVAL_P(p) = actual;
Z_STRLEN_P(p) = actual_len;
}
}
if (str_index[0] == '\\') {
++str_index;
--str_index_len;
if (actual[0] == '\\') {
if (inline_change) {
memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
--Z_STRLEN_P(p);
} else {
++actual;
}
--actual_len;
}
if (save[0] == '\\') {
++save;
}
if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
int fix_save = 0;
if (save[0] == '\\') {
save++;
fix_save = 1;
}
zend_error(E_ERROR, "Undefined constant '%s'", save);
if (fix_save) {
save--;
}
if (inline_change) {
str_efree(save);
}
save = NULL;
}
if (inline_change && save && save != actual) {
str_efree(save);
}
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
p->type = IS_STRING;
if (!inline_change) {
Z_STRVAL_P(p) = actual;
Z_STRLEN_P(p) = actual_len;
zval_copy_ctor(p);
}
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
}
ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
} else {
if (inline_change) {
str_efree(Z_STRVAL_P(p));
}
*p = const_value;
}
if (Z_REFCOUNT_PP(element) > 1) {
ALLOC_ZVAL(new_val);
*new_val = **element;
zval_copy_ctor(new_val);
Z_SET_REFCOUNT_P(new_val, 1);
Z_UNSET_ISREF_P(new_val);
/* preserve this bit for inheritance */
Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
zval_ptr_dtor(element);
*element = new_val;
}
switch (Z_TYPE(const_value)) {
case IS_STRING:
ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
break;
case IS_BOOL:
case IS_LONG:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
break;
case IS_DOUBLE:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
break;
case IS_NULL:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
break;
default:
ret = SUCCESS;
break;
}
if (ret == SUCCESS) {
zend_hash_move_forward(Z_ARRVAL_P(p));
}
zval_dtor(&const_value);
Z_SET_REFCOUNT_P(p, refcount);
Z_SET_ISREF_TO_P(p, is_ref);
}
break;
case IS_CONSTANT_ARRAY: {
zval **element, *new_val;
char *str_index;
uint str_index_len;
ulong num_index;
int ret;
SEPARATE_ZVAL_IF_NOT_REF(pp);
p = *pp;
Z_TYPE_P(p) = IS_ARRAY;
if (!inline_change) {
zval *tmp;
HashTable *tmp_ht = NULL;
ALLOC_HASHTABLE(tmp_ht);
zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
Z_ARRVAL_P(p) = tmp_ht;
}
/* First go over the array and see if there are any constant indices */
zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
zend_hash_move_forward(Z_ARRVAL_P(p));
continue;
}
Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
zend_hash_move_forward(Z_ARRVAL_P(p));
continue;
}
if (str_index[str_index_len - 2] == IS_CONSTANT_AST) {
zend_ast_evaluate(&const_value, *(zend_ast **)str_index);
ZEND_AST_DEL_REF(*(zend_ast **)str_index);
} else if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
char *actual;
const char *save = str_index;
if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
str_index_len -= ((colon - str_index) + 1);
str_index = colon;
} else {
if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
actual++;
str_index_len -= (actual - str_index);
str_index = actual;
}
}
if (str_index[0] == '\\') {
++str_index;
--str_index_len;
}
if (save[0] == '\\') {
++save;
}
if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
zend_error(E_ERROR, "Undefined constant '%s'", save);
}
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
}
ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
}
if (Z_REFCOUNT_PP(element) > 1) {
ALLOC_ZVAL(new_val);
*new_val = **element;
zval_copy_ctor(new_val);
Z_SET_REFCOUNT_P(new_val, 1);
Z_UNSET_ISREF_P(new_val);
/* preserve this bit for inheritance */
Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
zval_ptr_dtor(element);
*element = new_val;
}
switch (Z_TYPE(const_value)) {
case IS_STRING:
ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
break;
case IS_BOOL:
case IS_LONG:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
break;
case IS_DOUBLE:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
break;
case IS_NULL:
ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
break;
default:
ret = SUCCESS;
break;
}
if (ret == SUCCESS) {
zend_hash_move_forward(Z_ARRVAL_P(p));
}
zval_dtor(&const_value);
}
zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC);
zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
}
break;
case IS_CONSTANT_AST: {
zend_ast *ast = Z_AST_P(p);
MARK_CONSTANT_VISITED(p);
zend_ast_evaluate(p, ast TSRMLS_CC);
ZEND_AST_DEL_REF(ast);
}
zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant_inline_change, (void *) scope TSRMLS_CC);
zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
}
return 0;
}
+27 -5
View File
@@ -947,25 +947,47 @@ common_scalar:
| T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; }
;
static_class_constant:
class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
;
static_scalar: /* compile-time evaluated scalars */
common_scalar { $$ = $1; }
static_scalar_value { $$ = $1; }
;
static_scalar_value:
common_scalar { $$ = $1; }
| static_class_name_scalar { $$ = $1; }
| namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); }
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); }
| T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); }
| '+' static_scalar { ZVAL_LONG(&$1.u.constant, 0); add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
| '-' static_scalar { ZVAL_LONG(&$1.u.constant, 0); sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
| T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
| '[' static_array_pair_list ']' { $$ = $2; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
| static_class_constant { $$ = $1; }
| T_CLASS_C { $$ = $1; }
| static_operation { $$ = $1; }
;
static_class_constant:
class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
static_operation:
static_scalar_value '+' static_scalar_value { zend_ast_add_binary(&$$.u.constant, add_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value '-' static_scalar_value { zend_ast_add_binary(&$$.u.constant, sub_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value '*' static_scalar_value { zend_ast_add_binary(&$$.u.constant, mul_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value '/' static_scalar_value { zend_ast_add_binary(&$$.u.constant, div_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value '%' static_scalar_value { zend_ast_add_binary(&$$.u.constant, mod_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| '!' static_scalar_value { zend_ast_add_unary(&$$.u.constant, boolean_not_function, &$2.u.constant TSRMLS_CC); }
| '~' static_scalar_value { zend_ast_add_unary(&$$.u.constant, bitwise_not_function, &$2.u.constant TSRMLS_CC); }
| static_scalar_value '|' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_or_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value '&' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_and_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value '^' static_scalar_value { zend_ast_add_binary(&$$.u.constant, bitwise_xor_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value T_SL static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_left_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value T_SR static_scalar_value { zend_ast_add_binary(&$$.u.constant, shift_right_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| static_scalar_value '.' static_scalar_value { zend_ast_add_binary(&$$.u.constant, concat_function, &$1.u.constant, &$3.u.constant TSRMLS_CC); }
| '+' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, add_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); }
| '-' static_scalar_value { ZVAL_LONG(&$1.u.constant, 0); zend_ast_add_binary(&$$.u.constant, sub_function, &$1.u.constant, &$2.u.constant TSRMLS_CC); }
| '(' static_scalar_value ')' { $$ = $2; }
;
scalar:
T_STRING_VARNAME { $$ = $1; }
| class_name_scalar { $$ = $1; }
+3
View File
@@ -443,6 +443,7 @@ END_EXTERN_C()
#define Z_STRVAL(zval) (zval).value.str.val
#define Z_STRLEN(zval) (zval).value.str.len
#define Z_ARRVAL(zval) (zval).value.ht
#define Z_AST(zval) (zval).value.ast
#define Z_OBJVAL(zval) (zval).value.obj
#define Z_OBJ_HANDLE(zval) Z_OBJVAL(zval).handle
#define Z_OBJ_HT(zval) Z_OBJVAL(zval).handlers
@@ -458,6 +459,7 @@ END_EXTERN_C()
#define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p)
#define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p)
#define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p)
#define Z_AST_P(zval_p) Z_AST(*zval_p)
#define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p)
#define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p)
#define Z_RESVAL_P(zval_p) Z_RESVAL(*zval_p)
@@ -473,6 +475,7 @@ END_EXTERN_C()
#define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp)
#define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp)
#define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp)
#define Z_AST_PP(zval_p) Z_AST(**zval_p)
#define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp)
#define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp)
#define Z_RESVAL_PP(zval_pp) Z_RESVAL(**zval_pp)
+10
View File
@@ -22,6 +22,7 @@
#include <stdio.h>
#include "zend.h"
#include "zend_API.h"
#include "zend_ast.h"
#include "zend_globals.h"
#include "zend_constants.h"
#include "zend_list.h"
@@ -47,6 +48,9 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
}
}
break;
case IS_CONSTANT_AST:
ZEND_AST_DEL_REF(Z_AST_P(zvalue));
break;
case IS_OBJECT:
{
TSRMLS_FETCH();
@@ -81,6 +85,9 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
CHECK_ZVAL_STRING_REL(zvalue);
str_free(zvalue->value.str.val);
break;
case IS_CONSTANT_AST:
ZEND_AST_DEL_REF(Z_AST_P(zvalue));
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
case IS_OBJECT:
@@ -139,6 +146,9 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
zvalue->value.ht = tmp_ht;
}
break;
case IS_CONSTANT_AST:
ZEND_AST_ADD_REF(Z_AST_P(zvalue));
break;
case IS_OBJECT:
{
TSRMLS_FETCH();
+38 -24
View File
@@ -3252,12 +3252,16 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
if (param == NULL) {
ALLOC_ZVAL(assignment_value);
*assignment_value = *opline->op2.zv;
if ((Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
Z_TYPE_P(assignment_value)==IS_CONSTANT_ARRAY) {
Z_SET_REFCOUNT_P(assignment_value, 1);
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
} else {
zval_copy_ctor(assignment_value);
switch (Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST:
Z_SET_REFCOUNT_P(assignment_value, 1);
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
break;
default:
zval_copy_ctor(assignment_value);
break;
}
INIT_PZVAL(assignment_value);
} else {
@@ -3580,13 +3584,16 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
}
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zend_class_entry *old_scope = EG(scope);
switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST: {
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
}
}
if (OP1_TYPE == IS_CONST) {
CACHE_PTR(opline->op2.literal->cache_slot, value);
@@ -5187,20 +5194,27 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
name = GET_OP1_ZVAL_PTR(BP_VAR_R);
val = GET_OP2_ZVAL_PTR(BP_VAR_R);
if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
zval tmp;
zval *tmp_ptr = &tmp;
switch (Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST: {
zval tmp;
zval *tmp_ptr = &tmp;
ZVAL_COPY_VALUE(&tmp, val);
if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
zval_copy_ctor(&tmp);
ZVAL_COPY_VALUE(&tmp, val);
if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
zval_copy_ctor(&tmp);
}
INIT_PZVAL(&tmp);
zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
c.value = *tmp_ptr;
}
INIT_PZVAL(&tmp);
zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
c.value = *tmp_ptr;
} else {
INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
break;
default:
INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
break;
}
c.flags = CONST_CS; /* non persistent, case sensetive */
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+56 -36
View File
@@ -1435,12 +1435,16 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
if (param == NULL) {
ALLOC_ZVAL(assignment_value);
*assignment_value = *opline->op2.zv;
if ((Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
Z_TYPE_P(assignment_value)==IS_CONSTANT_ARRAY) {
Z_SET_REFCOUNT_P(assignment_value, 1);
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
} else {
zval_copy_ctor(assignment_value);
switch (Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST:
Z_SET_REFCOUNT_P(assignment_value, 1);
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
break;
default:
zval_copy_ctor(assignment_value);
break;
}
INIT_PZVAL(assignment_value);
} else {
@@ -3792,13 +3796,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
}
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zend_class_entry *old_scope = EG(scope);
switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST: {
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
}
}
if (IS_CONST == IS_CONST) {
CACHE_PTR(opline->op2.literal->cache_slot, value);
@@ -4089,20 +4096,27 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
name = opline->op1.zv;
val = opline->op2.zv;
if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
zval tmp;
zval *tmp_ptr = &tmp;
switch (Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST: {
zval tmp;
zval *tmp_ptr = &tmp;
ZVAL_COPY_VALUE(&tmp, val);
if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
zval_copy_ctor(&tmp);
ZVAL_COPY_VALUE(&tmp, val);
if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
zval_copy_ctor(&tmp);
}
INIT_PZVAL(&tmp);
zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
c.value = *tmp_ptr;
}
INIT_PZVAL(&tmp);
zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
c.value = *tmp_ptr;
} else {
INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
break;
default:
INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
break;
}
c.flags = CONST_CS; /* non persistent, case sensetive */
c.name = str_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
@@ -15635,13 +15649,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
}
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zend_class_entry *old_scope = EG(scope);
switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST: {
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
}
}
if (IS_VAR == IS_CONST) {
CACHE_PTR(opline->op2.literal->cache_slot, value);
@@ -25171,13 +25188,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
}
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zend_class_entry *old_scope = EG(scope);
switch (Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST: {
zend_class_entry *old_scope = EG(scope);
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
EG(scope) = ce;
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
}
}
if (IS_UNUSED == IS_CONST) {
CACHE_PTR(opline->op2.literal->cache_slot, value);
+3 -1
View File
@@ -1475,7 +1475,9 @@ PHP_ADD_SOURCES(Zend, \
zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
zend_closures.c zend_float.c zend_string.c zend_signal.c zend_generators.c)
zend_closures.c zend_float.c zend_string.c zend_signal.c \
zend_generators.c \
zend_ast.c)
if test -r "$abs_srcdir/Zend/zend_objects.c"; then
PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_default_classes.c)
+13 -5
View File
@@ -2599,9 +2599,14 @@ ZEND_METHOD(reflection_parameter, getDefaultValue)
*return_value = *precv->op2.zv;
INIT_PZVAL(return_value);
if ((Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) != IS_CONSTANT
&& (Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) != IS_CONSTANT_ARRAY) {
zval_copy_ctor(return_value);
switch (Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST:
break;
default:
zval_copy_ctor(return_value);
}
zval_update_constant_ex(&return_value, (void*)0, param->fptr->common.scope TSRMLS_CC);
}
@@ -3414,8 +3419,11 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
/* this is necessary to make it able to work with default array
* properties, returned to user */
if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zval_update_constant(&prop_copy, (void *) 1 TSRMLS_CC);
switch (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) {
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
case IS_CONSTANT_AST:
zval_update_constant(&prop_copy, (void *) 1 TSRMLS_CC);
}
add_assoc_zval(return_value, key, prop_copy);
+3 -1
View File
@@ -364,7 +364,9 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \
zend_stream.c zend_iterators.c zend_interfaces.c zend_objects.c \
zend_object_handlers.c zend_objects_API.c \
zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c \
zend_float.c zend_string.c zend_generators.c");
zend_float.c zend_string.c \
zend_generators.c \
zend_ast.c");
if (VCVERS == 1200) {
AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1);