Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix syntax error when using readonly with dnf #9512

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Zend/tests/gh9500.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
Bug GH-9500: Disjunctive Normal Form Types - readonly property followed by (
--FILE--
<?php
class Dnf
{
var A|(B&C) $a;
var (B&C)|A $b;
private A|(B&C) $c;
private (B&C)|A $d;
static A|(B&C) $e;
static (B&C)|A $f;
private static A|(B&C) $g;
private static (B&C)|A $h;
readonly private A|(B&C) $i;
readonly private (B&C)|A $j;
readonly A|(B&C) $k;
readonly (B&C)|A $l;
private readonly A|(B&C) $m;
private readonly (B&C)|A $n;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<?php

class A
{
    readonly static (A&B)|C $b; // valid
    static readonly (A&B)|C $a; // invalid
}

these more simple static forms are not in the test, I haven't tested it on this PR, but just to let you know :)

?>
DONE
--EXPECT--
DONE
28 changes: 26 additions & 2 deletions Zend/tests/readonly_function.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,34 @@ function readonly() {
echo "Hi!\n";
}

class A {
const readonly = 'Const hi!';

static function readonly() {
echo "Static hi!\n";
}
}

class B {
public $readonly = 'Prop hi!';

function readonly() {
echo "Instance hi!\n";
}
}

$b = new B();

readonly();
readonly ();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does using readonly () with the whitespace now break? Or is it unnecessary due to the move to the parser?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just unnecessary since this is no longer special-cased. This should still work. I can keep it if you prefer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No harm keeping it then :)

echo A::readonly, "\n";
A::readonly();
$b->readonly();
echo $b->readonly, "\n";

?>
--EXPECT--
Hi!
Hi!
Const hi!
Static hi!
Instance hi!
Prop hi!
17 changes: 16 additions & 1 deletion Zend/zend_language_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%type <ast> attribute_decl attribute attributes attribute_group namespace_declaration_name
%type <ast> match match_arm_list non_empty_match_arm_list match_arm match_arm_cond_list
%type <ast> enum_declaration_statement enum_backing_type enum_case enum_case_expr
%type <ast> function_name

%type <num> returns_ref function fn is_reference is_variadic variable_modifiers
%type <num> method_modifiers non_empty_member_modifiers member_modifier
Expand Down Expand Up @@ -560,8 +561,17 @@ unset_variable:
variable { $$ = zend_ast_create(ZEND_AST_UNSET, $1); }
;

function_name:
T_STRING { $$ = $1; }
| T_READONLY {
zval zv;
if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; }
$$ = zend_ast_create_zval(&zv);
}
;

function_declaration_statement:
function returns_ref T_STRING backup_doc_comment '(' parameter_list ')' return_type
function returns_ref function_name backup_doc_comment '(' parameter_list ')' return_type
backup_fn_flags '{' inner_statement_list '}' backup_fn_flags
{ $$ = zend_ast_create_decl(ZEND_AST_FUNC_DECL, $2 | $13, $1, $4,
zend_ast_get_str($3), $6, NULL, $11, $8, NULL); CG(extra_fn_flags) = $9; }
Expand Down Expand Up @@ -1270,6 +1280,11 @@ lexical_var:
function_call:
name argument_list
{ $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); }
| T_READONLY argument_list {
zval zv;
if (zend_lex_tstring(&zv, $1) == FAILURE) { YYABORT; }
$$ = zend_ast_create(ZEND_AST_CALL, zend_ast_create_zval(&zv), $2);
}
| class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
{ $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); }
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
Expand Down
6 changes: 0 additions & 6 deletions Zend/zend_language_scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -1729,12 +1729,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
RETURN_TOKEN_WITH_IDENT(T_READONLY);
}

/* Don't treat "readonly(" as a keyword, to allow using it as a function name. */
<ST_IN_SCRIPTING>"readonly"[ \n\r\t]*"(" {
yyless(strlen("readonly"));
RETURN_TOKEN_WITH_STR(T_STRING, 0);
}

<ST_IN_SCRIPTING>"unset" {
RETURN_TOKEN_WITH_IDENT(T_UNSET);
}
Expand Down