@@ -787,6 +787,96 @@ static void zend_do_free(znode *op1) /* {{{ */
787
787
}
788
788
/* }}} */
789
789
790
+
791
+ static char * zend_modifier_token_to_string (uint32_t token )
792
+ {
793
+ switch (token ) {
794
+ case T_PUBLIC :
795
+ return "public" ;
796
+ case T_PROTECTED :
797
+ return "protected" ;
798
+ case T_PRIVATE :
799
+ return "private" ;
800
+ case T_STATIC :
801
+ return "static" ;
802
+ case T_FINAL :
803
+ return "final" ;
804
+ case T_READONLY :
805
+ return "readonly" ;
806
+ case T_ABSTRACT :
807
+ return "abstract" ;
808
+ EMPTY_SWITCH_DEFAULT_CASE ()
809
+ }
810
+ }
811
+
812
+ uint32_t zend_modifier_token_to_flag (zend_modifier_target target , uint32_t token )
813
+ {
814
+ switch (token ) {
815
+ case T_PUBLIC :
816
+ return ZEND_ACC_PUBLIC ;
817
+ case T_PROTECTED :
818
+ return ZEND_ACC_PROTECTED ;
819
+ case T_PRIVATE :
820
+ return ZEND_ACC_PRIVATE ;
821
+ case T_READONLY :
822
+ if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP ) {
823
+ return ZEND_ACC_READONLY ;
824
+ }
825
+ break ;
826
+ case T_ABSTRACT :
827
+ if (target == ZEND_MODIFIER_TARGET_METHOD ) {
828
+ return ZEND_ACC_ABSTRACT ;
829
+ }
830
+ break ;
831
+ case T_FINAL :
832
+ if (target == ZEND_MODIFIER_TARGET_METHOD || target == ZEND_MODIFIER_TARGET_CONSTANT ) {
833
+ return ZEND_ACC_FINAL ;
834
+ }
835
+ break ;
836
+ case T_STATIC :
837
+ if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_METHOD ) {
838
+ return ZEND_ACC_STATIC ;
839
+ }
840
+ break ;
841
+ }
842
+
843
+ char * member ;
844
+ if (target == ZEND_MODIFIER_TARGET_PROPERTY ) {
845
+ member = "property" ;
846
+ } else if (target == ZEND_MODIFIER_TARGET_METHOD ) {
847
+ member = "method" ;
848
+ } else if (target == ZEND_MODIFIER_TARGET_CONSTANT ) {
849
+ member = "class constant" ;
850
+ } else if (target == ZEND_MODIFIER_TARGET_CPP ) {
851
+ member = "promoted property" ;
852
+ } else {
853
+ ZEND_UNREACHABLE ();
854
+ }
855
+
856
+ zend_throw_exception_ex (zend_ce_compile_error , 0 ,
857
+ "Cannot use the %s modifier on a %s" , zend_modifier_token_to_string (token ), member );
858
+ return 0 ;
859
+ }
860
+
861
+ uint32_t zend_modifier_list_to_flags (zend_modifier_target target , zend_ast * modifiers )
862
+ {
863
+ uint32_t flags = 0 ;
864
+ zend_ast_list * modifier_list = zend_ast_get_list (modifiers );
865
+
866
+ for (uint32_t i = 0 ; i < modifier_list -> children ; i ++ ) {
867
+ uint32_t new_flag = zend_modifier_token_to_flag (target , (uint32_t ) Z_LVAL_P (zend_ast_get_zval (modifier_list -> child [i ])));
868
+ if (!new_flag ) {
869
+ return 0 ;
870
+ }
871
+ flags = zend_add_member_modifier (flags , new_flag , target );
872
+ if (!flags ) {
873
+ return 0 ;
874
+ }
875
+ }
876
+
877
+ return flags ;
878
+ }
879
+
790
880
uint32_t zend_add_class_modifier (uint32_t flags , uint32_t new_flag ) /* {{{ */
791
881
{
792
882
uint32_t new_flags = flags | new_flag ;
@@ -812,7 +902,7 @@ uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
812
902
}
813
903
/* }}} */
814
904
815
- uint32_t zend_add_member_modifier (uint32_t flags , uint32_t new_flag ) /* {{{ */
905
+ uint32_t zend_add_member_modifier (uint32_t flags , uint32_t new_flag , zend_modifier_target target ) /* {{{ */
816
906
{
817
907
uint32_t new_flags = flags | new_flag ;
818
908
if ((flags & ZEND_ACC_PPP_MASK ) && (new_flag & ZEND_ACC_PPP_MASK )) {
@@ -837,9 +927,9 @@ uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
837
927
"Multiple readonly modifiers are not allowed" , 0 );
838
928
return 0 ;
839
929
}
840
- if ((new_flags & ZEND_ACC_ABSTRACT ) && (new_flags & ZEND_ACC_FINAL )) {
930
+ if (target == ZEND_MODIFIER_TARGET_METHOD && (new_flags & ZEND_ACC_ABSTRACT ) && (new_flags & ZEND_ACC_FINAL )) {
841
931
zend_throw_exception (zend_ce_compile_error ,
842
- "Cannot use the final modifier on an abstract class member " , 0 );
932
+ "Cannot use the final modifier on an abstract method " , 0 );
843
933
return 0 ;
844
934
}
845
935
return new_flags ;
@@ -7474,10 +7564,6 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f
7474
7564
zend_error_noreturn (E_COMPILE_ERROR , "Enum %s cannot include properties" , ZSTR_VAL (ce -> name ));
7475
7565
}
7476
7566
7477
- if (flags & ZEND_ACC_ABSTRACT ) {
7478
- zend_error_noreturn (E_COMPILE_ERROR , "Properties cannot be declared abstract" );
7479
- }
7480
-
7481
7567
for (i = 0 ; i < children ; ++ i ) {
7482
7568
zend_property_info * info ;
7483
7569
zend_ast * prop_ast = list -> child [i ];
@@ -7505,12 +7591,6 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f
7505
7591
doc_comment = zend_string_copy (zend_ast_get_str (doc_comment_ast ));
7506
7592
}
7507
7593
7508
- if (flags & ZEND_ACC_FINAL ) {
7509
- zend_error_noreturn (E_COMPILE_ERROR , "Cannot declare property %s::$%s final, "
7510
- "the final modifier is allowed only for methods, classes, and class constants" ,
7511
- ZSTR_VAL (ce -> name ), ZSTR_VAL (name ));
7512
- }
7513
-
7514
7594
if (zend_hash_exists (& ce -> properties_info , name )) {
7515
7595
zend_error_noreturn (E_COMPILE_ERROR , "Cannot redeclare %s::$%s" ,
7516
7596
ZSTR_VAL (ce -> name ), ZSTR_VAL (name ));
@@ -7583,16 +7663,14 @@ static void zend_compile_prop_group(zend_ast *ast) /* {{{ */
7583
7663
}
7584
7664
/* }}} */
7585
7665
7586
- static void zend_check_const_and_trait_alias_attr (uint32_t attr , const char * entity ) /* {{{ */
7666
+ static void zend_check_trait_alias_modifiers (uint32_t attr ) /* {{{ */
7587
7667
{
7588
7668
if (attr & ZEND_ACC_STATIC ) {
7589
- zend_error_noreturn (E_COMPILE_ERROR , "Cannot use ' static' as %s modifier" , entity );
7669
+ zend_error_noreturn (E_COMPILE_ERROR , "Cannot use \" static\" as method modifier in trait alias" );
7590
7670
} else if (attr & ZEND_ACC_ABSTRACT ) {
7591
- zend_error_noreturn (E_COMPILE_ERROR , "Cannot use ' abstract' as %s modifier" , entity );
7671
+ zend_error_noreturn (E_COMPILE_ERROR , "Cannot use \" abstract\" as method modifier in trait alias" );
7592
7672
} else if (attr & ZEND_ACC_FINAL ) {
7593
- zend_error_noreturn (E_COMPILE_ERROR , "Cannot use 'final' as %s modifier" , entity );
7594
- } else if (attr & ZEND_ACC_READONLY ) {
7595
- zend_error_noreturn (E_COMPILE_ERROR , "Cannot use 'readonly' as %s modifier" , entity );
7673
+ zend_error_noreturn (E_COMPILE_ERROR , "Cannot use \"final\" as method modifier in trait alias" );
7596
7674
}
7597
7675
}
7598
7676
/* }}} */
@@ -7613,10 +7691,6 @@ static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_as
7613
7691
zend_string * doc_comment = doc_comment_ast ? zend_string_copy (zend_ast_get_str (doc_comment_ast )) : NULL ;
7614
7692
zval value_zv ;
7615
7693
7616
- if (UNEXPECTED (flags & (ZEND_ACC_STATIC |ZEND_ACC_ABSTRACT |ZEND_ACC_READONLY ))) {
7617
- zend_check_const_and_trait_alias_attr (flags , "constant" );
7618
- }
7619
-
7620
7694
if (UNEXPECTED ((flags & ZEND_ACC_PRIVATE ) && (flags & ZEND_ACC_FINAL ))) {
7621
7695
zend_error_noreturn (
7622
7696
E_COMPILE_ERROR , "Private constant %s::%s cannot be final as it is not visible to other classes" ,
@@ -7687,7 +7761,7 @@ static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */
7687
7761
7688
7762
zend_trait_alias * alias ;
7689
7763
7690
- zend_check_const_and_trait_alias_attr (modifiers , "method" );
7764
+ zend_check_trait_alias_modifiers (modifiers );
7691
7765
7692
7766
alias = emalloc (sizeof (zend_trait_alias ));
7693
7767
zend_compile_method_ref (method_ref_ast , & alias -> trait_method );
0 commit comments