Created
November 21, 2014 17:56
-
-
Save Tyrael/2bfa66efbef585ddf9c6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c | |
index d15b85f..03d677a 100644 | |
--- a/Zend/zend_compile.c | |
+++ b/Zend/zend_compile.c | |
@@ -549,6 +549,25 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */ | |
} | |
/* }}} */ | |
+uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */ | |
+{ | |
+ uint32_t new_flags = flags | new_flag; | |
+ if ((flags & ZEND_ACC_PPP_MASK) && (new_flag & ZEND_ACC_PPP_MASK)) { | |
+ zend_error_noreturn(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed"); | |
+ } | |
+ if ((flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flag & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { | |
+ zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed"); | |
+ } | |
+ if ((flags & ZEND_ACC_FINAL_CLASS) && (new_flag & ZEND_ACC_FINAL_CLASS)) { | |
+ zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed"); | |
+ } | |
+ if (((new_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) || (new_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) && (new_flags & ZEND_ACC_FINAL_CLASS)) { | |
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class"); | |
+ } | |
+ return new_flags; | |
+} | |
+/* }}} */ | |
+ | |
uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */ | |
{ | |
uint32_t new_flags = flags | new_flag; | |
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h | |
index f9a66a3..b8ad51d 100644 | |
--- a/Zend/zend_compile.h | |
+++ b/Zend/zend_compile.h | |
@@ -162,7 +162,7 @@ typedef struct _zend_try_catch_element { | |
#define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS 0x20 | |
#define ZEND_ACC_FINAL_CLASS 0x40 | |
#define ZEND_ACC_INTERFACE 0x80 | |
-#define ZEND_ACC_TRAIT 0x120 | |
+#define ZEND_ACC_TRAIT 0x10000 | |
/* method flags (visibility) */ | |
/* The order of those must be kept - public < protected < private */ | |
@@ -454,6 +454,7 @@ ZEND_API binary_op_type get_binary_op(int opcode); | |
void zend_stop_lexing(TSRMLS_D); | |
void zend_emit_final_return(zval *zv TSRMLS_DC); | |
zend_ast *zend_ast_append_str(zend_ast *left, zend_ast *right); | |
+uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag); | |
uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag); | |
zend_ast *zend_ast_append_doc_comment(zend_ast *list TSRMLS_DC); | |
void zend_handle_encoding_declaration(zend_ast *ast TSRMLS_DC); | |
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y | |
index 8828620..d878ed3 100644 | |
--- a/Zend/zend_language_parser.y | |
+++ b/Zend/zend_language_parser.y | |
@@ -255,7 +255,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); | |
%type <ast> assignment_list | |
%type <num> returns_ref function is_reference is_variadic class_type variable_modifiers | |
-%type <num> method_modifiers trait_modifiers non_empty_member_modifiers member_modifier | |
+%type <num> method_modifiers non_empty_member_modifiers member_modifier | |
+%type <num> class_modifiers trait_modifiers non_empty_class_modifiers class_modifier | |
%type <str> backup_doc_comment | |
@@ -422,20 +423,38 @@ is_variadic: | |
; | |
class_declaration_statement: | |
- class_type { $<num>$ = CG(zend_lineno); } | |
+ class_modifiers class_type { $<num>$ = CG(zend_lineno); } | |
T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}' | |
- { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $<num>2, $6, | |
- zend_ast_get_str($3), $4, $5, $8); } | |
- | T_INTERFACE { $<num>$ = CG(zend_lineno); } | |
+ { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $2 | $1, $<num>3, $7, | |
+ zend_ast_get_str($4), $5, $6, $9); } | |
+ | class_modifiers T_INTERFACE { $<num>$ = CG(zend_lineno); } | |
T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}' | |
- { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $<num>2, $5, | |
- zend_ast_get_str($3), NULL, $4, $7); } | |
+ { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE | $1, $<num>3, $6, | |
+ zend_ast_get_str($4), NULL, $5, $8); } | |
+; | |
+ | |
+class_modifiers: | |
+ /* empty */ { $$ = ZEND_ACC_PUBLIC; } | |
+ | non_empty_class_modifiers | |
+ { $$ = $1; if (!($$ & ZEND_ACC_PPP_MASK)) { $$ |= ZEND_ACC_PUBLIC; } } | |
+; | |
+ | |
+non_empty_class_modifiers: | |
+ class_modifier { $$ = $1; } | |
+ | non_empty_class_modifiers class_modifier | |
+ { $$ = zend_add_class_modifier($1, $2); } | |
+; | |
+ | |
+class_modifier: | |
+ T_PUBLIC { $$ = ZEND_ACC_PUBLIC; } | |
+ | T_PROTECTED { $$ = ZEND_ACC_PROTECTED; } | |
+ | T_PRIVATE { $$ = ZEND_ACC_PRIVATE; } | |
+ | T_ABSTRACT { $$ = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } | |
+ | T_FINAL { $$ = ZEND_ACC_FINAL_CLASS; } | |
; | |
class_type: | |
T_CLASS { $$ = 0; } | |
- | T_ABSTRACT T_CLASS { $$ = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } | |
- | T_FINAL T_CLASS { $$ = ZEND_ACC_FINAL_CLASS; } | |
| T_TRAIT { $$ = ZEND_ACC_TRAIT; } | |
; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment