@@ -5761,6 +5761,8 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
57615761 zend_string * name = zval_make_interned_string (zend_ast_get_zval (var_ast ));
57625762 zend_bool is_ref = (param_ast -> attr & ZEND_PARAM_REF ) != 0 ;
57635763 zend_bool is_variadic = (param_ast -> attr & ZEND_PARAM_VARIADIC ) != 0 ;
5764+ uint32_t visibility =
5765+ param_ast -> attr & (ZEND_ACC_PUBLIC |ZEND_ACC_PROTECTED |ZEND_ACC_PRIVATE );
57645766
57655767 znode var_node , default_node ;
57665768 zend_uchar opcode ;
@@ -5829,16 +5831,16 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
58295831
58305832 if (type_ast ) {
58315833 uint32_t default_type = default_ast ? Z_TYPE (default_node .u .constant ) : IS_UNDEF ;
5834+ zend_bool force_nullable = default_type == IS_NULL && !visibility ;
58325835
58335836 op_array -> fn_flags |= ZEND_ACC_HAS_TYPE_HINTS ;
5834- arg_info -> type = zend_compile_typename (
5835- type_ast , default_type == IS_NULL , /* use_arena */ 0 );
5837+ arg_info -> type = zend_compile_typename (type_ast , force_nullable , /* use_arena */ 0 );
58365838
58375839 if (ZEND_TYPE_FULL_MASK (arg_info -> type ) & MAY_BE_VOID ) {
58385840 zend_error_noreturn (E_COMPILE_ERROR , "void cannot be used as a parameter type" );
58395841 }
58405842
5841- if (default_type > IS_NULL && default_type != IS_CONSTANT_AST
5843+ if (default_type != IS_UNDEF && default_type != IS_CONSTANT_AST && ! force_nullable
58425844 && !zend_is_valid_default_value (arg_info -> type , & default_node .u .constant )) {
58435845 zend_string * type_str = zend_type_to_string (arg_info -> type );
58445846 zend_error_noreturn (E_COMPILE_ERROR ,
@@ -5863,6 +5865,41 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
58635865 opline -> op2 .num = type_ast ?
58645866 ZEND_TYPE_FULL_MASK (arg_info -> type ) : MAY_BE_ANY ;
58655867 }
5868+
5869+ if (visibility ) {
5870+ zend_op_array * op_array = CG (active_op_array );
5871+ zend_class_entry * scope = op_array -> scope ;
5872+ zend_bool is_ctor =
5873+ scope && zend_string_equals_literal_ci (op_array -> function_name , "__construct" );
5874+ if (!is_ctor ) {
5875+ zend_error_noreturn (E_COMPILE_ERROR ,
5876+ "Cannot declare promoted property outside a constructor" );
5877+ }
5878+ if ((op_array -> fn_flags & ZEND_ACC_ABSTRACT )
5879+ || (scope -> ce_flags & ZEND_ACC_INTERFACE )) {
5880+ zend_error_noreturn (E_COMPILE_ERROR ,
5881+ "Cannot declare promoted property in an abstract constructor" );
5882+ }
5883+ if (ZEND_TYPE_FULL_MASK (arg_info -> type ) & MAY_BE_CALLABLE ) {
5884+ zend_string * str = zend_type_to_string (arg_info -> type );
5885+ zend_error_noreturn (E_COMPILE_ERROR ,
5886+ "Property %s::$%s cannot have type %s" ,
5887+ ZSTR_VAL (scope -> name ), ZSTR_VAL (name ), ZSTR_VAL (str ));
5888+ }
5889+
5890+ /* Always use uninitialized as the default. */
5891+ zval default_value ;
5892+ ZVAL_UNDEF (& default_value );
5893+
5894+ /* Recompile the type, as it has different memory management requirements. */
5895+ zend_type type = ZEND_TYPE_INIT_NONE (0 );
5896+ if (type_ast ) {
5897+ type = zend_compile_typename (type_ast , /* force_allow_null */ 0 , /* use_arena */ 1 );
5898+ }
5899+
5900+ zend_declare_typed_property (
5901+ scope , name , & default_value , visibility , /* doc_comment */ NULL , type );
5902+ }
58665903 }
58675904
58685905 /* These are assigned at the end to avoid uninitialized memory in case of an error */
@@ -5874,6 +5911,27 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
58745911 op_array -> num_args -- ;
58755912 }
58765913 zend_set_function_arg_flags ((zend_function * )op_array );
5914+
5915+ for (i = 0 ; i < list -> children ; i ++ ) {
5916+ zend_ast * param_ast = list -> child [i ];
5917+ uint32_t visibility =
5918+ param_ast -> attr & (ZEND_ACC_PUBLIC |ZEND_ACC_PROTECTED |ZEND_ACC_PRIVATE );
5919+ if (!visibility ) {
5920+ continue ;
5921+ }
5922+
5923+ /* Emit $this->prop = $prop for promoted properties. */
5924+ zend_string * name = zend_ast_get_str (param_ast -> child [1 ]);
5925+ znode name_node , value_node ;
5926+ name_node .op_type = IS_CONST ;
5927+ ZVAL_STR_COPY (& name_node .u .constant , name );
5928+ value_node .op_type = IS_CV ;
5929+ value_node .u .op .var = lookup_cv (name );
5930+
5931+ zend_op * opline = zend_emit_op (NULL , ZEND_ASSIGN_OBJ , NULL , & name_node );
5932+ opline -> extended_value = zend_alloc_cache_slots (3 );
5933+ zend_emit_op_data (& value_node );
5934+ }
58775935}
58785936/* }}} */
58795937
0 commit comments