}
(new Test)->foobar();
-// This should error, but doesn't
const BAR = self::class;
var_dump(BAR);
?>
---EXPECT--
+--EXPECTF--
string(4) "Test"
-string(0) ""
+
+Fatal error: Uncaught Error: Cannot use "self" when no class scope is active in %s:%d
+Stack trace:
+#0 {main}
+ thrown in %s on line %d
break;
}
case ZEND_AST_CONSTANT_CLASS:
- ZEND_ASSERT(EG(current_execute_data));
if (scope && scope->name) {
ZVAL_STR_COPY(result, scope->name);
} else {
ZVAL_EMPTY_STRING(result);
}
break;
+ case ZEND_AST_CLASS_NAME:
+ ZEND_ASSERT(ast->attr == ZEND_FETCH_CLASS_SELF);
+ if (scope && scope->name) {
+ ZVAL_STR_COPY(result, scope->name);
+ } else {
+ zend_throw_error(NULL, "Cannot use \"self\" when no class scope is active");
+ ret = FAILURE;
+ }
+ break;
case ZEND_AST_AND:
if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
ret = FAILURE;
void zend_compile_const_expr_class_name(zend_ast **ast_ptr) /* {{{ */
{
- zend_ast *class_ast = (*ast_ptr)->child[0];
- uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
+ zend_ast *ast = *ast_ptr;
+ zend_ast *class_ast = ast->child[0];
+ zend_string *class_name = zend_ast_get_str(class_ast);
+ uint32_t fetch_type = zend_get_class_fetch_type(class_name);
- /* TODO We should not use AST_CONSTANT_CLASS for this, because the semantics are slightly
- * different. */
+ /* For the const-eval representation store the fetch type instead of the name. */
if (fetch_type == ZEND_FETCH_CLASS_SELF) {
- zend_ast_destroy(*ast_ptr);
- *ast_ptr = zend_ast_create(ZEND_AST_CONSTANT_CLASS);
+ zend_string_release(class_name);
+ ast->child[0] = NULL;
+ ast->attr = fetch_type;
return;
}