]> granicus.if.org Git - php/commitdiff
Handle self::class separately from __CLASS__ in const eval
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 4 Jan 2019 10:28:07 +0000 (11:28 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 4 Jan 2019 10:46:57 +0000 (11:46 +0100)
Zend/tests/self_class_const_in_unknown_scope.phpt
Zend/zend_ast.c
Zend/zend_compile.c

index 240644dea8cb8f5f9ed20a20af75393af282a303..2eb3a89d710c9745fb9b207830720abf0781c426 100644 (file)
@@ -13,11 +13,14 @@ class Test {
 }
 (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
index 597dcc3edd22f8257ba9d12407272a11cc3fbb4f..bea20f646b33e1295afac15caf5b2f4666d5ac98 100644 (file)
@@ -511,13 +511,21 @@ ZEND_API int ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_c
                        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;
index f3f12ddbf1c612f9c3c5f6d81e9c3cfbc1932b61..30a648f3269f6827ab494115efb3820501730038 100644 (file)
@@ -7953,14 +7953,16 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
 
 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;
        }