summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_compile.c46
-rw-r--r--Zend/zend_execute.c68
-rw-r--r--Zend/zend_language_parser.y2
3 files changed, 66 insertions, 50 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 1840f6fbbb..5dc8e1a87f 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -1208,29 +1208,33 @@ void do_fetch_class(znode *result, znode *namespace_name, znode *class_name TSRM
SET_UNUSED(opline->op1);
}
CG(catch_begin) = fetch_class_op_number;
- if(class_name) {
- zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
- }
- if(class_name == NULL) {
- SET_UNUSED(opline->op2);
- opline->extended_value = ZEND_FETCH_CLASS_MAIN;
- } else if ((class_name->u.constant.value.str.len == (sizeof("self") - 1)) &&
- !memcmp(class_name->u.constant.value.str.val, "self", sizeof("self"))) {
- SET_UNUSED(opline->op2);
- opline->extended_value = ZEND_FETCH_CLASS_SELF;
- zval_dtor(&class_name->u.constant);
- } else if ((class_name->u.constant.value.str.len == (sizeof("parent") - 1)) &&
- !memcmp(class_name->u.constant.value.str.val, "parent", sizeof("parent"))) {
- SET_UNUSED(opline->op2);
- opline->extended_value = ZEND_FETCH_CLASS_PARENT;
- zval_dtor(&class_name->u.constant);
- } else if ((class_name->u.constant.value.str.len == (sizeof("main") - 1)) &&
- !memcmp(class_name->u.constant.value.str.val, "main", sizeof("main"))) {
+ if (class_name) {
+ if (class_name->op_type == IS_CONST) {
+ zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
+ if ((class_name->u.constant.value.str.len == (sizeof("self") - 1)) &&
+ !memcmp(class_name->u.constant.value.str.val, "self", sizeof("self"))) {
+ SET_UNUSED(opline->op2);
+ opline->extended_value = ZEND_FETCH_CLASS_SELF;
+ zval_dtor(&class_name->u.constant);
+ } else if ((class_name->u.constant.value.str.len == (sizeof("parent") - 1)) &&
+ !memcmp(class_name->u.constant.value.str.val, "parent", sizeof("parent"))) {
+ SET_UNUSED(opline->op2);
+ opline->extended_value = ZEND_FETCH_CLASS_PARENT;
+ zval_dtor(&class_name->u.constant);
+ } else if ((class_name->u.constant.value.str.len == (sizeof("main") - 1)) &&
+ !memcmp(class_name->u.constant.value.str.val, "main", sizeof("main"))) {
+ SET_UNUSED(opline->op2);
+ opline->extended_value = ZEND_FETCH_CLASS_MAIN;
+ zval_dtor(&class_name->u.constant);
+ } else {
+ opline->op2 = *class_name;
+ }
+ } else {
+ opline->op2 = *class_name;
+ }
+ } else {
SET_UNUSED(opline->op2);
opline->extended_value = ZEND_FETCH_CLASS_MAIN;
- zval_dtor(&class_name->u.constant);
- } else {
- opline->op2 = *class_name;
}
opline->result.u.var = get_temporary_variable(CG(active_op_array));
opline->result.op_type = IS_CONST; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 39a7b01b3d..412e04380b 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -2303,6 +2303,7 @@ int zend_import_const_handler(ZEND_OPCODE_HANDLER_ARGS)
int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS)
{
zend_class_entry **pce;
+ zend_class_entry *ce = NULL;
zend_bool is_const;
char *class_name_strval;
zend_uint class_name_strlen;
@@ -2335,48 +2336,59 @@ int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS)
is_const = (EX(opline)->op2.op_type == IS_CONST);
if (is_const) {
- class_name_strval = EX(opline)->op2.u.constant.value.str.val;
- class_name_strlen = EX(opline)->op2.u.constant.value.str.len;
+{
+ class_name_strval = EX(opline)->op2.u.constant.value.str.val;
+ class_name_strlen = EX(opline)->op2.u.constant.value.str.len;
+ }
} else {
class_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
- tmp = *class_name;
- zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
- zend_str_tolower(tmp.value.str.val, tmp.value.str.len);
+ if (class_name->type == IS_OBJECT) {
+ ce = Z_OBJCE_P(class_name);
+ } else {
+ tmp = *class_name;
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ zend_str_tolower(tmp.value.str.val, tmp.value.str.len);
- class_name_strval = tmp.value.str.val;
- class_name_strlen = tmp.value.str.len;
+ class_name_strval = tmp.value.str.val;
+ class_name_strlen = tmp.value.str.len;
+ }
}
- if (EX(opline)->op1.op_type == IS_UNUSED && EX(opline)->extended_value != ZEND_FETCH_CLASS_GLOBAL) {
- retval = zend_lookup_class(class_name_strval, class_name_strlen, &pce TSRMLS_CC);
-
- if(retval == FAILURE) {
- /* try namespace */
- if(zend_hash_find(&EG(global_namespace_ptr)->class_table, class_name_strval, class_name_strlen+1, (void **)&pce) == SUCCESS && (*pce)->type == ZEND_NAMESPACE) {
- retval = SUCCESS;
+ if (!ce) {
+ if (EX(opline)->op1.op_type == IS_UNUSED && EX(opline)->extended_value != ZEND_FETCH_CLASS_GLOBAL) {
+ retval = zend_lookup_class(class_name_strval, class_name_strlen, &pce TSRMLS_CC);
+
+ if(retval == FAILURE) {
+ /* try namespace */
+ if(zend_hash_find(&EG(global_namespace_ptr)->class_table, class_name_strval, class_name_strlen+1, (void **)&pce) == SUCCESS && (*pce)->type == ZEND_NAMESPACE) {
+ retval = SUCCESS;
+ }
}
- }
-
- } else {
- zend_namespace *ns;
- /* Looking for namespace */
- if(EX(opline)->extended_value == ZEND_FETCH_CLASS_GLOBAL) {
- ns = EG(global_namespace_ptr);
} else {
- if (zend_hash_find(&EG(global_namespace_ptr)->class_table, EX(opline)->op1.u.constant.value.str.val, EX(opline)->op1.u.constant.value.str.len+1, (void **)&pce) == FAILURE || (*pce)->type != ZEND_NAMESPACE) {
- zend_error(E_ERROR, "Namespace '%s' not found", EX(opline)->op1.u.constant.value.str.val);
+ zend_namespace *ns;
+
+ /* Looking for namespace */
+ if(EX(opline)->extended_value == ZEND_FETCH_CLASS_GLOBAL) {
+ ns = EG(global_namespace_ptr);
+ } else {
+ if (zend_hash_find(&EG(global_namespace_ptr)->class_table, EX(opline)->op1.u.constant.value.str.val, EX(opline)->op1.u.constant.value.str.len+1, (void **)&pce) == FAILURE || (*pce)->type != ZEND_NAMESPACE) {
+ zend_error(E_ERROR, "Namespace '%s' not found", EX(opline)->op1.u.constant.value.str.val);
+ }
+ ns = *pce;
}
- ns = *pce;
+ retval = zend_hash_find(&ns->class_table, class_name_strval, class_name_strlen+1, (void **)&pce);
+ }
+ if (retval==SUCCESS) {
+ ce = *pce;
}
- retval = zend_hash_find(&ns->class_table, class_name_strval, class_name_strlen+1, (void **)&pce);
}
if (retval == FAILURE) {
zend_error(E_ERROR, "Class '%s' not found", class_name_strval);
} else {
- EX_T(EX(opline)->result.u.var).EA.class_entry = *pce;
+ EX_T(EX(opline)->result.u.var).EA.class_entry = ce;
}
if (!is_const) {
zval_dtor(&tmp);
@@ -3120,7 +3132,7 @@ int zend_new_handler(ZEND_OPCODE_HANDLER_ARGS)
} else {
class_type = "abstract_class";
}
- zend_error(E_ERROR, "Cannot instantiate %s %s", class_type, EX_T(EX(opline)->op1.u.var).EA.class_entry->name);
+ zend_error(E_ERROR, "Cannot instantiate %s %s", class_type, EX_T(EX(opline)->op1.u.var).EA.class_entry->name);
}
EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr;
ALLOC_ZVAL(EX_T(EX(opline)->result.u.var).var.ptr);
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 31506e11db..50d495fbd6 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -643,7 +643,7 @@ function_call:
parse_class_entry:
T_NAMESPACE_NAME T_PAAMAYIM_NEKUDOTAYIM T_STRING T_PAAMAYIM_NEKUDOTAYIM { do_fetch_class(&$$, &$1, &$3 TSRMLS_CC); }
- | T_STRING T_PAAMAYIM_NEKUDOTAYIM { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
+ | static_or_variable_string T_PAAMAYIM_NEKUDOTAYIM { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
| T_PAAMAYIM_NEKUDOTAYIM { do_fetch_class(&$$, NULL, NULL TSRMLS_CC); }
;