}
/* }}} */
+static inline zend_bool zend_string_equals_str_ci(zend_string *str1, zend_string *str2) /* {{{ */
+{
+ return str1->len == str2->len
+ && !zend_binary_strcasecmp(str1->val, str1->len, str2->val, str2->len);
+}
+/* }}} */
+
static zend_constant *zend_lookup_reserved_const(const char *name, size_t len) /* {{{ */
{
zend_constant *c = zend_hash_find_ptr_lc(EG(zend_constants), name, len);
{
zend_constant *c;
- if (!(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
- /* Substitute case-sensitive (or lowercase) persistent constants */
- c = zend_hash_find_ptr(EG(zend_constants), name);
- if (c && (c->flags & CONST_PERSISTENT)) {
- ZVAL_DUP(zv, &c->value);
- return 1;
- }
+ /* Substitute case-sensitive (or lowercase) constants */
+ c = zend_hash_find_ptr(EG(zend_constants), name);
+ if (c && (
+ (c->flags & CONST_PERSISTENT)
+ || (Z_TYPE(c->value) < IS_OBJECT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)))
+ ) {
+ ZVAL_DUP(zv, &c->value);
+ return 1;
}
{
}
/* }}} */
+static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
+{
+ uint32_t fetch_type = zend_get_class_fetch_type(class_name);
+ zval *c;
+
+ if (CG(active_class_entry) && (fetch_type == ZEND_FETCH_CLASS_SELF || (fetch_type == ZEND_FETCH_CLASS_DEFAULT && zend_string_equals_str_ci(class_name, CG(active_class_entry)->name)))) {
+ c = zend_hash_find(&CG(active_class_entry)->constants_table, name);
+ } else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
+ zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), class_name->val, class_name->len);
+ if (ce) {
+ c = zend_hash_find(&ce->constants_table, name);
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ /* Substitute case-sensitive (or lowercase) persistent class constants */
+ if (c && Z_TYPE_P(c) < IS_OBJECT) {
+ ZVAL_DUP(zv, c);
+ return 1;
+ }
+
+ return 0;
+}
+
void zend_init_list(void *result, void *item) /* {{{ */
{
void** list = emalloc(sizeof(void*) * 2);
}
/* }}} */
-static inline zend_bool zend_string_equals_str_ci(zend_string *str1, zend_string *str2) /* {{{ */
-{
- return str1->len == str2->len
- && !zend_binary_strcasecmp(str1->val, str1->len, str2->val, str2->len);
-}
-/* }}} */
-
static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
{
switch (type & BP_VAR_MASK) {
znode class_node, const_node;
zend_op *opline, *class_op = NULL;
+ zend_string *resolved_name;
+
+ zend_eval_const_expr(&class_ast);
+ zend_eval_const_expr(&const_ast);
+
+ if (class_ast->kind == ZEND_AST_ZVAL) {
+ resolved_name = zend_resolve_class_name_ast(class_ast);
+ if (const_ast->kind == ZEND_AST_ZVAL && zend_try_ct_eval_class_const(&result->u.constant, resolved_name, zend_ast_get_str(const_ast))) {
+ result->op_type = IS_CONST;
+ zend_string_release(resolved_name);
+ return;
+ }
+ }
if (zend_is_const_default_class_ref(class_ast)) {
class_node.op_type = IS_CONST;
- ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
+ ZVAL_STR(&class_node.u.constant, resolved_name);
} else {
+ if (class_ast->kind == ZEND_AST_ZVAL) {
+ zend_string_release(resolved_name);
+ }
class_op = zend_compile_class_ref(&class_node, class_ast);
}
zend_compile_expr(&const_node, const_ast);
- if (class_op && const_node.op_type == IS_CONST && class_op->extended_value == ZEND_FETCH_CLASS_SELF && Z_TYPE(const_node.u.constant) == IS_STRING && CG(active_class_entry)) {
- zval *const_zv = zend_hash_find(&CG(active_class_entry)->constants_table, Z_STR(const_node.u.constant));
- if (const_zv && Z_TYPE_P(const_zv) < IS_CONSTANT) {
- CG(active_op_array)->last--;
- CG(active_op_array)->T--;
-
- result->op_type = IS_CONST;
- ZVAL_COPY(&result->u.constant, const_zv);
-
- zend_string_release(Z_STR(const_node.u.constant));
- return;
- }
- }
-
opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, &const_node);
zend_set_class_name_op1(opline, &class_node);
ZVAL_STR_COPY(&result->u.constant, CG(active_class_entry)->name);
}
break;
- case ZEND_FETCH_CLASS_STATIC:
- case ZEND_FETCH_CLASS_PARENT:
+ case ZEND_FETCH_CLASS_STATIC:
+ case ZEND_FETCH_CLASS_PARENT:
if (!CG(active_class_entry)) {
zend_error_noreturn(E_COMPILE_ERROR,
"Cannot access %s::class when no class scope is active",
zend_string_release(resolved_name);
break;
}
+ case ZEND_AST_CLASS_CONST:
+ {
+ zend_ast *class_ast = ast->child[0];
+ zend_ast *name_ast = ast->child[1];
+ zend_string *resolved_name;
+
+ zend_eval_const_expr(&class_ast);
+ zend_eval_const_expr(&name_ast);
+
+ if (class_ast->kind != ZEND_AST_ZVAL || name_ast->kind != ZEND_AST_ZVAL) {
+ return;
+ }
+
+ resolved_name = zend_resolve_class_name_ast(class_ast);
+
+ if (!zend_try_ct_eval_class_const(&result, resolved_name, zend_ast_get_str(name_ast))) {
+ zend_string_release(resolved_name);
+ return;
+ }
+
+ zend_string_release(resolved_name);
+ break;
+ }
+
default:
return;
}
}
/* }}} */
-/* {{{ proto public bool ReflectionParameter::isDefaultValueConstant()
- Returns whether the default value of this parameter is constant */
-ZEND_METHOD(reflection_parameter, isDefaultValueConstant)
-{
- zend_op *precv;
- parameter_reference *param;
-
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
-
- param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
- if (!param) {
- RETURN_FALSE;
- }
-
- precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
- if (precv && Z_TYPE_P(RT_CONSTANT(¶m->fptr->op_array, precv->op2)) == IS_CONSTANT) {
- RETURN_TRUE;
- }
-
- RETURN_FALSE;
-}
-/* }}} */
-
-/* {{{ proto public mixed ReflectionParameter::getDefaultValueConstantName()
- Returns the default value's constant name if default value is constant or null */
-ZEND_METHOD(reflection_parameter, getDefaultValueConstantName)
-{
- zend_op *precv;
- parameter_reference *param;
-
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
-
- param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
- if (!param) {
- return;
- }
-
- precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
- if (precv && Z_TYPE_P(RT_CONSTANT(¶m->fptr->op_array, precv->op2)) == IS_CONSTANT) {
- RETURN_STR(zend_string_copy(Z_STR_P(RT_CONSTANT(¶m->fptr->op_array, precv->op2))));
- }
-}
-/* }}} */
-
/* {{{ proto public bool ReflectionParameter::isVariadic()
Returns whether this parameter is a variadic parameter */
ZEND_METHOD(reflection_parameter, isVariadic)
ZEND_ME(reflection_parameter, isOptional, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, isDefaultValueAvailable, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getDefaultValue, arginfo_reflection__void, 0)
- ZEND_ME(reflection_parameter, isDefaultValueConstant, arginfo_reflection__void, 0)
- ZEND_ME(reflection_parameter, getDefaultValueConstantName, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, isVariadic, arginfo_reflection__void, 0)
PHP_FE_END
};
+++ /dev/null
---TEST--
-ReflectionParameter::isDefaultValueConstant() && getDefaultValueConstantName()
---FILE--
-<?php
-
-define("CONST_TEST_1", "const1");
-
-function ReflectionParameterTest($test1=array(), $test2 = CONST_TEST_1) {
- echo $test;
-}
-$reflect = new ReflectionFunction('ReflectionParameterTest');
-foreach($reflect->getParameters() as $param) {
- if($param->getName() == 'test1') {
- var_dump($param->isDefaultValueConstant());
- }
- if($param->getName() == 'test2') {
- var_dump($param->isDefaultValueConstant());
- }
- if($param->isDefaultValueAvailable() && $param->isDefaultValueConstant()) {
- var_dump($param->getDefaultValueConstantName());
- }
-}
-
-class Foo2 {
- const bar = 'Foo2::bar';
-}
-
-class Foo {
- const bar = 'Foo::bar';
-
- public function baz($param1 = self::bar, $param2=Foo2::bar, $param3=CONST_TEST_1) {
- }
-}
-
-$method = new ReflectionMethod('Foo', 'baz');
-$params = $method->getParameters();
-
-foreach ($params as $param) {
- if ($param->isDefaultValueConstant()) {
- var_dump($param->getDefaultValueConstantName());
- }
-}
-?>
-==DONE==
---EXPECT--
-bool(false)
-bool(true)
-string(12) "CONST_TEST_1"
-string(9) "self::bar"
-string(9) "Foo2::bar"
-string(12) "CONST_TEST_1"
-==DONE==