diff --git a/Zend/tests/typehints/bug62441.phpt b/Zend/tests/type_declarations/bug62441.phpt similarity index 100% rename from Zend/tests/typehints/bug62441.phpt rename to Zend/tests/type_declarations/bug62441.phpt diff --git a/Zend/tests/type_declarations/builtin/fully_qualified_array.phpt b/Zend/tests/type_declarations/builtin/fully_qualified_array.phpt new file mode 100644 index 000000000000..5af78a1bdb1c --- /dev/null +++ b/Zend/tests/type_declarations/builtin/fully_qualified_array.phpt @@ -0,0 +1,13 @@ +--TEST-- +Fully qualified (leading backslash) array type name must fail +--FILE-- + +--EXPECTF-- +Fatal error: Type declaration 'array' must be unqualified in %s on line %d diff --git a/Zend/tests/typehints/fully_qualified_scalar.phpt b/Zend/tests/type_declarations/builtin/fully_qualified_scalar.phpt similarity index 100% rename from Zend/tests/typehints/fully_qualified_scalar.phpt rename to Zend/tests/type_declarations/builtin/fully_qualified_scalar.phpt diff --git a/Zend/tests/type_declarations/builtin/namespace_relative_array.phpt b/Zend/tests/type_declarations/builtin/namespace_relative_array.phpt new file mode 100644 index 000000000000..8db15fe5269f --- /dev/null +++ b/Zend/tests/type_declarations/builtin/namespace_relative_array.phpt @@ -0,0 +1,11 @@ +--TEST-- +namespace\array is not a valid type declaration +--FILE-- + +--EXPECTF-- +Fatal error: Type declaration 'array' must be unqualified in %s on line %d diff --git a/Zend/tests/typehints/namespace_relative_scalar.phpt b/Zend/tests/type_declarations/builtin/namespace_relative_scalar.phpt similarity index 77% rename from Zend/tests/typehints/namespace_relative_scalar.phpt rename to Zend/tests/type_declarations/builtin/namespace_relative_scalar.phpt index 096d04738719..12ff9939a4e1 100644 --- a/Zend/tests/typehints/namespace_relative_scalar.phpt +++ b/Zend/tests/type_declarations/builtin/namespace_relative_scalar.phpt @@ -1,5 +1,5 @@ --TEST-- -namespace\int is not a valid type hint +namespace\int is not a valid type declaration --FILE-- +--EXPECTF-- +Fatal error: Type declaration 'callable' must be unqualified in %s on line %d diff --git a/Zend/tests/type_declarations/callable/namespace_relative_callable.phpt b/Zend/tests/type_declarations/callable/namespace_relative_callable.phpt new file mode 100644 index 000000000000..45afcf6e5b0b --- /dev/null +++ b/Zend/tests/type_declarations/callable/namespace_relative_callable.phpt @@ -0,0 +1,10 @@ +--TEST-- +namespace\callable is not a valid type declaration +--FILE-- + +--EXPECTF-- +Fatal error: Type declaration 'callable' must be unqualified in %s on line %d diff --git a/Zend/tests/typehints/fq_nullable.phpt b/Zend/tests/type_declarations/fq_nullable.phpt similarity index 100% rename from Zend/tests/typehints/fq_nullable.phpt rename to Zend/tests/type_declarations/fq_nullable.phpt diff --git a/Zend/tests/typehints/or_null.phpt b/Zend/tests/type_declarations/or_null.phpt similarity index 100% rename from Zend/tests/typehints/or_null.phpt rename to Zend/tests/type_declarations/or_null.phpt diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f6bff9830bf6..9ec1cdda2b4b 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -199,44 +199,46 @@ static bool zend_get_unqualified_name(const zend_string *name, const char **resu } /* }}} */ -struct reserved_class_name { - const char *name; - size_t len; -}; -static const struct reserved_class_name reserved_class_names[] = { - {ZEND_STRL("bool")}, - {ZEND_STRL("false")}, - {ZEND_STRL("float")}, - {ZEND_STRL("int")}, - {ZEND_STRL("null")}, - {ZEND_STRL("parent")}, - {ZEND_STRL("self")}, - {ZEND_STRL("static")}, - {ZEND_STRL("string")}, - {ZEND_STRL("true")}, - {ZEND_STRL("void")}, - {ZEND_STRL("never")}, - {ZEND_STRL("iterable")}, - {ZEND_STRL("object")}, - {ZEND_STRL("mixed")}, - /* These are not usable as class names because they're proper tokens, - * but they are here for class aliases. */ - {ZEND_STRL("array")}, - {ZEND_STRL("callable")}, - {NULL, 0} +typedef struct _builtin_type_info { + const char* name; + const size_t name_len; + const uint8_t type; +} builtin_type_info; + +static const builtin_type_info builtin_types[] = { + {ZEND_STRL("null"), IS_NULL}, + {ZEND_STRL("true"), IS_TRUE}, + {ZEND_STRL("false"), IS_FALSE}, + {ZEND_STRL("int"), IS_LONG}, + {ZEND_STRL("float"), IS_DOUBLE}, + {ZEND_STRL("string"), IS_STRING}, + {ZEND_STRL("bool"), _IS_BOOL}, + {ZEND_STRL("void"), IS_VOID}, + {ZEND_STRL("never"), IS_NEVER}, + {ZEND_STRL("iterable"), IS_ITERABLE}, + {ZEND_STRL("object"), IS_OBJECT}, + {ZEND_STRL("mixed"), IS_MIXED}, + /* Should be handled as ZEND_TYPE_ASTs but it may have a namespace component */ + {ZEND_STRL("array"), IS_ARRAY}, + {ZEND_STRL("callable"), IS_CALLABLE}, + {ZEND_STRL("static"), IS_STATIC}, + /* self and parent are effectively built-in types (and thus reserved), but they allow namespace components */ + {ZEND_STRL("self"), 0}, + {ZEND_STRL("parent"), 0}, + {NULL, 0, IS_UNDEF} }; static bool zend_is_reserved_class_name(const zend_string *name) /* {{{ */ { - const struct reserved_class_name *reserved = reserved_class_names; + const builtin_type_info *reserved = builtin_types; const char *uqname = ZSTR_VAL(name); size_t uqname_len = ZSTR_LEN(name); zend_get_unqualified_name(name, &uqname, &uqname_len); for (; reserved->name; ++reserved) { - if (uqname_len == reserved->len - && zend_binary_strcasecmp(uqname, uqname_len, reserved->name, reserved->len) == 0 + if (uqname_len == reserved->name_len + && zend_binary_strcasecmp(uqname, uqname_len, reserved->name, reserved->name_len) == 0 ) { return true; } @@ -262,29 +264,6 @@ void zend_assert_valid_class_name(const zend_string *name, const char *type) /* } /* }}} */ -typedef struct _builtin_type_info { - const char* name; - const size_t name_len; - const uint8_t type; -} builtin_type_info; - -static const builtin_type_info builtin_types[] = { - {ZEND_STRL("null"), IS_NULL}, - {ZEND_STRL("true"), IS_TRUE}, - {ZEND_STRL("false"), IS_FALSE}, - {ZEND_STRL("int"), IS_LONG}, - {ZEND_STRL("float"), IS_DOUBLE}, - {ZEND_STRL("string"), IS_STRING}, - {ZEND_STRL("bool"), _IS_BOOL}, - {ZEND_STRL("void"), IS_VOID}, - {ZEND_STRL("never"), IS_NEVER}, - {ZEND_STRL("iterable"), IS_ITERABLE}, - {ZEND_STRL("object"), IS_OBJECT}, - {ZEND_STRL("mixed"), IS_MIXED}, - {ZEND_STRL("static"), IS_STATIC}, - {NULL, 0, IS_UNDEF} -}; - typedef struct { const char *name; size_t name_len; @@ -7642,7 +7621,8 @@ static zend_type zend_compile_single_typename(zend_ast *ast) ZSTR_VAL(zend_string_tolower(type_name))); } - ZEND_ASSERT(type_code != IS_STATIC && "unqualified static type should have been handled by ZEND_AST_TYPE branch"); + ZEND_ASSERT(type_code != IS_STATIC && type_code != IS_ARRAY && type_code != IS_CALLABLE + && "unqualified array/callable/static type should have been handled by ZEND_AST_TYPE branch"); /* Transform iterable into a type union alias */ if (type_code == IS_ITERABLE) {