diff --git a/Zend/tests/friends/001.phpt b/Zend/tests/friends/001.phpt deleted file mode 100644 index 3a1148f562bb0..0000000000000 --- a/Zend/tests/friends/001.phpt +++ /dev/null @@ -1,8 +0,0 @@ ---TEST-- -Circular Friendship ---FILE-- - ---EXPECTF-- -Fatal error: Class A may not be friends with itself in %s/001.php on line %d diff --git a/Zend/tests/friends/002.phpt b/Zend/tests/friends/002.phpt deleted file mode 100644 index 94ce708d06d7a..0000000000000 --- a/Zend/tests/friends/002.phpt +++ /dev/null @@ -1,10 +0,0 @@ ---TEST-- -Circular Friendship Parent ---FILE-- - ---EXPECTF-- -Fatal error: Class B may not be friends with parent A in %s/002.php on line %d diff --git a/Zend/tests/friends/003.phpt b/Zend/tests/friends/003.phpt deleted file mode 100644 index 01cfe68d09d7f..0000000000000 --- a/Zend/tests/friends/003.phpt +++ /dev/null @@ -1,11 +0,0 @@ ---TEST-- -No Friendship ---FILE-- - ---EXPECTF-- -Fatal error: Class C is not a friend of A in %s/003.php on line %d - diff --git a/Zend/tests/friends/004.phpt b/Zend/tests/friends/004.phpt deleted file mode 100644 index e6721e44984f0..0000000000000 --- a/Zend/tests/friends/004.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -Friendship ---FILE-- -getFriendNames()); -} -?> ---EXPECT-- -array(1) { - [0]=> - string(1) "B" -} -array(0) { -} diff --git a/Zend/tests/friends/005.phpt b/Zend/tests/friends/005.phpt deleted file mode 100644 index 4cc7acf81c5a0..0000000000000 --- a/Zend/tests/friends/005.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---TEST-- -Friendship Inheritance ---FILE-- -getFriendNames()); -} -?> ---EXPECT-- -array(2) { - [0]=> - string(1) "B" - [1]=> - string(1) "C" -} -array(1) { - [0]=> - string(1) "C" -} - diff --git a/Zend/tests/friends/006.phpt b/Zend/tests/friends/006.phpt deleted file mode 100644 index f5bff4a2fbf7d..0000000000000 --- a/Zend/tests/friends/006.phpt +++ /dev/null @@ -1,8 +0,0 @@ ---TEST-- -Circular Friendship Interface ---FILE-- - ---EXPECTF-- -Fatal error: Interface A may not be friends with itself in %s/006.php on line %d diff --git a/Zend/tests/friends/007.phpt b/Zend/tests/friends/007.phpt deleted file mode 100644 index 0e44f02370faf..0000000000000 --- a/Zend/tests/friends/007.phpt +++ /dev/null @@ -1,10 +0,0 @@ ---TEST-- -Circular Friendship Parent Interface ---FILE-- - ---EXPECTF-- -Fatal error: Interface B may not be friends with parent A in %s/007.php on line %d diff --git a/Zend/tests/friends/008.phpt b/Zend/tests/friends/008.phpt deleted file mode 100644 index 4dc79fc56cda1..0000000000000 --- a/Zend/tests/friends/008.phpt +++ /dev/null @@ -1,10 +0,0 @@ ---TEST-- -No Friendship Interface ---FILE-- - ---EXPECTF-- -Fatal error: Class C is not a friend of A in %s/008.php on line %d diff --git a/Zend/tests/friends/010.phpt b/Zend/tests/friends/010.phpt deleted file mode 100644 index 68fbf66be0597..0000000000000 --- a/Zend/tests/friends/010.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---TEST-- -Friendship Inheritance Interfaces ---FILE-- -getFriendNames()); -} -?> ---EXPECT-- -array(2) { - [0]=> - string(1) "B" - [1]=> - string(1) "C" -} -array(1) { - [0]=> - string(1) "C" -} - diff --git a/Zend/tests/sealed/001.phpt b/Zend/tests/sealed/001.phpt new file mode 100644 index 0000000000000..4bfb0c59c48c6 --- /dev/null +++ b/Zend/tests/sealed/001.phpt @@ -0,0 +1,10 @@ +--TEST-- +Circular Sealing +--FILE-- + +--EXPECTF-- +Fatal error: Sealed class A may not permit inheritance for itself in %s/001.php on line %d diff --git a/Zend/tests/sealed/002.phpt b/Zend/tests/sealed/002.phpt new file mode 100644 index 0000000000000..8636fed4dd007 --- /dev/null +++ b/Zend/tests/sealed/002.phpt @@ -0,0 +1,11 @@ +--TEST-- +Circular Sealing Parent +--FILE-- + +--EXPECTF-- +Fatal error: Sealed class B may not permit inheritance from its parent A in %s/002.php on line %d diff --git a/Zend/tests/sealed/003.phpt b/Zend/tests/sealed/003.phpt new file mode 100644 index 0000000000000..6b0630218b5ba --- /dev/null +++ b/Zend/tests/sealed/003.phpt @@ -0,0 +1,13 @@ +--TEST-- +Not permitted class +--FILE-- + +--EXPECTF-- +Fatal error: Class C is not permitted to inherit from A in %s/003.php on line %d + diff --git a/Zend/tests/sealed/004.phpt b/Zend/tests/sealed/004.phpt new file mode 100644 index 0000000000000..a56fcdca6191a --- /dev/null +++ b/Zend/tests/sealed/004.phpt @@ -0,0 +1,45 @@ +--TEST-- +Reflection +--FILE-- +isSealed()); + var_dump($reflector->getPermittedClasses()); +} +?> +--EXPECT-- +bool(true) +array(1) { + [0]=> + string(1) "B" +} +bool(false) +array(0) { +} +bool(true) +array(1) { + [0]=> + string(1) "D" +} +bool(false) +array(0) { +} +bool(true) +array(1) { + [0]=> + string(1) "F" +} +bool(false) +array(0) { +} diff --git a/Zend/tests/sealed/005.phpt b/Zend/tests/sealed/005.phpt new file mode 100644 index 0000000000000..fb2ada7f65858 --- /dev/null +++ b/Zend/tests/sealed/005.phpt @@ -0,0 +1,39 @@ +--TEST-- +Sealing Inheritance +--FILE-- +isSealed()); + var_dump($reflector->getPermittedClasses()); +} +?> +--EXPECT-- +bool(true) +array(2) { + [0]=> + string(1) "B" + [1]=> + string(1) "C" +} +bool(true) +array(1) { + [0]=> + string(1) "C" +} +bool(false) +array(0) { +} +bool(false) +array(0) { +} + diff --git a/Zend/tests/sealed/006.phpt b/Zend/tests/sealed/006.phpt new file mode 100644 index 0000000000000..7640a317178d2 --- /dev/null +++ b/Zend/tests/sealed/006.phpt @@ -0,0 +1,8 @@ +--TEST-- +Circular Sealing Interface +--FILE-- + +--EXPECTF-- +Fatal error: Sealed interface A may not permit inheritance for itself in %s/001.php on line %d diff --git a/Zend/tests/sealed/007.phpt b/Zend/tests/sealed/007.phpt new file mode 100644 index 0000000000000..e84b7d4a3ce77 --- /dev/null +++ b/Zend/tests/sealed/007.phpt @@ -0,0 +1,10 @@ +--TEST-- +Circular Friendship Parent Interface +--FILE-- + +--EXPECTF-- +Fatal error: Sealed interface B may not permit inheritance from its parent A in %s/002.php on line %d diff --git a/Zend/tests/sealed/008.phpt b/Zend/tests/sealed/008.phpt new file mode 100644 index 0000000000000..6346ddf2f98c2 --- /dev/null +++ b/Zend/tests/sealed/008.phpt @@ -0,0 +1,10 @@ +--TEST-- +Not permitted class +--FILE-- + +--EXPECTF-- +Fatal error: Class C cannot implement sealed interface A in %s/008.php on line %d diff --git a/Zend/tests/friends/009.phpt b/Zend/tests/sealed/009.phpt similarity index 55% rename from Zend/tests/friends/009.phpt rename to Zend/tests/sealed/009.phpt index a63dc1da956e4..e5c51e47af909 100644 --- a/Zend/tests/friends/009.phpt +++ b/Zend/tests/sealed/009.phpt @@ -1,21 +1,24 @@ --TEST-- -Friendship Interfaces +Sealing Interfaces --FILE-- getFriendNames()); + + var_dump($reflector->isSealed()); + var_dump($reflector->getPermittedClasses()); } ?> --EXPECT-- +bool(true) array(1) { [0]=> string(1) "B" } +bool(false) array(0) { } diff --git a/Zend/tests/sealed/010.phpt b/Zend/tests/sealed/010.phpt new file mode 100644 index 0000000000000..8dcad5cb2d5ab --- /dev/null +++ b/Zend/tests/sealed/010.phpt @@ -0,0 +1,38 @@ +--TEST-- +Sealing Inheritance Interfaces +--FILE-- +isSealed()); + var_dump($reflector->getPermittedClasses()); +} +?> +--EXPECT-- +bool(true) +array(2) { + [0]=> + string(1) "B" + [1]=> + string(1) "C" +} +bool(false) +array(0) { +} +bool(true) +array(1) { + [0]=> + string(1) "D" +} +bool(false) +array(0) { +} diff --git a/Zend/tests/sealed/011.phpt b/Zend/tests/sealed/011.phpt new file mode 100644 index 0000000000000..46ef1cf24776c --- /dev/null +++ b/Zend/tests/sealed/011.phpt @@ -0,0 +1,36 @@ +--TEST-- +Happy path +--FILE-- + +OK +--EXPECT-- +OK + diff --git a/Zend/tests/sealed/012.phpt b/Zend/tests/sealed/012.phpt new file mode 100644 index 0000000000000..234a02bfc63b5 --- /dev/null +++ b/Zend/tests/sealed/012.phpt @@ -0,0 +1,24 @@ +--TEST-- +Implementing sealed interfaces +--FILE-- + +--EXPECT-- +Fatal error: Class K cannot implement sealed interface A in %s/012.php on line %d diff --git a/Zend/tests/sealed/013.phpt b/Zend/tests/sealed/013.phpt new file mode 100644 index 0000000000000..832ca5047392a --- /dev/null +++ b/Zend/tests/sealed/013.phpt @@ -0,0 +1,32 @@ +--TEST-- +Using sealed traits +--FILE-- +speak(); + +class D { use A; } // OK + +(new D)->speak(); + +class G extends C {} // OK + +(new G)->speak(); + +class H extends D {} // OK + +(new H)->speak(); + +class K { use A; } // K.O +?> +--EXPECT-- +*bark* *bark* *bark* *bark* +Fatal error: Class K cannot use sealed trait A in %s/013.php on line %d diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 61a0aa923dda9..91c882a4e497c 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -50,6 +50,7 @@ ZEND_API void (*zend_throw_exception_hook)(zend_object *ex); static zend_object_handlers default_exception_handlers; +/* @TODO: remove this check and declare Throwable sealed, permitting only Error and Exception */ /* {{{ zend_implement_throwable */ static int zend_implement_throwable(zend_class_entry *interface, zend_class_entry *class_type) { diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 40f0ab6571c60..cd3cc7b3436a4 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -1556,6 +1556,7 @@ zend_object_iterator *date_object_period_get_iterator(zend_class_entry *ce, zval return (zend_object_iterator*)iterator; } /* }}} */ +/* @TODO: remove this check and declare DateTimeInterface sealed, permitting only DateTime and DateTimeImmutable */ static int implement_date_interface_handler(zend_class_entry *interface, zend_class_entry *implementor) /* {{{ */ { if (implementor->type == ZEND_USER_CLASS &&