diff options
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/zend_compile.c | 28 | ||||
-rw-r--r-- | Zend/zend_compile.h | 2 | ||||
-rw-r--r-- | Zend/zend_language_parser.y | 23 |
3 files changed, 37 insertions, 16 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d273ed9870..c25b64bef6 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -367,13 +367,24 @@ void zend_do_echo(znode *arg TSRMLS_DC) SET_UNUSED(opline->op2); } -void zend_do_abstract_method(TSRMLS_D) +void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body TSRMLS_DC) { - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + if (modifiers->u.constant.value.lval & ZEND_ACC_ABSTRACT) { + if (body->u.constant.value.lval & ZEND_ACC_ABSTRACT) { + zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_RAISE_ABSTRACT_ERROR; - SET_UNUSED(opline->op1); - SET_UNUSED(opline->op2); + opline->opcode = ZEND_RAISE_ABSTRACT_ERROR; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + } else { + /* we had code in the function body */ + zend_error(E_COMPILE_ERROR, "Abstract function %s() cannot contain body", function_name->u.constant.value.str.val); + } + } else { + if (body->u.constant.value.lval & ZEND_ACC_ABSTRACT) { + zend_error(E_COMPILE_ERROR, "Non-abstract method %s() must contain body", function_name->u.constant.value.str.val); + } + } } @@ -899,7 +910,8 @@ void zend_do_free(znode *op1 TSRMLS_DC) int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier) { - if ((new_modifier->u.constant.value.lval & ZEND_ACC_PPP_MASK) + if ((current_access_type->u.constant.value.lval & ZEND_ACC_PPP_MASK) + && (new_modifier->u.constant.value.lval & ZEND_ACC_PPP_MASK) && ((current_access_type->u.constant.value.lval & ZEND_ACC_PPP_MASK) != (new_modifier->u.constant.value.lval & ZEND_ACC_PPP_MASK))) { zend_error(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed"); } @@ -2180,6 +2192,10 @@ void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_ty zend_property_info *existing_property_info; HashTable *target_symbol_table; + if (access_type & ZEND_ACC_ABSTRACT) { + zend_error(E_COMPILE_ERROR, "Properties cannot be declared abstract"); + } + if (zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &existing_property_info)==SUCCESS) { if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) { zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 5e16be77da..ec82fe727a 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -421,7 +421,7 @@ void zend_do_begin_import(TSRMLS_D); void zend_do_import(int type, znode *what TSRMLS_DC); void zend_do_end_import(znode *import_from TSRMLS_DC); -void zend_do_abstract_method(TSRMLS_D); +void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body TSRMLS_DC); ZEND_API void function_add_ref(zend_function *function); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 2310a655af..4dc5ba8b68 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -445,32 +445,37 @@ class_statement: variable_modifiers { CG(access_type) = $1.u.constant.value.lval; } class_variable_declaration ';' | class_constant_declaration ';' | method_modifiers T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, $1.u.constant.value.lval TSRMLS_CC); } '(' - parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); } - | T_ABSTRACT method_modifiers T_FUNCTION { $3.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$3, &$6, 1, $5.op_type, $2.u.constant.value.lval | ZEND_ACC_ABSTRACT TSRMLS_CC); } '(' - parameter_list ')' { zend_do_abstract_method(TSRMLS_C); zend_do_end_function_declaration(&$3 TSRMLS_CC); } ';' + parameter_list ')' method_body { zend_do_abstract_method(&$5, &$1, &$10 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); } | T_CLASS T_STRING extends_from '{' { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); } ; + +method_body: + ';' /* abstract method */ { $$.u.constant.value.lval = ZEND_ACC_ABSTRACT; } + | '{' inner_statement_list '}' { $$.u.constant.value.lval = 0; } +; + variable_modifiers: - non_empty_access_modifiers { $$ = $1; } + non_empty_member_modifiers { $$ = $1; } | T_VAR { $$.u.constant.value.lval = ZEND_ACC_PUBLIC; } ; method_modifiers: /* empty */ { $$.u.constant.value.lval = ZEND_ACC_PUBLIC; } - | non_empty_access_modifiers { $$ = $1; if (!($$.u.constant.value.lval & ZEND_ACC_PPP_MASK)) { $$.u.constant.value.lval |= ZEND_ACC_PUBLIC; } } + | non_empty_member_modifiers { $$ = $1; if (!($$.u.constant.value.lval & ZEND_ACC_PPP_MASK)) { $$.u.constant.value.lval |= ZEND_ACC_PUBLIC; } } ; -non_empty_access_modifiers: - access_modifier { $$ = $1; } - | non_empty_access_modifiers access_modifier { $$.u.constant.value.lval = zend_do_verify_access_types(&$1, &$2); } +non_empty_member_modifiers: + member_modifier { $$ = $1; } + | non_empty_member_modifiers member_modifier { $$.u.constant.value.lval = zend_do_verify_access_types(&$1, &$2); } ; -access_modifier: +member_modifier: T_PUBLIC { $$.u.constant.value.lval = ZEND_ACC_PUBLIC; } | T_PROTECTED { $$.u.constant.value.lval = ZEND_ACC_PROTECTED; } | T_PRIVATE { $$.u.constant.value.lval = ZEND_ACC_PRIVATE; } | T_STATIC { $$.u.constant.value.lval = ZEND_ACC_STATIC; } + | T_ABSTRACT { $$.u.constant.value.lval = ZEND_ACC_ABSTRACT; } ; class_variable_declaration: |