mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Import namespaced constants via new 'use const' sequence
This commit is contained in:
parent
e1125a6a89
commit
4adf49eeaf
13 changed files with 251 additions and 9 deletions
26
Zend/tests/use_const/alias.phpt
Normal file
26
Zend/tests/use_const/alias.phpt
Normal file
|
@ -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
|
22
Zend/tests/use_const/basic.phpt
Normal file
22
Zend/tests/use_const/basic.phpt
Normal file
|
@ -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
|
21
Zend/tests/use_const/conflicting_use.phpt
Normal file
21
Zend/tests/use_const/conflicting_use.phpt
Normal file
|
@ -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 bar\baz as baz because the name is already in use in %s on line %d
|
25
Zend/tests/use_const/function_and_cons.phpt
Normal file
25
Zend/tests/use_const/function_and_cons.phpt
Normal file
|
@ -0,0 +1,25 @@
|
|||
--TEST--
|
||||
use function and use const in the same block
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace foo {
|
||||
const bar = 'local const';
|
||||
function bar() {
|
||||
return 'local function';
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
use const foo\bar;
|
||||
use function foo\bar;
|
||||
var_dump(bar);
|
||||
var_dump(bar());
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(11) "local const"
|
||||
string(14) "local function"
|
||||
Done
|
18
Zend/tests/use_const/no_global_fallback.phpt
Normal file
18
Zend/tests/use_const/no_global_fallback.phpt
Normal file
|
@ -0,0 +1,18 @@
|
|||
--TEST--
|
||||
non-existent imported constants should not be looked up in the global table
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
const baz = NULL;
|
||||
}
|
||||
|
||||
namespace {
|
||||
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"
|
24
Zend/tests/use_const/shadow_core.phpt
Normal file
24
Zend/tests/use_const/shadow_core.phpt
Normal file
|
@ -0,0 +1,24 @@
|
|||
--TEST--
|
||||
shadowing a global core constant with a local version
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace foo {
|
||||
const PHP_VERSION = 42;
|
||||
}
|
||||
|
||||
namespace {
|
||||
var_dump(PHP_VERSION);
|
||||
}
|
||||
|
||||
namespace {
|
||||
use const foo\PHP_VERSION;
|
||||
var_dump(PHP_VERSION);
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(%d) "%s"
|
||||
int(42)
|
||||
Done
|
12
Zend/tests/use_const/shadow_core_null.phpt
Normal file
12
Zend/tests/use_const/shadow_core_null.phpt
Normal file
|
@ -0,0 +1,12 @@
|
|||
--TEST--
|
||||
shadowing null with a local version
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace foo {
|
||||
const null = 42;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot redeclare constant 'null' in %s on line %d
|
28
Zend/tests/use_const/shadow_global.phpt
Normal file
28
Zend/tests/use_const/shadow_global.phpt
Normal file
|
@ -0,0 +1,28 @@
|
|||
--TEST--
|
||||
shadowing a global constant with a local version
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
const bar = 'global bar';
|
||||
}
|
||||
|
||||
namespace foo {
|
||||
const bar = 'local bar';
|
||||
}
|
||||
|
||||
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
|
21
Zend/tests/use_const/shadow_global_same_ns.phpt
Normal file
21
Zend/tests/use_const/shadow_global_same_ns.phpt
Normal file
|
@ -0,0 +1,21 @@
|
|||
--TEST--
|
||||
shadowing global constants defined in the same namespace as use
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
namespace foo {
|
||||
const bar = 'local';
|
||||
}
|
||||
|
||||
namespace {
|
||||
const bar = 'global';
|
||||
|
||||
use const foo\bar;
|
||||
var_dump(bar);
|
||||
echo "Done\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(5) "local"
|
||||
Done
|
|
@ -205,6 +205,7 @@ void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
|
|||
CG(has_bracketed_namespaces) = 0;
|
||||
CG(current_import) = NULL;
|
||||
CG(current_import_function) = NULL;
|
||||
CG(current_import_const) = NULL;
|
||||
init_compiler_declarables(TSRMLS_C);
|
||||
zend_stack_init(&CG(context_stack));
|
||||
|
||||
|
@ -2098,7 +2099,7 @@ void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace,
|
|||
if (current_import_sub) {
|
||||
len = Z_STRLEN(element_name->u.constant)+1;
|
||||
lcname = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
|
||||
/* Check if function matches imported name */
|
||||
/* Check if function/const matches imported name */
|
||||
if (zend_hash_find(current_import_sub, lcname, len, (void**)&ns) == SUCCESS) {
|
||||
zval_dtor(&element_name->u.constant);
|
||||
element_name->u.constant = **ns;
|
||||
|
@ -2150,7 +2151,7 @@ void zend_resolve_function_name(znode *element_name, zend_bool check_namespace T
|
|||
|
||||
void zend_resolve_const_name(znode *element_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_resolve_non_class_name(element_name, check_namespace, NULL TSRMLS_CC);
|
||||
zend_resolve_non_class_name(element_name, check_namespace, CG(current_import_const) TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -7030,6 +7031,12 @@ void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC
|
|||
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;
|
||||
|
@ -7122,17 +7129,12 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_use_function(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, HashTable *current_import_sub TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *lcname;
|
||||
zval *name, *ns, tmp;
|
||||
zend_bool warn = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
ALLOC_ZVAL(ns);
|
||||
*ns = ns_name->u.constant;
|
||||
if (new_name) {
|
||||
|
@ -7162,7 +7164,7 @@ void zend_do_use_function(znode *ns_name, znode *new_name, int is_global TSRMLS_
|
|||
zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name));
|
||||
}
|
||||
|
||||
if (zend_hash_add(CG(current_import_function), lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
|
||||
if (zend_hash_add(current_import_sub, lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
|
||||
zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
|
||||
}
|
||||
if (warn) {
|
||||
|
@ -7173,6 +7175,28 @@ void zend_do_use_function(znode *ns_name, znode *new_name, int is_global TSRMLS_
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
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, CG(current_import_function) 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, CG(current_import_const) TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_op *opline;
|
||||
|
@ -7230,6 +7254,11 @@ void zend_do_end_namespace(TSRMLS_D) /* {{{ */
|
|||
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;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
|
|
@ -638,7 +638,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, HashTable *current_import_sub 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_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC);
|
||||
|
|
|
@ -132,6 +132,7 @@ 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;
|
||||
|
||||
|
|
|
@ -241,6 +241,7 @@ top_statement:
|
|||
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); }
|
||||
;
|
||||
|
||||
|
@ -268,6 +269,18 @@ use_function_declaration:
|
|||
| 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); }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue