Skip to content

Commit f48c232

Browse files
Guilherme BlancoJulien Pauli
authored andcommitted
Decoupled class declaration statement into more granular pieces.
1 parent 63346f4 commit f48c232

File tree

5 files changed

+70
-21
lines changed

5 files changed

+70
-21
lines changed

Zend/tests/access_modifiers_003.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ final final class test {
1010
echo "Done\n";
1111
?>
1212
--EXPECTF--
13-
Parse error: %s error,%sexpecting %s in %s on line %d
13+
Fatal error: Multiple final modifiers are not allowed in %s on line %d

Zend/tests/access_modifiers_013.phpt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Prevent abstract and final in the same class declaration
3+
--FILE--
4+
<?php
5+
6+
final abstract class C {
7+
private function priv() { }
8+
}
9+
10+
?>
11+
--EXPECTF--
12+
Fatal error: Cannot use the final modifier on an abstract class in %s on line %d

Zend/zend_compile.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,22 @@ void zend_do_free(znode *op1) /* {{{ */
540540
}
541541
/* }}} */
542542

543+
uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
544+
{
545+
uint32_t new_flags = flags | new_flag;
546+
if ((flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flag & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
547+
zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
548+
}
549+
if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
550+
zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
551+
}
552+
if ((new_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flags & ZEND_ACC_FINAL)) {
553+
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class");
554+
}
555+
return new_flags;
556+
}
557+
/* }}} */
558+
543559
uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
544560
{
545561
uint32_t new_flags = flags | new_flag;

Zend/zend_compile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,7 @@ ZEND_API binary_op_type get_binary_op(int opcode);
632632
void zend_stop_lexing(void);
633633
void zend_emit_final_return(zval *zv);
634634
zend_ast *zend_ast_append_str(zend_ast *left, zend_ast *right);
635+
uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag);
635636
uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag);
636637
zend_ast *zend_ast_append_doc_comment(zend_ast *list);
637638
void zend_handle_encoding_declaration(zend_ast *ast);

Zend/zend_language_parser.y

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,9 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
228228
%token T_POW_EQUAL "**= (T_POW_EQUAL)"
229229

230230
%type <ast> top_statement namespace_name name statement function_declaration_statement
231-
%type <ast> class_declaration_statement use_declaration const_decl inner_statement
231+
%type <ast> class_declaration_statement trait_declaration_statement
232+
%type <ast> interface_declaration_statement interface_extends_list
233+
%type <ast> use_declaration const_decl inner_statement
232234
%type <ast> expr optional_expr while_statement for_statement foreach_variable
233235
%type <ast> foreach_statement declare_statement finally_statement unset_variable variable
234236
%type <ast> extends_from parameter optional_type argument expr_without_variable global_var
@@ -243,15 +245,16 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
243245
%type <ast> top_statement_list use_declarations const_list inner_statement_list if_stmt
244246
%type <ast> alt_if_stmt for_exprs switch_case_list global_var_list static_var_list
245247
%type <ast> echo_expr_list unset_variables catch_list parameter_list class_statement_list
246-
%type <ast> implements_list interface_extends_list case_list if_stmt_without_else
248+
%type <ast> implements_list case_list if_stmt_without_else
247249
%type <ast> non_empty_parameter_list argument_list non_empty_argument_list property_list
248250
%type <ast> class_const_list name_list trait_adaptations method_body non_empty_for_exprs
249251
%type <ast> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars
250252
%type <ast> lexical_var_list encaps_list array_pair_list non_empty_array_pair_list
251253
%type <ast> assignment_list
252254

253-
%type <num> returns_ref function is_reference is_variadic class_type variable_modifiers
255+
%type <num> returns_ref function is_reference is_variadic variable_modifiers
254256
%type <num> method_modifiers trait_modifiers non_empty_member_modifiers member_modifier
257+
%type <num> class_modifiers class_modifier
255258

256259
%type <str> backup_doc_comment
257260

@@ -278,9 +281,11 @@ name:
278281
;
279282

280283
top_statement:
281-
statement { $$ = $1; }
282-
| function_declaration_statement { $$ = $1; }
283-
| class_declaration_statement { $$ = $1; }
284+
statement { $$ = $1; }
285+
| function_declaration_statement { $$ = $1; }
286+
| class_declaration_statement { $$ = $1; }
287+
| trait_declaration_statement { $$ = $1; }
288+
| interface_declaration_statement { $$ = $1; }
284289
| T_HALT_COMPILER '(' ')' ';'
285290
{ $$ = zend_ast_create(ZEND_AST_HALT_COMPILER,
286291
zend_ast_create_zval_from_long(zend_get_scanned_file_offset()));
@@ -333,8 +338,10 @@ inner_statement_list:
333338

334339
inner_statement:
335340
statement { $$ = $1; }
336-
| function_declaration_statement { $$ = $1; }
337-
| class_declaration_statement { $$ = $1; }
341+
| function_declaration_statement { $$ = $1; }
342+
| class_declaration_statement { $$ = $1; }
343+
| trait_declaration_statement { $$ = $1; }
344+
| interface_declaration_statement { $$ = $1; }
338345
| T_HALT_COMPILER '(' ')' ';'
339346
{ $$ = NULL; zend_error_noreturn(E_COMPILE_ERROR,
340347
"__HALT_COMPILER() can only be used from the outermost scope"); }
@@ -418,21 +425,34 @@ is_variadic:
418425
;
419426

420427
class_declaration_statement:
421-
class_type { $<num>$ = CG(zend_lineno); }
428+
class_modifiers T_CLASS { $<num>$ = CG(zend_lineno); }
422429
T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}'
423-
{ $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $<num>2, $6,
424-
zend_ast_get_str($3), $4, $5, $8); }
425-
| T_INTERFACE { $<num>$ = CG(zend_lineno); }
426-
T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}'
427-
{ $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $<num>2, $5,
428-
zend_ast_get_str($3), NULL, $4, $7); }
430+
{ $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $<num>3, $7, zend_ast_get_str($4), $5, $6, $9); }
431+
| T_CLASS { $<num>$ = CG(zend_lineno); }
432+
T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}'
433+
{ $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $<num>2, $6, zend_ast_get_str($3), $4, $5, $8); }
434+
;
435+
436+
class_modifiers:
437+
class_modifier { $$ = $1; }
438+
| class_modifiers class_modifier { $$ = zend_add_class_modifier($1, $2); }
439+
;
440+
441+
class_modifier:
442+
T_ABSTRACT { $$ = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; }
443+
| T_FINAL { $$ = ZEND_ACC_FINAL; }
429444
;
430445

431-
class_type:
432-
T_CLASS { $$ = 0; }
433-
| T_ABSTRACT T_CLASS { $$ = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; }
434-
| T_FINAL T_CLASS { $$ = ZEND_ACC_FINAL; }
435-
| T_TRAIT { $$ = ZEND_ACC_TRAIT; }
446+
trait_declaration_statement:
447+
T_TRAIT { $<num>$ = CG(zend_lineno); }
448+
T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}'
449+
{ $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_TRAIT, $<num>2, $6, zend_ast_get_str($3), $4, $5, $8); }
450+
;
451+
452+
interface_declaration_statement:
453+
T_INTERFACE { $<num>$ = CG(zend_lineno); }
454+
T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}'
455+
{ $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $<num>2, $5, zend_ast_get_str($3), NULL, $4, $7); }
436456
;
437457

438458
extends_from:

0 commit comments

Comments
 (0)