summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFerenc Kovacs <tyra3l@gmail.com>2013-12-06 05:39:49 +0100
committerFerenc Kovacs <tyra3l@gmail.com>2013-12-06 05:39:49 +0100
commit562fa252ad932f321131ab6f65ffaef8d62fc73a (patch)
tree75db37b349886e52699c390fdb0638ae9b7026ed
parentf0248bdce598a382899056d348d204c9d61746df (diff)
parent611da37617749c81ab22b1e44a0cc1f294cc493a (diff)
downloadphp-git-562fa252ad932f321131ab6f65ffaef8d62fc73a.tar.gz
Merge branch 'use-function' of git://github.com/igorw/php-src into igorw-use-function
-rw-r--r--Zend/tests/use_const/alias.phpt26
-rw-r--r--Zend/tests/use_const/basic.phpt22
-rw-r--r--Zend/tests/use_const/case_sensivity.phpt12
-rw-r--r--Zend/tests/use_const/conflicting_use.phpt21
-rw-r--r--Zend/tests/use_const/conflicting_use_alias.phpt18
-rw-r--r--Zend/tests/use_const/define_imported.phpt14
-rw-r--r--Zend/tests/use_const/define_imported_before.phpt18
-rw-r--r--Zend/tests/use_const/includes/foo_bar.php5
-rw-r--r--Zend/tests/use_const/includes/foo_php_version.php5
-rw-r--r--Zend/tests/use_const/includes/global_bar.php3
-rw-r--r--Zend/tests/use_const/includes/global_baz.php3
-rw-r--r--Zend/tests/use_const/no_global_fallback.phpt14
-rw-r--r--Zend/tests/use_const/self_parent.phpt12
-rw-r--r--Zend/tests/use_const/shadow_core.phpt16
-rw-r--r--Zend/tests/use_const/shadow_global.phpt25
-rw-r--r--Zend/tests/use_function/alias.phpt30
-rw-r--r--Zend/tests/use_function/basic.phpt26
-rw-r--r--Zend/tests/use_function/case_insensivity.phpt13
-rw-r--r--Zend/tests/use_function/conditional_function_declaration.phpt17
-rw-r--r--Zend/tests/use_function/conflicting_use.phpt25
-rw-r--r--Zend/tests/use_function/conflicting_use_alias.phpt20
-rw-r--r--Zend/tests/use_function/conflicting_use_const_alias.phpt23
-rw-r--r--Zend/tests/use_function/define_imported.phpt14
-rw-r--r--Zend/tests/use_function/define_imported_before.phpt18
-rw-r--r--Zend/tests/use_function/ignore_constants.phpt23
-rw-r--r--Zend/tests/use_function/includes/foo_bar.php7
-rw-r--r--Zend/tests/use_function/includes/foo_strlen.php7
-rw-r--r--Zend/tests/use_function/includes/global_bar.php5
-rw-r--r--Zend/tests/use_function/includes/global_baz.php4
-rw-r--r--Zend/tests/use_function/no_global_fallback.phpt13
-rw-r--r--Zend/tests/use_function/no_global_fallback2.phpt18
-rw-r--r--Zend/tests/use_function/self_parent.phpt12
-rw-r--r--Zend/tests/use_function/shadow_core.phpt16
-rw-r--r--Zend/tests/use_function/shadow_global.phpt25
-rw-r--r--Zend/zend_compile.c240
-rw-r--r--Zend/zend_compile.h17
-rw-r--r--Zend/zend_globals.h4
-rw-r--r--Zend/zend_language_parser.y26
38 files changed, 791 insertions, 26 deletions
diff --git a/Zend/tests/use_const/alias.phpt b/Zend/tests/use_const/alias.phpt
new file mode 100644
index 0000000000..f179393006
--- /dev/null
+++ b/Zend/tests/use_const/alias.phpt
@@ -0,0 +1,26 @@
+--TEST--
+aliasing imported constants to resolve naming conflicts
+--FILE--
+<?php
+
+namespace foo {
+ const baz = 42;
+}
+
+namespace bar {
+ const baz = 43;
+}
+
+namespace {
+ use const foo\baz as foo_baz,
+ bar\baz as bar_baz;
+ var_dump(foo_baz);
+ var_dump(bar_baz);
+ echo "Done\n";
+}
+
+?>
+--EXPECT--
+int(42)
+int(43)
+Done
diff --git a/Zend/tests/use_const/basic.phpt b/Zend/tests/use_const/basic.phpt
new file mode 100644
index 0000000000..6eaed7f27d
--- /dev/null
+++ b/Zend/tests/use_const/basic.phpt
@@ -0,0 +1,22 @@
+--TEST--
+import namespaced constant
+--FILE--
+<?php
+
+namespace foo\bar {
+ const baz = 42;
+ const qux = 43;
+}
+
+namespace {
+ use const foo\bar\baz, foo\bar\qux;
+ var_dump(baz);
+ var_dump(qux);
+ echo "Done\n";
+}
+
+?>
+--EXPECT--
+int(42)
+int(43)
+Done
diff --git a/Zend/tests/use_const/case_sensivity.phpt b/Zend/tests/use_const/case_sensivity.phpt
new file mode 100644
index 0000000000..1977daa93b
--- /dev/null
+++ b/Zend/tests/use_const/case_sensivity.phpt
@@ -0,0 +1,12 @@
+--TEST--
+importing const with same name but different case
+--FILE--
+<?php
+
+namespace {
+ use const foo\bar;
+ use const foo\BAR;
+}
+
+?>
+--EXPECT--
diff --git a/Zend/tests/use_const/conflicting_use.phpt b/Zend/tests/use_const/conflicting_use.phpt
new file mode 100644
index 0000000000..3b3c4b3262
--- /dev/null
+++ b/Zend/tests/use_const/conflicting_use.phpt
@@ -0,0 +1,21 @@
+--TEST--
+use const statements with conflicting names
+--FILE--
+<?php
+
+namespace foo {
+ const baz = 42;
+}
+
+namespace bar {
+ const baz = 42;
+}
+
+namespace {
+ use const foo\baz, bar\baz;
+ echo "Done\n";
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot use const bar\baz as baz because the name is already in use in %s on line %d
diff --git a/Zend/tests/use_const/conflicting_use_alias.phpt b/Zend/tests/use_const/conflicting_use_alias.phpt
new file mode 100644
index 0000000000..8b563a4ca9
--- /dev/null
+++ b/Zend/tests/use_const/conflicting_use_alias.phpt
@@ -0,0 +1,18 @@
+--TEST--
+use and use const with the same alias
+--FILE--
+<?php
+
+namespace {
+ const foo = 'foo';
+}
+
+namespace x {
+ use foo as bar;
+ use const foo as bar;
+ var_dump(bar);
+}
+
+?>
+--EXPECT--
+string(3) "foo"
diff --git a/Zend/tests/use_const/define_imported.phpt b/Zend/tests/use_const/define_imported.phpt
new file mode 100644
index 0000000000..5eb44be64a
--- /dev/null
+++ b/Zend/tests/use_const/define_imported.phpt
@@ -0,0 +1,14 @@
+--TEST--
+defining const with same name as imported should fail
+--FILE--
+<?php
+
+namespace {
+ use const foo\bar;
+
+ const bar = 42;
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot declare const bar because the name is already in use in %s on line %d
diff --git a/Zend/tests/use_const/define_imported_before.phpt b/Zend/tests/use_const/define_imported_before.phpt
new file mode 100644
index 0000000000..f674ce81e8
--- /dev/null
+++ b/Zend/tests/use_const/define_imported_before.phpt
@@ -0,0 +1,18 @@
+--TEST--
+using const with same name as defined should fail
+--FILE--
+<?php
+
+namespace {
+ const bar = 42;
+
+ use const foo\bar;
+}
+
+namespace {
+ echo "Done";
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot use const foo\bar as bar because the name is already in use in %s on line %d
diff --git a/Zend/tests/use_const/includes/foo_bar.php b/Zend/tests/use_const/includes/foo_bar.php
new file mode 100644
index 0000000000..90ed451f36
--- /dev/null
+++ b/Zend/tests/use_const/includes/foo_bar.php
@@ -0,0 +1,5 @@
+<?php
+
+namespace foo;
+
+const bar = 'local bar';
diff --git a/Zend/tests/use_const/includes/foo_php_version.php b/Zend/tests/use_const/includes/foo_php_version.php
new file mode 100644
index 0000000000..08f9fd150e
--- /dev/null
+++ b/Zend/tests/use_const/includes/foo_php_version.php
@@ -0,0 +1,5 @@
+<?php
+
+namespace foo;
+
+const PHP_VERSION = 42;
diff --git a/Zend/tests/use_const/includes/global_bar.php b/Zend/tests/use_const/includes/global_bar.php
new file mode 100644
index 0000000000..609d17b7b5
--- /dev/null
+++ b/Zend/tests/use_const/includes/global_bar.php
@@ -0,0 +1,3 @@
+<?php
+
+const bar = 'global bar';
diff --git a/Zend/tests/use_const/includes/global_baz.php b/Zend/tests/use_const/includes/global_baz.php
new file mode 100644
index 0000000000..8b6fba97b3
--- /dev/null
+++ b/Zend/tests/use_const/includes/global_baz.php
@@ -0,0 +1,3 @@
+<?php
+
+const baz = NULL;
diff --git a/Zend/tests/use_const/no_global_fallback.phpt b/Zend/tests/use_const/no_global_fallback.phpt
new file mode 100644
index 0000000000..a128f353ed
--- /dev/null
+++ b/Zend/tests/use_const/no_global_fallback.phpt
@@ -0,0 +1,14 @@
+--TEST--
+non-existent imported constants should not be looked up in the global table
+--FILE--
+<?php
+
+require 'includes/global_baz.php';
+
+use const foo\bar\baz;
+var_dump(baz);
+
+?>
+--EXPECTF--
+Notice: Use of undefined constant baz - assumed 'baz' in %s on line %d
+string(3) "baz"
diff --git a/Zend/tests/use_const/self_parent.phpt b/Zend/tests/use_const/self_parent.phpt
new file mode 100644
index 0000000000..b71f2ecc81
--- /dev/null
+++ b/Zend/tests/use_const/self_parent.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Allow self and parent in use const statement
+--FILE--
+<?php
+
+namespace {
+ use const self as foo;
+ use const parent as bar;
+}
+
+?>
+--EXPECT--
diff --git a/Zend/tests/use_const/shadow_core.phpt b/Zend/tests/use_const/shadow_core.phpt
new file mode 100644
index 0000000000..7d8bcbd189
--- /dev/null
+++ b/Zend/tests/use_const/shadow_core.phpt
@@ -0,0 +1,16 @@
+--TEST--
+shadowing a global core constant with a local version
+--FILE--
+<?php
+
+require 'includes/foo_php_version.php';
+
+use const foo\PHP_VERSION;
+
+var_dump(PHP_VERSION);
+echo "Done\n";
+
+?>
+--EXPECTF--
+int(42)
+Done
diff --git a/Zend/tests/use_const/shadow_global.phpt b/Zend/tests/use_const/shadow_global.phpt
new file mode 100644
index 0000000000..930cc9f0b8
--- /dev/null
+++ b/Zend/tests/use_const/shadow_global.phpt
@@ -0,0 +1,25 @@
+--TEST--
+shadowing a global constant with a local version
+--FILE--
+<?php
+
+namespace {
+ require 'includes/global_bar.php';
+ require 'includes/foo_bar.php';
+}
+
+namespace {
+ var_dump(bar);
+}
+
+namespace {
+ use const foo\bar;
+ var_dump(bar);
+ echo "Done\n";
+}
+
+?>
+--EXPECT--
+string(10) "global bar"
+string(9) "local bar"
+Done
diff --git a/Zend/tests/use_function/alias.phpt b/Zend/tests/use_function/alias.phpt
new file mode 100644
index 0000000000..5f7e97fff8
--- /dev/null
+++ b/Zend/tests/use_function/alias.phpt
@@ -0,0 +1,30 @@
+--TEST--
+aliasing imported functions to resolve naming conflicts
+--FILE--
+<?php
+
+namespace foo {
+ function baz() {
+ return 'foo.baz';
+ }
+}
+
+namespace bar {
+ function baz() {
+ return 'bar.baz';
+ }
+}
+
+namespace {
+ use function foo\baz as foo_baz,
+ bar\baz as bar_baz;
+ var_dump(foo_baz());
+ var_dump(bar_baz());
+ echo "Done\n";
+}
+
+?>
+--EXPECT--
+string(7) "foo.baz"
+string(7) "bar.baz"
+Done
diff --git a/Zend/tests/use_function/basic.phpt b/Zend/tests/use_function/basic.phpt
new file mode 100644
index 0000000000..513a96620c
--- /dev/null
+++ b/Zend/tests/use_function/basic.phpt
@@ -0,0 +1,26 @@
+--TEST--
+import namespaced function
+--FILE--
+<?php
+
+namespace foo\bar {
+ function baz() {
+ return 'foo.bar.baz';
+ }
+ function qux() {
+ return baz();
+ }
+}
+
+namespace {
+ use function foo\bar\baz, foo\bar\qux;
+ var_dump(baz());
+ var_dump(qux());
+ echo "Done\n";
+}
+
+?>
+--EXPECT--
+string(11) "foo.bar.baz"
+string(11) "foo.bar.baz"
+Done
diff --git a/Zend/tests/use_function/case_insensivity.phpt b/Zend/tests/use_function/case_insensivity.phpt
new file mode 100644
index 0000000000..ba6e3a7e4b
--- /dev/null
+++ b/Zend/tests/use_function/case_insensivity.phpt
@@ -0,0 +1,13 @@
+--TEST--
+importing function with same name but different case should fail
+--FILE--
+<?php
+
+namespace {
+ use function foo\bar;
+ use function foo\BAR;
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot use function foo\BAR as BAR because the name is already in use in %s on line %d
diff --git a/Zend/tests/use_function/conditional_function_declaration.phpt b/Zend/tests/use_function/conditional_function_declaration.phpt
new file mode 100644
index 0000000000..ccfb96103a
--- /dev/null
+++ b/Zend/tests/use_function/conditional_function_declaration.phpt
@@ -0,0 +1,17 @@
+--TEST--
+function that is conditionally defined at runtime should not cause compiler error
+--FILE--
+<?php
+
+if (0) {
+ function foo() {
+ }
+}
+
+use function bar\foo;
+
+echo "Done";
+
+?>
+--EXPECT--
+Done
diff --git a/Zend/tests/use_function/conflicting_use.phpt b/Zend/tests/use_function/conflicting_use.phpt
new file mode 100644
index 0000000000..0221fbdebb
--- /dev/null
+++ b/Zend/tests/use_function/conflicting_use.phpt
@@ -0,0 +1,25 @@
+--TEST--
+use function statements with conflicting names
+--FILE--
+<?php
+
+namespace foo {
+ function baz() {
+ return 'foo.baz';
+ }
+}
+
+namespace bar {
+ function baz() {
+ return 'bar.baz';
+ }
+}
+
+namespace {
+ use function foo\baz, bar\baz;
+ echo "Done\n";
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot use function bar\baz as baz because the name is already in use in %s on line %d
diff --git a/Zend/tests/use_function/conflicting_use_alias.phpt b/Zend/tests/use_function/conflicting_use_alias.phpt
new file mode 100644
index 0000000000..2870512014
--- /dev/null
+++ b/Zend/tests/use_function/conflicting_use_alias.phpt
@@ -0,0 +1,20 @@
+--TEST--
+use and use function with the same alias
+--FILE--
+<?php
+
+namespace {
+ function foo() {
+ return 'foo';
+ }
+}
+
+namespace x {
+ use foo as bar;
+ use function foo as bar;
+ var_dump(bar());
+}
+
+?>
+--EXPECT--
+string(3) "foo"
diff --git a/Zend/tests/use_function/conflicting_use_const_alias.phpt b/Zend/tests/use_function/conflicting_use_const_alias.phpt
new file mode 100644
index 0000000000..2e0faf0da2
--- /dev/null
+++ b/Zend/tests/use_function/conflicting_use_const_alias.phpt
@@ -0,0 +1,23 @@
+--TEST--
+use const and use function with the same alias
+--FILE--
+<?php
+
+namespace {
+ const foo = 'foo.const';
+ function foo() {
+ return 'foo.function';
+ }
+}
+
+namespace x {
+ use const foo as bar;
+ use function foo as bar;
+ var_dump(bar);
+ var_dump(bar());
+}
+
+?>
+--EXPECT--
+string(9) "foo.const"
+string(12) "foo.function"
diff --git a/Zend/tests/use_function/define_imported.phpt b/Zend/tests/use_function/define_imported.phpt
new file mode 100644
index 0000000000..c542a4d549
--- /dev/null
+++ b/Zend/tests/use_function/define_imported.phpt
@@ -0,0 +1,14 @@
+--TEST--
+defining function with same name as imported should fail
+--FILE--
+<?php
+
+namespace {
+ use function foo\bar;
+
+ function bar() {}
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot declare function bar because the name is already in use in %s on line %d
diff --git a/Zend/tests/use_function/define_imported_before.phpt b/Zend/tests/use_function/define_imported_before.phpt
new file mode 100644
index 0000000000..91974e0783
--- /dev/null
+++ b/Zend/tests/use_function/define_imported_before.phpt
@@ -0,0 +1,18 @@
+--TEST--
+using function with same name as defined should fail
+--FILE--
+<?php
+
+namespace {
+ function bar() {}
+
+ use function foo\bar;
+}
+
+namespace {
+ echo "Done";
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot use function foo\bar as bar because the name is already in use in %s on line %d
diff --git a/Zend/tests/use_function/ignore_constants.phpt b/Zend/tests/use_function/ignore_constants.phpt
new file mode 100644
index 0000000000..c50ff7357a
--- /dev/null
+++ b/Zend/tests/use_function/ignore_constants.phpt
@@ -0,0 +1,23 @@
+--TEST--
+use function should ignore namespaced constants
+--FILE--
+<?php
+
+namespace foo {
+ const bar = 42;
+}
+
+namespace {
+ const bar = 43;
+}
+
+namespace {
+ use function foo\bar;
+ var_dump(bar);
+ echo "Done\n";
+}
+
+?>
+--EXPECT--
+int(43)
+Done
diff --git a/Zend/tests/use_function/includes/foo_bar.php b/Zend/tests/use_function/includes/foo_bar.php
new file mode 100644
index 0000000000..6d2f8cab45
--- /dev/null
+++ b/Zend/tests/use_function/includes/foo_bar.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace foo;
+
+function bar() {
+ return 'local bar';
+}
diff --git a/Zend/tests/use_function/includes/foo_strlen.php b/Zend/tests/use_function/includes/foo_strlen.php
new file mode 100644
index 0000000000..d2df2aa2b4
--- /dev/null
+++ b/Zend/tests/use_function/includes/foo_strlen.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace foo;
+
+function strlen($str) {
+ return 4;
+}
diff --git a/Zend/tests/use_function/includes/global_bar.php b/Zend/tests/use_function/includes/global_bar.php
new file mode 100644
index 0000000000..6d7d91f805
--- /dev/null
+++ b/Zend/tests/use_function/includes/global_bar.php
@@ -0,0 +1,5 @@
+<?php
+
+function bar() {
+ return 'global bar';
+}
diff --git a/Zend/tests/use_function/includes/global_baz.php b/Zend/tests/use_function/includes/global_baz.php
new file mode 100644
index 0000000000..6383b9dd38
--- /dev/null
+++ b/Zend/tests/use_function/includes/global_baz.php
@@ -0,0 +1,4 @@
+<?php
+
+function baz() {
+}
diff --git a/Zend/tests/use_function/no_global_fallback.phpt b/Zend/tests/use_function/no_global_fallback.phpt
new file mode 100644
index 0000000000..6597d0d301
--- /dev/null
+++ b/Zend/tests/use_function/no_global_fallback.phpt
@@ -0,0 +1,13 @@
+--TEST--
+non-existent imported functions should not be looked up in the global table
+--FILE--
+<?php
+
+require 'includes/global_baz.php';
+
+use function foo\bar\baz;
+var_dump(baz());
+
+?>
+--EXPECTF--
+Fatal error: Call to undefined function foo\bar\baz() in %s on line %d
diff --git a/Zend/tests/use_function/no_global_fallback2.phpt b/Zend/tests/use_function/no_global_fallback2.phpt
new file mode 100644
index 0000000000..5d012c10e5
--- /dev/null
+++ b/Zend/tests/use_function/no_global_fallback2.phpt
@@ -0,0 +1,18 @@
+--TEST--
+non-existent imported functions should not be looked up in the global table
+--FILE--
+<?php
+
+namespace {
+ function test() {
+ echo "NO!";
+ }
+}
+namespace foo {
+ use function bar\test;
+ test();
+}
+
+?>
+--EXPECTF--
+Fatal error: Call to undefined function bar\test() in %s on line %d
diff --git a/Zend/tests/use_function/self_parent.phpt b/Zend/tests/use_function/self_parent.phpt
new file mode 100644
index 0000000000..f1e1fa84f1
--- /dev/null
+++ b/Zend/tests/use_function/self_parent.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Allow self and parent in use function statement
+--FILE--
+<?php
+
+namespace {
+ use function self as foo;
+ use function parent as bar;
+}
+
+?>
+--EXPECT--
diff --git a/Zend/tests/use_function/shadow_core.phpt b/Zend/tests/use_function/shadow_core.phpt
new file mode 100644
index 0000000000..8f92ff1e1b
--- /dev/null
+++ b/Zend/tests/use_function/shadow_core.phpt
@@ -0,0 +1,16 @@
+--TEST--
+shadowing a global core function with a local version
+--FILE--
+<?php
+
+require 'includes/foo_strlen.php';
+
+use function foo\strlen;
+
+var_dump(strlen('foo bar baz'));
+echo "Done\n";
+
+?>
+--EXPECT--
+int(4)
+Done
diff --git a/Zend/tests/use_function/shadow_global.phpt b/Zend/tests/use_function/shadow_global.phpt
new file mode 100644
index 0000000000..791bcdf4d5
--- /dev/null
+++ b/Zend/tests/use_function/shadow_global.phpt
@@ -0,0 +1,25 @@
+--TEST--
+shadowing a global function with a local version
+--FILE--
+<?php
+
+namespace {
+ require 'includes/global_bar.php';
+ require 'includes/foo_bar.php';
+}
+
+namespace {
+ var_dump(bar());
+}
+
+namespace {
+ use function foo\bar;
+ var_dump(bar());
+ echo "Done\n";
+}
+
+?>
+--EXPECT--
+string(10) "global bar"
+string(9) "local bar"
+Done
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 0bfe1569b5..35f5f30cba 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -197,6 +197,9 @@ void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
CG(in_namespace) = 0;
CG(has_bracketed_namespaces) = 0;
CG(current_import) = NULL;
+ CG(current_import_function) = NULL;
+ CG(current_import_const) = NULL;
+ zend_hash_init(&CG(const_filenames), 0, NULL, NULL, 0);
init_compiler_declarables(TSRMLS_C);
zend_stack_init(&CG(context_stack));
@@ -235,6 +238,7 @@ void shutdown_compiler(TSRMLS_D) /* {{{ */
zend_stack_destroy(&CG(list_stack));
zend_hash_destroy(&CG(filenames_table));
zend_llist_destroy(&CG(open_files));
+ zend_hash_destroy(&CG(const_filenames));
zend_stack_destroy(&CG(context_stack));
}
/* }}} */
@@ -417,12 +421,16 @@ int zend_add_ns_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS
lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
CALCULATE_LITERAL_HASH(lc_literal);
- ns_separator = (const char*)zend_memrchr(Z_STRVAL_P(zv), '\\', Z_STRLEN_P(zv)) + 1;
- lc_len = Z_STRLEN_P(zv) - (ns_separator - Z_STRVAL_P(zv));
- lc_name = zend_str_tolower_dup(ns_separator, lc_len);
- ZVAL_STRINGL(&c, lc_name, lc_len, 0);
- lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
- CALCULATE_LITERAL_HASH(lc_literal);
+ ns_separator = (const char*)zend_memrchr(Z_STRVAL_P(zv), '\\', Z_STRLEN_P(zv));
+
+ if (ns_separator != NULL) {
+ ns_separator += 1;
+ lc_len = Z_STRLEN_P(zv) - (ns_separator - Z_STRVAL_P(zv));
+ lc_name = zend_str_tolower_dup(ns_separator, lc_len);
+ ZVAL_STRINGL(&c, lc_name, lc_len, 0);
+ lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+ CALCULATE_LITERAL_HASH(lc_literal);
+ }
return ret;
}
@@ -1684,6 +1692,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
} else {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
zval key;
+ zval **ns_name;
if (CG(current_namespace)) {
/* Prefix function name with current namespace name */
@@ -1699,18 +1708,32 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
lcname = zend_str_tolower_dup(name, name_len);
}
+ /* Function name must not conflict with import names */
+ if (CG(current_import_function) &&
+ zend_hash_find(CG(current_import_function), lcname, Z_STRLEN(function_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
+
+ char *tmp = zend_str_tolower_dup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
+
+ if (Z_STRLEN_PP(ns_name) != Z_STRLEN(function_name->u.constant) ||
+ memcmp(tmp, lcname, Z_STRLEN(function_name->u.constant))) {
+ zend_error(E_COMPILE_ERROR, "Cannot declare function %s because the name is already in use", Z_STRVAL(function_name->u.constant));
+ }
+ efree(tmp);
+ }
+
opline->opcode = ZEND_DECLARE_FUNCTION;
opline->op1_type = IS_CONST;
build_runtime_defined_function_key(&key, lcname, name_len TSRMLS_CC);
opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
opline->op2_type = IS_CONST;
- LITERAL_STRINGL(opline->op2, lcname, name_len, 0);
+ LITERAL_STRINGL(opline->op2, lcname, name_len, 1);
CALCULATE_LITERAL_HASH(opline->op2.constant);
opline->extended_value = ZEND_DECLARE_FUNCTION;
zend_hash_quick_update(CG(function_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
zend_init_compiler_context(TSRMLS_C);
+ str_efree(lcname);
}
if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
@@ -1933,7 +1956,7 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace
char *lcname;
char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
- zend_resolve_non_class_name(function_name, check_namespace TSRMLS_CC);
+ zend_resolve_function_name(function_name, &check_namespace TSRMLS_CC);
if (check_namespace && CG(current_namespace) && !is_compound) {
/* We assume we call function from the current namespace
@@ -2070,12 +2093,12 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
}
/* }}} */
-void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
+void zend_resolve_non_class_name(znode *element_name, zend_bool *check_namespace, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC) /* {{{ */
{
znode tmp;
int len;
zval **ns;
- char *lcname, *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
+ char *lookup_name, *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
if (Z_STRVAL(element_name->u.constant)[0] == '\\') {
/* name starts with \ so it is known and unambiguos, nothing to do here but shorten it */
@@ -2084,15 +2107,35 @@ void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace
return;
}
- if(!check_namespace) {
+ if(!*check_namespace) {
return;
}
+ if (current_import_sub) {
+ len = Z_STRLEN(element_name->u.constant)+1;
+ if (case_sensitive) {
+ lookup_name = estrndup(Z_STRVAL(element_name->u.constant), len);
+ } else {
+ lookup_name = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
+ }
+ /* Check if function/const matches imported name */
+ if (zend_hash_find(current_import_sub, lookup_name, len, (void**)&ns) == SUCCESS) {
+ zval_dtor(&element_name->u.constant);
+ element_name->u.constant = **ns;
+ zval_copy_ctor(&element_name->u.constant);
+ efree(lookup_name);
+ *check_namespace = 0;
+ return;
+ }
+ efree(lookup_name);
+ }
+
if (compound && CG(current_import)) {
len = compound - Z_STRVAL(element_name->u.constant);
- lcname = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
+ /* namespace is always lowercase */
+ lookup_name = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
/* Check if first part of compound name is an import name */
- if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
+ if (zend_hash_find(CG(current_import), lookup_name, len+1, (void**)&ns) == SUCCESS) {
/* Substitute import name */
tmp.op_type = IS_CONST;
tmp.u.constant = **ns;
@@ -2102,10 +2145,11 @@ void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace
memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+len, Z_STRLEN(element_name->u.constant)+1);
zend_do_build_namespace_name(&tmp, &tmp, element_name TSRMLS_CC);
*element_name = tmp;
- efree(lcname);
+ efree(lookup_name);
+ *check_namespace = 0;
return;
}
- efree(lcname);
+ efree(lookup_name);
}
if (CG(current_namespace)) {
@@ -2121,6 +2165,18 @@ void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace
}
/* }}} */
+void zend_resolve_function_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC) /* {{{ */
+{
+ zend_resolve_non_class_name(element_name, check_namespace, 0, CG(current_import_function) TSRMLS_CC);
+}
+/* }}} */
+
+void zend_resolve_const_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC) /* {{{ */
+{
+ zend_resolve_non_class_name(element_name, check_namespace, 1, CG(current_import_const) TSRMLS_CC);
+}
+/* }}} */
+
void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC) /* {{{ */
{
char *lcname;
@@ -5618,7 +5674,7 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
break;
}
- zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
+ zend_resolve_const_name(constant_name, &check_namespace TSRMLS_CC);
if(!compound) {
fetch_type |= IS_CONSTANT_UNQUALIFIED;
@@ -5630,7 +5686,7 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
case ZEND_RT:
compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
- zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
+ zend_resolve_const_name(constant_name, &check_namespace TSRMLS_CC);
if(zend_constant_ct_subst(result, &constant_name->u.constant, 1 TSRMLS_CC)) {
break;
@@ -6981,6 +7037,18 @@ void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC
CG(current_import) = NULL;
}
+ if (CG(current_import_function)) {
+ zend_hash_destroy(CG(current_import_function));
+ efree(CG(current_import_function));
+ CG(current_import_function) = NULL;
+ }
+
+ if (CG(current_import_const)) {
+ zend_hash_destroy(CG(current_import_const));
+ efree(CG(current_import_const));
+ CG(current_import_const) = NULL;
+ }
+
if (CG(doc_comment)) {
efree(CG(doc_comment));
CG(doc_comment) = NULL;
@@ -7002,7 +7070,7 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
}
ALLOC_ZVAL(ns);
- *ns = ns_name->u.constant;
+ ZVAL_ZVAL(ns, &ns_name->u.constant, 0, 0);
if (new_name) {
name = &new_name->u.constant;
} else {
@@ -7015,8 +7083,7 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
if (p) {
ZVAL_STRING(name, p+1, 1);
} else {
- *name = *ns;
- zval_copy_ctor(name);
+ ZVAL_ZVAL(name, ns, 1, 0);
warn = !is_global && !CG(current_namespace);
}
}
@@ -7073,9 +7140,117 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
}
/* }}} */
+void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, int is_function, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC) /* {{{ */
+{
+ char *lookup_name;
+ zval *name, *ns, tmp;
+ zend_bool warn = 0;
+
+ ALLOC_ZVAL(ns);
+ ZVAL_ZVAL(ns, &ns_name->u.constant, 0, 0);
+ if (new_name) {
+ name = &new_name->u.constant;
+ } else {
+ const char *p;
+
+ /* The form "use A\B" is eqivalent to "use A\B as B".
+ So we extract the last part of compound name to use as a new_name */
+ name = &tmp;
+ p = zend_memrchr(Z_STRVAL_P(ns), '\\', Z_STRLEN_P(ns));
+ if (p) {
+ ZVAL_STRING(name, p+1, 1);
+ } else {
+ ZVAL_ZVAL(name, ns, 1, 0);
+ warn = !is_global && !CG(current_namespace);
+ }
+ }
+
+ if (case_sensitive) {
+ lookup_name = estrndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+ } else {
+ lookup_name = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+ }
+
+ if (CG(current_namespace)) {
+ /* Prefix import name with current namespace name to avoid conflicts with functions/consts */
+ char *c_ns_name = emalloc(Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) + 1);
+
+ zend_str_tolower_copy(c_ns_name, Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
+ c_ns_name[Z_STRLEN_P(CG(current_namespace))] = '\\';
+ memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lookup_name, Z_STRLEN_P(name)+1);
+ if (zend_hash_exists(lookup_table, c_ns_name, Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name)+1)) {
+ char *tmp2 = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
+
+ if (Z_STRLEN_P(ns) != Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
+ memcmp(tmp2, c_ns_name, Z_STRLEN_P(ns))) {
+ zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", is_function ? "function" : "const", Z_STRVAL_P(ns), Z_STRVAL_P(name));
+ }
+ efree(tmp2);
+ }
+ efree(c_ns_name);
+ } else if (is_function) {
+ zend_function *function;
+
+ if (zend_hash_find(lookup_table, lookup_name, Z_STRLEN_P(name)+1, (void **) &function) == SUCCESS && function->type == ZEND_USER_FUNCTION && strcmp(function->op_array.filename, CG(compiled_filename)) == 0) {
+ char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
+
+ if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
+ memcmp(c_tmp, lookup_name, Z_STRLEN_P(ns))) {
+ zend_error(E_COMPILE_ERROR, "Cannot use function %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
+ }
+ efree(c_tmp);
+ }
+ } else {
+ const char *filename;
+
+ if (zend_hash_find(lookup_table, lookup_name, Z_STRLEN_P(name)+1, (void **) &filename) == SUCCESS && strcmp(filename, CG(compiled_filename)) == 0) {
+ char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
+
+ if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
+ memcmp(c_tmp, lookup_name, Z_STRLEN_P(ns))) {
+ zend_error(E_COMPILE_ERROR, "Cannot use const %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
+ }
+ efree(c_tmp);
+ }
+ }
+
+ if (zend_hash_add(current_import_sub, lookup_name, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
+ zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", is_function ? "function" : "const", Z_STRVAL_P(ns), Z_STRVAL_P(name));
+ }
+ if (warn) {
+ zend_error(E_WARNING, "The use %s statement with non-compound name '%s' has no effect", is_function ? "function" : "const", Z_STRVAL_P(name));
+ }
+ efree(lookup_name);
+ zval_dtor(name);
+}
+/* }}} */
+
+void zend_do_use_function(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{{ */
+{
+ if (!CG(current_import_function)) {
+ CG(current_import_function) = emalloc(sizeof(HashTable));
+ zend_hash_init(CG(current_import_function), 0, NULL, ZVAL_PTR_DTOR, 0);
+ }
+
+ zend_do_use_non_class(ns_name, new_name, is_global, 1, 0, CG(current_import_function), CG(function_table) TSRMLS_CC);
+}
+/* }}} */
+
+void zend_do_use_const(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{{ */
+{
+ if (!CG(current_import_const)) {
+ CG(current_import_const) = emalloc(sizeof(HashTable));
+ zend_hash_init(CG(current_import_const), 0, NULL, ZVAL_PTR_DTOR, 0);
+ }
+
+ zend_do_use_non_class(ns_name, new_name, is_global, 0, 1, CG(current_import_const), &CG(const_filenames) TSRMLS_CC);
+}
+/* }}} */
+
void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
{
zend_op *opline;
+ zval **ns_name;
if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) {
zend_error_noreturn(E_COMPILE_ERROR, "Arrays are not allowed as constants");
@@ -7096,11 +7271,26 @@ void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
*name = tmp;
}
+ /* Constant name must not conflict with import names */
+ if (CG(current_import_const) &&
+ zend_hash_find(CG(current_import_const), Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
+
+ char *tmp = estrndup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
+
+ if (Z_STRLEN_PP(ns_name) != Z_STRLEN(name->u.constant) ||
+ memcmp(tmp, Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant))) {
+ zend_error(E_COMPILE_ERROR, "Cannot declare const %s because the name is already in use", Z_STRVAL(name->u.constant));
+ }
+ efree(tmp);
+ }
+
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_DECLARE_CONST;
SET_UNUSED(opline->result);
SET_NODE(opline->op1, name);
SET_NODE(opline->op2, value);
+
+ zend_hash_add(&CG(const_filenames), Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1, CG(compiled_filename), strlen(CG(compiled_filename))+1, NULL);
}
/* }}} */
@@ -7125,6 +7315,16 @@ void zend_do_end_namespace(TSRMLS_D) /* {{{ */
efree(CG(current_import));
CG(current_import) = NULL;
}
+ if (CG(current_import_function)) {
+ zend_hash_destroy(CG(current_import_function));
+ efree(CG(current_import_function));
+ CG(current_import_function) = NULL;
+ }
+ if (CG(current_import_const)) {
+ zend_hash_destroy(CG(current_import_const));
+ efree(CG(current_import_const));
+ CG(current_import_const) = NULL;
+ }
}
/* }}} */
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 5ffd6b4855..e3f06a0012 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -75,7 +75,7 @@ typedef struct _zend_literal {
#define Z_HASH_P(zv) \
(((zend_literal*)(zv))->hash_value)
-typedef union _znode_op {
+typedef union _znode_op {
zend_uint constant;
zend_uint var;
zend_uint num;
@@ -87,7 +87,7 @@ typedef union _znode_op {
void *ptr; /* Used for passing pointers from the compile to execution phase, currently used for traits */
} znode_op;
-typedef struct _znode { /* used only during compilation */
+typedef struct _znode { /* used only during compilation */
int op_type;
union {
znode_op op;
@@ -244,7 +244,7 @@ typedef struct _zend_arg_info {
} zend_arg_info;
/* the following structure repeats the layout of zend_arg_info,
- * but its fields have different meaning. It's used as the first element of
+ * but its fields have different meaning. It's used as the first element of
* arg_info array to define properties of internal functions.
*/
typedef struct _zend_internal_function_info {
@@ -267,7 +267,7 @@ typedef struct _zend_compiled_variable {
struct _zend_op_array {
/* Common elements */
zend_uchar type;
- const char *function_name;
+ const char *function_name;
zend_class_entry *scope;
zend_uint fn_flags;
union _zend_function *prototype;
@@ -443,7 +443,9 @@ ZEND_API char *zend_get_compiled_filename(TSRMLS_D);
ZEND_API int zend_get_compiled_lineno(TSRMLS_D);
ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D);
-void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace TSRMLS_DC);
+void zend_resolve_non_class_name(znode *element_name, zend_bool *check_namespace, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC);
+void zend_resolve_function_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC);
+void zend_resolve_const_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC);
void zend_resolve_class_name(znode *class_name TSRMLS_DC);
ZEND_API const char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len);
@@ -642,6 +644,9 @@ void zend_do_begin_namespace(const znode *name, zend_bool with_brackets TSRMLS_D
void zend_do_end_namespace(TSRMLS_D);
void zend_verify_namespace(TSRMLS_D);
void zend_do_use(znode *name, znode *new_name, int is_global TSRMLS_DC);
+void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, int is_function, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC);
+void zend_do_use_function(znode *name, znode *new_name, int is_global TSRMLS_DC);
+void zend_do_use_const(znode *name, znode *new_name, int is_global TSRMLS_DC);
void zend_do_end_compilation(TSRMLS_D);
void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC);
@@ -681,7 +686,7 @@ void zend_class_add_ref(zend_class_entry **ce);
ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal);
#define zend_unmangle_property_name(mangled_property, mangled_property_len, class_name, prop_name) \
- zend_unmangle_property_name_ex(mangled_property, mangled_property_len, class_name, prop_name, NULL)
+ zend_unmangle_property_name_ex(mangled_property, mangled_property_len, class_name, prop_name, NULL)
ZEND_API int zend_unmangle_property_name_ex(const char *mangled_property, int mangled_property_len, const char **class_name, const char **prop_name, int *prop_len);
#define ZEND_FUNCTION_DTOR (void (*)(void *)) zend_function_dtor
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index b9a5b39914..27d471fa06 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -131,9 +131,13 @@ struct _zend_compiler_globals {
zval *current_namespace;
HashTable *current_import;
+ HashTable *current_import_function;
+ HashTable *current_import_const;
zend_bool in_namespace;
zend_bool has_bracketed_namespaces;
+ HashTable const_filenames;
+
zend_compiler_context context;
zend_stack context_stack;
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index a71dfb0956..1eb7b3170b 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -241,6 +241,8 @@ top_statement:
| T_NAMESPACE '{' { zend_do_begin_namespace(NULL, 1 TSRMLS_CC); }
top_statement_list '}' { zend_do_end_namespace(TSRMLS_C); }
| T_USE use_declarations ';' { zend_verify_namespace(TSRMLS_C); }
+ | T_USE T_FUNCTION use_function_declarations ';' { zend_verify_namespace(TSRMLS_C); }
+ | T_USE T_CONST use_const_declarations ';' { zend_verify_namespace(TSRMLS_C); }
| constant_declaration ';' { zend_verify_namespace(TSRMLS_C); }
;
@@ -256,6 +258,30 @@ use_declaration:
| T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use(&$2, &$4, 1 TSRMLS_CC); }
;
+use_function_declarations:
+ use_function_declarations ',' use_function_declaration
+ | use_function_declaration
+;
+
+use_function_declaration:
+ namespace_name { zend_do_use_function(&$1, NULL, 0 TSRMLS_CC); }
+ | namespace_name T_AS T_STRING { zend_do_use_function(&$1, &$3, 0 TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name { zend_do_use_function(&$2, NULL, 1 TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use_function(&$2, &$4, 1 TSRMLS_CC); }
+;
+
+use_const_declarations:
+ use_const_declarations ',' use_const_declaration
+ | use_const_declaration
+;
+
+use_const_declaration:
+ namespace_name { zend_do_use_const(&$1, NULL, 0 TSRMLS_CC); }
+ | namespace_name T_AS T_STRING { zend_do_use_const(&$1, &$3, 0 TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name { zend_do_use_const(&$2, NULL, 1 TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use_const(&$2, &$4, 1 TSRMLS_CC); }
+;
+
constant_declaration:
constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_constant(&$3, &$5 TSRMLS_CC); }
| T_CONST T_STRING '=' static_scalar { zend_do_declare_constant(&$2, &$4 TSRMLS_CC); }