]> granicus.if.org Git - php/commitdiff
Added support for "namespace::" prefix that is resolved to current namespace name.
authorDmitry Stogov <dmitry@php.net>
Tue, 20 Nov 2007 08:53:17 +0000 (08:53 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 20 Nov 2007 08:53:17 +0000 (08:53 +0000)
Zend/tests/lsb_006.phpt
Zend/tests/lsb_007.phpt
Zend/tests/ns_057.phpt [new file with mode: 0755]
Zend/tests/ns_058.phpt [new file with mode: 0755]
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_language_parser.y

index e6296a967404293d087c4b6d59e460a98b9e501b..39bff7fa92690af4704a42526208b8e92f8987ca 100644 (file)
@@ -9,4 +9,4 @@ class Foo extends static {
 ?>
 ==DONE==
 --EXPECTF--
-Parse error: syntax error, unexpected T_STATIC, expecting T_STRING or T_PAAMAYIM_NEKUDOTAYIM in %s on line %d
+Parse error: syntax error, unexpected T_STATIC, expecting T_STRING or T_PAAMAYIM_NEKUDOTAYIM or T_NAMESPACE in %s on line %d
index 6366f09b0f662d7742daece09a5e0f7e2576389f..68c2fc2757b293df3fd022ee1a63a885c073e63a 100644 (file)
@@ -9,4 +9,4 @@ class Foo implements static {
 ?>
 ==DONE==
 --EXPECTF--
-Parse error: syntax error, unexpected T_STATIC, expecting T_STRING or T_PAAMAYIM_NEKUDOTAYIM in %s on line %d
+Parse error: syntax error, unexpected T_STATIC, expecting T_STRING or T_PAAMAYIM_NEKUDOTAYIM or T_NAMESPACE in %s on line %d
diff --git a/Zend/tests/ns_057.phpt b/Zend/tests/ns_057.phpt
new file mode 100755 (executable)
index 0000000..2496343
--- /dev/null
@@ -0,0 +1,56 @@
+--TEST--
+057: Usage of 'namespace' in compound names (inside namespase)
+--FILE--
+<?php
+namespace test::ns1;
+
+const C = "const ok\n";
+
+function foo() {
+       return "func ok\n";
+}
+
+class foo {
+       const C = "const ok\n";
+       const C2 = namespace::C;
+       static $var = "var ok\n";
+       function __construct() {
+               echo "class ok\n";
+       }
+       static function bar() {
+               return "method ok\n";
+       }
+}
+
+function f1($x=namespace::C) {
+       return $x;
+}
+function f2($x=namespace::foo::C) {
+       return $x;
+}
+
+function f3(namespace::foo $x) {
+       return "ok\n";
+}
+
+echo namespace::C;
+echo namespace::foo();
+echo namespace::foo::C;
+echo namespace::foo::C2;
+echo namespace::foo::$var;
+echo namespace::foo::bar();
+echo namespace::f1();
+echo namespace::f2();
+echo namespace::f3(new namespace::foo());
+?>
+--EXPECTF--
+const ok
+func ok
+const ok
+const ok
+var ok
+method ok
+const ok
+const ok
+class ok
+ok
diff --git a/Zend/tests/ns_058.phpt b/Zend/tests/ns_058.phpt
new file mode 100755 (executable)
index 0000000..6c86f10
--- /dev/null
@@ -0,0 +1,54 @@
+--TEST--
+058: Usage of 'namespace' in compound names (out of namespase)
+--FILE--
+<?php
+const C = "const ok\n";
+
+function foo() {
+       return "func ok\n";
+}
+
+class foo {
+       const C = "const ok\n";
+       const C2 = namespace::C;
+       static $var = "var ok\n";
+       function __construct() {
+               echo "class ok\n";
+       }
+       static function bar() {
+               return "method ok\n";
+       }
+}
+
+function f1($x=namespace::C) {
+       return $x;
+}
+function f2($x=namespace::foo::C) {
+       return $x;
+}
+
+function f3(namespace::foo $x) {
+       return "ok\n";
+}
+
+echo namespace::C;
+echo namespace::foo();
+echo namespace::foo::C;
+echo namespace::foo::C2;
+echo namespace::foo::$var;
+echo namespace::foo::bar();
+echo namespace::f1();
+echo namespace::f2();
+echo namespace::f3(new namespace::foo());
+?>
+--EXPECT--
+const ok
+func ok
+const ok
+const ok
+var ok
+method ok
+const ok
+const ok
+class ok
+ok
index 9155fa77c22ceb8a063282c4bad23fa10775a78a..9facc210bb20ff7330fce051dc99432c9026c225 100644 (file)
@@ -1394,6 +1394,14 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
        zend_op *opline;
        zend_arg_info *cur_arg_info;
 
+       if (class_type->op_type == IS_CONST &&
+           Z_UNILEN(class_type->u.constant) == 0) {
+               /* Usage of namespace as class name not in namespace */
+               zval_dtor(&class_type->u.constant);
+               zend_error(E_COMPILE_ERROR, "Cannot use 'namespace' as a class name");
+               return;
+       }
+
        if (CG(active_op_array)->scope &&
                ((CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) &&
            (Z_TYPE(varname->u.constant) == IS_STRING || Z_TYPE(varname->u.constant) == IS_UNICODE) &&
@@ -1705,6 +1713,14 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
        long fetch_class_op_number;
        zend_op *opline;
 
+       if (class_name->op_type == IS_CONST &&
+           Z_UNILEN(class_name->u.constant) == 0) {
+               /* Usage of namespace as class name not in namespace */
+               zval_dtor(&class_name->u.constant);
+               zend_error(E_COMPILE_ERROR, "Cannot use 'namespace' as a class name");
+               return;
+       }
+       
        fetch_class_op_number = get_next_op_number(CG(active_op_array));
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
@@ -1767,13 +1783,20 @@ void zend_do_fetch_class_name(znode *result, znode *class_name_entry, znode *cla
 }
 /* }}} */
 
-void zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
+int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
 {
        znode class_node;
        unsigned char *ptr = NULL;
        zend_op *opline;
        ulong fetch_type = 0;
 
+       if (class_name->op_type == IS_CONST &&
+           Z_UNILEN(class_name->u.constant) == 0) {
+               /* namespace::func() not in namespace */
+               zval_dtor(&class_name->u.constant);
+               return zend_do_begin_function_call(method_name, 0 TSRMLS_CC);
+       }
+
        if (method_name->op_type == IS_CONST) {
                zstr lcname;
                unsigned int lcname_len;
@@ -1860,6 +1883,7 @@ void zend_do_begin_class_member_function_call(znode *class_name, znode *method_n
 
        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
        zend_do_extended_fcall_begin(TSRMLS_C);
+       return 1; /* Dynamic */
 }
 /* }}} */
 
@@ -3828,6 +3852,15 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
                        }
                        break;
                case ZEND_RT:
+                       if (constant_container &&
+                           constant_container->op_type == IS_CONST &&
+                           Z_UNILEN(constant_container->u.constant) == 0) {
+                               /* Usage of namespace as class name not in namespace */
+                               zval_dtor(&constant_container->u.constant);
+                               constant_container = NULL;
+                               check_namespace = 0;
+                       }
+
                        if (constant_container ||
                            !zend_constant_ct_subst(result, &constant_name->u.constant TSRMLS_CC)) {
                                zend_op *opline;
index 4ab381f92504003864f9a1675856e2844fda721b..1a11224495b17151e6fc12a66ea2590a2790a5a8 100644 (file)
@@ -416,7 +416,7 @@ void zend_do_clone(znode *result, znode *expr TSRMLS_DC);
 void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC);
 void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC);
 void zend_do_fetch_class_name(znode *result, znode *class_entry, znode *class_name TSRMLS_DC);
-void zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC);
+int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC);
 void zend_do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC);
 void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
 void zend_do_handle_exception(TSRMLS_D);
index 3d0332d4ba56a1565269719eb093e660ebea4814..976c069edb811fcdce2356dc7f871300493189cb 100644 (file)
@@ -643,9 +643,9 @@ function_call:
        |       T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { $3.u.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); }
                        function_call_parameter_list
                        ')' { zend_do_end_function_call(&$2, &$$, &$5, 0, $3.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
-       |       class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
+       |       class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { $4.u.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
                        function_call_parameter_list
-                       ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+                       ')' { zend_do_end_function_call($4.u.opline_num?NULL:&$3, &$$, &$6, $4.u.opline_num, $4.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
        |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
                        function_call_parameter_list
                        ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
@@ -663,12 +663,14 @@ function_call:
 class_name:
                T_STRING { $$ = $1; }
        |       T_STATIC { $$.op_type = IS_CONST; ZVAL_ASCII_STRINGL(&$$.u.constant, "static", sizeof("static")-1, 1);}
+       |       T_NAMESPACE {if (CG(current_namespace)) { $1.op_type = IS_CONST; $1.u.constant = *CG(current_namespace); zval_copy_ctor(&$1.u.constant); zend_do_build_namespace_name(&$$, NULL, &$1 TSRMLS_CC); } else { $$.op_type = IS_CONST; ZVAL_EMPTY_TEXT(&$$.u.constant); } }
        |       T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, NULL, &$2 TSRMLS_CC); }
        |       class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
 ;
 
 fully_qualified_class_name:
                T_STRING { $$ = $1; }
+       |       T_NAMESPACE {if (CG(current_namespace)) { $1.op_type = IS_CONST; $1.u.constant = *CG(current_namespace); zval_copy_ctor(&$1.u.constant); zend_do_build_namespace_name(&$$, NULL, &$1 TSRMLS_CC); } else { $$.op_type = IS_CONST; ZVAL_EMPTY_TEXT(&$$.u.constant); } }
        |       T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, NULL, &$2 TSRMLS_CC); }
        |       fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
 ;