Skip to content

Commit 5274b65

Browse files
oplanreBilge
authored andcommitted
Implement static classes
1 parent 1f64e7c commit 5274b65

File tree

11 files changed

+43
-11
lines changed

11 files changed

+43
-11
lines changed

Zend/Optimizer/escape_analysis.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "Optimizer/zend_optimizer_internal.h"
2121
#include "zend_bitset.h"
2222
#include "zend_cfg.h"
23+
#include "zend_compile.h"
2324
#include "zend_ssa.h"
2425
#include "zend_inference.h"
2526
#include "zend_dump.h"
@@ -162,7 +163,7 @@ static bool is_allocation_def(zend_op_array *op_array, zend_ssa *ssa, int def, i
162163
script, op_array, opline);
163164
uint32_t forbidden_flags =
164165
/* These flags will always cause an exception */
165-
ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
166+
ZEND_ACC_STATIC|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
166167
| ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT;
167168
if (ce
168169
&& !ce->parent

Zend/zend_API.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1795,13 +1795,15 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties)
17951795
* calling zend_merge_properties(). */
17961796
static zend_always_inline zend_result _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
17971797
{
1798-
if (UNEXPECTED(class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS|ZEND_ACC_ENUM))) {
1798+
if (UNEXPECTED(class_type->ce_flags & (ZEND_ACC_STATIC|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS|ZEND_ACC_ENUM))) {
17991799
if (class_type->ce_flags & ZEND_ACC_INTERFACE) {
18001800
zend_throw_error(NULL, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name));
18011801
} else if (class_type->ce_flags & ZEND_ACC_TRAIT) {
18021802
zend_throw_error(NULL, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name));
18031803
} else if (class_type->ce_flags & ZEND_ACC_ENUM) {
18041804
zend_throw_error(NULL, "Cannot instantiate enum %s", ZSTR_VAL(class_type->name));
1805+
} else if (class_type->ce_flags & ZEND_ACC_STATIC) {
1806+
zend_throw_error(NULL, "Cannot instantiate static class %s", ZSTR_VAL(class_type->name));
18051807
} else {
18061808
zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name));
18071809
}

Zend/zend_ast.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,6 +1837,9 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
18371837
if (decl->flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
18381838
smart_str_appends(str, "abstract ");
18391839
}
1840+
if (decl->flags & ZEND_ACC_STATIC) {
1841+
smart_str_appends(str, "static ");
1842+
}
18401843
if (decl->flags & ZEND_ACC_FINAL) {
18411844
smart_str_appends(str, "final ");
18421845
}

