]> granicus.if.org Git - php/commitdiff
Use ZEND_FETCH_CLASS_NAME for dynamic self::class etc
authorNikita Popov <nikic@php.net>
Tue, 5 May 2015 16:22:20 +0000 (18:22 +0200)
committerNikita Popov <nikic@php.net>
Tue, 5 May 2015 19:14:03 +0000 (21:14 +0200)
Extend the opcode to support getting the parent and static name and
then use it for dynamic ::class resolution.

Zend/zend_compile.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index c92a25a705389c043b33d02741a2ae3f65d53b06..2e05b359661f51715856abc950e175801784d246 100644 (file)
@@ -6349,16 +6349,8 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast) /* {{{ */
        switch (fetch_type) {
                case ZEND_FETCH_CLASS_SELF:
                        if (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) {
-                               zval class_str_zv;
-                               zend_ast *class_str_ast, *class_const_ast;
-
-                               ZVAL_STRING(&class_str_zv, "class");
-                               class_str_ast = zend_ast_create_zval(&class_str_zv);
-                               class_const_ast = zend_ast_create(ZEND_AST_CLASS_CONST, name_ast, class_str_ast);
-
-                               zend_compile_expr(result, class_const_ast);
-
-                               zval_ptr_dtor(&class_str_zv);
+                               zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
+                               opline->extended_value = fetch_type;
                        } else {
                                result->op_type = IS_CONST;
                                ZVAL_STR_COPY(&result->u.constant, CG(active_class_entry)->name);
@@ -6367,17 +6359,8 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast) /* {{{ */
                case ZEND_FETCH_CLASS_STATIC:
                case ZEND_FETCH_CLASS_PARENT:
                        {
-                               zval class_str_zv;
-                               zend_ast *class_str_ast, *class_const_ast;
-
-                               ZVAL_STRING(&class_str_zv, "class");
-                               class_str_ast = zend_ast_create_zval(&class_str_zv);
-                               class_const_ast = zend_ast_create(
-                                       ZEND_AST_CLASS_CONST, name_ast, class_str_ast);
-
-                               zend_compile_expr(result, class_const_ast);
-
-                               zval_ptr_dtor(&class_str_zv);
+                               zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
+                               opline->extended_value = fetch_type;
                        }
                        break;
                case ZEND_FETCH_CLASS_DEFAULT:
@@ -6518,6 +6501,8 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
 
 void zend_compile_magic_const(znode *result, zend_ast *ast) /* {{{ */
 {
+       zend_op *opline;
+
        if (zend_try_ct_eval_magic_const(&result->u.constant, ast)) {
                result->op_type = IS_CONST;
                return;
@@ -6527,7 +6512,8 @@ void zend_compile_magic_const(znode *result, zend_ast *ast) /* {{{ */
                    CG(active_class_entry) &&
                    (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != 0);
 
-       zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
+       opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
+       opline->extended_value = ZEND_FETCH_CLASS_SELF;
 }
 /* }}} */
 
index c618ab3d8ffaa72be6d6793065949207e48461e4..7d449f40c8f78c83ea77fa3795ae1f1e176c4fad 100644 (file)
@@ -5076,9 +5076,6 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
                                CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
                        }
                        ZVAL_DUP(EX_VAR(opline->result.var), value);
-               } else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) {
-                       /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
-                       ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
                } else {
                        zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
                }
@@ -7847,7 +7844,22 @@ ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, ANY, ANY)
        USE_OPLINE
 
        if (EG(scope) && EG(scope)->name) {
-               ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->name);
+               switch (opline->extended_value) {
+                       case ZEND_FETCH_CLASS_SELF:
+                               ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->name);
+                               break;
+                       case ZEND_FETCH_CLASS_PARENT:
+                               if (EG(scope)->parent) {
+                                       ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->parent->name);
+                               } else {
+                                       ZVAL_EMPTY_STRING(EX_VAR(opline->result.var));
+                               }
+                               break;
+                       case ZEND_FETCH_CLASS_STATIC:
+                               ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(called_scope)->name);
+                               break;
+                       EMPTY_SWITCH_DEFAULT_CASE()
+               }
        } else {
                ZVAL_EMPTY_STRING(EX_VAR(opline->result.var));
        }
index a9342fc111eca8cb8003916a11ca1a4053b7cacc..2e2f0209bf86eb52e79682440558047ae33005ce 100644 (file)
@@ -1793,7 +1793,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_HANDLER(
        USE_OPLINE
 
        if (EG(scope) && EG(scope)->name) {
-               ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->name);
+               switch (opline->extended_value) {
+                       case ZEND_FETCH_CLASS_SELF:
+                               ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->name);
+                               break;
+                       case ZEND_FETCH_CLASS_PARENT:
+                               if (EG(scope)->parent) {
+                                       ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->parent->name);
+                               } else {
+                                       ZVAL_EMPTY_STRING(EX_VAR(opline->result.var));
+                               }
+                               break;
+                       case ZEND_FETCH_CLASS_STATIC:
+                               ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(called_scope)->name);
+                               break;
+                       EMPTY_SWITCH_DEFAULT_CASE()
+               }
        } else {
                ZVAL_EMPTY_STRING(EX_VAR(opline->result.var));
        }
@@ -5819,9 +5834,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONS
                                CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
                        }
                        ZVAL_DUP(EX_VAR(opline->result.var), value);
-               } else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) {
-                       /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
-                       ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
                } else {
                        zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
                }
@@ -17408,9 +17420,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_
                                CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
                        }
                        ZVAL_DUP(EX_VAR(opline->result.var), value);
-               } else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) {
-                       /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
-                       ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
                } else {
                        zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
                }
@@ -23780,9 +23789,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON
                                CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
                        }
                        ZVAL_DUP(EX_VAR(opline->result.var), value);
-               } else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) {
-                       /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
-                       ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
                } else {
                        zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
                }