Skip to content

Commit c08b0ba

Browse files
GH-16067: prevent invalid abstract during compilation of methods
For classes that are not declared `abstract`, produce a compiler error for any `abstract` methods. For anonymous classes, since they cannot be made abstract, the error message is slightly different.
1 parent 01ae6e9 commit c08b0ba

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

Zend/tests/abstract_implicit.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ class NotAbstract {
1616
}
1717
?>
1818
--EXPECTF--
19-
Fatal error: Class NotAbstract contains 1 abstract method and must therefore be declared abstract or implement the remaining method (NotAbstract::bar) in %s on line %d
19+
Fatal error: Class NotAbstract contains abstract method NotAbstract::bar and must therefore be declared abstract in %s on line %d

Zend/tests/anon/gh16067.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ $c = new class {
88
}
99
?>
1010
--EXPECTF--
11-
Fatal error: Class class@anonymous must implement 1 abstract method (class@anonymous::f) in %s on line 3
11+
Fatal error: Anonymous class class@anonymous cannot contain abstract method class@anonymous::f in %s on line 4

Zend/zend_compile.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8067,6 +8067,27 @@ static zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string
80678067
zend_error(E_COMPILE_WARNING, "Private methods cannot be final as they are never overridden by other classes");
80688068
}
80698069

8070+
if ((fn_flags & ZEND_ACC_ABSTRACT) &&
8071+
!(ce->ce_flags & (ZEND_ACC_EXPLICIT_ABSTRACT_CLASS|ZEND_ACC_TRAIT)) &&
8072+
!in_interface
8073+
) {
8074+
// Don't say that the class should be declared abstract if it is
8075+
// anonymous and can't be abstract
8076+
const char *msg;
8077+
if (ce->ce_flags & ZEND_ACC_ANON_CLASS) {
8078+
msg = "Anonymous class %s cannot contain abstract method %s::%s";
8079+
} else {
8080+
msg = "Class %s contains abstract method %s::%s and must therefore be declared abstract";
8081+
}
8082+
zend_error_noreturn(
8083+
E_COMPILE_ERROR,
8084+
msg,
8085+
ZSTR_VAL(ce->name),
8086+
ZSTR_VAL(ce->name),
8087+
ZSTR_VAL(name)
8088+
);
8089+
}
8090+
80708091
if (in_interface) {
80718092
if (!(fn_flags & ZEND_ACC_PUBLIC)) {
80728093
zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method "

0 commit comments

Comments
 (0)