@@ -753,6 +753,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
753753 zend_param_must_be_ref (func , i + 1 );
754754 if (UNEXPECTED (EG (exception ))) {
755755 ZEND_CALL_NUM_ARGS (call ) = i ;
756+ cleanup_args :
756757 zend_vm_stack_free_args (call );
757758 zend_vm_stack_free_call_frame (call );
758759 if (EG (current_execute_data ) == & dummy_execute_data ) {
@@ -774,27 +775,57 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
774775 }
775776
776777 if (fci -> named_params ) {
778+ ZEND_ASSERT (fci -> no_separation && "Do we want to support separation?" );
779+
777780 zend_string * name ;
778- zval * val ;
779- ZEND_HASH_FOREACH_STR_KEY_VAL (fci -> named_params , name , val ) {
780- ZEND_ASSERT (name && "named_params may only contain named params" );
781-
782- void * cache_slot = NULL ;
783- uint32_t arg_num ;
784- zval * target = zend_handle_named_arg (& call , name , & arg_num , & cache_slot );
785- if (!target ) {
786- zend_vm_stack_free_args (call );
787- zend_vm_stack_free_call_frame (call );
788- if (EG (current_execute_data ) == & dummy_execute_data ) {
789- EG (current_execute_data ) = dummy_execute_data .prev_execute_data ;
781+ zval * arg ;
782+ uint32_t arg_num = ZEND_CALL_NUM_ARGS (call ) + 1 ;
783+ zend_bool have_named_params = 0 ;
784+ ZEND_HASH_FOREACH_STR_KEY_VAL (fci -> named_params , name , arg ) {
785+ zval * target ;
786+ if (name ) {
787+ void * cache_slot = NULL ;
788+ have_named_params = 1 ;
789+ target = zend_handle_named_arg (& call , name , & arg_num , & cache_slot );
790+ if (!target ) {
791+ goto cleanup_args ;
790792 }
791- return FAILURE ;
793+ } else {
794+ if (have_named_params ) {
795+ zend_throw_error (NULL ,
796+ "Cannot use positional argument after named argument" );
797+ goto cleanup_args ;
798+ }
799+
800+ target = ZEND_CALL_ARG (call , arg_num );
792801 }
793802
794- /* TODO */
795- /*if (ARG_SHOULD_BE_SENT_BY_REF(func, arg_num)) {
796- }*/
797- ZVAL_COPY (target , val );
803+ if (ARG_SHOULD_BE_SENT_BY_REF (func , arg_num )) {
804+ if (UNEXPECTED (!Z_ISREF_P (arg ))) {
805+ if (!fci -> no_separation ) {
806+ /* TODO ? */
807+ } else if (!ARG_MAY_BE_SENT_BY_REF (func , arg_num )) {
808+ /* By-value send is not allowed -- emit a warning,
809+ * but still perform the call with a by-value send. */
810+ zend_param_must_be_ref (func , arg_num );
811+ if (UNEXPECTED (EG (exception ))) {
812+ goto cleanup_args ;
813+ }
814+ }
815+ }
816+ } else {
817+ if (Z_ISREF_P (arg ) &&
818+ !(func -> common .fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE )) {
819+ /* don't separate references for __call */
820+ arg = Z_REFVAL_P (arg );
821+ }
822+ }
823+
824+ ZVAL_COPY (target , arg );
825+ if (!name ) {
826+ ZEND_CALL_NUM_ARGS (call )++ ;
827+ arg_num ++ ;
828+ }
798829 } ZEND_HASH_FOREACH_END ();
799830 }
800831
0 commit comments