Skip to content

Commit cf60230

Browse files
committed
add more tests and fix access modifiers
1 parent 2fa4328 commit cf60230

File tree

6 files changed

+60
-19
lines changed

6 files changed

+60
-19
lines changed

Zend/zend_compile.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -893,19 +893,20 @@ uint32_t zend_modifier_token_to_flag(zend_modifier_target target, uint32_t token
893893
}
894894
break;
895895
case T_READONLY:
896-
if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
896+
if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP || target == ZEND_MODIFIER_TARGET_INNER_CLASS) {
897897
return ZEND_ACC_READONLY;
898898
}
899899
break;
900900
case T_ABSTRACT:
901-
if (target == ZEND_MODIFIER_TARGET_METHOD || target == ZEND_MODIFIER_TARGET_PROPERTY) {
901+
if (target == ZEND_MODIFIER_TARGET_METHOD || target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_INNER_CLASS) {
902902
return ZEND_ACC_ABSTRACT;
903903
}
904904
break;
905905
case T_FINAL:
906906
if (target == ZEND_MODIFIER_TARGET_METHOD
907907
|| target == ZEND_MODIFIER_TARGET_CONSTANT
908908
|| target == ZEND_MODIFIER_TARGET_PROPERTY
909+
|| target == ZEND_MODIFIER_TARGET_INNER_CLASS
909910
|| target == ZEND_MODIFIER_TARGET_PROPERTY_HOOK) {
910911
return ZEND_ACC_FINAL;
911912
}
@@ -9195,13 +9196,21 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
91959196
// - final
91969197
// - readonly
91979198
// - abstract
9198-
ce->ce_flags |= decl->attr & (ZEND_ACC_FINAL|ZEND_ACC_READONLY|ZEND_ACC_ABSTRACT);
9199+
decl->flags |= decl->attr & ZEND_ACC_FINAL;
9200+
if (decl->attr & ZEND_ACC_ABSTRACT) {
9201+
decl->flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
9202+
}
9203+
if (decl->attr & ZEND_ACC_READONLY) {
9204+
decl->flags |= ZEND_ACC_READONLY_CLASS & ZEND_ACC_NO_DYNAMIC_PROPERTIES;
9205+
}
91999206

9200-
// configure the const stand-ins for a nested class. This should only include:
9207+
// configure for a nested class. This should only include:
92019208
// - public
92029209
// - private
92039210
// - protected
92049211
int propFlags = decl->attr & (ZEND_ACC_PUBLIC|ZEND_ACC_PROTECTED|ZEND_ACC_PRIVATE);
9212+
// remove the flags from attrs
9213+
decl->attr &= ~(ZEND_ACC_PUBLIC|ZEND_ACC_PROTECTED|ZEND_ACC_PRIVATE|ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT|ZEND_ACC_READONLY);
92059214

92069215
// if a class is private or protected, we need to require the correct scope
92079216
ce->required_scope = propFlags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED) ? CG(active_class_entry) : NULL;

Zend/zend_language_parser.y

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,14 @@ class_modifier:
627627
| T_READONLY { $$ = ZEND_ACC_READONLY_CLASS|ZEND_ACC_NO_DYNAMIC_PROPERTIES; }
628628
;
629629

630+
inner_class_modifiers:
631+
non_empty_member_modifiers
632+
{ $$ = zend_modifier_list_to_flags(ZEND_MODIFIER_TARGET_INNER_CLASS, $1);
633+
if (!$$) { YYERROR; } }
634+
| %empty
635+
{ $$ = ZEND_ACC_PUBLIC; }
636+
;
637+
630638
trait_declaration_statement:
631639
T_TRAIT { $<num>$ = CG(zend_lineno); }
632640
T_STRING backup_doc_comment '{' class_statement_list '}'
@@ -954,14 +962,6 @@ inner_class_statement:
954962
{ $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $<num>3, $6, zend_ast_get_str($2), $4, $5, $8, NULL, NULL); }
955963
;
956964

957-
inner_class_modifiers:
958-
non_empty_member_modifiers
959-
{ $$ = zend_modifier_list_to_flags(ZEND_MODIFIER_TARGET_INNER_CLASS, $1);
960-
if (!$$) { YYERROR; } }
961-
| %empty
962-
{ $$ = ZEND_ACC_PUBLIC; }
963-
;
964-
965965
attributed_class_statement:
966966
property_modifiers optional_type_without_static property_list ';'
967967
{ $$ = zend_ast_create(ZEND_AST_PROP_GROUP, $2, $3, NULL);

tests/classes/inner_classes/access_modifiers_007.phpt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,24 @@ abstract inner classes
44
<?php
55

66
class Outer {
7-
abstract class Inner {}
7+
public abstract class Inner {}
88
}
99

10-
$extended = new class extends Outer:>Inner{};
10+
class Extended extends Outer:>Inner {}
11+
12+
$extended = new Extended();
1113

1214
var_dump($extended);
1315
$reflection = new ReflectionClass('Outer:>Inner');
1416
var_dump($reflection->isAbstract());
1517
new Outer:>Inner();
1618
?>
1719
--EXPECTF--
18-
last one fails
20+
object(Extended)#1 (0) {
21+
}
22+
bool(true)
23+
24+
Fatal error: Uncaught Error: Cannot instantiate abstract class Outer:>Inner in %s:%d
25+
Stack trace:
26+
#0 {main}
27+
thrown in %s on line %d

tests/classes/inner_classes/inheritance.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ inheritance
55

66
class Outer {
77
abstract class Other {}
8-
class Middle extends Other {
9-
class Inner1 {} // extends Outer:>Middle
10-
class Inner2 extends Outer:>Middle {} // extends Outer
8+
class Middle extends Outer:>Other {
9+
class Inner1 extends Outer:>Other {}
10+
class Inner2 extends Outer:>Middle {}
1111
}
1212
}
1313
?>

tests/classes/inner_classes/return_types_006.phpt

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

13-
public function test() { return new self:>PrivateInner()->test(); }
13+
public function test(): mixed { return new self:>PrivateInner()->test(); }
1414
}
1515

1616
$foo = new Outer()->test();
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
outer class visibility
3+
--FILE--
4+
<?php
5+
6+
class Outer {
7+
private class Inner {}
8+
private class Other {
9+
public function __construct(private Outer:>Inner $inner) {}
10+
11+
public function reset(): void {
12+
$prev = $this->inner;
13+
$this->inner = new Outer:>Inner();
14+
var_dump($prev === $this->inner);
15+
}
16+
}
17+
public static function test(): void {
18+
new self:>Other(new Outer:>Inner());
19+
}
20+
}
21+
Outer::test();
22+
?>
23+
--EXPECT--

0 commit comments

Comments
 (0)