mirror of
https://github.com/php/php-src.git
synced 2025-01-21 11:13:38 +08:00
Namespace resolution streamlining patch
[DOC] new resolution rules should be documented soon
This commit is contained in:
parent
caa133b3d3
commit
1b4134c07b
@ -20,26 +20,21 @@ function test3(\foo\bar $bar) {
|
||||
function test4(\Exception $e) {
|
||||
echo "ok\n";
|
||||
}
|
||||
function test5(Exception $e) {
|
||||
echo "ok\n";
|
||||
}
|
||||
function test6(\bar $bar) {
|
||||
function test5(\bar $bar) {
|
||||
echo "bug\n";
|
||||
}
|
||||
|
||||
$x = new bar();
|
||||
$y = new Exception();
|
||||
$y = new \Exception();
|
||||
test1($x);
|
||||
test2($x);
|
||||
test3($x);
|
||||
test4($y);
|
||||
test5($y);
|
||||
test6($x);
|
||||
test5($x);
|
||||
--EXPECTF--
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
|
||||
Catchable fatal error: Argument 1 passed to foo\test6() must be an instance of bar, instance of foo\bar given, called in %sbug42802.php on line 23
|
||||
Catchable fatal error: Argument 1 passed to foo\test5() must be an instance of bar, instance of foo\bar given, called in %sbug42802.php on line %d and defined in %sbug42802.php on line %d
|
||||
|
@ -15,6 +15,7 @@ const C = "foo\\foo\\foo::C\n";
|
||||
}
|
||||
|
||||
namespace foo;
|
||||
use \ArrayObject;
|
||||
|
||||
const C = "foo\\C\n";
|
||||
const I = 11;
|
||||
@ -89,7 +90,6 @@ echo foo::C;
|
||||
echo \foo\foo::C;
|
||||
echo ArrayObject::STD_PROP_LIST . "\n";
|
||||
echo E_ERROR . "\n";
|
||||
|
||||
echo "second\n";
|
||||
echo \foo\foo::C1;
|
||||
echo \foo\foo::C2;
|
||||
|
@ -10,6 +10,6 @@ class foo {
|
||||
|
||||
$foo = new foo;
|
||||
$foo->bar($foo); // Ok!
|
||||
$foo->bar(new stdclass); // Error, ok!
|
||||
$foo->bar(new \stdclass); // Error, ok!
|
||||
--EXPECTF--
|
||||
Catchable fatal error: Argument 1 passed to foobar\foo::bar() must be an instance of foobar\foo, instance of stdClass given, called in %sbug43332_1.php on line 10 and defined in %sbug43332_1.php on line 5
|
||||
|
@ -11,7 +11,7 @@ class_alias('foo\bar', 'baz');
|
||||
|
||||
use \baz as stdClass;
|
||||
|
||||
var_dump(new foo\bar);
|
||||
var_dump(new bar);
|
||||
var_dump(new stdClass);
|
||||
var_dump(new \baz);
|
||||
|
||||
|
@ -15,7 +15,7 @@ use test\ns1 as ns2;
|
||||
use test\ns1;
|
||||
|
||||
Foo::bar();
|
||||
test\ns1\Foo::bar();
|
||||
\test\ns1\Foo::bar();
|
||||
Bar::bar();
|
||||
ns2\Foo::bar();
|
||||
ns1\Foo::bar();
|
||||
|
@ -1,9 +1,9 @@
|
||||
--TEST--
|
||||
004: Name conflict (php name)
|
||||
004: Using global class name from namespace (unqualified - fail)
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test\ns1;
|
||||
|
||||
echo get_class(new Exception()),"\n";
|
||||
--EXPECT--
|
||||
Exception
|
||||
--EXPECTF--
|
||||
Fatal error: Class 'test\ns1\Exception' not found in %sns_004.php on line %d
|
@ -15,35 +15,27 @@ class Foo {
|
||||
}
|
||||
}
|
||||
new Foo();
|
||||
new X\Foo();
|
||||
new Y\Foo();
|
||||
new \X\Foo();
|
||||
Foo::bar();
|
||||
X\Foo::bar();
|
||||
Y\Foo::bar();
|
||||
\X\Foo::bar();
|
||||
echo Foo::C;
|
||||
echo X\Foo::C;
|
||||
echo Y\Foo::C;
|
||||
echo \X\Foo::C;
|
||||
echo Foo::$var;
|
||||
echo X\Foo::$var;
|
||||
echo Y\Foo::$var;
|
||||
echo \X\Foo::$var;
|
||||
--EXPECT--
|
||||
class ok
|
||||
class ok
|
||||
class ok
|
||||
class ok
|
||||
method ok
|
||||
method ok
|
||||
method ok
|
||||
method ok
|
||||
const ok
|
||||
const ok
|
||||
const ok
|
||||
const ok
|
||||
var ok
|
||||
var ok
|
||||
var ok
|
||||
var ok
|
||||
|
@ -10,23 +10,18 @@ class Foo {
|
||||
function f1($x=Foo::C) {
|
||||
echo $x;
|
||||
}
|
||||
function f2($x=A\Foo::C) {
|
||||
function f2($x=B\Foo::C) {
|
||||
echo $x;
|
||||
}
|
||||
function f3($x=B\Foo::C) {
|
||||
echo $x;
|
||||
}
|
||||
function f4($x=\A\Foo::C) {
|
||||
function f3($x=\A\Foo::C) {
|
||||
echo $x;
|
||||
}
|
||||
echo Foo::C;
|
||||
echo A\Foo::C;
|
||||
echo B\Foo::C;
|
||||
echo \A\Foo::C;
|
||||
f1();
|
||||
f2();
|
||||
f3();
|
||||
f4();
|
||||
--EXPECT--
|
||||
ok
|
||||
ok
|
||||
@ -34,5 +29,3 @@ ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
|
@ -5,6 +5,8 @@
|
||||
--FILE--
|
||||
<?php
|
||||
namespace A;
|
||||
use \ArrayObject;
|
||||
|
||||
function f1($x = ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
|
@ -15,25 +15,20 @@ function f1($x = ArrayObject::STD_PROP_LIST) {
|
||||
function f2($x = \ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
function f3($x = A\ArrayObject::STD_PROP_LIST) {
|
||||
function f3($x = \A\ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
function f4($x = B\ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
function f5($x = \A\ArrayObject::STD_PROP_LIST) {
|
||||
var_dump($x);
|
||||
}
|
||||
var_dump(ArrayObject::STD_PROP_LIST);
|
||||
var_dump(\ArrayObject::STD_PROP_LIST);
|
||||
var_dump(A\ArrayObject::STD_PROP_LIST);
|
||||
var_dump(B\ArrayObject::STD_PROP_LIST);
|
||||
var_dump(\A\ArrayObject::STD_PROP_LIST);
|
||||
f1();
|
||||
f2();
|
||||
f3();
|
||||
f4();
|
||||
f5();
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
@ -41,8 +36,6 @@ int(1)
|
||||
int(2)
|
||||
int(2)
|
||||
int(2)
|
||||
int(2)
|
||||
int(1)
|
||||
int(2)
|
||||
int(2)
|
||||
int(2)
|
||||
|
@ -15,35 +15,27 @@ class X {
|
||||
}
|
||||
}
|
||||
new X();
|
||||
new X\X();
|
||||
new Y\X();
|
||||
new \X\X();
|
||||
X::bar();
|
||||
X\X::bar();
|
||||
Y\X::bar();
|
||||
\X\X::bar();
|
||||
echo X::C;
|
||||
echo X\X::C;
|
||||
echo Y\X::C;
|
||||
echo \X\X::C;
|
||||
echo X::$var;
|
||||
echo X\X::$var;
|
||||
echo Y\X::$var;
|
||||
echo \X\X::$var;
|
||||
--EXPECT--
|
||||
class ok
|
||||
class ok
|
||||
class ok
|
||||
class ok
|
||||
method ok
|
||||
method ok
|
||||
method ok
|
||||
method ok
|
||||
const ok
|
||||
const ok
|
||||
const ok
|
||||
const ok
|
||||
var ok
|
||||
var ok
|
||||
var ok
|
||||
var ok
|
||||
|
@ -7,7 +7,7 @@ function foo() {
|
||||
echo "ok\n";
|
||||
}
|
||||
\Exception\foo();
|
||||
Exception::bar();
|
||||
\Exception::bar();
|
||||
--EXPECTF--
|
||||
ok
|
||||
|
||||
|
@ -6,13 +6,13 @@
|
||||
<?php
|
||||
namespace test\ns1;
|
||||
|
||||
class Foo implements SplObserver {
|
||||
class Foo implements \SplObserver {
|
||||
function update(\SplSubject $x) {
|
||||
echo "ok\n";
|
||||
}
|
||||
}
|
||||
|
||||
class Bar implements SplSubject {
|
||||
class Bar implements \SplSubject {
|
||||
function attach(\SplObserver $x) {
|
||||
echo "ok\n";
|
||||
}
|
||||
|
@ -11,23 +11,18 @@ class Foo {
|
||||
function test2(\test\ns1\Foo $x) {
|
||||
echo "ok\n";
|
||||
}
|
||||
function test3(Exception $x) {
|
||||
echo "ok\n";
|
||||
}
|
||||
function test4(\Exception $x) {
|
||||
function test3(\Exception $x) {
|
||||
echo "ok\n";
|
||||
}
|
||||
}
|
||||
|
||||
$foo = new Foo();
|
||||
$ex = new Exception();
|
||||
$ex = new \Exception();
|
||||
$foo->test1($foo);
|
||||
$foo->test2($foo);
|
||||
$foo->test3($ex);
|
||||
$foo->test4($ex);
|
||||
?>
|
||||
--EXPECT--
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
|
@ -5,14 +5,15 @@
|
||||
--FILE--
|
||||
<?php
|
||||
namespace test\ns1;
|
||||
use \SplObserver;
|
||||
|
||||
class Foo implements SplObserver {
|
||||
function update(SplSubject $x) {
|
||||
function update(\SplSubject $x) {
|
||||
echo "ok\n";
|
||||
}
|
||||
}
|
||||
|
||||
class Bar implements SplSubject {
|
||||
class Bar implements \SplSubject {
|
||||
function attach(SplObserver $x) {
|
||||
echo "ok\n";
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ echo namespace\foo::bar();
|
||||
echo namespace\f1();
|
||||
echo namespace\f2();
|
||||
echo namespace\f3(new namespace\foo());
|
||||
echo namespace\unknown;
|
||||
?>
|
||||
--EXPECTF--
|
||||
const ok
|
||||
@ -54,3 +55,5 @@ const ok
|
||||
const ok
|
||||
class ok
|
||||
ok
|
||||
|
||||
Fatal error: Undefined constant 'Test\ns1\unknown' in %sns_057.php on line %d
|
@ -40,8 +40,9 @@ echo namespace\foo::bar();
|
||||
echo namespace\f1();
|
||||
echo namespace\f2();
|
||||
echo namespace\f3(new namespace\foo());
|
||||
echo namespace\unknown;
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
const ok
|
||||
func ok
|
||||
const ok
|
||||
@ -52,3 +53,5 @@ const ok
|
||||
const ok
|
||||
class ok
|
||||
ok
|
||||
|
||||
Fatal error: Undefined constant 'unknown' in %sns_058.php on line %d
|
||||
|
@ -11,7 +11,7 @@ class bar {
|
||||
}
|
||||
}
|
||||
|
||||
new bar(new stdclass);
|
||||
new bar(new \stdclass);
|
||||
new bar(null);
|
||||
|
||||
?>
|
||||
|
@ -12,7 +12,7 @@ class bar {
|
||||
}
|
||||
|
||||
new bar(null);
|
||||
new bar(new stdclass);
|
||||
new bar(new \stdclass);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
|
@ -22,7 +22,7 @@ class test implements foo {
|
||||
|
||||
new bar(new test);
|
||||
new bar(null);
|
||||
new bar(new stdclass);
|
||||
new bar(new \stdclass);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
|
@ -11,12 +11,9 @@ $x = function (\stdclass $x = NULL) {
|
||||
|
||||
$x(NULL);
|
||||
$x(new \stdclass);
|
||||
$x(new stdclass);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
NULL
|
||||
object(stdClass)#%d (0) {
|
||||
}
|
||||
object(stdClass)#%d (0) {
|
||||
}
|
||||
|
@ -9,16 +9,16 @@ $x = function (\stdclass $x = NULL) {
|
||||
var_dump($x);
|
||||
};
|
||||
|
||||
class stdclass { }
|
||||
class stdclass extends \stdclass { }
|
||||
|
||||
$x(NULL);
|
||||
$x(new stdclass);
|
||||
$x(new stdclass);
|
||||
$x(new \stdclass);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
NULL
|
||||
object(foo\stdClass)#%d (0) {
|
||||
object(foo\stdclass)#%d (0) {
|
||||
}
|
||||
object(foo\stdClass)#%d (0) {
|
||||
object(stdClass)#%d (0) {
|
||||
}
|
||||
|
@ -516,7 +516,7 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
|
||||
|
||||
/* Ugly hack to support constants as static array indices */
|
||||
#define IS_CONSTANT_TYPE_MASK 0x0f
|
||||
#define IS_CONSTANT_RT_NS_CHECK 0x10
|
||||
#define IS_CONSTANT_UNQUALIFIED 0x10
|
||||
#define IS_CONSTANT_INDEX 0x80
|
||||
#define IS_LEXICAL_VAR 0x20
|
||||
#define IS_LEXICAL_REF 0x40
|
||||
|
@ -1535,42 +1535,28 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace
|
||||
zend_function *function;
|
||||
char *lcname;
|
||||
int prefix_len = 0;
|
||||
char *is_compound = NULL;
|
||||
char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
|
||||
|
||||
if (Z_STRVAL(function_name->u.constant)[0] == '\\') {
|
||||
is_compound = memchr(Z_STRVAL(function_name->u.constant)+1, '\\', Z_STRLEN(function_name->u.constant)-1);
|
||||
} else {
|
||||
is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
|
||||
}
|
||||
if (check_namespace) {
|
||||
ulong unused;
|
||||
zend_resolve_non_class_name(function_name, check_namespace TSRMLS_CC);
|
||||
|
||||
zend_resolve_non_class_name(function_name, &unused, 2, 1 TSRMLS_CC);
|
||||
if (Z_STRVAL(function_name->u.constant)[0] == '\\') {
|
||||
memmove(Z_STRVAL(function_name->u.constant), Z_STRVAL(function_name->u.constant)+1, Z_STRLEN(function_name->u.constant));
|
||||
--Z_STRLEN(function_name->u.constant);
|
||||
}
|
||||
if (CG(current_namespace) && !is_compound) {
|
||||
if (check_namespace && CG(current_namespace) && !is_compound) {
|
||||
/* We assume we call function from the current namespace
|
||||
if it is not prefixed. */
|
||||
|
||||
/* In run-time PHP will check for function with full name and
|
||||
internal function with short name */
|
||||
prefix_len = Z_STRLEN_P(CG(current_namespace)) + 1;
|
||||
}
|
||||
} else if (Z_STRVAL(function_name->u.constant)[0] == '\\') {
|
||||
memmove(Z_STRVAL(function_name->u.constant), Z_STRVAL(function_name->u.constant)+1, Z_STRLEN(function_name->u.constant));
|
||||
--Z_STRLEN(function_name->u.constant);
|
||||
}
|
||||
|
||||
zend_do_begin_dynamic_function_call(function_name, 1 TSRMLS_CC);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lcname = zend_str_tolower_dup(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
|
||||
if ((zend_hash_find(CG(function_table), lcname, function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) ||
|
||||
((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
|
||||
(function->type == ZEND_INTERNAL_FUNCTION))) {
|
||||
zend_do_begin_dynamic_function_call(function_name, prefix_len TSRMLS_CC);
|
||||
efree(lcname);
|
||||
return 1; /* Dynamic */
|
||||
}
|
||||
((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
|
||||
(function->type == ZEND_INTERNAL_FUNCTION))) {
|
||||
zend_do_begin_dynamic_function_call(function_name, 0 TSRMLS_CC);
|
||||
efree(lcname);
|
||||
return 1; /* Dynamic */
|
||||
}
|
||||
efree(function_name->u.constant.value.str.val);
|
||||
function_name->u.constant.value.str.val = lcname;
|
||||
|
||||
@ -1636,14 +1622,14 @@ void zend_do_clone(znode *result, const znode *expr TSRMLS_DC)
|
||||
}
|
||||
|
||||
|
||||
void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TSRMLS_DC)
|
||||
void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC)
|
||||
{
|
||||
unsigned char *ptr = NULL;
|
||||
zend_op *opline;
|
||||
zend_op *opline, *opline2;
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
|
||||
if (prefix_len) {
|
||||
if (ns_call) {
|
||||
char *slash;
|
||||
/* In run-time PHP will check for function with full name and
|
||||
internal function with short name */
|
||||
opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
|
||||
@ -1654,15 +1640,18 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TS
|
||||
Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
|
||||
Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(opline->op2.u.constant);
|
||||
opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_OP_DATA;
|
||||
opline->op1.op_type = IS_CONST;
|
||||
Z_TYPE(opline->op1.u.constant) = IS_STRING;
|
||||
Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(function_name->u.constant) - prefix_len;
|
||||
Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(function_name->u.constant) + prefix_len, Z_STRLEN(opline->op1.u.constant));
|
||||
opline->op2.op_type = IS_CONST;
|
||||
ZVAL_BOOL(&opline->op2.u.constant, (memchr(Z_STRVAL(opline->op1.u.constant), '\\', Z_STRLEN(opline->op1.u.constant)) != NULL));
|
||||
opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
|
||||
opline2 = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline2->opcode = ZEND_OP_DATA;
|
||||
opline2->op1.op_type = IS_CONST;
|
||||
Z_TYPE(opline2->op1.u.constant) = IS_LONG;
|
||||
slash = zend_memrchr(Z_STRVAL(opline->op1.u.constant), '\\', Z_STRLEN(opline->op1.u.constant));
|
||||
if(!slash) {
|
||||
zend_error(E_CORE_ERROR, "Namespaced name %s should contain slash", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
/* this is the length of namespace prefix */
|
||||
Z_LVAL(opline2->op1.u.constant) = slash-Z_STRVAL(opline->op1.u.constant)+1;
|
||||
/* this is the hash of the non-prefixed part, lowercased */
|
||||
opline2->extended_value = zend_hash_func(slash+1, Z_STRLEN(opline->op1.u.constant)-Z_LVAL(opline2->op1.u.constant)+1);
|
||||
} else {
|
||||
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
|
||||
opline->op2 = *function_name;
|
||||
@ -1678,34 +1667,33 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
|
||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||
}
|
||||
|
||||
/* type = 1 for constant, 2 for function */
|
||||
void zend_resolve_non_class_name(znode *element_name, ulong *fetch_type, int type, int check_namespace TSRMLS_DC)
|
||||
void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace TSRMLS_DC)
|
||||
{
|
||||
znode tmp;
|
||||
int len;
|
||||
zval **ns;
|
||||
char *lcname, *check_import = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
|
||||
char *lcname, *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
|
||||
|
||||
if (Z_STRVAL(element_name->u.constant)[0] == '\\') {
|
||||
check_namespace = 0;
|
||||
check_import = 0;
|
||||
/* name starts with \ so it is known and unambiguos, nothing to do here but shorten it */
|
||||
memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+1, Z_STRLEN(element_name->u.constant));
|
||||
--Z_STRLEN(element_name->u.constant);
|
||||
return;
|
||||
}
|
||||
|
||||
if (check_import && CG(current_import)) {
|
||||
len = check_import - Z_STRVAL(element_name->u.constant);
|
||||
if(!check_namespace) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
/* 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 (!check_import && type == 1) {
|
||||
/* tell zend_get_constant_ex this is an ambiguous T_STRING */
|
||||
*fetch_type |= IS_CONSTANT_RT_NS_CHECK;
|
||||
}
|
||||
/* Substitute import name */
|
||||
tmp.op_type = IS_CONST;
|
||||
tmp.u.constant = **ns;
|
||||
@ -1714,22 +1702,14 @@ void zend_resolve_non_class_name(znode *element_name, ulong *fetch_type, int typ
|
||||
Z_STRLEN(element_name->u.constant) -= len;
|
||||
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);
|
||||
if (Z_STRVAL(tmp.u.constant)[0] != '\\') {
|
||||
/* make this a \global\namespaced\element */
|
||||
znode global;
|
||||
|
||||
zend_do_build_namespace_name(&global, NULL, &tmp TSRMLS_CC);
|
||||
*element_name = global;
|
||||
} else {
|
||||
*element_name = tmp;
|
||||
}
|
||||
*element_name = tmp;
|
||||
efree(lcname);
|
||||
return;
|
||||
}
|
||||
efree(lcname);
|
||||
}
|
||||
|
||||
if (check_namespace && CG(current_namespace)) {
|
||||
if (CG(current_namespace)) {
|
||||
tmp = *element_name;
|
||||
Z_STRLEN(tmp.u.constant) = sizeof("\\")-1 + Z_STRLEN(element_name->u.constant) + Z_STRLEN_P(CG(current_namespace));
|
||||
Z_STRVAL(tmp.u.constant) = (char *) emalloc(Z_STRLEN(tmp.u.constant)+1);
|
||||
@ -1738,11 +1718,6 @@ void zend_resolve_non_class_name(znode *element_name, ulong *fetch_type, int typ
|
||||
memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN_P(CG(current_namespace)) + sizeof("\\")-1]), Z_STRVAL(element_name->u.constant), Z_STRLEN(element_name->u.constant)+1);
|
||||
STR_FREE(Z_STRVAL(element_name->u.constant));
|
||||
*element_name = tmp;
|
||||
if (type == 1) {
|
||||
/* We assume we use constant from the current namespace
|
||||
if it is not prefixed. */
|
||||
*fetch_type |= IS_CONSTANT_RT_NS_CHECK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1757,8 +1732,7 @@ void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_
|
||||
compound = memchr(Z_STRVAL(class_name->u.constant), '\\', Z_STRLEN(class_name->u.constant));
|
||||
if (compound) {
|
||||
/* This is a compound class name that contains namespace prefix */
|
||||
if (Z_TYPE(class_name->u.constant) == IS_STRING &&
|
||||
Z_STRVAL(class_name->u.constant)[0] == '\\') {
|
||||
if (Z_STRVAL(class_name->u.constant)[0] == '\\') {
|
||||
/* The STRING name has "\" prefix */
|
||||
Z_STRLEN(class_name->u.constant) -= 1;
|
||||
memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant)+1);
|
||||
@ -1784,11 +1758,12 @@ void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_
|
||||
memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+len, Z_STRLEN(class_name->u.constant)+1);
|
||||
zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
|
||||
*class_name = tmp;
|
||||
efree(lcname);
|
||||
return;
|
||||
}
|
||||
efree(lcname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Here name is not prefixed with \ and not imported */
|
||||
if (CG(current_namespace)) {
|
||||
tmp.op_type = IS_CONST;
|
||||
tmp.u.constant = *CG(current_namespace);
|
||||
@ -1808,23 +1783,7 @@ void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_
|
||||
class_name->u.constant = **ns;
|
||||
zval_copy_ctor(&class_name->u.constant);
|
||||
} else if (CG(current_namespace)) {
|
||||
zend_class_entry **pce;
|
||||
|
||||
if (check_ns_name) {
|
||||
/* PHP will need to perform additional checks at run-time to
|
||||
determine if we assume namespace or class name. */
|
||||
*fetch_type |= ZEND_FETCH_CLASS_RT_NS_NAME;
|
||||
}
|
||||
|
||||
if ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) ||
|
||||
(zend_hash_find(CG(class_table), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&pce) == SUCCESS &&
|
||||
(*pce)->type == ZEND_INTERNAL_CLASS)) {
|
||||
/* There is an internal class with the same name exists.
|
||||
PHP will need to perform additional cheks at run-time to
|
||||
determine if we assume class in current namespace or
|
||||
internal one. */
|
||||
*fetch_type |= ZEND_FETCH_CLASS_RT_NS_CHECK;
|
||||
}
|
||||
/* plain name, no import - prepend current namespace to it */
|
||||
tmp.op_type = IS_CONST;
|
||||
tmp.u.constant = *CG(current_namespace);
|
||||
zval_copy_ctor(&tmp.u.constant);
|
||||
@ -2059,7 +2018,6 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
|
||||
}
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
|
||||
opline->extended_value = fetch_type & ~ZEND_FETCH_CLASS_RT_NS_NAME;
|
||||
opline->op1 = class_node;
|
||||
opline->op2 = *method_name;
|
||||
|
||||
@ -2077,11 +2035,6 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
|
||||
|
||||
nsname = Z_STRVAL(class_node.u.constant);
|
||||
nsname_len = Z_STRLEN(class_node.u.constant);
|
||||
if (fetch_type & ZEND_FETCH_CLASS_RT_NS_NAME) {
|
||||
/* Remove namespace name */
|
||||
nsname = (char *)memchr(nsname, '\\', nsname_len) + 1;
|
||||
nsname_len -= (nsname - Z_STRVAL(class_node.u.constant));
|
||||
}
|
||||
len = nsname_len + 1 + Z_STRLEN(method_name->u.constant);
|
||||
fname = emalloc(len + 1);
|
||||
memcpy(fname, nsname, nsname_len);
|
||||
@ -3924,9 +3877,9 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
|
||||
znode tmp;
|
||||
zend_op *opline;
|
||||
int type;
|
||||
char *check_import;
|
||||
char *compound;
|
||||
ulong fetch_type = 0;
|
||||
int unknown_should_fatal = 0;
|
||||
int unknown_should_fail = 0;
|
||||
|
||||
if (constant_container) {
|
||||
switch (mode) {
|
||||
@ -3955,7 +3908,6 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
|
||||
opline->opcode = ZEND_FETCH_CONSTANT;
|
||||
opline->result.op_type = IS_TMP_VAR;
|
||||
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||
opline->extended_value = fetch_type & ~ZEND_FETCH_CLASS_RT_NS_NAME;
|
||||
opline->op1 = *constant_container;
|
||||
opline->op2 = *constant_name;
|
||||
*result = opline->result;
|
||||
@ -3964,100 +3916,46 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
|
||||
return;
|
||||
}
|
||||
/* namespace constant */
|
||||
/* only one that did not contain \ from the start can be converted to string if unknown */
|
||||
switch (mode) {
|
||||
case ZEND_CT:
|
||||
if (check_namespace == 2) {
|
||||
unknown_should_fatal = 1;
|
||||
check_namespace = 0;
|
||||
}
|
||||
type = zend_get_class_fetch_type(Z_STRVAL(constant_name->u.constant), Z_STRLEN(constant_name->u.constant));
|
||||
check_import = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
|
||||
compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
|
||||
/* this is a namespace constant, or an unprefixed constant */
|
||||
|
||||
if (Z_STRVAL(constant_name->u.constant)[0] == '\\') {
|
||||
check_namespace = 0;
|
||||
if (memchr(Z_STRVAL(constant_name->u.constant)+1, '\\', Z_STRLEN(constant_name->u.constant)-1)) {
|
||||
/* tell engine this is an explicit namespaced constant, which
|
||||
results in fatal error if constant not found, see
|
||||
zend_execute_API.c::zval_update_constant_ex() */
|
||||
unknown_should_fatal = 1;
|
||||
}
|
||||
check_import = 0;
|
||||
} else if (check_import) {
|
||||
unknown_should_fatal = 1;
|
||||
}
|
||||
if (ZEND_FETCH_CLASS_STATIC == type) {
|
||||
zend_error(E_ERROR, "\"static\\\" is not allowed in compile-time constants");
|
||||
}
|
||||
|
||||
zend_resolve_non_class_name(constant_name, &fetch_type, 1, check_namespace TSRMLS_CC);
|
||||
if (zend_constant_ct_subst(result, &constant_name->u.constant, 0 TSRMLS_CC)) {
|
||||
break;
|
||||
}
|
||||
fetch_type &= IS_CONSTANT_RT_NS_CHECK;
|
||||
if (unknown_should_fatal) {
|
||||
fetch_type |= ZEND_FETCH_CLASS_RT_NS_CHECK;
|
||||
|
||||
zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
|
||||
|
||||
if(!compound) {
|
||||
fetch_type |= IS_CONSTANT_UNQUALIFIED;
|
||||
}
|
||||
|
||||
*result = *constant_name;
|
||||
result->u.constant.type = IS_CONSTANT | fetch_type;
|
||||
break;
|
||||
case ZEND_RT:
|
||||
/* this is a namespace constant, or an unprefixed constant */
|
||||
/* check_namespace = 2 means namespace\ prefix passed in */
|
||||
/* check_namespace = 0 means \constant\name passed in */
|
||||
/* check_namespace = 1 means constant\name passed in or name passed in */
|
||||
compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
|
||||
|
||||
if (check_namespace == 2) {
|
||||
unknown_should_fatal = 1;
|
||||
check_namespace = 0;
|
||||
}
|
||||
type = zend_get_class_fetch_type(Z_STRVAL(constant_name->u.constant), Z_STRLEN(constant_name->u.constant));
|
||||
if (ZEND_FETCH_CLASS_STATIC == type) {
|
||||
zend_error(E_ERROR, "\"static::\" is not allowed in compile-time constants");
|
||||
zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
|
||||
|
||||
if(zend_constant_ct_subst(result, &constant_name->u.constant, 1 TSRMLS_CC)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (Z_STRVAL(constant_name->u.constant)[0] == '\\') {
|
||||
check_namespace = 0;
|
||||
check_import = 0;
|
||||
if (memchr(Z_STRVAL(constant_name->u.constant)+1, '\\', Z_STRLEN(constant_name->u.constant)-1)) {
|
||||
/* tell engine this is an explicit namespaced constant, which
|
||||
results in fatal error if constant not found */
|
||||
unknown_should_fatal = 1;
|
||||
}
|
||||
|
||||
/* we can only check for compile-time if the constant is explicitly
|
||||
\top\level */
|
||||
check_compile_time:
|
||||
if (zend_constant_ct_subst(result, &constant_name->u.constant, 1 TSRMLS_CC)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
check_import = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
|
||||
if (check_import) {
|
||||
unknown_should_fatal = 1;
|
||||
}
|
||||
|
||||
if (!check_namespace || !CG(current_namespace)) {
|
||||
goto check_compile_time;
|
||||
}
|
||||
}
|
||||
/* we reach here if the constant name is ambiguous (not \this) */
|
||||
/* we will store nsname and <whatever>, where
|
||||
<whatever> is the actual constant name passed in (foo or foo/foo)
|
||||
and ZEND_FETCH_CONSTANT will first look for nsname/<whatever> and then
|
||||
<whatever> after current_import is applied to <whatever> */
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
if (unknown_should_fatal) {
|
||||
fetch_type = ZEND_FETCH_CLASS_RT_NS_CHECK;
|
||||
}
|
||||
opline->opcode = ZEND_FETCH_CONSTANT;
|
||||
opline->result.op_type = IS_TMP_VAR;
|
||||
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||
*result = opline->result;
|
||||
|
||||
SET_UNUSED(opline->op1);
|
||||
zend_resolve_non_class_name(constant_name, &fetch_type, 1, check_namespace TSRMLS_CC);
|
||||
opline->extended_value = fetch_type;
|
||||
if(compound) {
|
||||
/* the name is unambiguous */
|
||||
opline->extended_value = 0;
|
||||
} else {
|
||||
opline->extended_value = IS_CONSTANT_UNQUALIFIED;
|
||||
}
|
||||
opline->op2 = *constant_name;
|
||||
break;
|
||||
}
|
||||
@ -5308,7 +5206,7 @@ void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
|
||||
if (CG(current_namespace)) {
|
||||
/* Prefix constant name with name of current namespace */
|
||||
/* Prefix constant name with name of current namespace, lowercased */
|
||||
znode tmp;
|
||||
|
||||
tmp.op_type = IS_CONST;
|
||||
|
@ -359,7 +359,7 @@ 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, ulong *fetch_type, int type, int check_namespace TSRMLS_DC);
|
||||
void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace TSRMLS_DC);
|
||||
void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_name TSRMLS_DC);
|
||||
ZEND_API char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len);
|
||||
|
||||
@ -636,8 +636,6 @@ int zendlex(znode *zendlval TSRMLS_DC);
|
||||
#define ZEND_FETCH_CLASS_INTERFACE 6
|
||||
#define ZEND_FETCH_CLASS_STATIC 7
|
||||
#define ZEND_FETCH_CLASS_MASK 0x0f
|
||||
#define ZEND_FETCH_CLASS_RT_NS_CHECK 0x20
|
||||
#define ZEND_FETCH_CLASS_RT_NS_NAME 0x40
|
||||
#define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80
|
||||
#define ZEND_FETCH_CLASS_SILENT 0x0100
|
||||
|
||||
|
@ -281,11 +281,10 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
|
||||
char *class_name;
|
||||
zval **ret_constant;
|
||||
|
||||
/* Skip leading :: */
|
||||
/* Skip leading \\ */
|
||||
if (name[0] == '\\') {
|
||||
name += 1;
|
||||
name_len -= 1;
|
||||
flags &= ZEND_FETCH_CLASS_SILENT;
|
||||
}
|
||||
|
||||
|
||||
@ -335,10 +334,7 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
|
||||
efree(lcname);
|
||||
} else {
|
||||
efree(lcname);
|
||||
if ((flags & IS_CONSTANT_RT_NS_CHECK) == 0) {
|
||||
/* Check for class */
|
||||
ce = zend_fetch_class(class_name, class_name_len, flags TSRMLS_CC);
|
||||
}
|
||||
ce = zend_fetch_class(class_name, class_name_len, flags TSRMLS_CC);
|
||||
}
|
||||
if (retval && ce) {
|
||||
if (zend_hash_find(&ce->constants_table, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
|
||||
@ -350,34 +346,28 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
|
||||
} else if (!ce) {
|
||||
retval = 0;
|
||||
}
|
||||
efree(class_name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((colon = zend_memrchr(name, '\\', name_len)) &&
|
||||
colon > name) {
|
||||
/* non-class constant */
|
||||
if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) {
|
||||
/* compound constant name */
|
||||
int class_name_len = colon - name;
|
||||
int const_name_len = name_len - class_name_len - 1;
|
||||
int prefix_len = colon - name;
|
||||
int const_name_len = name_len - prefix_len - 1;
|
||||
char *constant_name = colon + 1;
|
||||
char *lcname;
|
||||
char *nsname;
|
||||
unsigned int nsname_len;
|
||||
|
||||
class_name = estrndup(name, class_name_len);
|
||||
lcname = zend_str_tolower_dup(class_name, class_name_len);
|
||||
lcname = zend_str_tolower_dup(name, prefix_len);
|
||||
/* Check for namespace constant */
|
||||
|
||||
/* Concatenate lowercase namespace name and constant name */
|
||||
lcname = erealloc(lcname, class_name_len + 1 + const_name_len + 1);
|
||||
lcname[class_name_len] = '\\';
|
||||
memcpy(lcname + class_name_len + 1, constant_name, const_name_len + 1);
|
||||
lcname = erealloc(lcname, prefix_len + 1 + const_name_len + 1);
|
||||
lcname[prefix_len] = '\\';
|
||||
memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1);
|
||||
|
||||
nsname = lcname;
|
||||
nsname_len = class_name_len + 1 + const_name_len;
|
||||
|
||||
if (zend_hash_find(EG(zend_constants), nsname, nsname_len+1, (void **) &c) == SUCCESS) {
|
||||
if (zend_hash_find(EG(zend_constants), lcname, prefix_len + 1 + const_name_len + 1, (void **) &c) == SUCCESS) {
|
||||
efree(lcname);
|
||||
efree(class_name);
|
||||
*result = c->value;
|
||||
zval_update_constant_ex(&result, (void*)1, NULL TSRMLS_CC);
|
||||
zval_copy_ctor(result);
|
||||
@ -387,17 +377,14 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
|
||||
}
|
||||
|
||||
efree(lcname);
|
||||
|
||||
if ((flags & IS_CONSTANT_RT_NS_CHECK) != 0) {
|
||||
/* name requires runtime resolution, need to check non-namespaced name */
|
||||
if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) {
|
||||
name = constant_name;
|
||||
name_len = const_name_len;
|
||||
efree(class_name);
|
||||
return zend_get_constant(name, name_len, result TSRMLS_CC);
|
||||
}
|
||||
retval = 0;
|
||||
finish:
|
||||
efree(class_name);
|
||||
|
||||
if (retval) {
|
||||
zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
|
||||
*result = **ret_constant;
|
||||
|
@ -519,7 +519,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
|
||||
} else {
|
||||
char *save = actual;
|
||||
int actual_len = Z_STRLEN_P(p);
|
||||
if (Z_TYPE_P(p) & IS_CONSTANT_RT_NS_CHECK) {
|
||||
if (Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) {
|
||||
actual = (char *)zend_memrchr(actual, '\\', actual_len) + 1;
|
||||
actual_len -= (actual - Z_STRVAL_P(p));
|
||||
if (inline_change) {
|
||||
@ -537,7 +537,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
|
||||
}
|
||||
--actual_len;
|
||||
}
|
||||
if (Z_TYPE_P(p) & ZEND_FETCH_CLASS_RT_NS_CHECK) {
|
||||
if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
|
||||
int fix_save = 0;
|
||||
if (save[0] == '\\') {
|
||||
save++;
|
||||
@ -612,7 +612,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
|
||||
str_index_len -= ((colon - str_index) + 1);
|
||||
str_index = colon;
|
||||
} else {
|
||||
if (str_index[str_index_len - 2] & IS_CONSTANT_RT_NS_CHECK) {
|
||||
if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
|
||||
actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3) + 1;
|
||||
str_index_len -= (actual - str_index);
|
||||
str_index = actual;
|
||||
@ -624,7 +624,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
|
||||
if (save[0] == '\\') {
|
||||
++save;
|
||||
}
|
||||
if (str_index[str_index_len - 2] & ZEND_FETCH_CLASS_RT_NS_CHECK) {
|
||||
if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
|
||||
zend_error(E_ERROR, "Undefined constant '%s'", save);
|
||||
}
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
|
||||
@ -1472,7 +1472,6 @@ zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len,
|
||||
{
|
||||
zend_class_entry **pce;
|
||||
int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0;
|
||||
int rt_ns_check = (fetch_type & ZEND_FETCH_CLASS_RT_NS_CHECK) ? 1 : 0;
|
||||
int silent = (fetch_type & ZEND_FETCH_CLASS_SILENT) != 0;
|
||||
|
||||
fetch_type &= ZEND_FETCH_CLASS_MASK;
|
||||
@ -1506,36 +1505,14 @@ check_fetch_type:
|
||||
break;
|
||||
}
|
||||
|
||||
if (zend_lookup_class_ex(class_name, class_name_len, (!rt_ns_check & use_autoload), &pce TSRMLS_CC) == FAILURE) {
|
||||
if (rt_ns_check) {
|
||||
/* Check if we have internal class with the same name */
|
||||
char *php_name;
|
||||
uint php_name_len;
|
||||
|
||||
php_name = zend_memrchr(class_name, '\\', class_name_len);
|
||||
if (php_name) {
|
||||
php_name++;
|
||||
php_name_len = class_name_len - (php_name - class_name);
|
||||
php_name = zend_str_tolower_dup(php_name, php_name_len);
|
||||
if (zend_hash_find(EG(class_table), php_name, php_name_len + 1, (void **) &pce) == SUCCESS &&
|
||||
(*pce)->type == ZEND_INTERNAL_CLASS
|
||||
) {
|
||||
efree(php_name);
|
||||
return *pce;
|
||||
}
|
||||
efree(php_name);
|
||||
}
|
||||
}
|
||||
if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC) == FAILURE) {
|
||||
if (use_autoload) {
|
||||
if (rt_ns_check && zend_lookup_class_ex(class_name, class_name_len, 1, &pce TSRMLS_CC) == SUCCESS) {
|
||||
return *pce;
|
||||
}
|
||||
if (!silent && !EG(exception)) {
|
||||
if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
|
||||
zend_error(E_ERROR, "Interface '%s' not found", class_name);
|
||||
} else {
|
||||
zend_error(E_ERROR, "Class '%s' not found", class_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
@ -769,7 +769,7 @@ common_scalar:
|
||||
static_scalar: /* compile-time evaluated scalars */
|
||||
common_scalar { $$ = $1; }
|
||||
| namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); }
|
||||
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 2 TSRMLS_CC); }
|
||||
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); }
|
||||
| T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); }
|
||||
| '+' static_scalar { ZVAL_LONG(&$1.u.constant, 0); add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
|
||||
| '-' static_scalar { ZVAL_LONG(&$1.u.constant, 0); sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
|
||||
@ -778,14 +778,14 @@ static_scalar: /* compile-time evaluated scalars */
|
||||
;
|
||||
|
||||
static_class_constant:
|
||||
class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 2 TSRMLS_CC); }
|
||||
class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
scalar:
|
||||
T_STRING_VARNAME { $$ = $1; }
|
||||
| class_constant { $$ = $1; }
|
||||
| namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC); }
|
||||
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_RT, 2 TSRMLS_CC); }
|
||||
| T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_RT, 0 TSRMLS_CC); }
|
||||
| T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); }
|
||||
| common_scalar { $$ = $1; }
|
||||
| '"' encaps_list '"' { $$ = $2; }
|
||||
@ -993,7 +993,7 @@ isset_variables:
|
||||
;
|
||||
|
||||
class_constant:
|
||||
class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 2 TSRMLS_CC); }
|
||||
class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); }
|
||||
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
|
@ -2108,8 +2108,8 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
|
||||
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
|
||||
|
||||
if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc))==FAILURE) {
|
||||
if (zend_hash_quick_find(EG(function_table), Z_STRVAL(op_data->op1.u.constant), Z_STRLEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==FAILURE ||
|
||||
(Z_BVAL(op_data->op2.u.constant) && EX(fbc)->type != ZEND_INTERNAL_FUNCTION)) {
|
||||
char *short_name = Z_STRVAL(opline->op1.u.constant)+Z_LVAL(op_data->op1.u.constant);
|
||||
if (zend_hash_quick_find(EG(function_table), short_name, Z_STRLEN(opline->op1.u.constant)-Z_LVAL(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==FAILURE) {
|
||||
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL(opline->op2.u.constant));
|
||||
}
|
||||
}
|
||||
@ -2974,39 +2974,21 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
|
||||
if (OP1_TYPE == IS_UNUSED) {
|
||||
/* namespaced constant */
|
||||
if (!zend_get_constant_ex(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL, opline->extended_value TSRMLS_CC)) {
|
||||
char *actual = Z_STRVAL(opline->op2.u.constant);
|
||||
|
||||
if (opline->extended_value & IS_CONSTANT_RT_NS_CHECK) {
|
||||
actual = (char *)zend_memrchr(actual, '\\', Z_STRLEN(opline->op2.u.constant)) + 1;
|
||||
Z_STRLEN(opline->op2.u.constant) -= (actual - Z_STRVAL(opline->op2.u.constant));
|
||||
actual = estrndup(actual, Z_STRLEN(opline->op2.u.constant));
|
||||
efree(Z_STRVAL(opline->op2.u.constant));
|
||||
Z_STRVAL(opline->op2.u.constant) = actual;
|
||||
}
|
||||
if (Z_STRVAL(opline->op2.u.constant)[0] == '\\') {
|
||||
if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
|
||||
zend_error_noreturn(E_ERROR, "Undefined constant '%s'",
|
||||
Z_STRVAL(opline->op2.u.constant)+1,
|
||||
Z_STRVAL(opline->op2.u.constant)+1);
|
||||
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
|
||||
char *actual = (char *)zend_memrchr(Z_STRVAL(opline->op2.u.constant), '\\', Z_STRLEN(opline->op2.u.constant));
|
||||
if(!actual) {
|
||||
actual = Z_STRVAL(opline->op2.u.constant);
|
||||
} else {
|
||||
actual++;
|
||||
}
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
|
||||
Z_STRVAL(opline->op2.u.constant)+1,
|
||||
Z_STRVAL(opline->op2.u.constant)+1);
|
||||
EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
|
||||
++Z_STRVAL(EX_T(opline->result.u.var).tmp_var);
|
||||
--Z_STRLEN(EX_T(opline->result.u.var).tmp_var);
|
||||
/* non-qualified constant - allow text substitution */
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
|
||||
ZVAL_STRING(&EX_T(opline->result.u.var).tmp_var, actual, Z_STRLEN(opline->op2.u.constant)-(actual - Z_STRVAL(opline->op2.u.constant)));
|
||||
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
|
||||
} else {
|
||||
if (opline->extended_value & ZEND_FETCH_CLASS_RT_NS_CHECK) {
|
||||
zend_error_noreturn(E_ERROR, "Undefined constant '%s'",
|
||||
Z_STRVAL(opline->op2.u.constant),
|
||||
Z_STRVAL(opline->op2.u.constant));
|
||||
}
|
||||
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
|
||||
Z_STRVAL(opline->op2.u.constant),
|
||||
Z_STRVAL(opline->op2.u.constant));
|
||||
EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
|
||||
zend_error_noreturn(E_ERROR, "Undefined constant '%s'",
|
||||
Z_STRVAL(opline->op2.u.constant), Z_STRVAL(opline->op2.u.constant));
|
||||
}
|
||||
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
} else {
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user