]> granicus.if.org Git - php/commitdiff
Compile class const refs to CONST zval
authorNikita Popov <nikic@php.net>
Thu, 26 Jun 2014 14:35:30 +0000 (16:35 +0200)
committerNikita Popov <nikic@php.net>
Thu, 26 Jun 2014 14:35:30 +0000 (16:35 +0200)
Zend/zend_compile.c
Zend/zend_language_parser.y

index 98229e21bde8b53edd7abfdba895eea8958c19cf..58b9252e5e35629e91c53b5a29e6ac67a6fe108f 100644 (file)
@@ -6111,6 +6111,7 @@ void zend_compile_const_expr(zend_ast **ast_ptr TSRMLS_DC);
 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) {
@@ -6118,7 +6119,6 @@ void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC) /* {{{
                }
                efree(ast);
        } else {
-               zend_compile_const_expr(&ast TSRMLS_CC);
                ZVAL_NEW_AST(&result->u.constant, ast);
        }
 }
@@ -7794,7 +7794,46 @@ zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) {
                || 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) {
@@ -7813,6 +7852,12 @@ 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) {
index 5142b465c95a75f7f2b049cca8e0bc67f0ff96b0..fc24b7e878cf0960a445ebc911f0c345ef4bb21e 100644 (file)
@@ -972,10 +972,6 @@ common_scalar:
                          $$.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); }
 ;
@@ -983,7 +979,9 @@ static_scalar: /* compile-time evaluated scalars */
 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(&$$); }