mirror of
https://github.com/php/php-src.git
synced 2024-11-27 20:03:40 +08:00
Allow throwing exception while loading parent class
This is a fix for symfony/symfony#32995. The behavior is: * Throwing exception when loading parent/interface is allowed (and we will also throw one if the class is simply not found). * If this happens, the bucket key for the class is reset, so it's possibly to try registering the same class again. * However, if the class has already been used due to a variance obligation, the exception is upgraded to a fatal error, as we cannot safely unregister the class stub anymore.
This commit is contained in:
parent
679cbee870
commit
4b9ebd837b
@ -6,4 +6,7 @@ class test implements a {
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Interface 'a' not found in %sbug30519.php on line 2
|
||||
Fatal error: Uncaught Error: Interface 'a' not found in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
@ -10,4 +10,7 @@ var_dump($a instanceOf A);
|
||||
echo "ok\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Interface 'RecurisiveFooFar' not found in %s on line %d
|
||||
Fatal error: Uncaught Error: Interface 'RecurisiveFooFar' not found in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
@ -24,11 +24,14 @@ var_dump(new Foo());
|
||||
--EXPECTF--
|
||||
string(3) "Foo"
|
||||
string(3) "Bar"
|
||||
string(3) "Foo"
|
||||
string(3) "Bar"
|
||||
|
||||
Fatal error: During class fetch: Uncaught Exception: Bar in %s:%d
|
||||
Fatal error: Uncaught Exception: Bar in %s:%d
|
||||
Stack trace:
|
||||
#0 [internal function]: {closure}('Bar')
|
||||
#1 %s(%d): spl_autoload_call('Bar')
|
||||
#2 [internal function]: {closure}('Foo')
|
||||
#3 %s(%d): spl_autoload_call('Foo')
|
||||
#4 {main} in %s on line %d
|
||||
#4 {main}
|
||||
thrown in %s on line %d
|
||||
|
@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
Exception while loading class -- parent case
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
spl_autoload_register(function($class) {
|
||||
throw new Exception("Class $class does not exist");
|
||||
});
|
||||
|
||||
// Graceful failure allowed
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
try {
|
||||
class B extends A {
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
}
|
||||
|
||||
interface I {}
|
||||
|
||||
spl_autoload_register(function($class) {
|
||||
// Tie up B in a variance obligation.
|
||||
class X {
|
||||
public function test(): I {}
|
||||
}
|
||||
class Y extends X {
|
||||
public function test(): B {}
|
||||
}
|
||||
}, true, true);
|
||||
|
||||
// Fallback to fatal error, as we can't unlink class B anymore.
|
||||
try {
|
||||
class B extends A implements I {
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Class A does not exist
|
||||
Class A does not exist
|
||||
|
||||
Fatal error: During inheritance of B with variance dependencies: Uncaught Exception: Class A does not exist in %s:%d
|
||||
Stack trace:
|
||||
#0 [internal function]: {closure}('A')
|
||||
#1 %s(%d): spl_autoload_call('A')
|
||||
#2 {main} in %s on line %d
|
@ -0,0 +1,51 @@
|
||||
--TEST--
|
||||
Exception while loading class -- interface case
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
spl_autoload_register(function($class) {
|
||||
throw new Exception("Class $class does not exist");
|
||||
});
|
||||
|
||||
class A {}
|
||||
|
||||
// Graceful failure allowed
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
try {
|
||||
class B extends A implements I {
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
}
|
||||
|
||||
interface J {}
|
||||
|
||||
spl_autoload_register(function($class) {
|
||||
// Tie up B in a variance obligation.
|
||||
class X {
|
||||
public function test(): J {}
|
||||
}
|
||||
class Y extends X {
|
||||
public function test(): B {}
|
||||
}
|
||||
}, true, true);
|
||||
|
||||
// Fallback to fatal error, as we can't unlink class B anymore.
|
||||
try {
|
||||
class B extends A implements I, J {
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Class I does not exist
|
||||
Class I does not exist
|
||||
|
||||
Fatal error: During inheritance of B with variance dependencies: Uncaught Exception: Class I does not exist in %s:%d
|
||||
Stack trace:
|
||||
#0 [internal function]: {closure}('I')
|
||||
#1 %s(%d): spl_autoload_call('I')
|
||||
#2 {main} in %s on line %d
|
@ -7,9 +7,13 @@ spl_autoload_register(function($class) {
|
||||
class X extends B {}
|
||||
});
|
||||
|
||||
class B extends A {
|
||||
try {
|
||||
class B extends A {
|
||||
}
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Class 'B' not found in %s on line %d
|
||||
--EXPECT--
|
||||
Class 'B' not found
|
||||
|
@ -7,9 +7,13 @@ spl_autoload_register(function($class) {
|
||||
class X implements B {}
|
||||
});
|
||||
|
||||
interface B extends A {
|
||||
try {
|
||||
interface B extends A {
|
||||
}
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Interface 'B' not found in %s on line %d
|
||||
--EXPECT--
|
||||
Interface 'B' not found
|
||||
|
@ -12,9 +12,10 @@ class A implements I {
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: During class fetch: Uncaught ReflectionException: Class A does not exist in %s:%d
|
||||
Fatal error: Uncaught ReflectionException: Class A does not exist in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): ReflectionClass->__construct('A')
|
||||
#1 [internal function]: {closure}('I')
|
||||
#2 %s(%d): spl_autoload_call('I')
|
||||
#3 {main} in %s on line %d
|
||||
#3 {main}
|
||||
thrown in %s on line %d
|
||||
|
@ -1081,7 +1081,11 @@ ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
zend_do_link_class(ce, lc_parent_name);
|
||||
if (zend_do_link_class(ce, lc_parent_name) == FAILURE) {
|
||||
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(rtd_key));
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -229,7 +229,7 @@ typedef struct _zend_oparray_context {
|
||||
/* op_array or class is preloaded | | | */
|
||||
#define ZEND_ACC_PRELOADED (1 << 10) /* X | X | | */
|
||||
/* | | | */
|
||||
/* Class Flags (unused: 23...) | | | */
|
||||
/* Class Flags (unused: 24...) | | | */
|
||||
/* =========== | | | */
|
||||
/* | | | */
|
||||
/* Special class types | | | */
|
||||
@ -281,6 +281,9 @@ typedef struct _zend_oparray_context {
|
||||
/* Class is linked apart from variance obligations. | | | */
|
||||
#define ZEND_ACC_NEARLY_LINKED (1 << 22) /* X | | | */
|
||||
/* | | | */
|
||||
/* Whether this class was used in its unlinked state. | | | */
|
||||
#define ZEND_ACC_HAS_UNLINKED_USES (1 << 23) /* X | | | */
|
||||
/* | | | */
|
||||
/* Function Flags (unused: 23, 26) | | | */
|
||||
/* ============== | | | */
|
||||
/* | | | */
|
||||
|
@ -921,6 +921,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *
|
||||
if ((flags & ZEND_FETCH_CLASS_ALLOW_UNLINKED) ||
|
||||
((flags & ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED) &&
|
||||
(ce->ce_flags & ZEND_ACC_NEARLY_LINKED))) {
|
||||
ce->ce_flags |= ZEND_ACC_HAS_UNLINKED_USES;
|
||||
return ce;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "zend_interfaces.h"
|
||||
#include "zend_smart_str.h"
|
||||
#include "zend_operators.h"
|
||||
#include "zend_exceptions.h"
|
||||
|
||||
static void add_dependency_obligation(zend_class_entry *ce, zend_class_entry *dependency_ce);
|
||||
static void add_compatibility_obligation(
|
||||
@ -1437,26 +1438,17 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_do_implement_interfaces(zend_class_entry *ce) /* {{{ */
|
||||
static void zend_do_implement_interfaces(zend_class_entry *ce, zend_class_entry **interfaces) /* {{{ */
|
||||
{
|
||||
zend_class_entry **interfaces, *iface;
|
||||
uint32_t num_interfaces = 0;
|
||||
zend_class_entry *iface;
|
||||
uint32_t num_parent_interfaces = ce->parent ? ce->parent->num_interfaces : 0;
|
||||
uint32_t num_interfaces = num_parent_interfaces;
|
||||
zend_string *key;
|
||||
zend_class_constant *c;
|
||||
uint32_t i, j;
|
||||
|
||||
if (ce->parent && ce->parent->num_interfaces) {
|
||||
interfaces = emalloc(sizeof(zend_class_entry*) * (ce->parent->num_interfaces + ce->num_interfaces));
|
||||
memcpy(interfaces, ce->parent->interfaces, sizeof(zend_class_entry*) * ce->parent->num_interfaces);
|
||||
num_interfaces = ce->parent->num_interfaces;
|
||||
} else {
|
||||
interfaces = emalloc(sizeof(zend_class_entry*) * ce->num_interfaces);
|
||||
}
|
||||
|
||||
for (i = 0; i < ce->num_interfaces; i++) {
|
||||
iface = zend_fetch_class_by_name(
|
||||
ce->interface_names[i].name, ce->interface_names[i].lc_name,
|
||||
ZEND_FETCH_CLASS_INTERFACE|ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED);
|
||||
iface = interfaces[num_parent_interfaces + i];
|
||||
if (!(iface->ce_flags & ZEND_ACC_LINKED)) {
|
||||
add_dependency_obligation(ce, iface);
|
||||
}
|
||||
@ -1467,7 +1459,7 @@ static void zend_do_implement_interfaces(zend_class_entry *ce) /* {{{ */
|
||||
}
|
||||
for (j = 0; j < num_interfaces; j++) {
|
||||
if (interfaces[j] == iface) {
|
||||
if (!ce->parent || j >= ce->parent->num_interfaces) {
|
||||
if (j >= num_parent_interfaces) {
|
||||
efree(interfaces);
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
|
||||
return;
|
||||
@ -1497,7 +1489,7 @@ static void zend_do_implement_interfaces(zend_class_entry *ce) /* {{{ */
|
||||
ce->interfaces = interfaces;
|
||||
ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES;
|
||||
|
||||
i = ce->parent ? ce->parent->num_interfaces : 0;
|
||||
i = num_parent_interfaces;
|
||||
for (; i < ce->num_interfaces; i++) {
|
||||
do_interface_implementation(ce, ce->interfaces[i]);
|
||||
}
|
||||
@ -2399,11 +2391,66 @@ static void report_variance_errors(zend_class_entry *ce) {
|
||||
zend_hash_index_del(all_obligations, num_key);
|
||||
}
|
||||
|
||||
ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name) /* {{{ */
|
||||
static void check_unrecoverable_load_failure(zend_class_entry *ce) {
|
||||
/* If this class has been used while unlinked through a variance obligation, it is not legal
|
||||
* to remove the class from the class table and throw an exception, because there is already
|
||||
* a dependence on the inheritance hierarchy of this specific class. Instead we fall back to
|
||||
* a fatal error, as would happen if we did not allow exceptions in the first place. */
|
||||
if (ce->ce_flags & ZEND_ACC_HAS_UNLINKED_USES) {
|
||||
zend_string *exception_str;
|
||||
zval exception_zv;
|
||||
ZEND_ASSERT(EG(exception) && "Exception must have been thrown");
|
||||
ZVAL_OBJ(&exception_zv, EG(exception));
|
||||
Z_ADDREF(exception_zv);
|
||||
zend_clear_exception();
|
||||
exception_str = zval_get_string(&exception_zv);
|
||||
zend_error_noreturn(E_ERROR,
|
||||
"During inheritance of %s with variance dependencies: Uncaught %s", ZSTR_VAL(ce->name), ZSTR_VAL(exception_str));
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API int zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name) /* {{{ */
|
||||
{
|
||||
/* Load parent/interface dependencies first, so we can still gracefully abort linking
|
||||
* with an exception and remove the class from the class table. This is only possible
|
||||
* if no variance obligations on the current class have been added during autoloading. */
|
||||
zend_class_entry *parent = NULL;
|
||||
zend_class_entry **interfaces = NULL;
|
||||
|
||||
if (ce->parent_name) {
|
||||
zend_class_entry *parent = zend_fetch_class_by_name(
|
||||
ce->parent_name, lc_parent_name, ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED);
|
||||
parent = zend_fetch_class_by_name(
|
||||
ce->parent_name, lc_parent_name,
|
||||
ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (!parent) {
|
||||
check_unrecoverable_load_failure(ce);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ce->num_interfaces) {
|
||||
/* Also copy the parent interfaces here, so we don't need to reallocate later. */
|
||||
uint32_t i, num_parent_interfaces = parent ? parent->num_interfaces : 0;
|
||||
interfaces = emalloc(
|
||||
sizeof(zend_class_entry *) * (ce->num_interfaces + num_parent_interfaces));
|
||||
if (num_parent_interfaces) {
|
||||
memcpy(interfaces, parent->interfaces,
|
||||
sizeof(zend_class_entry *) * num_parent_interfaces);
|
||||
}
|
||||
for (i = 0; i < ce->num_interfaces; i++) {
|
||||
zend_class_entry *iface = zend_fetch_class_by_name(
|
||||
ce->interface_names[i].name, ce->interface_names[i].lc_name,
|
||||
ZEND_FETCH_CLASS_INTERFACE |
|
||||
ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (!iface) {
|
||||
check_unrecoverable_load_failure(ce);
|
||||
efree(interfaces);
|
||||
return FAILURE;
|
||||
}
|
||||
interfaces[num_parent_interfaces + i] = iface;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
if (!(parent->ce_flags & ZEND_ACC_LINKED)) {
|
||||
add_dependency_obligation(ce, parent);
|
||||
}
|
||||
@ -2413,7 +2460,7 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_na
|
||||
zend_do_bind_traits(ce);
|
||||
}
|
||||
if (ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES) {
|
||||
zend_do_implement_interfaces(ce);
|
||||
zend_do_implement_interfaces(ce, interfaces);
|
||||
}
|
||||
if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
|
||||
zend_verify_abstract_class(ce);
|
||||
@ -2423,7 +2470,7 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_na
|
||||
|
||||
if (!(ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE)) {
|
||||
ce->ce_flags |= ZEND_ACC_LINKED;
|
||||
return;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
ce->ce_flags |= ZEND_ACC_NEARLY_LINKED;
|
||||
@ -2434,6 +2481,8 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_na
|
||||
report_variance_errors(ce);
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -30,7 +30,7 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par
|
||||
#define zend_do_inheritance(ce, parent_ce) \
|
||||
zend_do_inheritance_ex(ce, parent_ce, 0)
|
||||
|
||||
ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name);
|
||||
ZEND_API int zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name);
|
||||
|
||||
void zend_verify_abstract_class(zend_class_entry *ce);
|
||||
void zend_check_deprecated_constructor(const zend_class_entry *ce);
|
||||
|
@ -7273,8 +7273,8 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST)
|
||||
if (UNEXPECTED(!zv)) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
|
||||
} else {
|
||||
zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if (zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2))) == FAILURE) {
|
||||
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
@ -7292,13 +7292,14 @@ ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT)
|
||||
|
||||
ce = CACHED_PTR(opline->extended_value);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
zv = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
|
||||
zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1));
|
||||
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
|
||||
ZEND_ASSERT(zv != NULL);
|
||||
ce = Z_CE_P(zv);
|
||||
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
|
||||
SAVE_OPLINE();
|
||||
zend_do_link_class(ce, (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if (zend_do_link_class(ce, (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL) == FAILURE) {
|
||||
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, rtd_key);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
|
@ -2444,13 +2444,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE
|
||||
|
||||
ce = CACHED_PTR(opline->extended_value);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
zv = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
|
||||
zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1));
|
||||
zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
|
||||
ZEND_ASSERT(zv != NULL);
|
||||
ce = Z_CE_P(zv);
|
||||
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
|
||||
SAVE_OPLINE();
|
||||
zend_do_link_class(ce, (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if (zend_do_link_class(ce, (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL) == FAILURE) {
|
||||
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, rtd_key);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
@ -6382,8 +6383,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CON
|
||||
if (UNEXPECTED(!zv)) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
|
||||
} else {
|
||||
zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if (zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2))) == FAILURE) {
|
||||
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
}
|
||||
|
@ -3731,7 +3731,9 @@ static void preload_link(void)
|
||||
} else {
|
||||
CG(zend_lineno) = ce->info.user.line_start;
|
||||
}
|
||||
zend_do_link_class(ce, NULL);
|
||||
if (zend_do_link_class(ce, NULL) == FAILURE) {
|
||||
ZEND_ASSERT(0 && "Class linking failed?");
|
||||
}
|
||||
CG(in_compilation) = 0;
|
||||
CG(compiled_filename) = NULL;
|
||||
|
||||
|
@ -68,4 +68,15 @@ foreach (new \RecursiveIteratorIterator (new fooIterator ($foo)) as $bar) ;
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Class 'NotExists' not found in %s(%d) : eval()'d code on line 1
|
||||
Fatal error: Uncaught Error: Class 'NotExists' not found in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): eval()
|
||||
#1 %s(%d): fooIterator->__destruct()
|
||||
#2 {main}
|
||||
|
||||
Next Error: Class 'NotExists' not found in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): eval()
|
||||
#1 %s(%d): fooIterator->__destruct()
|
||||
#2 {main}
|
||||
thrown in %s on line %d
|
||||
|
@ -14,4 +14,7 @@ class C implements UndefI
|
||||
--EXPECTF--
|
||||
In autoload: string(6) "UndefI"
|
||||
|
||||
Fatal error: Interface 'UndefI' not found in %s on line %d
|
||||
Fatal error: Uncaught Error: Interface 'UndefI' not found in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
@ -14,4 +14,7 @@ class C extends UndefBase
|
||||
--EXPECTF--
|
||||
In autoload: string(9) "UndefBase"
|
||||
|
||||
Fatal error: Class 'UndefBase' not found in %s on line %d
|
||||
Fatal error: Uncaught Error: Class 'UndefBase' not found in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
@ -13,4 +13,10 @@ try {
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Class 'B' not found in %s on line %d
|
||||
bool(false)
|
||||
bool(false)
|
||||
|
||||
Fatal error: Uncaught Error: Class 'B' not found in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
Loading…
Reference in New Issue
Block a user