summaryrefslogtreecommitdiffstats
path: root/ast-upstream.patch
blob: 47e64faa5e1dcb391f18434ba059eb9d35d039c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
diff --git a/README.md b/README.md
index 1017536..adbe819 100644
--- a/README.md
+++ b/README.md
@@ -256,9 +256,9 @@ ast\flags\CLASS_ANONYMOUS
 // Used by ast\AST_PARAM (combinable)
 ast\flags\PARAM_REF
 ast\flags\PARAM_VARIADIC
-ast\flags\MODIFIER_PUBLIC (only in php 8.0+)
-ast\flags\MODIFIER_PROTECTED (only in php 8.0+)
-ast\flags\MODIFIER_PRIVATE (only in php 8.0+)
+ast\flags\PARAM_MODIFIER_PUBLIC (available since 1.0.8, same as ast\flags\MODIFIER_* in PHP >= 8.0)
+ast\flags\PARAM_MODIFIER_PROTECTED (available since 1.0.8)
+ast\flags\PARAM_MODIFIER_PRIVATE (available since 1.0.8)
 
 // Used by ast\AST_TYPE (exclusive)
 ast\flags\TYPE_ARRAY
@@ -412,6 +412,7 @@ AST_METHOD:           name, docComment, params, stmts, returnType, attributes
 AST_METHOD_CALL:      expr, method, args
 AST_METHOD_REFERENCE: class, method
 AST_NAME:             name
+AST_NAMED_ARG:        name, expr             // php 8.0 named parameters
 AST_NAMESPACE:        name, stmts
 AST_NEW:              class, args
 AST_NULLABLE_TYPE:    type                   // Used only since PHP 7.1
diff --git a/ast.c b/ast.c
index 540a8d8..eeb6b5a 100644
--- a/ast.c
+++ b/ast.c
@@ -65,6 +65,14 @@
 #if PHP_VERSION_ID < 80000
 # define IS_STATIC 20
 # define IS_MIXED 21
+/* In PHP 7.0-7.4, PARAM_REF and PARAM_VARIADIC were 1 and 2. */
+# define PARAM_MODIFIER_PUBLIC    (1 << 2)
+# define PARAM_MODIFIER_PROTECTED (1 << 3)
+# define PARAM_MODIFIER_PRIVATE   (1 << 4)
+#else
+# define PARAM_MODIFIER_PUBLIC    ZEND_ACC_PUBLIC
+# define PARAM_MODIFIER_PROTECTED ZEND_ACC_PROTECTED
+# define PARAM_MODIFIER_PRIVATE   ZEND_ACC_PRIVATE
 #endif
 
 /* This contains state of the ast Node creator. */
