From df5a413be4bf0545bff6fc6583d7f5c7289dcb2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 29 Aug 2025 16:11:30 +0200 Subject: [PATCH 1/3] zend_portability: Add `ZEND_ATTRIBUTE_NODISCARD` --- Zend/zend_portability.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 49961139202f8..674912ddf892b 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 +# 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 3e99869a2541d9b0e81ff875602c363323474a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 29 Aug 2025 16:15:12 +0200 Subject: [PATCH 2/3] 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/tests/attributes/constants/multiple_constants_error.phpt | 4 +++- Zend/zend_ast.c | 4 ++-- Zend/zend_ast.h | 2 +- Zend/zend_compile.c | 2 +- 4 files changed, 7 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); From ba326b6a7135aca0f29997676ca65bbe9463a08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 29 Aug 2025 16:57:23 +0200 Subject: [PATCH 3/3] zend_portability: Support C++ for `ZEND_ATTRIBUTE_NODISCARD` Co-authored-by: David CARLIER --- Zend/zend_portability.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 674912ddf892b..277204260ce82 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -248,7 +248,7 @@ char *alloca(); # define ZEND_ATTRIBUTE_ALLOC_SIZE2(X,Y) #endif -#if __STDC_VERSION__ >= 202311L +#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__))