@@ -1155,6 +1155,13 @@ ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char
11551155}
11561156/* }}} */
11571157
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+
11581165static zend_constant * zend_lookup_reserved_const (const char * name , size_t len ) /* {{{ */
11591166{
11601167 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
11691176{
11701177 zend_constant * c ;
11711178
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 ;
11791187 }
11801188
11811189 {
@@ -1198,6 +1206,33 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i
11981206}
11991207/* }}} */
12001208
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+
12011236void zend_init_list (void * result , void * item ) /* {{{ */
12021237{
12031238 void * * list = emalloc (sizeof (void * ) * 2 );
@@ -1627,13 +1662,6 @@ ZEND_API size_t zend_dirname(char *path, size_t len)
16271662}
16281663/* }}} */
16291664
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-
16371665static void zend_adjust_for_fetch_type (zend_op * opline , uint32_t type ) /* {{{ */
16381666{
16391667 switch (type & BP_VAR_MASK ) {
@@ -5814,30 +5842,32 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
58145842
58155843 znode class_node , const_node ;
58165844 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+ }
58175858
58185859 if (zend_is_const_default_class_ref (class_ast )) {
58195860 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 );
58215862 } else {
5863+ if (class_ast -> kind == ZEND_AST_ZVAL ) {
5864+ zend_string_release (resolved_name );
5865+ }
58225866 class_op = zend_compile_class_ref (& class_node , class_ast );
58235867 }
58245868
58255869 zend_compile_expr (& const_node , const_ast );
58265870
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-
58415871 opline = zend_emit_op_tmp (result , ZEND_FETCH_CONSTANT , NULL , & const_node );
58425872
58435873 zend_set_class_name_op1 (opline , & class_node );
@@ -5877,8 +5907,8 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast) /* {{{ */
58775907 ZVAL_STR_COPY (& result -> u .constant , CG (active_class_entry )-> name );
58785908 }
58795909 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 :
58825912 if (!CG (active_class_entry )) {
58835913 zend_error_noreturn (E_COMPILE_ERROR ,
58845914 "Cannot access %s::class when no class scope is active" ,
@@ -6555,6 +6585,30 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
65556585 zend_string_release (resolved_name );
65566586 break ;
65576587 }
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+
65586612 default :
65596613 return ;
65606614 }
0 commit comments