From 6ba5f7e195f3d9492adad49e8966597affe39990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 29 Aug 2025 19:57:04 +0200 Subject: [PATCH 1/2] zend_ast: Mark `zend_ast_list_add()` as `ZEND_ATTRIBUTE_NODISCARD` (#19632) * zend_portability: Add `ZEND_ATTRIBUTE_NODISCARD` * zend_ast: Mark `zend_ast_list_add()` as `ZEND_ATTRIBUTE_NODISCARD` This actually caught a bug in the implementation of attributes on regular constants: A list of 4 constants with an attribute did not correctly result in an error, since the reallocated list wasn't stored anywhere. * zend_portability: Support C++ for `ZEND_ATTRIBUTE_NODISCARD` Co-authored-by: David CARLIER --------- Co-authored-by: David CARLIER --- .../attributes/constants/multiple_constants_error.phpt | 4 +++- Zend/zend_ast.c | 4 ++-- Zend/zend_ast.h | 2 +- Zend/zend_compile.c | 2 +- Zend/zend_portability.h | 8 ++++++++ 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Zend/tests/attributes/constants/multiple_constants_error.phpt b/Zend/tests/attributes/constants/multiple_constants_error.phpt index d4258c9f4d080..b7ee91d3f1d97 100644 --- a/Zend/tests/attributes/constants/multiple_constants_error.phpt +++ b/Zend/tests/attributes/constants/multiple_constants_error.phpt @@ -5,7 +5,9 @@ Error trying to add attributes to multiple constants at once #[\Foo] const First = 1, - Second = 2; + Second = 2, + Third = 3, + Fourth = 4; ?> --EXPECTF-- diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index fd2526fb5e667..2f66d8d5cd2b1 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -498,7 +498,7 @@ static inline bool is_power_of_two(uint32_t n) { return ((n != 0) && (n == (n & (~n + 1)))); } -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) { +ZEND_ATTRIBUTE_NODISCARD ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) { zend_ast_list *list = zend_ast_get_list(ast); if (list->children >= 4 && is_power_of_two(list->children)) { list = zend_ast_realloc(list, @@ -2956,7 +2956,7 @@ zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr) /* Since constants are already stored in a list, just add the attributes * to that list instead of storing them elsewhere; * zend_compile_const_decl() checks the kind of the list elements. */ - zend_ast_list_add(ast, attr); + ast = zend_ast_list_add(ast, attr); break; EMPTY_SWITCH_DEFAULT_CASE() } diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 8ce1c49f6bb0c..fb48b187252b3 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -320,7 +320,7 @@ ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, .. ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...); #endif -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *list, zend_ast *op); +ZEND_ATTRIBUTE_NODISCARD ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *list, zend_ast *op); ZEND_API zend_ast *zend_ast_create_decl( zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 875239515441e..e01b985b6d68f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4391,7 +4391,7 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string ZSTR_INIT_LITERAL("description", 0)); arg = zend_ast_create(ZEND_AST_NAMED_ARG, name, arg); } - zend_ast_list_add((zend_ast *) args, arg); + args = (zend_ast_list *)zend_ast_list_add((zend_ast *) args, arg); } zend_compile_call_common(result, (zend_ast*)args, fbc, lineno); diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 49961139202f8..277204260ce82 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -248,6 +248,14 @@ char *alloca(); # define ZEND_ATTRIBUTE_ALLOC_SIZE2(X,Y) #endif +#if __STDC_VERSION__ >= 202311L || (defined(__cplusplus) && __cplusplus >= 201703L) +# define ZEND_ATTRIBUTE_NODISCARD [[nodiscard]] +#elif __has_attribute(__warn_unused_result__) +# define ZEND_ATTRIBUTE_NODISCARD __attribute__((__warn_unused_result__)) +#else +# define ZEND_ATTRIBUTE_NODISCARD +#endif + #if ZEND_GCC_VERSION >= 3000 # define ZEND_ATTRIBUTE_CONST __attribute__((const)) #else From 914f9ad49be800e887b4c5df637ff9af02eb5eeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 29 Aug 2025 19:58:44 +0200 Subject: [PATCH 2/2] Optimizer/zend_dump: Fix printing of the exception table (#19634) A newline was missing for finally blocks. --- Zend/Optimizer/zend_dump.c | 2 +- ext/opcache/tests/opt/gh18107_1.phpt | 1 + ext/opcache/tests/opt/gh18107_2.phpt | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Zend/Optimizer/zend_dump.c b/Zend/Optimizer/zend_dump.c index 4e46b38a8eb5e..64deb7085edf3 100644 --- a/Zend/Optimizer/zend_dump.c +++ b/Zend/Optimizer/zend_dump.c @@ -1164,7 +1164,7 @@ ZEND_API void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_fl } if (op_array->try_catch_array[i].finally_end) { fprintf(stderr, - ", %04u", + ", %04u\n", op_array->try_catch_array[i].finally_end); } else { fprintf(stderr, ", -\n"); diff --git a/ext/opcache/tests/opt/gh18107_1.phpt b/ext/opcache/tests/opt/gh18107_1.phpt index c99fa7efa40d3..fea270a4d5a08 100644 --- a/ext/opcache/tests/opt/gh18107_1.phpt +++ b/ext/opcache/tests/opt/gh18107_1.phpt @@ -41,6 +41,7 @@ $_main: 0011 FAST_RET T5 EXCEPTION TABLE: 0006, -, 0007, 0011 + Fatal error: Uncaught Exception: Should happen in %s:%d Stack trace: #0 {main} diff --git a/ext/opcache/tests/opt/gh18107_2.phpt b/ext/opcache/tests/opt/gh18107_2.phpt index 573bcd5ae4a6f..aaf58b4f820de 100644 --- a/ext/opcache/tests/opt/gh18107_2.phpt +++ b/ext/opcache/tests/opt/gh18107_2.phpt @@ -48,6 +48,7 @@ $_main: 0015 RETURN int(1) EXCEPTION TABLE: 0006, 0006, 0010, 0014 + Fatal error: Uncaught Exception: Should happen in %s:%d Stack trace: #0 {main}