@@ -107,11 +115,9 @@ static const char *class_flags[] = {
 static const char *param_flags[] = {
 	AST_FLAG(PARAM_REF),
 	AST_FLAG(PARAM_VARIADIC),
-#if PHP_VERSION_ID >= 80000
-	AST_FLAG(MODIFIER_PUBLIC),
-	AST_FLAG(MODIFIER_PROTECTED),
-	AST_FLAG(MODIFIER_PRIVATE),
-#endif
+	AST_FLAG(PARAM_MODIFIER_PUBLIC),
+	AST_FLAG(PARAM_MODIFIER_PROTECTED),
+	AST_FLAG(PARAM_MODIFIER_PRIVATE),
 	NULL
 };
 
@@ -1368,6 +1374,10 @@ PHP_MINIT_FUNCTION(ast) {
 	ast_register_flag_constant("MODIFIER_ABSTRACT", ZEND_ACC_ABSTRACT);
 	ast_register_flag_constant("MODIFIER_FINAL", ZEND_ACC_FINAL);
 
+	ast_register_flag_constant("PARAM_MODIFIER_PUBLIC", PARAM_MODIFIER_PUBLIC);
+	ast_register_flag_constant("PARAM_MODIFIER_PROTECTED", PARAM_MODIFIER_PROTECTED);
+	ast_register_flag_constant("PARAM_MODIFIER_PRIVATE", PARAM_MODIFIER_PRIVATE);
+
 	ast_register_flag_constant("RETURNS_REF", ZEND_ACC_RETURN_REFERENCE);
 	ast_register_flag_constant("FUNC_RETURNS_REF", ZEND_ACC_RETURN_REFERENCE);
 	ast_register_flag_constant("FUNC_GENERATOR", ZEND_ACC_GENERATOR);
diff --git a/ast_data.c b/ast_data.c
index 9b6ce55..8538572 100644
--- a/ast_data.c
+++ b/ast_data.c
@@ -63,6 +63,7 @@ const zend_ast_kind ast_kinds[] = {
 	ZEND_AST_CLASS_CONST_GROUP,
 	ZEND_AST_DIM,
 	ZEND_AST_PROP,
+	ZEND_AST_NULLSAFE_PROP,
 	ZEND_AST_STATIC_PROP,
 	ZEND_AST_CALL,
 	ZEND_AST_CLASS_CONST,
@@ -94,7 +95,9 @@ const zend_ast_kind ast_kinds[] = {
 	ZEND_AST_ATTRIBUTE,
 	ZEND_AST_MATCH,
 	ZEND_AST_MATCH_ARM,
+	ZEND_AST_NAMED_ARG,
 	ZEND_AST_METHOD_CALL,
+	ZEND_AST_NULLSAFE_METHOD_CALL,
 	ZEND_AST_STATIC_CALL,
 	ZEND_AST_CONDITIONAL,
 	ZEND_AST_TRY,
@@ -170,6 +173,7 @@ const char *ast_kind_to_name(zend_ast_kind kind) {
 		case ZEND_AST_CLASS_CONST_GROUP: return "AST_CLASS_CONST_GROUP";
 		case ZEND_AST_DIM: return "AST_DIM";
 		case ZEND_AST_PROP: return "AST_PROP";
+		case ZEND_AST_NULLSAFE_PROP: return "AST_NULLSAFE_PROP";
 		case ZEND_AST_STATIC_PROP: return "AST_STATIC_PROP";
 		case ZEND_AST_CALL: return "AST_CALL";
 		case ZEND_AST_CLASS_CONST: return "AST_CLASS_CONST";
@@ -201,7 +205,9 @@ const char *ast_kind_to_name(zend_ast_kind kind) {
 		case ZEND_AST_ATTRIBUTE: return "AST_ATTRIBUTE";
 		case ZEND_AST_MATCH: return "AST_MATCH";
 		case ZEND_AST_MATCH_ARM: return "AST_MATCH_ARM";
+		case ZEND_AST_NAMED_ARG: return "AST_NAMED_ARG";
 		case ZEND_AST_METHOD_CALL: return "AST_METHOD_CALL";
+		case ZEND_AST_NULLSAFE_METHOD_CALL: return "AST_NULLSAFE_METHOD_CALL";
 		case ZEND_AST_STATIC_CALL: return "AST_STATIC_CALL";
 		case ZEND_AST_CONDITIONAL: return "AST_CONDITIONAL";
 		case ZEND_AST_TRY: return "AST_TRY";
@@ -442,6 +448,12 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) {
 				case 1: return AST_STR(str_prop);
 			}
 			return NULL;
+		case ZEND_AST_NULLSAFE_PROP:
+			switch (child) {
+				case 0: return AST_STR(str_expr);
+				case 1: return AST_STR(str_prop);
+			}
+			return NULL;
 		case ZEND_AST_STATIC_PROP:
 			switch (child) {
 				case 0: return AST_STR(str_class);
@@ -631,6 +643,12 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) {
 				case 1: return AST_STR(str_expr);
 			}
 			return NULL;
+		case ZEND_AST_NAMED_ARG:
+			switch (child) {
+				case 0: return AST_STR(str_name);
+				case 1: return AST_STR(str_expr);
+			}
+			return NULL;
 		case ZEND_AST_METHOD_CALL:
 			switch (child) {
 				case 0: return AST_STR(str_expr);
@@ -638,6 +656,13 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) {
 				case 2: return AST_STR(str_args);
 			}
 			return NULL;
+		case ZEND_AST_NULLSAFE_METHOD_CALL:
+			switch (child) {
+				case 0: return AST_STR(str_expr);
+				case 1: return AST_STR(str_method);
+				case 2: return AST_STR(str_args);
+			}
+			return NULL;
 		case ZEND_AST_STATIC_CALL:
 			switch (child) {
 				case 0: return AST_STR(str_class);
@@ -759,6 +784,7 @@ void ast_register_kind_constants(INIT_FUNC_ARGS) {
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_CLASS_CONST_GROUP", ZEND_AST_CLASS_CONST_GROUP, CONST_CS | CONST_PERSISTENT);
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_DIM", ZEND_AST_DIM, CONST_CS | CONST_PERSISTENT);
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_PROP", ZEND_AST_PROP, CONST_CS | CONST_PERSISTENT);
+	REGISTER_NS_LONG_CONSTANT("ast", "AST_NULLSAFE_PROP", ZEND_AST_NULLSAFE_PROP, CONST_CS | CONST_PERSISTENT);
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_STATIC_PROP", ZEND_AST_STATIC_PROP, CONST_CS | CONST_PERSISTENT);
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_CALL", ZEND_AST_CALL, CONST_CS | CONST_PERSISTENT);
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_CLASS_CONST", ZEND_AST_CLASS_CONST, CONST_CS | CONST_PERSISTENT);
@@ -790,7 +816,9 @@ void ast_register_kind_constants(INIT_FUNC_ARGS) {
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_ATTRIBUTE", ZEND_AST_ATTRIBUTE, CONST_CS | CONST_PERSISTENT);
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_MATCH", ZEND_AST_MATCH, CONST_CS | CONST_PERSISTENT);
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_MATCH_ARM", ZEND_AST_MATCH_ARM, CONST_CS | CONST_PERSISTENT);
+	REGISTER_NS_LONG_CONSTANT("ast", "AST_NAMED_ARG", ZEND_AST_NAMED_ARG, CONST_CS | CONST_PERSISTENT);
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_METHOD_CALL", ZEND_AST_METHOD_CALL, CONST_CS | CONST_PERSISTENT);
+	REGISTER_NS_LONG_CONSTANT("ast", "AST_NULLSAFE_METHOD_CALL", ZEND_AST_NULLSAFE_METHOD_CALL, CONST_CS | CONST_PERSISTENT);
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_STATIC_CALL", ZEND_AST_STATIC_CALL, CONST_CS | CONST_PERSISTENT);
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_CONDITIONAL", ZEND_AST_CONDITIONAL, CONST_CS | CONST_PERSISTENT);
 	REGISTER_NS_LONG_CONSTANT("ast", "AST_TRY", ZEND_AST_TRY, CONST_CS | CONST_PERSISTENT);
diff --git a/ast_stub.php b/ast_stub.php
index a38f0f6..fb71a54 100644
--- a/ast_stub.php
+++ b/ast_stub.php
@@ -66,45 +66,48 @@ const AST_GOTO = 285;
 const AST_BREAK = 286;
 const AST_CONTINUE = 287;
 const AST_CLASS_NAME = 276;
-const AST_CLASS_CONST_GROUP = 545;
+const AST_CLASS_CONST_GROUP = 546;
 const AST_DIM = 512;
 const AST_PROP = 513;
-const AST_STATIC_PROP = 514;
-const AST_CALL = 515;
-const AST_CLASS_CONST = 516;
-const AST_ASSIGN = 517;
-const AST_ASSIGN_REF = 518;
-const AST_ASSIGN_OP = 519;
-const AST_BINARY_OP = 520;
-const AST_ARRAY_ELEM = 525;
-const AST_NEW = 526;
-const AST_INSTANCEOF = 527;
-const AST_YIELD = 528;
-const AST_STATIC = 531;
-const AST_WHILE = 532;
-const AST_DO_WHILE = 533;
-const AST_IF_ELEM = 534;
-const AST_SWITCH = 535;
-const AST_SWITCH_CASE = 536;
-const AST_DECLARE = 537;
-const AST_PROP_ELEM = 774;
-const AST_PROP_GROUP = 773;
-const AST_CONST_ELEM = 775;
-const AST_USE_TRAIT = 538;
-const AST_TRAIT_PRECEDENCE = 539;
-const AST_METHOD_REFERENCE = 540;
-const AST_NAMESPACE = 541;
-const AST_USE_ELEM = 542;
-const AST_TRAIT_ALIAS = 543;
-const AST_GROUP_USE = 544;
-const AST_ATTRIBUTE = 546;
-const AST_MATCH = 547;
-const AST_MATCH_ARM = 548;
+const AST_NULLSAFE_PROP = 514;
+const AST_STATIC_PROP = 515;
+const AST_CALL = 516;
+const AST_CLASS_CONST = 517;
+const AST_ASSIGN = 518;
+const AST_ASSIGN_REF = 519;
+const AST_ASSIGN_OP = 520;
+const AST_BINARY_OP = 521;
+const AST_ARRAY_ELEM = 526;
+const AST_NEW = 527;
+const AST_INSTANCEOF = 528;
+const AST_YIELD = 529;
+const AST_STATIC = 532;
+const AST_WHILE = 533;
+const AST_DO_WHILE = 534;
+const AST_IF_ELEM = 535;
+const AST_SWITCH = 536;
+const AST_SWITCH_CASE = 537;
+const AST_DECLARE = 538;
+const AST_PROP_ELEM = 775;
+const AST_PROP_GROUP = 774;
+const AST_CONST_ELEM = 776;
+const AST_USE_TRAIT = 539;
+const AST_TRAIT_PRECEDENCE = 540;
+const AST_METHOD_REFERENCE = 541;
+const AST_NAMESPACE = 542;
+const AST_USE_ELEM = 543;
+const AST_TRAIT_ALIAS = 544;
+const AST_GROUP_USE = 545;
+const AST_ATTRIBUTE = 547;
+const AST_MATCH = 548;
+const AST_MATCH_ARM = 549;
+const AST_NAMED_ARG = 550;
 const AST_METHOD_CALL = 768;
-const AST_STATIC_CALL = 769;
-const AST_CONDITIONAL = 770;
-const AST_TRY = 771;
-const AST_CATCH = 772;
+const AST_NULLSAFE_METHOD_CALL = 769;
+const AST_STATIC_CALL = 770;
+const AST_CONDITIONAL = 771;
+const AST_TRY = 772;
+const AST_CATCH = 773;
 const AST_FOR = 1024;
 const AST_FOREACH = 1025;
 const AST_PARAM = 1280;
@@ -121,6 +124,9 @@ const MODIFIER_PRIVATE = 4;
 const MODIFIER_STATIC = 16;
 const MODIFIER_ABSTRACT = 64;
 const MODIFIER_FINAL = 32;
+const PARAM_MODIFIER_PUBLIC = 1;
+const PARAM_MODIFIER_PROTECTED = 2;
+const PARAM_MODIFIER_PRIVATE = 4;
 const RETURNS_REF = 4096;
 const FUNC_RETURNS_REF = 4096;
 const FUNC_GENERATOR = 16777216;
@@ -184,14 +190,14 @@ const EXEC_REQUIRE_ONCE = 16;
 const USE_NORMAL = 1;
 const USE_FUNCTION = 2;
 const USE_CONST = 4;
-const MAGIC_LINE = 372;
-const MAGIC_FILE = 373;
-const MAGIC_DIR = 374;
-const MAGIC_NAMESPACE = 379;
-const MAGIC_FUNCTION = 378;
-const MAGIC_METHOD = 377;
-const MAGIC_CLASS = 375;
-const MAGIC_TRAIT = 376;
+const MAGIC_LINE = 375;
+const MAGIC_FILE = 376;
+const MAGIC_DIR = 377;
+const MAGIC_NAMESPACE = 382;
+const MAGIC_FUNCTION = 381;
+const MAGIC_METHOD = 380;
+const MAGIC_CLASS = 378;
+const MAGIC_TRAIT = 379;
 const ARRAY_SYNTAX_LIST = 1;
 const ARRAY_SYNTAX_LONG = 2;
 const ARRAY_SYNTAX_SHORT = 3;
diff --git a/php_ast.h b/php_ast.h
index d3c0550..3324275 100644
--- a/php_ast.h
+++ b/php_ast.h
@@ -62,10 +62,15 @@ extern ast_str_globals str_globals;
 # define ZEND_AST_TYPE_UNION ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 2)
 # define ZEND_AST_ATTRIBUTE_LIST ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 3)
 # define ZEND_AST_MATCH_ARM_LIST ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 4)
+/* 2 child nodes */
 # define ZEND_AST_CLASS_CONST_GROUP 0x2fe
 # define ZEND_AST_ATTRIBUTE 0x2fd
 # define ZEND_AST_MATCH 0x2fc
 # define ZEND_AST_MATCH_ARM 0x2fb
+# define ZEND_AST_NAMED_ARG 0x2fa
+# define ZEND_AST_NULLSAFE_PROP 0x2f9
+/* 3 child nodes */
+# define ZEND_AST_NULLSAFE_METHOD_CALL 0x3ff
 // NOTE: The first hex digit is the number of child nodes a given kind has
 #endif
 
diff --git a/tests/attributes_01.phpt b/tests/attributes_01.phpt
index c66cc97..da04cb7 100644
--- a/tests/attributes_01.phpt
+++ b/tests/attributes_01.phpt
@@ -11,13 +11,13 @@ $code = <<<'PHP'
 <?php
 namespace NS;
 
-<<SomeAttribute>>
-function test(<<namespace\SomeAttribute(2+2)>> Type $arg) {
+@@SomeAttribute
+function test(@@namespace\SomeAttribute(2+2) Type $arg) {
 }
 
-$x = <<SomeAttribute>> function () {};
+$x = @@SomeAttribute function () {};
 
-$y = <<SomeAttribute>> fn (<<\SomeAttribute>> $a) => $x;
+$y = @@SomeAttribute fn (@@\SomeAttribute $a) => $x;
 PHP;
 
 echo ast_dump(ast\parse_code($code, $version=70));
diff --git a/tests/attributes_02.phpt b/tests/attributes_02.phpt
index 117f1f0..c6c7c8c 100644
--- a/tests/attributes_02.phpt
+++ b/tests/attributes_02.phpt
@@ -11,16 +11,16 @@ $code = <<<'PHP'
 <?php
 namespace NS;
 
-<<\SomeAttribute()>>
+@@\SomeAttribute()
 class X {
-    <<Attr1>>
-    <<Attr2(true)>>
+    @@Attr1
+    @@Attr2(true)
     public $prop;
 
-    <<Attr3>>
+    @@Attr3
     public const CONST_WITH_ATTRIBUTE = 123;
 
-    <<Attr4>>
+    @@Attr4
     public static function hasAttribute() {}
 }
 PHP;
diff --git a/tests/metadata.phpt b/tests/metadata.phpt
index 6dead6e..8eee972 100644
--- a/tests/metadata.phpt
+++ b/tests/metadata.phpt
@@ -88,6 +88,7 @@ AST_CLASS_NAME: []
 AST_CLASS_CONST_GROUP: (combinable) [MODIFIER_PUBLIC, MODIFIER_PROTECTED, MODIFIER_PRIVATE]
 AST_DIM: (combinable) [DIM_ALTERNATIVE_SYNTAX]
 AST_PROP: []
+AST_NULLSAFE_PROP: []
 AST_STATIC_PROP: []
 AST_CALL: []
 AST_CLASS_CONST: []
@@ -119,11 +120,13 @@ AST_GROUP_USE: [USE_NORMAL, USE_FUNCTION, USE_CONST]
 AST_ATTRIBUTE: []
 AST_MATCH: []
 AST_MATCH_ARM: []
+AST_NAMED_ARG: []
 AST_METHOD_CALL: []
+AST_NULLSAFE_METHOD_CALL: []
 AST_STATIC_CALL: []
 AST_CONDITIONAL: (combinable) [PARENTHESIZED_CONDITIONAL]
 AST_TRY: []
 AST_CATCH: []
 AST_FOR: []
 AST_FOREACH: []
-AST_PARAM: (combinable) [PARAM_REF, PARAM_VARIADIC%S]
+AST_PARAM: (combinable) [PARAM_REF, PARAM_VARIADIC, PARAM_MODIFIER_PUBLIC, PARAM_MODIFIER_PROTECTED, PARAM_MODIFIER_PRIVATE]
diff --git a/tests/parse_code_parse_error.phpt b/tests/parse_code_parse_error.phpt
index 57504cf..d82c043 100644
--- a/tests/parse_code_parse_error.phpt
+++ b/tests/parse_code_parse_error.phpt
@@ -18,11 +18,11 @@ try {
 
 ?>
 --EXPECTF--
-ParseError: syntax error, unexpected '&', expecting end of file in string code:1
+ParseError: syntax error, unexpected %s&%s expecting end of file in string code:1
 Stack trace:
 #0 %s(%d): ast\parse_code('%s', %d)
 #1 {main}
-ParseError: syntax error, unexpected '&', expecting end of file in file.php:1
+ParseError: syntax error, unexpected %s&%s expecting end of file in file.php:1
 Stack trace:
 #0 %s(%d): ast\parse_code('%s', %d, 'file.php')
 #1 {main}
diff --git a/tests/parse_file_parse_error.phpt b/tests/parse_file_parse_error.phpt
index 88c0678..8e4a003 100644
--- a/tests/parse_file_parse_error.phpt
+++ b/tests/parse_file_parse_error.phpt
@@ -11,7 +11,7 @@ try {
 
 ?>
 --EXPECTF--
-ParseError: syntax error, unexpected ')' in %stests/invalid_file.php:3
+ParseError: syntax error, unexpected %s)%s in %stests/invalid_file.php:3
 Stack trace:
 #0 %s(%d): ast\parse_file('%s', %d)
 #1 {main}
diff --git a/tests/php80_named_params.phpt b/tests/php80_named_params.phpt
new file mode 100644
index 0000000..8ecffaf
--- /dev/null
+++ b/tests/php80_named_params.phpt
@@ -0,0 +1,52 @@
+--TEST--
+Named parameters in PHP 8.0
+--SKIPIF--
+<?php if (PHP_VERSION_ID < 80000) die('skip PHP >= 8.0 only'); ?>
+--FILE--
+<?php
+
+require __DIR__ . '/../util.php';
+
+$code = <<<'PHP'
+<?php
+$foo(first: 1, second: 2);
+count(var: $argv);
+$other->count(1, myVar:$foo, myVar: 1);  // error
+PHP;
+
+$node = ast\parse_code($code, $version=70);
+echo ast_dump($node), "\n";
+--EXPECTF--
+AST_STMT_LIST
+    0: AST_CALL
+        expr: AST_VAR
+            name: "foo"
+        args: AST_ARG_LIST
+            0: AST_NAMED_ARG
+                name: "first"
+                expr: 1
+            1: AST_NAMED_ARG
+                name: "second"
+                expr: 2
+    1: AST_CALL
+        expr: AST_NAME
+            flags: NAME_NOT_FQ (%d)
+            name: "count"
+        args: AST_ARG_LIST
+            0: AST_NAMED_ARG
+                name: "var"
+                expr: AST_VAR
+                    name: "argv"
+    2: AST_METHOD_CALL
+        expr: AST_VAR
+            name: "other"
+        method: "count"
+        args: AST_ARG_LIST
+            0: 1
+            1: AST_NAMED_ARG
+                name: "myVar"
+                expr: AST_VAR
+                    name: "foo"
+            2: AST_NAMED_ARG
+                name: "myVar"
+                expr: 1
diff --git a/tests/php80_nullsafe_operator.phpt b/tests/php80_nullsafe_operator.phpt
new file mode 100644
index 0000000..38e253f
--- /dev/null
+++ b/tests/php80_nullsafe_operator.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Nullsafe operator in PHP 8.0
+--SKIPIF--
+<?php if (PHP_VERSION_ID < 80000) die('skip PHP >= 8.0 only'); ?>
+--FILE--
+<?php
+
+require __DIR__ . '/../util.php';
+
+$code = <<<'PHP'
+<?php
+$foo?->bar(2);
+$a = $b?->c;
+$a = new $b?->c;
+PHP;
+
+$node = ast\parse_code($code, $version=70);
+echo ast_dump($node), "\n";
+--EXPECTF--
+AST_STMT_LIST
+    0: AST_NULLSAFE_METHOD_CALL
+        expr: AST_VAR
+            name: "foo"
+        method: "bar"
+        args: AST_ARG_LIST
+            0: 2
+    1: AST_ASSIGN
+        var: AST_VAR
+            name: "a"
+        expr: AST_NULLSAFE_PROP
+            expr: AST_VAR
+                name: "b"
+            prop: "c"
+    2: AST_ASSIGN
+        var: AST_VAR
+            name: "a"
+        expr: AST_NEW
+            class: AST_NULLSAFE_PROP
+                expr: AST_VAR
+                    name: "b"
+                prop: "c"
+            args: AST_ARG_LIST
\ No newline at end of file
diff --git a/tests/php80_promotion.phpt b/tests/php80_promotion.phpt
index 5c58380..b9a91d6 100644
--- a/tests/php80_promotion.phpt
+++ b/tests/php80_promotion.phpt
@@ -38,13 +38,13 @@ AST_STMT_LIST
                 docComment: "/** Doc comment for __construct */"
                 params: AST_PARAM_LIST
                     0: AST_PARAM
-                        flags: MODIFIER_PUBLIC (%d)
+                        flags: PARAM_MODIFIER_PUBLIC (%d)
                         type: AST_TYPE
                             flags: TYPE_LONG (4)
                         name: "a"
                         default: null
                     1: AST_PARAM
-                        flags: PARAM_REF | MODIFIER_PRIVATE (%d)
+                        flags: PARAM_REF | PARAM_MODIFIER_PRIVATE (%d)
                         type: AST_NAME
                             flags: NAME_NOT_FQ (1)
                             name: "stdClass"
@@ -54,7 +54,7 @@ AST_STMT_LIST
                                 flags: NAME_NOT_FQ (1)
                                 name: "null"
                     2: AST_PARAM
-                        flags: MODIFIER_PROTECTED (%d)
+                        flags: PARAM_MODIFIER_PROTECTED (%d)
                         type: AST_TYPE
                             flags: TYPE_ITERABLE (13)
                         name: "c"