Zend/zend_compile.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,7 @@ uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
931931
"Multiple abstract modifiers are not allowed", 0);
932932
return 0;
933933
}
934+
934935
if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
935936
zend_throw_exception(zend_ce_compile_error, "Multiple final modifiers are not allowed", 0);
936937
return 0;
@@ -944,6 +945,12 @@ uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
944945
"Cannot use the final modifier on an abstract class", 0);
945946
return 0;
946947
}
948+
if ((flags & ZEND_ACC_STATIC) && (new_flag & ZEND_ACC_STATIC)) {
949+
zend_throw_exception(zend_ce_compile_error,
950+
"Multiple static modifiers are not allowed", 0);
951+
return 0;
952+
}
953+
947954
return new_flags;
948955
}
949956
/* }}} */
@@ -960,6 +967,10 @@ uint32_t zend_add_anonymous_class_modifier(uint32_t flags, uint32_t new_flag)
960967
zend_throw_exception(zend_ce_compile_error, "Cannot use the final modifier on an anonymous class", 0);
961968
return 0;
962969
}
970+
if (new_flag & ZEND_ACC_STATIC) {
971+
zend_throw_exception(zend_ce_compile_error, "Cannot use the static modifier on an anonymous class", 0);
972+
return 0;
973+
}
963974
if ((flags & ZEND_ACC_READONLY_CLASS) && (new_flag & ZEND_ACC_READONLY_CLASS)) {
964975
zend_throw_exception(zend_ce_compile_error, "Multiple readonly modifiers are not allowed", 0);
965976
return 0;
@@ -8610,7 +8621,7 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
86108621
/* Reset lineno for final opcodes and errors */
86118622
CG(zend_lineno) = ast->lineno;
86128623

8613-
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) {
8624+
if ((ce->ce_flags & (ZEND_ACC_STATIC|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
86148625
zend_verify_abstract_class(ce);
86158626
}
86168627

Zend/zend_language_parser.y

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,7 @@ class_modifier:
617617
T_ABSTRACT { $$ = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; }
618618
| T_FINAL { $$ = ZEND_ACC_FINAL; }
619619
| T_READONLY { $$ = ZEND_ACC_READONLY_CLASS|ZEND_ACC_NO_DYNAMIC_PROPERTIES; }
620+
| T_STATIC { $$ = ZEND_ACC_STATIC; }
620621
;
621622

622623
trait_declaration_statement:

ext/mysqli/mysqli.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
758758
if (ce == NULL) {
759759
ce = zend_standard_class_def;
760760
}
761-
if (UNEXPECTED(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
761+
if (UNEXPECTED(ce->ce_flags & (ZEND_ACC_STATIC|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
762762
zend_throw_error(NULL, "Class %s cannot be instantiated", ZSTR_VAL(ce->name));
763763
RETURN_THROWS();
764764
}

ext/reflection/php_reflection.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,9 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char
348348
if (ce->ce_flags & ZEND_ACC_READONLY_CLASS) {
349349
smart_str_append_printf(str, "readonly ");
350350
}
351+
if (ce->ce_flags & ZEND_ACC_STATIC) {
352+
smart_str_append_printf(str, "static ");
353+
}
351354
smart_str_append_printf(str, "class ");
352355
}
353356
smart_str_append_printf(str, "%s", ZSTR_VAL(ce->name));
@@ -1575,7 +1578,6 @@ ZEND_METHOD(Reflection, getModifierNames)
15751578
if (modifiers & ZEND_ACC_FINAL) {
15761579
add_next_index_stringl(return_value, "final", sizeof("final")-1);
15771580
}
1578-
15791581
/* These are mutually exclusive */
15801582
switch (modifiers & ZEND_ACC_PPP_MASK) {
15811583
case ZEND_ACC_PUBLIC:
@@ -4934,7 +4936,7 @@ ZEND_METHOD(ReflectionClass, isInstantiable)
49344936
RETURN_THROWS();
49354937
}
49364938
GET_REFLECTION_OBJECT_PTR(ce);
4937-
if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_ENUM)) {
4939+
if (ce->ce_flags & (ZEND_ACC_STATIC|ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_ENUM)) {
49384940
RETURN_FALSE;
49394941
}
49404942

@@ -4959,7 +4961,7 @@ ZEND_METHOD(ReflectionClass, isCloneable)
49594961
RETURN_THROWS();
49604962
}
49614963
GET_REFLECTION_OBJECT_PTR(ce);
4962-
if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_ENUM)) {
4964+
if (ce->ce_flags & (ZEND_ACC_STATIC|ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_ENUM)) {
49634965
RETURN_FALSE;
49644966
}
49654967
if (!Z_ISUNDEF(intern->obj)) {
@@ -5028,7 +5030,7 @@ ZEND_METHOD(ReflectionClass, getModifiers)
50285030
{
50295031
reflection_object *intern;
50305032
zend_class_entry *ce;
5031-
uint32_t keep_flags = ZEND_ACC_FINAL | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_READONLY_CLASS;
5033+
uint32_t keep_flags = ZEND_ACC_STATIC| ZEND_ACC_FINAL | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_READONLY_CLASS;
50325034

50335035
if (zend_parse_parameters_none() == FAILURE) {
50345036
RETURN_THROWS();
@@ -5433,7 +5435,7 @@ ZEND_METHOD(ReflectionClass, isIterable)
54335435

54345436
GET_REFLECTION_OBJECT_PTR(ce);
54355437

5436-
if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS |
5438+
if (ce->ce_flags & (ZEND_ACC_STATIC| ZEND_ACC_INTERFACE | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS |
54375439
ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
54385440
RETURN_FALSE;
54395441
}

ext/reflection/php_reflection.stub.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ class ReflectionClass implements Reflector
249249
public const int IS_FINAL = UNKNOWN;
250250
/** @cvalue ZEND_ACC_READONLY_CLASS */
251251
public const int IS_READONLY = UNKNOWN;
252+
/** @cvalue ZEND_ACC_STATIC */
253+
public const int IS_STATIC = UNKNOWN;
252254

253255
public string $name;
254256

ext/reflection/php_reflection_arginfo.h

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/tokenizer/tokenizer.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ PHP_METHOD(PhpToken, tokenize)
106106
zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(token_class->name));
107107
RETURN_THROWS();
108108
}
109+
if (token_class->ce_flags & ZEND_ACC_STATIC) {
110+
zend_throw_error(NULL, "Cannot instantiate static class %s", ZSTR_VAL(token_class->name));
111+
RETURN_THROWS();
112+
}
109113
if (zend_update_class_constants(token_class) == FAILURE) {
110114
RETURN_THROWS();
111115
}

main/streams/userspace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ static zend_result call_method_if_exists(
260260

261261
static void user_stream_create_object(struct php_user_stream_wrapper *uwrap, php_stream_context *context, zval *object)
262262
{
263-
if (uwrap->ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
263+
if (uwrap->ce->ce_flags & (ZEND_ACC_STATIC|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
264264
ZVAL_UNDEF(object);
265265
return;
266266
}

0 commit comments

Comments
 (0)