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) {
}
efree(ast);
} else {
- zend_compile_const_expr(&ast TSRMLS_CC);
ZVAL_NEW_AST(&result->u.constant, ast);
}
}
|| 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) {
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) {
$$.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); }
;
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(&$$); }