mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
[RFC] Allow #[\Deprecated] on traits (#19045)
https://wiki.php.net/rfc/deprecated_traits
This commit is contained in:
@@ -3,9 +3,10 @@ Constants listed in valid targets when used wrong (internal attribute)
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[Deprecated]
|
||||
class Example {}
|
||||
function demo(
|
||||
#[Deprecated] $v
|
||||
) {}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Attribute "Deprecated" cannot target class (allowed targets: function, method, class constant, constant) in %s on line %d
|
||||
Fatal error: Attribute "Deprecated" cannot target parameter (allowed targets: class, function, method, class constant, constant) in %s on line %d
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
--TEST--
|
||||
#[\DelayedTargetValidation] with #[\Deprecated]: validator errors delayed
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[DelayedTargetValidation]
|
||||
#[Deprecated]
|
||||
interface DemoInterface {}
|
||||
|
||||
#[DelayedTargetValidation]
|
||||
#[Deprecated]
|
||||
class DemoClass {}
|
||||
|
||||
#[DelayedTargetValidation]
|
||||
#[Deprecated]
|
||||
enum DemoEnum {}
|
||||
|
||||
$cases = [
|
||||
new ReflectionClass('DemoInterface'),
|
||||
new ReflectionClass('DemoClass'),
|
||||
new ReflectionClass('DemoEnum'),
|
||||
];
|
||||
foreach ($cases as $r) {
|
||||
echo str_repeat("*", 20) . "\n";
|
||||
echo $r . "\n";
|
||||
$attributes = $r->getAttributes();
|
||||
var_dump($attributes);
|
||||
try {
|
||||
$attributes[1]->newInstance();
|
||||
} catch (Error $e) {
|
||||
echo get_class($e) . ": " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
********************
|
||||
Interface [ <user> interface DemoInterface ] {
|
||||
@@ %s %d-%d
|
||||
|
||||
- Constants [0] {
|
||||
}
|
||||
|
||||
- Static properties [0] {
|
||||
}
|
||||
|
||||
- Static methods [0] {
|
||||
}
|
||||
|
||||
- Properties [0] {
|
||||
}
|
||||
|
||||
- Methods [0] {
|
||||
}
|
||||
}
|
||||
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(ReflectionAttribute)#%d (1) {
|
||||
["name"]=>
|
||||
string(23) "DelayedTargetValidation"
|
||||
}
|
||||
[1]=>
|
||||
object(ReflectionAttribute)#%d (1) {
|
||||
["name"]=>
|
||||
string(10) "Deprecated"
|
||||
}
|
||||
}
|
||||
Error: Cannot apply #[\Deprecated] to interface DemoInterface
|
||||
********************
|
||||
Class [ <user> class DemoClass ] {
|
||||
@@ %s %d-%d
|
||||
|
||||
- Constants [0] {
|
||||
}
|
||||
|
||||
- Static properties [0] {
|
||||
}
|
||||
|
||||
- Static methods [0] {
|
||||
}
|
||||
|
||||
- Properties [0] {
|
||||
}
|
||||
|
||||
- Methods [0] {
|
||||
}
|
||||
}
|
||||
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(ReflectionAttribute)#%d (1) {
|
||||
["name"]=>
|
||||
string(23) "DelayedTargetValidation"
|
||||
}
|
||||
[1]=>
|
||||
object(ReflectionAttribute)#%d (1) {
|
||||
["name"]=>
|
||||
string(10) "Deprecated"
|
||||
}
|
||||
}
|
||||
Error: Cannot apply #[\Deprecated] to class DemoClass
|
||||
********************
|
||||
Enum [ <user> enum DemoEnum implements UnitEnum ] {
|
||||
@@ %s %d-%d
|
||||
|
||||
- Constants [0] {
|
||||
}
|
||||
|
||||
- Static properties [0] {
|
||||
}
|
||||
|
||||
- Static methods [1] {
|
||||
Method [ <internal, prototype UnitEnum> static public method cases ] {
|
||||
|
||||
- Parameters [0] {
|
||||
}
|
||||
- Return [ array ]
|
||||
}
|
||||
}
|
||||
|
||||
- Properties [1] {
|
||||
Property [ public protected(set) readonly string $name ]
|
||||
}
|
||||
|
||||
- Methods [0] {
|
||||
}
|
||||
}
|
||||
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(ReflectionAttribute)#%d (1) {
|
||||
["name"]=>
|
||||
string(23) "DelayedTargetValidation"
|
||||
}
|
||||
[1]=>
|
||||
object(ReflectionAttribute)#%d (1) {
|
||||
["name"]=>
|
||||
string(10) "Deprecated"
|
||||
}
|
||||
}
|
||||
Error: Cannot apply #[\Deprecated] to enum DemoEnum
|
||||
@@ -40,6 +40,14 @@ class DemoClass {
|
||||
}
|
||||
}
|
||||
|
||||
#[DelayedTargetValidation]
|
||||
#[Deprecated] // Does something here
|
||||
trait DeprecatedTrait {}
|
||||
|
||||
class WithDeprecatedTrait {
|
||||
use DeprecatedTrait;
|
||||
}
|
||||
|
||||
#[DelayedTargetValidation]
|
||||
#[Deprecated] // Does something here
|
||||
function demoFn() {
|
||||
@@ -61,6 +69,7 @@ demoFn();
|
||||
var_dump(GLOBAL_CONST);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Deprecated: Trait DeprecatedTrait used by WithDeprecatedTrait is deprecated in %s on line %d
|
||||
Got: example
|
||||
|
||||
Deprecated: Method DemoClass::printVal() is deprecated in %s on line %d
|
||||
|
||||
11
Zend/tests/attributes/deprecated/error_on_class.phpt
Normal file
11
Zend/tests/attributes/deprecated/error_on_class.phpt
Normal file
@@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
#[\Deprecated]: Using on a class
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[\Deprecated]
|
||||
class Demo {}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot apply #[\Deprecated] to class Demo in %s on line %d
|
||||
11
Zend/tests/attributes/deprecated/error_on_enum.phpt
Normal file
11
Zend/tests/attributes/deprecated/error_on_enum.phpt
Normal file
@@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
#[\Deprecated]: Using on an enum
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[\Deprecated]
|
||||
enum Demo {}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot apply #[\Deprecated] to enum Demo in %s on line %d
|
||||
11
Zend/tests/attributes/deprecated/error_on_interface.phpt
Normal file
11
Zend/tests/attributes/deprecated/error_on_interface.phpt
Normal file
@@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
#[\Deprecated]: Using on an interface
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[\Deprecated]
|
||||
interface Demo {}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot apply #[\Deprecated] to interface Demo in %s on line %d
|
||||
33
Zend/tests/attributes/deprecated/traits/basic.phpt
Normal file
33
Zend/tests/attributes/deprecated/traits/basic.phpt
Normal file
@@ -0,0 +1,33 @@
|
||||
--TEST--
|
||||
#[\Deprecated]: Basic trait deprecation
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[\Deprecated("please do not use")]
|
||||
trait DemoTrait1 {}
|
||||
|
||||
#[\Deprecated("will be removed in 3.0", since: "2.7")]
|
||||
trait DemoTrait2 {}
|
||||
|
||||
#[\Deprecated(message: "going away")]
|
||||
trait DemoTrait3 {}
|
||||
|
||||
#[\Deprecated(since: "3.5")]
|
||||
trait DemoTrait4 {}
|
||||
|
||||
class DemoClass {
|
||||
use DemoTrait1;
|
||||
use DemoTrait2;
|
||||
use DemoTrait3;
|
||||
use DemoTrait4;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Deprecated: Trait DemoTrait1 used by DemoClass is deprecated, please do not use in %s on line %d
|
||||
|
||||
Deprecated: Trait DemoTrait2 used by DemoClass is deprecated since 2.7, will be removed in 3.0 in %s on line %d
|
||||
|
||||
Deprecated: Trait DemoTrait3 used by DemoClass is deprecated, going away in %s on line %d
|
||||
|
||||
Deprecated: Trait DemoTrait4 used by DemoClass is deprecated since 3.5 in %s on line %d
|
||||
18
Zend/tests/attributes/deprecated/traits/inheritance.phpt
Normal file
18
Zend/tests/attributes/deprecated/traits/inheritance.phpt
Normal file
@@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
#[\Deprecated]: Deprecated traits only apply to direct use, not inheritance
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[\Deprecated]
|
||||
trait DemoTrait {}
|
||||
|
||||
class DemoClass {
|
||||
use DemoTrait;
|
||||
}
|
||||
|
||||
class ChildClass extends DemoClass {
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Deprecated: Trait DemoTrait used by DemoClass is deprecated in %s on line %d
|
||||
@@ -0,0 +1,43 @@
|
||||
--TEST--
|
||||
#[\Deprecated]: `insteadof` rendering a trait unused still triggers deprecation messages
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[Deprecated]
|
||||
trait DemoTraitA {
|
||||
public function lowerCase(): string {
|
||||
return 'a';
|
||||
}
|
||||
public function upperCase(): string {
|
||||
return 'A';
|
||||
}
|
||||
}
|
||||
|
||||
#[Deprecated]
|
||||
trait DemoTraitB {
|
||||
public function lowerCase(): string {
|
||||
return 'b';
|
||||
}
|
||||
public function upperCase(): string {
|
||||
return 'B';
|
||||
}
|
||||
}
|
||||
|
||||
class DemoClass {
|
||||
use DemoTraita, DemoTraitB {
|
||||
DemoTraitA::lowerCase insteadof DemoTraitB;
|
||||
DemoTraitA::upperCase insteadof DemoTraitB;
|
||||
}
|
||||
}
|
||||
|
||||
$d = new DemoClass();
|
||||
var_dump($d->lowerCase());
|
||||
var_dump($d->upperCase());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Deprecated: Trait DemoTraitA used by DemoClass is deprecated in %s on line %d
|
||||
|
||||
Deprecated: Trait DemoTraitB used by DemoClass is deprecated in %s on line %d
|
||||
string(1) "a"
|
||||
string(1) "A"
|
||||
22
Zend/tests/attributes/deprecated/traits/multiple_traits.phpt
Normal file
22
Zend/tests/attributes/deprecated/traits/multiple_traits.phpt
Normal file
@@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
#[\Deprecated]: Using multiple traits
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[\Deprecated]
|
||||
trait DemoTraitA {}
|
||||
|
||||
#[\Deprecated]
|
||||
trait DemoTraitB {}
|
||||
|
||||
trait DemoTraitC {}
|
||||
|
||||
class DemoClass {
|
||||
use DemoTraitA, DemoTraitB, DemoTraitC;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Deprecated: Trait DemoTraitA used by DemoClass is deprecated in %s on line %d
|
||||
|
||||
Deprecated: Trait DemoTraitB used by DemoClass is deprecated in %s on line %d
|
||||
@@ -0,0 +1,25 @@
|
||||
--TEST--
|
||||
#[\Deprecated]: Deprecation converted to ErrorException does not break
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function my_error_handler(int $errno, string $errstr, ?string $errfile = null, ?int $errline = null) {
|
||||
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||
}
|
||||
|
||||
set_error_handler('my_error_handler');
|
||||
|
||||
#[\Deprecated]
|
||||
trait DemoTrait {}
|
||||
|
||||
class DemoClass {
|
||||
use DemoTrait;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught ErrorException: Trait DemoTrait used by DemoClass is deprecated in %s:%d
|
||||
Stack trace:
|
||||
#0 %s: my_error_handler(16384, 'Trait DemoTrait...', '%s', %d)
|
||||
#1 {main}
|
||||
thrown in %s on line %d
|
||||
@@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
#[\Deprecated]: Trait using a deprecated trait
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[\Deprecated]
|
||||
trait DemoTraitA {}
|
||||
|
||||
trait DemoTraitB {
|
||||
use DemoTraitA;
|
||||
}
|
||||
|
||||
class DemoClass {
|
||||
use DemoTraitB;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Deprecated: Trait DemoTraitA used by DemoTraitB is deprecated in %s on line %d
|
||||
43
Zend/tests/attributes/deprecated/traits/with_conflicts.phpt
Normal file
43
Zend/tests/attributes/deprecated/traits/with_conflicts.phpt
Normal file
@@ -0,0 +1,43 @@
|
||||
--TEST--
|
||||
#[\Deprecated]: Using multiple traits with conflict resolution
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[Deprecated]
|
||||
trait DemoTraitA {
|
||||
public function lowerCase(): string {
|
||||
return 'a';
|
||||
}
|
||||
public function upperCase(): string {
|
||||
return 'A';
|
||||
}
|
||||
}
|
||||
|
||||
#[Deprecated]
|
||||
trait DemoTraitB {
|
||||
public function lowerCase(): string {
|
||||
return 'b';
|
||||
}
|
||||
public function upperCase(): string {
|
||||
return 'B';
|
||||
}
|
||||
}
|
||||
|
||||
class DemoClass {
|
||||
use DemoTraita, DemoTraitB {
|
||||
DemoTraitA::lowerCase insteadof DemoTraitB;
|
||||
DemoTraitB::upperCase insteadof DemoTraitA;
|
||||
}
|
||||
}
|
||||
|
||||
$d = new DemoClass();
|
||||
var_dump($d->lowerCase());
|
||||
var_dump($d->upperCase());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Deprecated: Trait DemoTraitA used by DemoClass is deprecated in %s on line %d
|
||||
|
||||
Deprecated: Trait DemoTraitB used by DemoClass is deprecated in %s on line %d
|
||||
string(1) "a"
|
||||
string(1) "B"
|
||||
@@ -110,6 +110,25 @@ static zend_string *validate_attribute(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static zend_string *validate_deprecated(
|
||||
zend_attribute *attr,
|
||||
uint32_t target,
|
||||
zend_class_entry *scope
|
||||
) {
|
||||
if (target != ZEND_ATTRIBUTE_TARGET_CLASS) {
|
||||
/* Being used for a method or something, validation does not apply */
|
||||
return NULL;
|
||||
}
|
||||
if (!(scope->ce_flags & ZEND_ACC_TRAIT)) {
|
||||
const char *type = zend_get_object_type_case(scope, false);
|
||||
return zend_strpprintf(0, "Cannot apply #[\\Deprecated] to %s %s", type, ZSTR_VAL(scope->name));
|
||||
}
|
||||
|
||||
scope->ce_flags |= ZEND_ACC_DEPRECATED;
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
ZEND_METHOD(Attribute, __construct)
|
||||
{
|
||||
zend_long flags = ZEND_ATTRIBUTE_TARGET_ALL;
|
||||
@@ -579,6 +598,7 @@ void zend_register_attribute_ce(void)
|
||||
|
||||
zend_ce_deprecated = register_class_Deprecated();
|
||||
attr = zend_mark_internal_attribute(zend_ce_deprecated);
|
||||
attr->validator = validate_deprecated;
|
||||
|
||||
zend_ce_nodiscard = register_class_NoDiscard();
|
||||
attr = zend_mark_internal_attribute(zend_ce_nodiscard);
|
||||
|
||||
@@ -77,7 +77,7 @@ final class Override
|
||||
/**
|
||||
* @strict-properties
|
||||
*/
|
||||
#[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_FUNCTION|Attribute::TARGET_CLASS_CONSTANT|Attribute::TARGET_CONSTANT)]
|
||||
#[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_FUNCTION|Attribute::TARGET_CLASS_CONSTANT|Attribute::TARGET_CONSTANT|Attribute::TARGET_CLASS)]
|
||||
final class Deprecated
|
||||
{
|
||||
public readonly ?string $message;
|
||||
|
||||
4
Zend/zend_attributes_arginfo.h
generated
4
Zend/zend_attributes_arginfo.h
generated
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: fa08288df8338c1a16fbf83c179c4084a56007e1 */
|
||||
* Stub hash: b868cb33f41d9442f42d0cec84e33fcc09f5d88c */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Attribute___construct, 0, 0, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "Attribute::TARGET_ALL")
|
||||
@@ -253,7 +253,7 @@ static zend_class_entry *register_class_Deprecated(void)
|
||||
zend_string *attribute_name_Attribute_class_Deprecated_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1);
|
||||
zend_attribute *attribute_Attribute_class_Deprecated_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_Deprecated_0, 1);
|
||||
zend_string_release(attribute_name_Attribute_class_Deprecated_0);
|
||||
ZVAL_LONG(&attribute_Attribute_class_Deprecated_0->args[0].value, ZEND_ATTRIBUTE_TARGET_METHOD | ZEND_ATTRIBUTE_TARGET_FUNCTION | ZEND_ATTRIBUTE_TARGET_CLASS_CONST | ZEND_ATTRIBUTE_TARGET_CONST);
|
||||
ZVAL_LONG(&attribute_Attribute_class_Deprecated_0->args[0].value, ZEND_ATTRIBUTE_TARGET_METHOD | ZEND_ATTRIBUTE_TARGET_FUNCTION | ZEND_ATTRIBUTE_TARGET_CLASS_CONST | ZEND_ATTRIBUTE_TARGET_CONST | ZEND_ATTRIBUTE_TARGET_CLASS);
|
||||
|
||||
return class_entry;
|
||||
}
|
||||
|
||||
@@ -255,6 +255,9 @@ typedef struct _zend_oparray_context {
|
||||
/* or IS_CONSTANT_VISITED_MARK | | | */
|
||||
#define ZEND_CLASS_CONST_IS_CASE (1 << 6) /* | | | X */
|
||||
/* | | | */
|
||||
/* deprecation flag | | | */
|
||||
#define ZEND_ACC_DEPRECATED (1 << 11) /* X | X | | X */
|
||||
/* | | | */
|
||||
/* has #[\Override] attribute | | | */
|
||||
#define ZEND_ACC_OVERRIDE (1 << 28) /* | X | X | */
|
||||
/* | | | */
|
||||
@@ -272,7 +275,7 @@ typedef struct _zend_oparray_context {
|
||||
#define ZEND_ACC_PROTECTED_SET (1 << 11) /* | | X | */
|
||||
#define ZEND_ACC_PRIVATE_SET (1 << 12) /* | | X | */
|
||||
/* | | | */
|
||||
/* Class Flags (unused: 30,31) | | | */
|
||||
/* Class Flags (unused: 31) | | | */
|
||||
/* =========== | | | */
|
||||
/* | | | */
|
||||
/* Special class types | | | */
|
||||
@@ -290,7 +293,7 @@ typedef struct _zend_oparray_context {
|
||||
/* | | | */
|
||||
/* Class has magic methods __get/__set/__unset/ | | | */
|
||||
/* __isset that use guards | | | */
|
||||
#define ZEND_ACC_USE_GUARDS (1 << 11) /* X | | | */
|
||||
#define ZEND_ACC_USE_GUARDS (1 << 30) /* X | | | */
|
||||
/* | | | */
|
||||
/* Class constants updated | | | */
|
||||
#define ZEND_ACC_CONSTANTS_UPDATED (1 << 12) /* X | | | */
|
||||
@@ -341,9 +344,6 @@ typedef struct _zend_oparray_context {
|
||||
/* Function Flags (unused: 30) | | | */
|
||||
/* ============== | | | */
|
||||
/* | | | */
|
||||
/* deprecation flag | | | */
|
||||
#define ZEND_ACC_DEPRECATED (1 << 11) /* | X | | X */
|
||||
/* | | | */
|
||||
/* Function returning by reference | | | */
|
||||
#define ZEND_ACC_RETURN_REFERENCE (1 << 12) /* | X | | */
|
||||
/* | | | */
|
||||
|
||||
@@ -2006,6 +2006,27 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_constant(const zend_consta
|
||||
zend_string_release(message_suffix);
|
||||
}
|
||||
|
||||
ZEND_API ZEND_COLD void zend_use_of_deprecated_trait(
|
||||
zend_class_entry *trait,
|
||||
const zend_string *used_by
|
||||
) {
|
||||
zend_string *message_suffix = ZSTR_EMPTY_ALLOC();
|
||||
|
||||
if (get_deprecation_suffix_from_attribute(trait->attributes, trait, &message_suffix) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
int code = trait->type == ZEND_INTERNAL_CLASS ? E_DEPRECATED : E_USER_DEPRECATED;
|
||||
|
||||
zend_error_unchecked(code, "Trait %s used by %s is deprecated%S",
|
||||
ZSTR_VAL(trait->name),
|
||||
ZSTR_VAL(used_by),
|
||||
message_suffix
|
||||
);
|
||||
|
||||
zend_string_release(message_suffix);
|
||||
}
|
||||
|
||||
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void)
|
||||
{
|
||||
zend_error(E_DEPRECATED, "Automatic conversion of false to array is deprecated");
|
||||
|
||||
@@ -66,6 +66,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_functi
|
||||
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_nodiscard_function(const zend_function *fbc);
|
||||
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_class_constant(const zend_class_constant *c, const zend_string *constant_name);
|
||||
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_constant(const zend_constant *c, const zend_string *constant_name);
|
||||
ZEND_API ZEND_COLD void zend_use_of_deprecated_trait(zend_class_entry *trait, const zend_string *used_by);
|
||||
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void);
|
||||
ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num);
|
||||
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim);
|
||||
|
||||
@@ -3524,6 +3524,13 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
|
||||
free_alloca(traits_and_interfaces, use_heap);
|
||||
return NULL;
|
||||
}
|
||||
if (UNEXPECTED(trait->ce_flags & ZEND_ACC_DEPRECATED)) {
|
||||
zend_use_of_deprecated_trait(trait, ce->name);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
free_alloca(traits_and_interfaces, use_heap);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
for (j = 0; j < i; j++) {
|
||||
if (traits_and_interfaces[j] == trait) {
|
||||
/* skip duplications */
|
||||
|
||||
Reference in New Issue
Block a user