Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit dfbe9aa

Browse files
committed
core: set zend_pass_function as default constructor
This is to make the semantics of when a class cannot be instiantiated obvious rather than needed to remember to call the get_constructor() handler.
1 parent 05eda43 commit dfbe9aa

35 files changed

+255
-121
lines changed

‎Zend/Optimizer/escape_analysis.c‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ static bool is_allocation_def(zend_op_array *op_array, zend_ssa *ssa, int def, i
169169
&& !ce->create_object
170170
&& ce->default_object_handlers->get_constructor == zend_std_get_constructor
171171
&& ce->default_object_handlers->dtor_obj == zend_objects_destroy_object
172-
&& !ce->constructor
172+
&& (!ce->constructor||zend_is_pass_function(ce->constructor))
173173
&& !ce->destructor
174174
&& !ce->__get
175175
&& !ce->__set
@@ -238,7 +238,7 @@ static bool is_local_def(zend_op_array *op_array, zend_ssa *ssa, int def, int va
238238
&& !ce->create_object
239239
&& ce->default_object_handlers->get_constructor == zend_std_get_constructor
240240
&& ce->default_object_handlers->dtor_obj == zend_objects_destroy_object
241-
&& !ce->constructor
241+
&& (!ce->constructor||zend_is_pass_function(ce->constructor))
242242
&& !ce->destructor
243243
&& !ce->__get
244244
&& !ce->__set

‎Zend/Optimizer/zend_inference.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3395,7 +3395,7 @@ static zend_always_inline zend_result _zend_update_type_info(
33953395
}
33963396
/* New objects without constructors cannot escape. */
33973397
if (ce
3398-
&& !ce->constructor
3398+
&& (!ce->constructor||zend_is_pass_function(ce->constructor))
33993399
&& !ce->create_object
34003400
&& ce->default_object_handlers->get_constructor == zend_std_get_constructor) {
34013401
tmp &= ~MAY_BE_RCN;

‎Zend/zend_builtin_functions.c‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ ZEND_MINIT_FUNCTION(core) { /* {{{ */
3838
zend_register_default_classes();
3939

4040
zend_standard_class_def = register_class_stdClass();
41+
/* Assign dummy constructor */
42+
zend_standard_class_def->constructor = (zend_function*) &zend_pass_function;
4143

4244
return SUCCESS;
4345
}

‎Zend/zend_compile.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9351,6 +9351,11 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
93519351
ce->ce_flags |= ZEND_ACC_TOP_LEVEL;
93529352
}
93539353

9354+
/* Add a default "pass" constructor if none are defined */
9355+
if (ce->constructor == NULL && (ce->ce_flags & (ZEND_ACC_ENUM|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT)) == 0) {
9356+
ce->constructor = (zend_function *) &zend_pass_function;
9357+
}
9358+
93549359
if (ce->__serialize == NULL && zend_hash_exists(&ce->function_table, ZSTR_KNOWN(ZEND_STR_SLEEP))) {
93559360
zend_error(E_DEPRECATED, "The __sleep() serialization magic method has been deprecated."
93569361
" Implement __serialize() instead (or in addition, if support for old PHP versions is necessary)");

‎Zend/zend_compile.h‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,13 @@ struct _zend_execute_data {
634634
zend_array *extra_named_params;
635635
};
636636

637+
/* export zend_pass_function to allow comparisons against it */
638+
extern ZEND_API const zend_internal_function zend_pass_function;
639+
640+
static zend_always_inline bool zend_is_pass_function(const zend_function *fn) {
641+
return fn == (const zend_function*) &zend_pass_function;
642+
}
643+
637644
#define ZEND_CALL_HAS_THIS IS_OBJECT_EX
638645

639646
/* Top 16 bits of Z_TYPE_INFO(EX(This)) are used as call_info flags */

‎Zend/zend_execute.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ ZEND_END_ARG_INFO()
142142
ZEND_API const zend_internal_function zend_pass_function = {
143143
ZEND_INTERNAL_FUNCTION, /* type */
144144
{0, 0, 0}, /* arg_flags */
145-
0, /* fn_flags */
145+
ZEND_ACC_PUBLIC, /* fn_flags */
146146
NULL, /* name */
147147
NULL, /* scope */
148148
NULL, /* prototype */

‎Zend/zend_execute.h‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,6 @@ ZEND_API zend_result zend_eval_stringl(const char *str, size_t str_len, zval *re
5858
ZEND_API zend_result zend_eval_string_ex(const char *str, zval *retval_ptr, const char *string_name, bool handle_exceptions);
5959
ZEND_API zend_result zend_eval_stringl_ex(const char *str, size_t str_len, zval *retval_ptr, const char *string_name, bool handle_exceptions);
6060

61-
/* export zend_pass_function to allow comparisons against it */
62-
extern ZEND_API const zend_internal_function zend_pass_function;
63-
6461
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(const zend_execute_data *execute_data);
6562
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_function *fbc);
6663
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_nodiscard_function(const zend_function *fbc);

‎Zend/zend_inheritance.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
187187
ce->__debugInfo = parent->__debugInfo;
188188
}
189189

190-
if (ce->constructor) {
190+
if (ce->constructor&& !zend_is_pass_function(ce->constructor)) {
191191
if (parent->constructor && UNEXPECTED(parent->constructor->common.fn_flags & ZEND_ACC_FINAL)) {
192192
zend_error_noreturn(E_ERROR, "Cannot override final %s::%s() with %s::%s()",
193193
ZSTR_VAL(parent->name), ZSTR_VAL(parent->constructor->common.function_name),

‎Zend/zend_vm_def.h‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5969,7 +5969,15 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N
59695969
}
59705970

59715971
constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
5972-
if (constructor == NULL) {
5972+
if (UNEXPECTED(constructor == NULL)) {
5973+
/* No constructor implies that an internal get_constructor was overwritten and threw an exception. */
5974+
if (UNEXPECTED(!EG(exception))) {
5975+
zend_throw_error(NULL, "No constructor for %s class", ZSTR_VAL(ce->name));
5976+
}
5977+
HANDLE_EXCEPTION();
5978+
}
5979+
/* Pass function is special */
5980+
else if (zend_is_pass_function(constructor)) {
59735981
/* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
59745982
* opcode is DO_FCALL in case EXT instructions are used. */
59755983
if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
@@ -5982,7 +5990,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N
59825990

59835991
/* Perform a dummy function call */
59845992
call = zend_vm_stack_push_call_frame(
5985-
ZEND_CALL_FUNCTION, (zend_function*) &zend_pass_function,
5993+
ZEND_CALL_FUNCTION, constructor,
59865994
opline->extended_value, NULL);
59875995
} else {
59885996
if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {

‎Zend/zend_vm_execute.h‎

Lines changed: 60 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /