summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend.h1
-rw-r--r--Zend/zend_API.c1
-rw-r--r--Zend/zend_compile.c8
-rw-r--r--Zend/zend_compile.h2
-rw-r--r--Zend/zend_execute.c24
-rw-r--r--Zend/zend_language_parser.y12
6 files changed, 33 insertions, 15 deletions
diff --git a/Zend/zend.h b/Zend/zend.h
index d835014ab9..cb935c0a43 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -280,6 +280,7 @@ struct _zend_class_entry {
struct _zend_class_entry *parent;
int *refcount;
zend_bool constants_updated;
+ zend_bool is_namespace;
HashTable function_table;
HashTable default_properties;
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index e013d16a57..8c1c0bea60 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1215,6 +1215,7 @@ ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_
class_entry->refcount = (int *) malloc(sizeof(int));
*class_entry->refcount = 1;
class_entry->constants_updated = 0;
+ class_entry->is_namespace = 0;
zend_hash_init(&class_entry->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1);
zend_hash_init(&class_entry->static_members, 0, NULL, ZVAL_PTR_DTOR, 1);
zend_hash_init(&class_entry->constants, 0, NULL, ZVAL_PTR_DTOR, 1);
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index e438e575a2..c81c4f0283 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -841,10 +841,7 @@ int zend_do_begin_function_call(znode *function_name TSRMLS_DC)
zend_str_tolower(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
if (zend_hash_find(CG(function_table), function_name->u.constant.value.str.val, function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) {
- znode tmp = *function_name;
-
- zval_copy_ctor(&tmp.u.constant);
- zend_do_begin_dynamic_function_call(&tmp TSRMLS_CC);
+ zend_do_begin_dynamic_function_call(function_name TSRMLS_CC);
return 1; /* Dynamic */
}
@@ -1705,7 +1702,7 @@ void zend_do_default_before_statement(znode *case_list, znode *default_token TSR
}
-void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znode *parent_class_name TSRMLS_DC)
+void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znode *parent_class_name, zend_bool is_namespace TSRMLS_DC)
{
zend_op *opline;
int runtime_inheritance = 0;
@@ -1718,6 +1715,7 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
new_class_entry.refcount = (int *) emalloc(sizeof(int));
*new_class_entry.refcount = 1;
new_class_entry.constants_updated = 0;
+ new_class_entry.is_namespace = is_namespace;
zend_str_tolower(new_class_entry.name, new_class_entry.name_length);
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 0c9b439dba..0b73d0ee60 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -303,7 +303,7 @@ void zend_do_case_before_statement(znode *case_list, znode *case_token, znode *c
void zend_do_case_after_statement(znode *result, znode *case_token TSRMLS_DC);
void zend_do_default_before_statement(znode *case_list, znode *default_token TSRMLS_DC);
-void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znode *parent_class_name TSRMLS_DC);
+void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znode *parent_class_name, zend_bool is_namespace TSRMLS_DC);
void zend_do_end_class_declaration(znode *class_token TSRMLS_DC);
void zend_do_declare_property(znode *var_name, znode *value, int declaration_type TSRMLS_DC);
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index bbfc99390d..c0cd0ff88f 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -532,8 +532,7 @@ static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type
switch (opline->extended_value) {
case ZEND_FETCH_LOCAL:
- //target_symbol_table = EG(active_symbol_table);
- target_symbol_table = EG(namespace)?&EG(namespace)->static_members:EG(active_symbol_table);
+ target_symbol_table = EG(active_symbol_table);
break;
case ZEND_FETCH_GLOBAL:
if (opline->op1.op_type == IS_VAR) {
@@ -1009,6 +1008,7 @@ typedef struct _zend_execute_data {
object_info object;
temp_variable *Ts;
zend_bool original_in_execution;
+ zend_class_entry *calling_namespace;
} zend_execute_data;
#define EX(element) execute_data.element
@@ -1552,7 +1552,8 @@ binary_assign_op_addr: {
convert_to_string(&tmp);
function_name = &tmp;
zend_str_tolower(tmp.value.str.val, tmp.value.str.len);
-
+
+ EX(calling_namespace) = EG(namespace);
if (EX(opline)->op1.op_type != IS_UNUSED) {
if (EX(opline)->op1.op_type==IS_CONST) { /* used for class::function() */
zval **object_ptr_ptr;
@@ -1565,7 +1566,14 @@ binary_assign_op_addr: {
EX(object).ptr = *object_ptr_ptr;
EX(object).ptr->refcount++; /* For this pointer */
}
- active_function_table = &EX(Ts)[EX(opline)->op1.u.var].EA.class_entry->function_table;
+
+ {
+ zend_class_entry *ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry;
+ active_function_table = &ce->function_table;
+ if (ce->is_namespace) {
+ EX(calling_namespace) = ce;
+ }
+ }
} else { /* used for member function calls */
EX(object).ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
@@ -1637,9 +1645,12 @@ overloaded_function_call_cont:
do_fcall_common:
{
zval **original_return_value;
+ zend_class_entry *current_namespace;
int return_value_used = RETURN_VALUE_USED(EX(opline));
zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) EX(opline)->extended_value, NULL);
+ current_namespace = EG(namespace);
+ EG(namespace) = EX(calling_namespace);
EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr;
@@ -1723,6 +1734,8 @@ do_fcall_common:
EG(function_state_ptr) = &EX(function_state);
zend_ptr_stack_clear_multiple(TSRMLS_C);
+ EG(namespace) = current_namespace;
+
if (EG(exception)) {
if (EX(opline)->op2.u.opline_num == -1) {
RETURN_FROM_EXECUTE_LOOP(execute_data);
@@ -2034,6 +2047,9 @@ send_by_ref:
NEXT_OPCODE();
case ZEND_NEW:
{
+ if (EX(Ts)[EX(opline)->op1.u.var].EA.class_entry->is_namespace) {
+ zend_error(E_ERROR, "Cannot instantiate a namespace");
+ }
EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr;
ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr);
object_init_ex(EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(Ts)[EX(opline)->op1.u.var].EA.class_entry);
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 5b0206b864..14c47faa91 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -209,7 +209,7 @@ unticked_statement:
T_CATCH '(' T_VARIABLE ')' { zend_do_begin_catch(&$1, &$8 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
| T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); }
| T_DELETE cvar ';' { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1, ZEND_UNSET_OBJ TSRMLS_CC); }
- | T_NAMESPACE namespace_class_entry { do_namespace(&$2 TSRMLS_CC); }
+ | T_NAMESPACE namespace_class_entry ';' { do_namespace(&$2 TSRMLS_CC); }
| T_NAMESPACE ';' { do_namespace(NULL TSRMLS_CC); }
;
@@ -238,8 +238,9 @@ unticked_declaration_statement:
'(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
| T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$4, 0, $3.op_type TSRMLS_CC); }
parameter_list '(' inner_statement_list ')' ';' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
- | T_CLASS T_STRING { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
- | T_CLASS T_STRING T_EXTENDS T_STRING { zend_do_begin_class_declaration(&$1, &$2, &$4 TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
+ | T_NAMESPACE T_STRING { zend_do_begin_class_declaration(&$1, &$2, NULL, 1 TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
+ | T_CLASS T_STRING { zend_do_begin_class_declaration(&$1, &$2, NULL, 0 TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
+ | T_CLASS T_STRING T_EXTENDS T_STRING { zend_do_begin_class_declaration(&$1, &$2, &$4, 0 TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
;
@@ -393,8 +394,9 @@ class_statement:
parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
| T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$4, 1, $3.op_type TSRMLS_CC); }
parameter_list '(' inner_statement_list ')' ';' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
- | T_CLASS T_STRING { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
- | T_CLASS T_STRING T_EXTENDS T_STRING { zend_do_begin_class_declaration(&$1, &$2, &$4 TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
+ | T_NAMESPACE T_STRING { zend_do_begin_class_declaration(&$1, &$2, NULL, 1 TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
+ | T_CLASS T_STRING { zend_do_begin_class_declaration(&$1, &$2, NULL, 0 TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
+ | T_CLASS T_STRING T_EXTENDS T_STRING { zend_do_begin_class_declaration(&$1, &$2, &$4, 0 TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
;
is_reference: