From: Nikita Popov Date: Thu, 26 Jun 2014 14:35:30 +0000 (+0200) Subject: Compile class const refs to CONST zval X-Git-Tag: POST_AST_MERGE^2~183 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b83c70416b0754834f7505bd8ab57a6476493da0;p=php Compile class const refs to CONST zval --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 98229e21bd..58b9252e5e 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6111,6 +6111,7 @@ void zend_compile_const_expr(zend_ast **ast_ptr TSRMLS_DC); void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */ { //zend_eval_const_expr(&ast TSRMLS_CC); + zend_compile_const_expr(&ast TSRMLS_CC); if (ast->kind == ZEND_CONST) { ZVAL_COPY_VALUE(&result->u.constant, zend_ast_get_zval(ast)); if (Z_TYPE(result->u.constant) == IS_ARRAY) { @@ -6118,7 +6119,6 @@ void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ } efree(ast); } else { - zend_compile_const_expr(&ast TSRMLS_CC); ZVAL_NEW_AST(&result->u.constant, ast); } } @@ -7794,7 +7794,46 @@ zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) { || kind == ZEND_BW_NOT || kind == ZEND_BOOL_NOT || kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS || kind == ZEND_AST_CONDITIONAL - || kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM; + || kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM + || kind == ZEND_AST_CLASS_CONST; +} + +void zend_compile_const_expr_class_const(zend_ast **ast_ptr TSRMLS_DC) { + zend_ast *ast = *ast_ptr; + zend_ast *class_ast = ast->child[0]; + zend_ast *const_ast = ast->child[1]; + znode class_name, const_name; + zval result; + int fetch_type; + + if (class_ast->kind != ZEND_CONST) { + zend_error_noreturn(E_COMPILE_ERROR, + "Dynamic class names are not allowed in compile-time class constant references"); + } + + zend_compile_expr(&class_name, class_ast TSRMLS_CC); + zend_compile_expr(&const_name, const_ast TSRMLS_CC); + fetch_type = zend_get_class_fetch_type( + Z_STRVAL(class_name.u.constant), Z_STRLEN(class_name.u.constant)); + + if (ZEND_FETCH_CLASS_STATIC == fetch_type) { + zend_error_noreturn(E_COMPILE_ERROR, + "\"static::\" is not allowed in compile-time constants"); + } else if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) { + zend_resolve_class_name(&class_name TSRMLS_CC); + } + + zend_do_build_full_name(NULL, &class_name, &const_name, 1 TSRMLS_CC); + + ZVAL_COPY_VALUE(&result, &class_name.u.constant); + Z_TYPE_INFO(result) = IS_CONSTANT_EX; + if (IS_INTERNED(Z_STR(result))) { + Z_TYPE_FLAGS(result) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); + } + Z_CONST_FLAGS(result) = fetch_type; + + zend_ast_destroy(ast); + *ast_ptr = zend_ast_create_constant(&result); } void zend_compile_const_expr(zend_ast **ast_ptr TSRMLS_DC) { @@ -7813,6 +7852,12 @@ void zend_compile_const_expr(zend_ast **ast_ptr TSRMLS_DC) { zend_compile_const_expr(&ast->child[i] TSRMLS_CC); } } + + switch (ast->kind) { + case ZEND_AST_CLASS_CONST: + zend_compile_const_expr_class_const(ast_ptr TSRMLS_CC); + break; + } } void zend_compile_stmt(zend_ast *ast TSRMLS_DC) { diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 5142b465c9..fc24b7e878 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -972,10 +972,6 @@ common_scalar: $$.u.ast = zend_ast_create_constant(&empty_str); } ; -static_class_constant: - class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); } -; - static_scalar: /* compile-time evaluated scalars */ static_scalar_value { zend_do_constant_expression(&$$, $1.u.ast TSRMLS_CC); } ; @@ -983,7 +979,9 @@ static_scalar: /* compile-time evaluated scalars */ static_scalar_value: T_CONSTANT_ENCAPSED_STRING { $$.u.ast = AST_ZVAL(&$1); } | static_class_name_scalar { $$.u.ast = AST_ZVAL(&$1); } - | static_class_constant { $$.u.ast = AST_ZVAL(&$1); } + | class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING + { $$.u.ast = zend_ast_create_binary( + ZEND_AST_CLASS_CONST, AST_ZVAL(&$1), AST_ZVAL(&$3)); } | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); $$.u.ast = AST_ZVAL(&$$); } | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = AST_ZVAL(&$$); } | T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = AST_ZVAL(&$$); }