va_start(va, format);
zend_vspprintf(&message, 0, format, va);
if (strict) {
- zend_throw_exception(zend_get_type_exception(), message, 0);
+ zend_throw_exception(zend_get_type_exception(), message, E_ERROR);
} else {
zend_error(E_WARNING, message);
}
ZEND_API void zend_wrong_param_count(void) /* {{{ */
{
- if (ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_STRICT_TYPEHINTS) {
+ if (EX_PREV_USES_STRICT_TYPES()) {
zend_wrong_param_count_ex(1);
} else {
zend_wrong_param_count_ex(0);
va_list va;
int retval;
- if (ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_STRICT_TYPEHINTS) {
+ if (EX_PREV_USES_STRICT_TYPES()) {
flags |= ZEND_PARSE_PARAMS_STRICT;
}
int retval;
int flags = 0;
- if (ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_STRICT_TYPEHINTS) {
+ if (EX_PREV_USES_STRICT_TYPES()) {
flags |= ZEND_PARSE_PARAMS_STRICT;
}
* wrong branch here. */
zend_bool is_method = EG(current_execute_data)->func->common.scope != NULL;
- if (ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_STRICT_TYPEHINTS) {
+ if (EX_PREV_USES_STRICT_TYPES()) {
flags |= ZEND_PARSE_PARAMS_STRICT;
}
zval **object;
zend_class_entry *ce;
- if (ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_STRICT_TYPEHINTS) {
+ if (EX_PREV_USES_STRICT_TYPES()) {
flags |= ZEND_PARSE_PARAMS_STRICT;
}
#define ZPP_ERROR_WRONG_COUNT 5
#define ZEND_PARSE_PARAMETERS_START_EX(flags, min_num_args, max_num_args) do { \
- zend_bool _strict = (EX_CALL_INFO() & ZEND_CALL_STRICT_TYPEHINTS) ? 1 : 0; \
+ zend_bool _strict = EX_PREV_USES_STRICT_TYPES(); \
const int _flags = (flags) | (_strict ? ZEND_PARSE_PARAMS_STRICT : 0); \
int _min_num_args = (min_num_args); \
int _max_num_args = (max_num_args); \
static void init_compiler_declarables(void) /* {{{ */
{
ZVAL_LONG(&CG(declarables).ticks, 0);
- CG(declarables).strict_types = 0;
}
/* }}} */
{
CG(has_bracketed_namespaces) = 0;
zend_end_namespace();
- /* strict typehinting is per-file */
- CG(declarables).strict_types = 0;
}
/* }}} */
if (return_info->type_hint != IS_UNDEF) {
zend_op *opline = zend_emit_op(NULL, ZEND_VERIFY_RETURN_TYPE, expr, NULL);
- opline->extended_value = (CG(declarables).strict_types ? ZEND_RETURN_TYPE_STRICT : 0)
- & (returns_reference ? ZEND_RETURN_TYPE_BYREF : 0);
+ opline->extended_value = (returns_reference ? ZEND_RETURN_REF : 0);
}
}
/* }}} */
opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc);
}
- call_flags = (opline->opcode == ZEND_NEW ? ZEND_CALL_CTOR : 0)
- | (CG(declarables).strict_types ? ZEND_CALL_STRICT_TYPEHINTS : 0);
+ call_flags = (opline->opcode == ZEND_NEW ? ZEND_CALL_CTOR : 0);
opline = zend_emit_op(result, zend_get_call_op(opline->opcode, fbc), NULL, NULL);
opline->op1.num = call_flags;
/* for scalar, weak return types, the value may be casted
* thus, for constants, we need to store them in a tmp var
*/
- if (expr_node.op_type == IS_CONST && !CG(declarables).strict_types) {
+ if (expr_node.op_type == IS_CONST && !(CG(active_op_array)->fn_flags & ZEND_ACC_STRICT_TYPES)) {
znode expr_node_copy = expr_node;
zend_emit_op_tmp(&expr_node, ZEND_QM_ASSIGN, &expr_node_copy, NULL);
zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must have 0 or 1 as its value");
}
- CG(declarables).strict_types = Z_LVAL(value_zv);
+ if (Z_LVAL(value_zv) == 1) {
+ CG(active_op_array)->fn_flags |= ZEND_ACC_STRICT_TYPES;
+ }
+
} else {
zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", name->val);
}
init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
+ op_array->fn_flags |= (orig_op_array->fn_flags & ZEND_ACC_STRICT_TYPES);
op_array->fn_flags |= decl->flags;
op_array->line_start = decl->start_lineno;
op_array->line_end = decl->end_lineno;
/* Function has a return type hint (or class has such non-private function) */
#define ZEND_ACC_HAS_RETURN_TYPE 0x40000000
+/* op_array uses strict mode types */
+#define ZEND_ACC_STRICT_TYPES 0x80000000
+
char *zend_visibility_string(uint32_t fn_flags);
typedef struct _zend_property_info {
#define ZEND_CALL_FREE_EXTRA_ARGS (1 << 2) /* equal to IS_TYPE_REFCOUNTED */
#define ZEND_CALL_CTOR (1 << 3)
#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 4)
-#define ZEND_CALL_STRICT_TYPEHINTS (1 << 5)
-
-#define ZEND_RETURN_TYPE_STRICT (1 << 0)
-#define ZEND_RETURN_TYPE_BYREF (1 << 1)
#define ZEND_CALL_INFO(call) \
(Z_TYPE_INFO((call)->This) >> 24)
#define EX_CALL_INFO() ZEND_CALL_INFO(execute_data)
#define EX_CALL_KIND() ZEND_CALL_KIND(execute_data)
#define EX_NUM_ARGS() ZEND_CALL_NUM_ARGS(execute_data)
-#define EX_USES_STRICT_TYPES() ((EX_CALL_INFO() & ZEND_CALL_STRICT_TYPEHINTS) ? 1 : 0)
+
+#define EX_USES_STRICT_TYPES() _EX_USES_STRICT_TYPES(EG(current_execute_data))
+#define EX_PREV_USES_STRICT_TYPES() _EX_USES_STRICT_TYPES(EG(current_execute_data)->prev_execute_data)
+#define _EX_USES_STRICT_TYPES(ex_data) ((ex_data) && (ex_data)->func && ZEND_USER_CODE((ex_data)->func->type) && ((ex_data)->func->op_array.fn_flags & ZEND_ACC_STRICT_TYPES) ? 1 : 0)
#define EX_VAR(n) ZEND_CALL_VAR(execute_data, n)
#define EX_VAR_NUM(n) ZEND_CALL_VAR_NUM(execute_data, n)
}
}
} else {
- zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
+ zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
efree(error);
func = (zend_function*)&zend_pass_function;
called_scope = NULL;
zend_function *fbc = call->func;
zval *ret;
- ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS);
-
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
zend_function *fbc = call->func;
zval *ret;
- ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS);
-
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
zend_function *fbc = call->func;
zval *ret;
- ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS);
-
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
zend_object *object = Z_OBJ(call->This);
zval *ret;
- ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS);
-
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
- if (EXPECTED((opline->extended_value & ZEND_RETURN_TYPE_BYREF) == 0)) {
+ if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
- zend_verify_return_type(EX(func), retval_ptr, opline->extended_value & ZEND_RETURN_TYPE_STRICT);
+ zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
#endif
}
CHECK_EXCEPTION();
ZEND_VM_C_GOTO(send_array);
}
}
- zend_error(E_WARNING, "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args)));
+ zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args)));
if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) {
OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
}
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
- zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_USES_STRICT_TYPES());
+ zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_PREV_USES_STRICT_TYPES());
CHECK_EXCEPTION();
}
}
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
- zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2), EX_USES_STRICT_TYPES());
+ zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2), EX_PREV_USES_STRICT_TYPES());
}
CHECK_EXCEPTION();
ZEND_VM_C_LABEL(try_strlen):
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
- } else if (EXPECTED(0 == EX_USES_STRICT_TYPES())) {
+ } else if (EXPECTED(!EX_USES_STRICT_TYPES())) {
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
ZEND_VM_C_GOTO(try_strlen);
zval_dtor(&tmp);
} else {
ZEND_VM_C_LABEL(strlen_error):
- zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
}
FREE_OP1();
CHECK_EXCEPTION();
zend_function *fbc = call->func;
zval *ret;
- ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS);
-
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
zend_function *fbc = call->func;
zval *ret;
- ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS);
-
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
zend_function *fbc = call->func;
zval *ret;
- ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS);
-
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
zend_object *object = Z_OBJ(call->This);
zval *ret;
- ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS);
-
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
goto send_array;
}
}
- zend_error(E_WARNING, "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args)));
+ zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args)));
if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) {
OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
}
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
- zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_USES_STRICT_TYPES());
+ zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_PREV_USES_STRICT_TYPES());
CHECK_EXCEPTION();
}
}
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
- zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2), EX_USES_STRICT_TYPES());
+ zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2), EX_PREV_USES_STRICT_TYPES());
}
CHECK_EXCEPTION();
try_strlen:
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
- } else if (EXPECTED(0 == EX_USES_STRICT_TYPES())) {
+ } else if (EXPECTED(!EX_USES_STRICT_TYPES())) {
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
goto try_strlen;
zval_dtor(&tmp);
} else {
strlen_error:
- zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
}
CHECK_EXCEPTION();
}
}
} else {
- zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
+ zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
efree(error);
func = (zend_function*)&zend_pass_function;
called_scope = NULL;
retval_ptr = EX_CONSTANT(opline->op1);
- if (EXPECTED((opline->extended_value & ZEND_RETURN_TYPE_BYREF) == 0)) {
+ if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
- zend_verify_return_type(EX(func), retval_ptr, opline->extended_value & ZEND_RETURN_TYPE_STRICT);
+ zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
#endif
}
CHECK_EXCEPTION();
}
}
} else {
- zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
+ zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
efree(error);
func = (zend_function*)&zend_pass_function;
called_scope = NULL;
}
}
} else {
- zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
+ zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
efree(error);
func = (zend_function*)&zend_pass_function;
called_scope = NULL;
retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
- if (EXPECTED((opline->extended_value & ZEND_RETURN_TYPE_BYREF) == 0)) {
+ if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
- zend_verify_return_type(EX(func), retval_ptr, opline->extended_value & ZEND_RETURN_TYPE_STRICT);
+ zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
#endif
}
CHECK_EXCEPTION();
retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
- if (EXPECTED((opline->extended_value & ZEND_RETURN_TYPE_BYREF) == 0)) {
+ if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
- zend_verify_return_type(EX(func), retval_ptr, opline->extended_value & ZEND_RETURN_TYPE_STRICT);
+ zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
#endif
}
CHECK_EXCEPTION();
retval_ptr = NULL;
- if (EXPECTED((opline->extended_value & ZEND_RETURN_TYPE_BYREF) == 0)) {
+ if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
- zend_verify_return_type(EX(func), retval_ptr, opline->extended_value & ZEND_RETURN_TYPE_STRICT);
+ zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
#endif
}
CHECK_EXCEPTION();
try_strlen:
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
- } else if (EXPECTED(0 == EX_USES_STRICT_TYPES())) {
+ } else if (EXPECTED(!EX_USES_STRICT_TYPES())) {
if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
goto try_strlen;
zval_dtor(&tmp);
} else {
strlen_error:
- zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
}
CHECK_EXCEPTION();
retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
- if (EXPECTED((opline->extended_value & ZEND_RETURN_TYPE_BYREF) == 0)) {
+ if (EXPECTED((opline->extended_value & ZEND_RETURN_REF) == 0)) {
/* Does not return by reference */
SEPARATE_ZVAL(retval_ptr);
} else {
SEPARATE_ZVAL_NOREF(retval_ptr);
}
- zend_verify_return_type(EX(func), retval_ptr, opline->extended_value & ZEND_RETURN_TYPE_STRICT);
+ zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
#endif
}
CHECK_EXCEPTION();
try_strlen:
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
- } else if (EXPECTED(0 == EX_USES_STRICT_TYPES())) {
+ } else if (EXPECTED(!EX_USES_STRICT_TYPES())) {
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
goto try_strlen;
zval_dtor(&tmp);
} else {
strlen_error:
- zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
}
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();