Skip to content

Commit c230aa9

Browse files
committed
Correctly handle multiple constants in typed declaration
While here also fix AST printing support.
1 parent 03b163b commit c230aa9

6 files changed

+52
-16
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
AST printing support for typed constants
3+
--FILE--
4+
<?php
5+
6+
try {
7+
assert(false && new class {
8+
public const int X = 1;
9+
});
10+
} catch (AssertionError $e) {
11+
echo $e->getMessage(), "\n";
12+
}
13+
14+
?>
15+
--EXPECT--
16+
assert(false && new class {
17+
public const int X = 1;
18+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Multiple typed constants in one declaration
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public const int X = 1, Y = "foo";
8+
}
9+
10+
?>
11+
--EXPECTF--
12+
Fatal error: Cannot use string as value for class constant Test::Y of type int in %s on line %d

Zend/zend_ast.c

+4
Original file line numberDiff line numberDiff line change
@@ -1924,6 +1924,10 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
19241924

19251925
zend_ast_export_visibility(str, ast->attr);
19261926
smart_str_appends(str, "const ");
1927+
if (ast->child[2]) {
1928+
zend_ast_export_type(str, ast->child[2], indent);
1929+
smart_str_appendc(str, ' ');
1930+
}
19271931

19281932
ast = ast->child[0];
19291933

Zend/zend_ast.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ enum _zend_ast_kind {
145145
ZEND_AST_USE_ELEM,
146146
ZEND_AST_TRAIT_ALIAS,
147147
ZEND_AST_GROUP_USE,
148-
ZEND_AST_CLASS_CONST_GROUP,
149148
ZEND_AST_ATTRIBUTE,
150149
ZEND_AST_MATCH,
151150
ZEND_AST_MATCH_ARM,
@@ -161,6 +160,8 @@ enum _zend_ast_kind {
161160
ZEND_AST_CATCH,
162161
ZEND_AST_PROP_GROUP,
163162
ZEND_AST_PROP_ELEM,
163+
ZEND_AST_CONST_ELEM,
164+
ZEND_AST_CLASS_CONST_GROUP,
164165

165166
// Pseudo node for initializing enums
166167
ZEND_AST_CONST_ENUM_INIT,
@@ -169,7 +170,6 @@ enum _zend_ast_kind {
169170
ZEND_AST_FOR = 4 << ZEND_AST_NUM_CHILDREN_SHIFT,
170171
ZEND_AST_FOREACH,
171172
ZEND_AST_ENUM_CASE,
172-
ZEND_AST_CONST_ELEM,
173173

174174
/* 5 child nodes */
175175
ZEND_AST_PARAM = 5 << ZEND_AST_NUM_CHILDREN_SHIFT,

Zend/zend_compile.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -7693,7 +7693,7 @@ static void zend_check_trait_alias_modifiers(uint32_t attr) /* {{{ */
76937693
}
76947694
/* }}} */
76957695

7696-
static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_ast *attr_ast)
7696+
static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_ast *attr_ast, zend_ast *type_ast)
76977697
{
76987698
zend_ast_list *list = zend_ast_get_list(ast);
76997699
zend_class_entry *ce = CG(active_class_entry);
@@ -7705,7 +7705,6 @@ static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_as
77057705
zend_ast *name_ast = const_ast->child[0];
77067706
zend_ast **value_ast_ptr = &const_ast->child[1];
77077707
zend_ast *doc_comment_ast = const_ast->child[2];
7708-
zend_ast *type_ast = const_ast->child[3];
77097708
zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast));
77107709
zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
77117710
zval value_zv;
@@ -7752,8 +7751,9 @@ static void zend_compile_class_const_group(zend_ast *ast) /* {{{ */
77527751
{
77537752
zend_ast *const_ast = ast->child[0];
77547753
zend_ast *attr_ast = ast->child[1];
7754+
zend_ast *type_ast = ast->child[2];
77557755

7756-
zend_compile_class_const_decl(const_ast, ast->attr, attr_ast);
7756+
zend_compile_class_const_decl(const_ast, ast->attr, attr_ast, type_ast);
77577757
}
77587758
/* }}} */
77597759

Zend/zend_language_parser.y

+13-11
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
267267
%type <ast> echo_expr_list unset_variables catch_name_list catch_list optional_variable parameter_list class_statement_list
268268
%type <ast> implements_list case_list if_stmt_without_else
269269
%type <ast> non_empty_parameter_list argument_list non_empty_argument_list property_list
270-
%type <ast> class_const_list first_class_const_decl class_const_decl class_name_list trait_adaptations method_body non_empty_for_exprs
270+
%type <ast> class_const_list class_const_decl class_name_list trait_adaptations method_body non_empty_for_exprs
271271
%type <ast> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars
272272
%type <ast> lexical_var_list encaps_list
273273
%type <ast> array_pair non_empty_array_pair_list array_pair_list possible_array_pair
@@ -940,7 +940,10 @@ attributed_class_statement:
940940
{ $$ = zend_ast_create(ZEND_AST_PROP_GROUP, $2, $3, NULL);
941941
$$->attr = $1; }
942942
| class_const_modifiers T_CONST class_const_list ';'
943-
{ $$ = zend_ast_create(ZEND_AST_CLASS_CONST_GROUP, $3, NULL);
943+
{ $$ = zend_ast_create(ZEND_AST_CLASS_CONST_GROUP, $3, NULL, NULL);
944+
$$->attr = $1; }
945+
| class_const_modifiers T_CONST type_expr class_const_list ';'
946+
{ $$ = zend_ast_create(ZEND_AST_CLASS_CONST_GROUP, $4, NULL, $3);
944947
$$->attr = $1; }
945948
| method_modifiers function returns_ref identifier backup_doc_comment '(' parameter_list ')'
946949
return_type backup_fn_flags method_body backup_fn_flags
@@ -1076,21 +1079,20 @@ property:
10761079

10771080
class_const_list:
10781081
class_const_list ',' class_const_decl { $$ = zend_ast_list_add($1, $3); }
1079-
| first_class_const_decl { $$ = zend_ast_create_list(1, ZEND_AST_CLASS_CONST_DECL, $1); }
1080-
;
1081-
1082-
first_class_const_decl:
1083-
T_STRING '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL), NULL); }
1084-
| semi_reserved '=' expr backup_doc_comment { zval zv; if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; } $$ = zend_ast_create(ZEND_AST_CONST_ELEM, zend_ast_create_zval(&zv), $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL), NULL); }
1085-
| type_expr identifier '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $2, $4, ($5 ? zend_ast_create_zval_from_str($5) : NULL), $1); }
1082+
| class_const_decl { $$ = zend_ast_create_list(1, ZEND_AST_CLASS_CONST_DECL, $1); }
10861083
;
10871084

10881085
class_const_decl:
1089-
identifier '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL), NULL); }
1086+
T_STRING '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); }
1087+
| semi_reserved '=' expr backup_doc_comment {
1088+
zval zv;
1089+
if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; }
1090+
$$ = zend_ast_create(ZEND_AST_CONST_ELEM, zend_ast_create_zval(&zv), $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL));
1091+
}
10901092
;
10911093

10921094
const_decl:
1093-
T_STRING '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL), NULL); }
1095+
T_STRING '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); }
10941096
;
10951097

10961098
echo_expr_list:

0 commit comments

Comments
 (0)