@@ -107,6 +107,11 @@ static const char *class_flags[] = {
107107static const char * param_flags [] = {
108108 AST_FLAG (PARAM_REF ),
109109 AST_FLAG (PARAM_VARIADIC ),
110+ #if PHP_VERSION_ID >= 80000
111+ AST_FLAG (MODIFIER_PUBLIC ),
112+ AST_FLAG (MODIFIER_PROTECTED ),
113+ AST_FLAG (MODIFIER_PRIVATE ),
114+ #endif
110115 NULL
111116};
112117
@@ -287,6 +292,8 @@ static const ast_flag_info flag_info[] = {
287292 { ZEND_AST_CONDITIONAL , 1 , conditional_flags },
288293};
289294
295+ // NOTE(tandre) in php 8, to get a writeable pointer to a property, OBJ_PROP_NUM(AST_CACHE_SLOT_PROPNAME) can be used.
296+
290297static inline void ast_update_property (zval * object , zend_string * name , zval * value , void * * cache_slot ) {
291298#if PHP_VERSION_ID < 80000
292299 zval name_zv ;
@@ -339,6 +346,7 @@ static zend_ast *get_ast(zend_string *code, zend_arena **ast_arena, char *filena
339346 return ast ;
340347}
341348
349+ /* Returns whether node->attr (i.e. flags) is used by this node kind. Not to be confused with php 8.0's attributes. */
342350static inline zend_bool ast_kind_uses_attr (zend_ast_kind kind ) {
343351 return kind == ZEND_AST_PARAM || kind == ZEND_AST_TYPE || kind == ZEND_AST_TRAIT_ALIAS
344352 || kind == ZEND_AST_UNARY_OP || kind == ZEND_AST_BINARY_OP || kind == ZEND_AST_ASSIGN_OP
@@ -380,6 +388,9 @@ static inline zend_bool ast_is_name(zend_ast *ast, zend_ast *parent, uint32_t i)
380388 || parent -> kind == ZEND_AST_NEW || parent -> kind == ZEND_AST_STATIC_CALL
381389 || parent -> kind == ZEND_AST_CLASS_CONST || parent -> kind == ZEND_AST_STATIC_PROP
382390 || parent -> kind == ZEND_AST_PROP_GROUP || parent -> kind == ZEND_AST_CLASS_NAME
391+ #if PHP_VERSION_ID >= 80000
392+ || parent -> kind == ZEND_AST_ATTRIBUTE
393+ #endif
383394 ;
384395 }
385396
@@ -507,7 +518,11 @@ static inline zend_ast_attr ast_assign_op_to_binary_op(zend_ast_attr attr) {
507518static inline zend_ast * * ast_get_children (zend_ast * ast , uint32_t * count ) {
508519 if (ast_kind_is_decl (ast -> kind )) {
509520 zend_ast_decl * decl = (zend_ast_decl * ) ast ;
521+ #if PHP_VERSION_ID >= 80000
522+ * count = decl -> kind == ZEND_AST_CLASS ? 4 : 5 ;
523+ #else
510524 * count = decl -> kind == ZEND_AST_CLASS ? 3 : 4 ;
525+ #endif
511526 return decl -> child ;
512527 } else if (zend_ast_is_list (ast )) {
513528 zend_ast_list * list = zend_ast_get_list (ast );
@@ -622,14 +637,44 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t
622637 }
623638 }
624639
640+ #if PHP_VERSION_ID >= 80000
641+ if (state -> version < 80 ) {
642+ switch (ast_kind ) {
643+ case ZEND_AST_PARAM :
644+ if (i >= 3 ) {
645+ /* Skip attributes and doc comment */
646+ continue ;
647+ }
648+ break ;
649+ case ZEND_AST_METHOD :
650+ case ZEND_AST_FUNC_DECL :
651+ case ZEND_AST_CLOSURE :
652+ case ZEND_AST_ARROW_FUNC :
653+ if (i == 4 ) {
654+ continue ;
655+ }
656+ break ;
657+ case ZEND_AST_CLASS :
658+ if (i == 3 ) {
659+ continue ;
660+ }
661+ break ;
662+ case ZEND_AST_PROP_GROUP :
663+ if (i == 2 ) {
664+ continue ;
665+ }
666+ break ;
667+ }
668+ }
669+ #endif
625670 /* This AST_CATCH check should occur before ast_is_name() */
626671#if PHP_VERSION_ID < 70100
627672 if (ast_kind == ZEND_AST_CATCH && i == 0 ) {
628673 /* Emulate PHP 7.1 format (name list) */
629674 zval tmp ;
630675 ast_create_virtual_node (& tmp , AST_NAME , child -> attr , child , state );
631676 ast_create_virtual_node_ex (
632- & child_zv , ZEND_AST_NAME_LIST , 0 , zend_ast_get_lineno (child ), state , 1 , & tmp );
677+ & child_zv , ZEND_AST_NAME_LIST , 0 , zend_ast_get_lineno (child ), state , 1 , & tmp );
633678 } else
634679#endif
635680 if (ast_is_name (child , ast , i )) {
@@ -693,11 +738,35 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t
693738 zval tmp ;
694739 ZVAL_NULL (& tmp );
695740 zend_hash_add_new (ht , AST_STR (str_docComment ), & tmp );
741+ return ;
742+ }
743+ #endif
744+ #if PHP_VERSION_ID < 80000
745+ if (state -> version >= 80 ) {
746+ if (ast_kind == ZEND_AST_PARAM ) {
747+ zval tmp ;
748+ ZVAL_NULL (& tmp );
749+ zend_hash_add_new (ht , AST_STR (str_attributes ), & tmp );
750+ zend_hash_add_new (ht , AST_STR (str_docComment ), & tmp );
751+ return ;
752+ } else if (ast_kind == ZEND_AST_PROP_GROUP ) {
753+ zval tmp ;
754+ ZVAL_NULL (& tmp );
755+ zend_hash_add_new (ht , AST_STR (str_attributes ), & tmp );
756+ return ;
757+ }
696758 }
697759#endif
698760
699761 if (ast_kind_is_decl (ast_kind )) {
700762 zval id_zval ;
763+ #if PHP_VERSION_ID < 80000
764+ if (state -> version >= 80 ) {
765+ zval tmp ;
766+ ZVAL_NULL (& tmp );
767+ zend_hash_add_new (ht , AST_STR (str_attributes ), & tmp );
768+ }
769+ #endif
701770 ZVAL_LONG (& id_zval , state -> declIdCounter );
702771 state -> declIdCounter ++ ;
703772 zend_hash_add_new (ht , AST_STR (str___declId ), & id_zval );
@@ -755,6 +824,15 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) {
755824 ast -> kind = ZEND_AST_UNARY_OP ;
756825 ast -> attr = AST_MINUS ;
757826 break ;
827+ #if PHP_VERSION_ID >= 80000
828+ case ZEND_AST_CLASS_CONST_GROUP :
829+ // ast->child is [AST_CLASS_CONST_DECL, optional attributes_list]
830+ if (state -> version < 80 ) {
831+ // Keep class constants as a list of numerically indexed values in php 8
832+ ast_to_zval (zv , ast -> child [0 ], state );
833+ return ;
834+ }
835+ #endif
758836#if PHP_VERSION_ID >= 70400
759837 case ZEND_AST_PROP_GROUP :
760838 if (state -> version < 70 ) {
@@ -876,14 +954,32 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) {
876954#if PHP_VERSION_ID < 70400
877955 if (ast -> kind == ZEND_AST_PROP_DECL && state -> version >= 70 ) {
878956 zval type_zval ;
879- zval prop_group_zval = * zv ;
957+ zval prop_group_zval ;
958+ ZVAL_COPY_VALUE (& prop_group_zval , zv );
880959 ZVAL_NULL (& type_zval );
881960 // For version 70, create an AST_PROP_GROUP wrapping the created AST_PROP_DECL.
882- ast_create_virtual_node_ex (
883- zv , ZEND_AST_PROP_GROUP , ast -> attr , zend_ast_get_lineno (ast ), state , 2 , & type_zval , & prop_group_zval );
961+ if (state -> version >= 80 ) {
962+ // For version 80, add a null attributes node.
963+ ast_create_virtual_node_ex (
964+ zv , ZEND_AST_PROP_GROUP , ast -> attr , zend_ast_get_lineno (ast ), state , 3 , & type_zval , & prop_group_zval , & type_zval );
965+ } else {
966+ ast_create_virtual_node_ex (
967+ zv , ZEND_AST_PROP_GROUP , ast -> attr , zend_ast_get_lineno (ast ), state , 2 , & type_zval , & prop_group_zval );
968+ }
884969 ast_update_property_long (& prop_group_zval , AST_STR (str_flags ), 0 , AST_CACHE_SLOT_FLAGS );
885970 }
886971#endif
972+ #if PHP_VERSION_ID < 80000
973+ if (ast -> kind == ZEND_AST_CLASS_CONST_DECL && state -> version >= 80 ) {
974+ zval const_decl_zval ;
975+ zval attributes_zval ;
976+ ZVAL_COPY_VALUE (& const_decl_zval , zv );
977+ ZVAL_NULL (& attributes_zval );
978+ // For version 80, create an AST_CLASS_CONST_GROUP wrapping the created AST_CLASS_CONST_DECL
979+ ast_create_virtual_node_ex (
980+ zv , ZEND_AST_CLASS_CONST_GROUP , 0 , zend_ast_get_lineno (ast ), state , 2 , & const_decl_zval , & attributes_zval );
981+ }
982+ #endif
887983}
888984
889985static const zend_long versions [] = {50 , 60 , 70 , 80 };
0 commit comments