-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Added support for keywords for class/method/label/declare/namespace/class const names #438
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
Changes from 5 commits
18c78af
6c34181
5af2f2a
370d424
c7696de
f8687b0
b50dcce
0a36008
630e909
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
--TEST-- | ||
Basic keyword support | ||
--FILE-- | ||
<?php | ||
|
||
class return { | ||
const finally = 1; | ||
|
||
public $catch = 1; | ||
} | ||
|
||
class yield { | ||
public function __toString() { | ||
return 1; | ||
} | ||
|
||
public static function default () { | ||
} | ||
|
||
public function namespace () { | ||
} | ||
} | ||
|
||
yield::default(); | ||
|
||
switch (return::finally) { | ||
case (new return)->catch: | ||
case new yield: | ||
echo "O"; | ||
default: | ||
goto try; | ||
} | ||
echo "goto T_TRY failed"; | ||
try: | ||
|
||
(new yield)->namespace(); | ||
|
||
interface global {} | ||
|
||
class abstract extends namespace\yield implements \global { | ||
public function __construct (array $array, callable $call) { | ||
} | ||
} | ||
|
||
if (new abstract(["array_arg"], function () {})) { | ||
echo "k"; | ||
|
||
// Test if it doesn't throw a parse error. fatal error is normal. | ||
// inner_keyword | ||
interface function extends const, break, continue, goto, echo, throw, if, do, for, foreach, declare, instanceof, as, switch, print, class, interface, while, trait, extends, implements, new, clone, var, eval, include, require, use, insteadof, isset, empty, abstract, final, private, protected, public, unset, list, array, callable, or, and, xor {} | ||
|
||
// keyword | ||
$obj->elseif->endif->else->endwhile->endfor->endforeach->enddeclare->endswitch->case->exit; | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
Ok | ||
Fatal error: %s in %s on line %d |
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -201,6 +201,11 @@ void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */ | |
zend_stack_init(&CG(context_stack)); | ||
|
||
CG(encoding_declared) = 0; | ||
CG(tokenbufptr) = -1; | ||
CG(tokenbuffer) = emalloc(sizeof(token_buf) * ((CG(tokenbufsize) = ZEND_INIT_TOKEN_BUF_SIZE) + 1)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we need to be clever here. Why not just assign CG(tokenbufsize) = ZEND_INIT_TOKEN_BUF_SIZE separately? It would be much more readable. |
||
CG(tokenbuffer)++->token = 0; | ||
CG(tokenbuf_in_class) = -1; | ||
CG(tokenbuf_fn_decl) = -1; | ||
} | ||
/* }}} */ | ||
|
||
|
@@ -236,6 +241,7 @@ void shutdown_compiler(TSRMLS_D) /* {{{ */ | |
zend_hash_destroy(&CG(filenames_table)); | ||
zend_llist_destroy(&CG(open_files)); | ||
zend_stack_destroy(&CG(context_stack)); | ||
efree(--CG(tokenbuffer)); | ||
} | ||
/* }}} */ | ||
|
||
|
@@ -4943,9 +4949,13 @@ void zend_do_begin_class_declaration(const znode *class_token, znode *class_name | |
|
||
lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant)); | ||
|
||
if (!(strcmp(lcname, "self") && strcmp(lcname, "parent"))) { | ||
if (!(strcmp(lcname, "self") && strcmp(lcname, "parent") && strcmp(lcname, "static"))) { | ||
efree(lcname); | ||
zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", Z_STRVAL(class_name->u.constant)); | ||
if (parent_class_name) { | ||
zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", Z_STRVAL(class_name->u.constant)); | ||
} else { | ||
zend_error(E_COMPILE_ERROR, "Cannot use '%s' as interface name as it is reserved", Z_STRVAL(class_name->u.constant)); | ||
} | ||
} | ||
|
||
/* Class name must not conflict with import names */ | ||
|
@@ -6735,7 +6745,6 @@ int zendlex(znode *zendlval TSRMLS_DC) /* {{{ */ | |
} | ||
|
||
again: | ||
Z_TYPE(zendlval->u.constant) = IS_LONG; | ||
retval = lex_scan(&zendlval->u.constant TSRMLS_CC); | ||
switch (retval) { | ||
case T_COMMENT: | ||
|
@@ -6932,9 +6941,11 @@ void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC | |
if (name) { | ||
lcname = zend_str_tolower_dup(Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)); | ||
if (((Z_STRLEN(name->u.constant) == sizeof("self")-1) && | ||
!memcmp(lcname, "self", sizeof("self")-1)) || | ||
!memcmp(lcname, "self", sizeof("self")-1)) || | ||
((Z_STRLEN(name->u.constant) == sizeof("parent")-1) && | ||
!memcmp(lcname, "parent", sizeof("parent")-1))) { | ||
!memcmp(lcname, "parent", sizeof("parent")-1)) || | ||
((Z_STRLEN(name->u.constant) == sizeof("static")-1) && | ||
!memcmp(lcname, "static", sizeof("static")-1))) { | ||
zend_error(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant)); | ||
} | ||
efree(lcname); | ||
|
@@ -7002,9 +7013,11 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{ | |
lcname = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name)); | ||
|
||
if (((Z_STRLEN_P(name) == sizeof("self")-1) && | ||
!memcmp(lcname, "self", sizeof("self")-1)) || | ||
((Z_STRLEN_P(name) == sizeof("parent")-1) && | ||
!memcmp(lcname, "parent", sizeof("parent")-1))) { | ||
!memcmp(lcname, "self", sizeof("self")-1)) || | ||
((Z_STRLEN_P(name) == sizeof("parent")-1) && | ||
!memcmp(lcname, "parent", sizeof("parent")-1)) || | ||
((Z_STRLEN_P(name) == sizeof("static")-1) && | ||
!memcmp(lcname, "static", sizeof("static")-1))) { | ||
zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name)); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why replace a working test with something completely different? If we need to test for if as class name, we can add different test, but that's not what this test was about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@smalyshev actually a class named
namespace
is supported. So the test was superfluous in it's old state.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bwoebi if it's supported, change the outcome of the test, why rewrite it to something completely different testing something else not related to the bug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@smalyshev good question… Don't remember why I had changed the test. Reverted test now and updated expectf to match actual state.