@@ -54,6 +54,18 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(znode *node) {
54
54
return (zend_ast * ) ast ;
55
55
}
56
56
57
+ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_fcc (void ) {
58
+ zend_ast_fcc * ast ;
59
+
60
+ ast = zend_ast_alloc (sizeof (zend_ast_fcc ));
61
+ ast -> kind = ZEND_AST_CALLABLE_CONVERT ;
62
+ ast -> attr = 0 ;
63
+ ast -> lineno = ZEND_MAP_PTR_NEW_OFFSET ();
64
+ ZEND_MAP_PTR_NEW (ast -> fptr );
65
+
66
+ return (zend_ast * ) ast ;
67
+ }
68
+
57
69
static zend_always_inline zend_ast * zend_ast_create_zval_int (zval * zv , uint32_t attr , uint32_t lineno ) {
58
70
zend_ast_zval * ast ;
59
71
@@ -1009,81 +1021,96 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
1009
1021
switch (ast -> kind ) {
1010
1022
case ZEND_AST_CALL : {
1011
1023
ZEND_ASSERT (ast -> child [1 ]-> kind == ZEND_AST_CALLABLE_CONVERT );
1024
+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast -> child [1 ];
1025
+ fptr = ZEND_MAP_PTR_GET (fcc_ast -> fptr );
1012
1026
1013
- zend_string * function_name = zend_ast_get_str (ast -> child [0 ]);
1014
- zend_string * function_name_lc = zend_string_tolower (function_name );
1015
- fptr = zend_fetch_function (function_name_lc );
1016
- if (!fptr && ast -> child [0 ]-> attr != ZEND_NAME_FQ ) {
1017
- const char * backslash = zend_memrchr (ZSTR_VAL (function_name_lc ), '\\' , ZSTR_LEN (function_name_lc ));
1018
- if (backslash ) {
1019
- fptr = zend_fetch_function_str (backslash + 1 , ZSTR_LEN (function_name_lc ) - (backslash - ZSTR_VAL (function_name_lc ) + 1 ));
1020
- }
1021
- }
1022
- zend_string_release (function_name_lc );
1023
1027
if (!fptr ) {
1024
- zend_throw_error (NULL , "Call to undefined function %s()" , ZSTR_VAL (function_name ));
1025
- return FAILURE ;
1028
+ zend_string * function_name = zend_ast_get_str (ast -> child [0 ]);
1029
+ zend_string * function_name_lc = zend_string_tolower (function_name );
1030
+ fptr = zend_fetch_function (function_name_lc );
1031
+ if (!fptr && ast -> child [0 ]-> attr != ZEND_NAME_FQ ) {
1032
+ const char * backslash = zend_memrchr (ZSTR_VAL (function_name_lc ), '\\' , ZSTR_LEN (function_name_lc ));
1033
+ if (backslash ) {
1034
+ fptr = zend_fetch_function_str (backslash + 1 , ZSTR_LEN (function_name_lc ) - (backslash - ZSTR_VAL (function_name_lc ) + 1 ));
1035
+ }
1036
+ }
1037
+ zend_string_release (function_name_lc );
1038
+ if (!fptr ) {
1039
+ zend_throw_error (NULL , "Call to undefined function %s()" , ZSTR_VAL (function_name ));
1040
+ return FAILURE ;
1041
+ }
1042
+
1043
+ ZEND_MAP_PTR_SET (fcc_ast -> fptr , fptr );
1026
1044
}
1045
+
1027
1046
break ;
1028
1047
}
1029
1048
case ZEND_AST_STATIC_CALL : {
1030
1049
ZEND_ASSERT (ast -> child [2 ]-> kind == ZEND_AST_CALLABLE_CONVERT );
1050
+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast -> child [2 ];
1031
1051
1032
- zend_class_entry * ce = zend_ast_fetch_class (ast -> child [0 ], scope );
1033
- if (!ce ) {
1034
- return FAILURE ;
1035
- }
1036
- zend_string * method_name = zend_ast_get_str (ast -> child [1 ]);
1037
- if (ce -> get_static_method ) {
1038
- fptr = ce -> get_static_method (ce , method_name );
1039
- } else {
1040
- fptr = zend_hash_find_ptr_lc (& ce -> function_table , method_name );
1041
- if (fptr ) {
1042
- if (!(fptr -> common .fn_flags & ZEND_ACC_PUBLIC )) {
1043
- if (UNEXPECTED (fptr -> common .scope != scope )) {
1044
- if (
1045
- UNEXPECTED (fptr -> op_array .fn_flags & ZEND_ACC_PRIVATE )
1046
- || UNEXPECTED (!zend_check_protected (zend_get_function_root_class (fptr ), scope ))
1047
- ) {
1048
- if (ce -> __callstatic ) {
1049
- zend_throw_error (NULL , "Creating a callable for the magic __callStatic() method is not supported in constant expressions" );
1050
- } else {
1051
- zend_bad_method_call (fptr , method_name , scope );
1052
- }
1052
+ fptr = ZEND_MAP_PTR_GET (fcc_ast -> fptr );
1053
1053
1054
- return FAILURE ;
1054
+ if (!fptr ) {
1055
+ zend_class_entry * ce = zend_ast_fetch_class (ast -> child [0 ], scope );
1056
+ if (!ce ) {
1057
+ return FAILURE ;
1058
+ }
1059
+ zend_string * method_name = zend_ast_get_str (ast -> child [1 ]);
1060
+ if (ce -> get_static_method ) {
1061
+ fptr = ce -> get_static_method (ce , method_name );
1062
+ } else {
1063
+ fptr = zend_hash_find_ptr_lc (& ce -> function_table , method_name );
1064
+ if (fptr ) {
1065
+ if (!(fptr -> common .fn_flags & ZEND_ACC_PUBLIC )) {
1066
+ if (UNEXPECTED (fptr -> common .scope != scope )) {
1067
+ if (
1068
+ UNEXPECTED (fptr -> op_array .fn_flags & ZEND_ACC_PRIVATE )
1069
+ || UNEXPECTED (!zend_check_protected (zend_get_function_root_class (fptr ), scope ))
1070
+ ) {
1071
+ if (ce -> __callstatic ) {
1072
+ zend_throw_error (NULL , "Creating a callable for the magic __callStatic() method is not supported in constant expressions" );
1073
+ } else {
1074
+ zend_bad_method_call (fptr , method_name , scope );
1075
+ }
1076
+
1077
+ return FAILURE ;
1078
+ }
1055
1079
}
1056
1080
}
1057
- }
1058
- } else {
1059
- if (ce -> __callstatic ) {
1060
- zend_throw_error (NULL , "Creating a callable for the magic __callStatic() method is not supported in constant expressions" );
1061
1081
} else {
1062
- zend_undefined_method (ce , method_name );
1082
+ if (ce -> __callstatic ) {
1083
+ zend_throw_error (NULL , "Creating a callable for the magic __callStatic() method is not supported in constant expressions" );
1084
+ } else {
1085
+ zend_undefined_method (ce , method_name );
1086
+ }
1087
+
1088
+ return FAILURE ;
1063
1089
}
1090
+ }
1064
1091
1092
+ if (!(fptr -> common .fn_flags & ZEND_ACC_STATIC )) {
1093
+ zend_non_static_method_call (fptr );
1094
+
1065
1095
return FAILURE ;
1066
1096
}
1067
- }
1068
-
1069
- if (!(fptr -> common .fn_flags & ZEND_ACC_STATIC )) {
1070
- zend_non_static_method_call (fptr );
1071
-
1072
- return FAILURE ;
1073
- }
1074
- if ((fptr -> common .fn_flags & ZEND_ACC_ABSTRACT )) {
1075
- zend_abstract_method_call (fptr );
1076
-
1077
- return FAILURE ;
1078
- } else if (fptr -> common .scope -> ce_flags & ZEND_ACC_TRAIT ) {
1079
- zend_error (E_DEPRECATED ,
1080
- "Calling static trait method %s::%s is deprecated, "
1081
- "it should only be called on a class using the trait" ,
1082
- ZSTR_VAL (fptr -> common .scope -> name ), ZSTR_VAL (fptr -> common .function_name ));
1083
- if (EG (exception )) {
1097
+ if ((fptr -> common .fn_flags & ZEND_ACC_ABSTRACT )) {
1098
+ zend_abstract_method_call (fptr );
1099
+
1084
1100
return FAILURE ;
1101
+ } else if (fptr -> common .scope -> ce_flags & ZEND_ACC_TRAIT ) {
1102
+ zend_error (E_DEPRECATED ,
1103
+ "Calling static trait method %s::%s is deprecated, "
1104
+ "it should only be called on a class using the trait" ,
1105
+ ZSTR_VAL (fptr -> common .scope -> name ), ZSTR_VAL (fptr -> common .function_name ));
1106
+ if (EG (exception )) {
1107
+ return FAILURE ;
1108
+ }
1085
1109
}
1110
+
1111
+ ZEND_MAP_PTR_SET (fcc_ast -> fptr , fptr );
1086
1112
}
1113
+
1087
1114
break ;
1088
1115
}
1089
1116
}
@@ -1182,6 +1209,8 @@ static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
1182
1209
size = sizeof (zend_ast_zval );
1183
1210
} else if (ast -> kind == ZEND_AST_OP_ARRAY ) {
1184
1211
size = sizeof (zend_ast_op_array );
1212
+ } else if (ast -> kind == ZEND_AST_CALLABLE_CONVERT ) {
1213
+ size = sizeof (zend_ast_fcc );
1185
1214
} else if (zend_ast_is_list (ast )) {
1186
1215
uint32_t i ;
1187
1216
zend_ast_list * list = zend_ast_get_list (ast );
@@ -1249,6 +1278,13 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
1249
1278
new -> lineno = old -> lineno ;
1250
1279
new -> op_array = old -> op_array ;
1251
1280
buf = (void * )((char * )buf + sizeof (zend_ast_op_array ));
1281
+ } else if (ast -> kind == ZEND_AST_CALLABLE_CONVERT ) {
1282
+ zend_ast_fcc * new = (zend_ast_fcc * )buf ;
1283
+ new -> kind = ZEND_AST_CALLABLE_CONVERT ;
1284
+ new -> attr = ast -> attr ;
1285
+ new -> lineno = ast -> lineno ;
1286
+ new -> fptr__ptr = ((zend_ast_fcc * ) ast )-> fptr__ptr ;
1287
+ buf = (void * )((char * )buf + sizeof (zend_ast_fcc ));
1252
1288
} else if (zend_ast_is_decl (ast )) {
1253
1289
/* Not implemented. */
1254
1290
ZEND_UNREACHABLE ();
0 commit comments