@@ -1155,6 +1155,13 @@ ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char
1155
1155
}
1156
1156
/* }}} */
1157
1157
1158
+ static inline zend_bool zend_string_equals_str_ci (zend_string * str1 , zend_string * str2 ) /* {{{ */
1159
+ {
1160
+ return str1 -> len == str2 -> len
1161
+ && !zend_binary_strcasecmp (str1 -> val , str1 -> len , str2 -> val , str2 -> len );
1162
+ }
1163
+ /* }}} */
1164
+
1158
1165
static zend_constant * zend_lookup_reserved_const (const char * name , size_t len ) /* {{{ */
1159
1166
{
1160
1167
zend_constant * c = zend_hash_find_ptr_lc (EG (zend_constants ), name , len );
@@ -1169,13 +1176,14 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i
1169
1176
{
1170
1177
zend_constant * c ;
1171
1178
1172
- if (!(CG (compiler_options ) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION )) {
1173
- /* Substitute case-sensitive (or lowercase) persistent constants */
1174
- c = zend_hash_find_ptr (EG (zend_constants ), name );
1175
- if (c && (c -> flags & CONST_PERSISTENT )) {
1176
- ZVAL_DUP (zv , & c -> value );
1177
- return 1 ;
1178
- }
1179
+ /* Substitute case-sensitive (or lowercase) constants */
1180
+ c = zend_hash_find_ptr (EG (zend_constants ), name );
1181
+ if (c && (
1182
+ (c -> flags & CONST_PERSISTENT )
1183
+ || (Z_TYPE (c -> value ) < IS_CONSTANT && !(CG (compiler_options ) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION )))
1184
+ ) {
1185
+ ZVAL_DUP (zv , & c -> value );
1186
+ return 1 ;
1179
1187
}
1180
1188
1181
1189
{
@@ -1198,6 +1206,33 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i
1198
1206
}
1199
1207
/* }}} */
1200
1208
1209
+ static zend_bool zend_try_ct_eval_class_const (zval * zv , zend_string * class_name , zend_string * name ) /* {{{ */
1210
+ {
1211
+ uint32_t fetch_type = zend_get_class_fetch_type (class_name );
1212
+ zval * c ;
1213
+
1214
+ if (CG (active_class_entry ) && (fetch_type == ZEND_FETCH_CLASS_SELF || (fetch_type == ZEND_FETCH_CLASS_DEFAULT && zend_string_equals_str_ci (class_name , CG (active_class_entry )-> name )))) {
1215
+ c = zend_hash_find (& CG (active_class_entry )-> constants_table , name );
1216
+ } else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG (compiler_options ) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION )) {
1217
+ zend_class_entry * ce = zend_hash_find_ptr (CG (class_table ), class_name );
1218
+ if (ce ) {
1219
+ c = zend_hash_find (& ce -> constants_table , name );
1220
+ } else {
1221
+ return 0 ;
1222
+ }
1223
+ } else {
1224
+ return 0 ;
1225
+ }
1226
+
1227
+ /* Substitute case-sensitive (or lowercase) persistent class constants */
1228
+ if (c && Z_TYPE_P (c ) < IS_CONSTANT ) {
1229
+ ZVAL_DUP (zv , c );
1230
+ return 1 ;
1231
+ }
1232
+
1233
+ return 0 ;
1234
+ }
1235
+
1201
1236
void zend_init_list (void * result , void * item ) /* {{{ */
1202
1237
{
1203
1238
void * * list = emalloc (sizeof (void * ) * 2 );
@@ -1627,13 +1662,6 @@ ZEND_API size_t zend_dirname(char *path, size_t len)
1627
1662
}
1628
1663
/* }}} */
1629
1664
1630
- static inline zend_bool zend_string_equals_str_ci (zend_string * str1 , zend_string * str2 ) /* {{{ */
1631
- {
1632
- return str1 -> len == str2 -> len
1633
- && !zend_binary_strcasecmp (str1 -> val , str1 -> len , str2 -> val , str2 -> len );
1634
- }
1635
- /* }}} */
1636
-
1637
1665
static void zend_adjust_for_fetch_type (zend_op * opline , uint32_t type ) /* {{{ */
1638
1666
{
1639
1667
switch (type & BP_VAR_MASK ) {
@@ -5814,30 +5842,32 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
5814
5842
5815
5843
znode class_node , const_node ;
5816
5844
zend_op * opline , * class_op = NULL ;
5845
+ zend_string * resolved_name ;
5846
+
5847
+ zend_eval_const_expr (& class_ast );
5848
+ zend_eval_const_expr (& const_ast );
5849
+
5850
+ if (class_ast -> kind == ZEND_AST_ZVAL ) {
5851
+ resolved_name = zend_resolve_class_name_ast (class_ast );
5852
+ if (const_ast -> kind == ZEND_AST_ZVAL && zend_try_ct_eval_class_const (& result -> u .constant , resolved_name , zend_ast_get_str (const_ast ))) {
5853
+ result -> op_type = IS_CONST ;
5854
+ zend_string_release (resolved_name );
5855
+ return ;
5856
+ }
5857
+ }
5817
5858
5818
5859
if (zend_is_const_default_class_ref (class_ast )) {
5819
5860
class_node .op_type = IS_CONST ;
5820
- ZVAL_STR (& class_node .u .constant , zend_resolve_class_name_ast ( class_ast ) );
5861
+ ZVAL_STR (& class_node .u .constant , resolved_name );
5821
5862
} else {
5863
+ if (class_ast -> kind == ZEND_AST_ZVAL ) {
5864
+ zend_string_release (resolved_name );
5865
+ }
5822
5866
class_op = zend_compile_class_ref (& class_node , class_ast );
5823
5867
}
5824
5868
5825
5869
zend_compile_expr (& const_node , const_ast );
5826
5870
5827
- if (class_op && const_node .op_type == IS_CONST && class_op -> extended_value == ZEND_FETCH_CLASS_SELF && Z_TYPE (const_node .u .constant ) == IS_STRING && CG (active_class_entry )) {
5828
- zval * const_zv = zend_hash_find (& CG (active_class_entry )-> constants_table , Z_STR (const_node .u .constant ));
5829
- if (const_zv && Z_TYPE_P (const_zv ) < IS_CONSTANT ) {
5830
- CG (active_op_array )-> last -- ;
5831
- CG (active_op_array )-> T -- ;
5832
-
5833
- result -> op_type = IS_CONST ;
5834
- ZVAL_COPY (& result -> u .constant , const_zv );
5835
-
5836
- zend_string_release (Z_STR (const_node .u .constant ));
5837
- return ;
5838
- }
5839
- }
5840
-
5841
5871
opline = zend_emit_op_tmp (result , ZEND_FETCH_CONSTANT , NULL , & const_node );
5842
5872
5843
5873
zend_set_class_name_op1 (opline , & class_node );
@@ -5877,8 +5907,8 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast) /* {{{ */
5877
5907
ZVAL_STR_COPY (& result -> u .constant , CG (active_class_entry )-> name );
5878
5908
}
5879
5909
break ;
5880
- case ZEND_FETCH_CLASS_STATIC :
5881
- case ZEND_FETCH_CLASS_PARENT :
5910
+ case ZEND_FETCH_CLASS_STATIC :
5911
+ case ZEND_FETCH_CLASS_PARENT :
5882
5912
if (!CG (active_class_entry )) {
5883
5913
zend_error_noreturn (E_COMPILE_ERROR ,
5884
5914
"Cannot access %s::class when no class scope is active" ,
@@ -6555,6 +6585,30 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
6555
6585
zend_string_release (resolved_name );
6556
6586
break ;
6557
6587
}
6588
+ case ZEND_AST_CLASS_CONST :
6589
+ {
6590
+ zend_ast * class_ast = ast -> child [0 ];
6591
+ zend_ast * name_ast = ast -> child [1 ];
6592
+ zend_string * resolved_name ;
6593
+
6594
+ zend_eval_const_expr (& class_ast );
6595
+ zend_eval_const_expr (& name_ast );
6596
+
6597
+ if (class_ast -> kind != ZEND_AST_ZVAL || name_ast -> kind != ZEND_AST_ZVAL ) {
6598
+ return ;
6599
+ }
6600
+
6601
+ resolved_name = zend_resolve_class_name_ast (class_ast );
6602
+
6603
+ if (!zend_try_ct_eval_class_const (& result , resolved_name , zend_ast_get_str (name_ast ))) {
6604
+ zend_string_release (resolved_name );
6605
+ return ;
6606
+ }
6607
+
6608
+ zend_string_release (resolved_name );
6609
+ break ;
6610
+ }
6611
+
6558
6612
default :
6559
6613
return ;
6560
6614
}
0 commit comments