diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-01-08 15:57:13 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-02-11 12:16:30 +0100 |
commit | d933591674ddcda342e80f32ca77dee1ada23fd7 (patch) | |
tree | aebbc5f633d1497f6c1715431d650a97e746e020 /Zend/zend_compile.c | |
parent | 69819baee34f24e42305516e61fdc7e61593a3bb (diff) | |
download | php-git-d933591674ddcda342e80f32ca77dee1ada23fd7.tar.gz |
Add support for $obj::class
This allows $obj::class, which gives the same result as get_class($obj).
Anything other than an object results in TypeError.
RFC: https://wiki.php.net/rfc/class_name_literal_on_object
Closes GH-5065.
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r-- | Zend/zend_compile.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d17185fbb8..d43bb6f4a3 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1551,7 +1551,7 @@ static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_a zval *class_name; if (class_ast->kind != ZEND_AST_ZVAL) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use ::class with dynamic class name"); + return 0; } class_name = zend_ast_get_zval(class_ast); @@ -8246,15 +8246,27 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */ void zend_compile_class_name(znode *result, zend_ast *ast) /* {{{ */ { zend_ast *class_ast = ast->child[0]; - zend_op *opline; if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast)) { result->op_type = IS_CONST; return; } - opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL); - opline->op1.num = zend_get_class_fetch_type(zend_ast_get_str(class_ast)); + if (class_ast->kind == ZEND_AST_ZVAL) { + zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL); + opline->op1.num = zend_get_class_fetch_type(zend_ast_get_str(class_ast)); + } else { + znode expr_node; + zend_compile_expr(&expr_node, class_ast); + if (expr_node.op_type == IS_CONST) { + /* Unlikely case that happen if class_ast is constant folded. + * Handle it here, to avoid needing a CONST specialization in the VM. */ + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use ::class on value of type %s", + zend_get_type_by_const(Z_TYPE(expr_node.u.constant))); + } + + zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, &expr_node, NULL); + } } /* }}} */ @@ -8491,6 +8503,11 @@ void zend_compile_const_expr_class_name(zend_ast **ast_ptr) /* {{{ */ { zend_ast *ast = *ast_ptr; zend_ast *class_ast = ast->child[0]; + if (class_ast->kind != ZEND_AST_ZVAL) { + zend_error_noreturn(E_COMPILE_ERROR, + "(expression)::class cannot be used in constant expressions"); + } + zend_string *class_name = zend_ast_get_str(class_ast); uint32_t fetch_type = zend_get_class_fetch_type(class_name); |