summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend_compile.c28
-rw-r--r--Zend/zend_compile.h2
-rw-r--r--Zend/zend_language_parser.y23
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: