Skip to content

Commit 10b2f63

Browse files
committed
only allow enums and fix test
1 parent 2640748 commit 10b2f63

File tree

8 files changed

+61
-29
lines changed

8 files changed

+61
-29
lines changed

Zend/zend_API.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1840,7 +1840,7 @@ static zend_always_inline zend_result _object_and_properties_init(zval *arg, zen
18401840
}
18411841

18421842
// preloading may have changed the class type from ZEND_NAMESPACE_CLASS, so we need to check for user/internal class
1843-
if (check_class != scope && check_class->lexical_scope && (check_class->lexical_scope->type != ZEND_USER_CLASS && check_class->lexical_scope->type != ZEND_INTERNAL_CLASS)) {
1843+
if (check_class != scope && check_class->lexical_scope && (check_class->lexical_scope->type == ZEND_USER_CLASS || check_class->lexical_scope->type == ZEND_INTERNAL_CLASS)) {
18441844
check_class = check_class->lexical_scope;
18451845
goto check_lexical_scope;
18461846
}

Zend/zend_compile.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9179,6 +9179,11 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
91799179
"\\", 1,
91809180
ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name));
91819181

9182+
if (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) {
9183+
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s inside a trait",
9184+
ZSTR_VAL(name));
9185+
}
9186+
91829187
/* configure the class from the modifiers */
91839188
decl->flags |= decl->attr & ZEND_ACC_FINAL;
91849189
if (decl->attr & ZEND_ACC_ABSTRACT) {

Zend/zend_execute.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,7 @@ static zend_always_inline bool i_zend_check_property_type(const zend_property_in
10471047

10481048
static zend_result zend_check_type_visibility(const zend_class_entry *ce, const zend_property_info *info, uint32_t current_visibility)
10491049
{
1050+
check_lexical_scope:
10501051
/* public classes are always visible */
10511052
if (!ce->required_scope) {
10521053
return SUCCESS;
@@ -1065,14 +1066,19 @@ static zend_result zend_check_type_visibility(const zend_class_entry *ce, const
10651066

10661067
/* a private class is visible if it is the same class as the lexical scope and the current visibility is private */
10671068
if (ce->required_scope_absolute && ce->required_scope == info->ce) {
1068-
if (current_visibility < ZEND_ACC_PRIVATE) {
1069+
if ((current_visibility & ZEND_ACC_PPP_MASK) < ZEND_ACC_PRIVATE) {
10691070
zend_type_error("Cannot declare private class %s to a %s property in %s::%s", ZSTR_VAL(ce->name), zend_visibility_string(current_visibility), ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
10701071
return FAILURE;
10711072
}
10721073

10731074
return SUCCESS;
10741075
}
10751076

1077+
if (ce->lexical_scope != info->ce && ce->lexical_scope && (ce->lexical_scope->type == ZEND_USER_CLASS || ce->lexical_scope->type == ZEND_INTERNAL_CLASS)) {
1078+
ce = ce->lexical_scope;
1079+
goto check_lexical_scope;
1080+
}
1081+
10761082
zend_type_error("Cannot declare %s to weaker visible property %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
10771083
return FAILURE;
10781084
}

Zend/zend_language_parser.y

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,6 @@ class_statement_list:
954954
nested_class_statement:
955955
T_CLASS T_STRING { $<num>$ = CG(zend_lineno); } extends_from implements_list backup_doc_comment '{' class_statement_list '}'
956956
{ $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $<num>3, $6, zend_ast_get_str($2), $4, $5, $8, NULL, NULL); }
957-
| trait_declaration_statement { $$ = $1; }
958957
| enum_declaration_statement { $$ = $1; }
959958
;
960959

tests/classes/inner_classes/access_modifiers_002.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ class Outer {
1010

1111
?>
1212
--EXPECTF--
13-
Parse error: syntax error, unexpected identifier "int", expecting "class" in %s on line %d
13+
Parse error: syntax error, unexpected identifier "int", expecting "class" or "enum" in %s on line %d
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
nested enums
3+
--FILE--
4+
<?php
5+
enum Status {
6+
case Active;
7+
case Inactive;
8+
9+
private enum Processing {
10+
case Pending;
11+
case Completed;
12+
}
13+
14+
public class Message {
15+
16+
private Processing $processing = Processing::Pending;
17+
18+
public function __construct(private Status $status) {}
19+
20+
public function getMessage(): string {
21+
return match ([$this->status, $this->processing]) {
22+
[Status::Active, Processing::Pending] => "Active and Pending",
23+
[Status::Active, Processing::Completed] => "Active and Completed",
24+
[Status::Inactive, Processing::Pending] => "Inactive and Pending",
25+
[Status::Inactive, Processing::Completed] => throw new LogicException('should not happen'),
26+
};
27+
}
28+
}
29+
30+
public function createMessage(): Message {
31+
return new Message($this);
32+
}
33+
}
34+
35+
var_dump(Status::Active->createMessage());
36+
echo Status::Inactive->createMessage()->getMessage() . "\n";
37+
?>
38+
--EXPECT--
39+
object(Status\Message)#3 (2) {
40+
["processing":"Status\Message":private]=>
41+
enum(Status\Processing::Pending)
42+
["status":"Status\Message":private]=>
43+
enum(Status::Active)
44+
}
45+
Inactive and Pending

tests/classes/inner_classes/trait_001.phpt

Lines changed: 0 additions & 20 deletions
This file was deleted.

tests/classes/inner_classes/trait_usage_001.phpt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,5 @@ var_dump(class_exists(Outer\Inner::class));
1717
var_dump(class_exists(Foo\Inner::class));
1818

1919
?>
20-
--EXPECT--
21-
object(Outer\Inner)#1 (0) {
22-
}
23-
bool(true)
24-
bool(false)
20+
--EXPECTF--
21+
Fatal error: Cannot declare class Outer\Inner inside a trait in %s on line %d

0 commit comments

Comments
 (0)