From 1d94fb1ad057f628f1cb4ea990496624ccecf72f Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Wed, 6 Aug 2025 06:07:55 -0600 Subject: [PATCH 1/8] perl.h: Remove obsolete comment This comment is not true; it may have been true once. assert.h is always included, and assert() is always supposed to be defined, since at least C89. But the code acts like it is possible to not be defined; it's not a big deal to retain that check, so I'm leaving it in. --- perl.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/perl.h b/perl.h index 0b8bce9c6ed2..99ae7f4e5b90 100644 --- a/perl.h +++ b/perl.h @@ -5119,8 +5119,6 @@ Gid_t getegid (void); "\", line %d", STRINGIFY(what), __LINE__), \ (void) 0)), ((void)0)) -/* assert() gets defined if DEBUGGING. - * If no DEBUGGING, the has not been included. */ #ifndef assert # define assert(what) Perl_assert(what) #endif From c502b737821ff4d7cfc8fed74672c4dedb4b6459 Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Tue, 5 Aug 2025 13:42:56 -0600 Subject: [PATCH 2/8] Cleanup Perl_assert definition PERL_DEB2 is too obscure for me. Simply use #ifdef DEBUGGING --- perl.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/perl.h b/perl.h index 99ae7f4e5b90..8f11f6e25118 100644 --- a/perl.h +++ b/perl.h @@ -5113,11 +5113,16 @@ Gid_t getegid (void); /* Keep the old croak based assert for those who want it, and as a fallback if the platform is so heretically non-ANSI that it can't assert. */ -#define Perl_assert(what) PERL_DEB2( \ - ((what) ? ((void) 0) : \ - (Perl_croak_nocontext("Assertion %s failed: file \"" __FILE__ \ - "\", line %d", STRINGIFY(what), __LINE__), \ - (void) 0)), ((void)0)) +#ifdef DEBUGGING +# define Perl_assert(what) \ + ((what) \ + ? ((void) 0) \ + : (Perl_croak_nocontext("Assertion %s failed: file \"" __FILE__ \ + "\", line %d", STRINGIFY(what), __LINE__), \ + (void) 0)) +#else +# define Perl_assert(what) ((void) 0) +#endif #ifndef assert # define assert(what) Perl_assert(what) From 907b1dec0a29043add24aff7fae8dbe3e4105dd5 Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Wed, 6 Aug 2025 05:50:27 -0600 Subject: [PATCH 3/8] Reformat Perl_assert() definition This changes the white space in preparation for the next commit --- perl.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/perl.h b/perl.h index 8f11f6e25118..2af7826dfc50 100644 --- a/perl.h +++ b/perl.h @@ -5115,11 +5115,12 @@ Gid_t getegid (void); #ifdef DEBUGGING # define Perl_assert(what) \ - ((what) \ - ? ((void) 0) \ - : (Perl_croak_nocontext("Assertion %s failed: file \"" __FILE__ \ - "\", line %d", STRINGIFY(what), __LINE__), \ - (void) 0)) + ((what) \ + ? ((void) 0) \ + : (Perl_croak_nocontext("Assertion %s failed:" \ + " file \"" __FILE__ "\", line %d", \ + STRINGIFY(what), __LINE__), \ + (void) 0)) #else # define Perl_assert(what) ((void) 0) #endif From 2c5267ad5cfd4172c2bd8cc5765617fe3405f908 Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Wed, 6 Aug 2025 06:00:53 -0600 Subject: [PATCH 4/8] Fix Perl_assert() definition Source code line numbers now have a typedef and format so that they work on a variety of platforms. --- perl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/perl.h b/perl.h index 2af7826dfc50..c5fcefa5c33a 100644 --- a/perl.h +++ b/perl.h @@ -5118,8 +5118,8 @@ Gid_t getegid (void); ((what) \ ? ((void) 0) \ : (Perl_croak_nocontext("Assertion %s failed:" \ - " file \"" __FILE__ "\", line %d", \ - STRINGIFY(what), __LINE__), \ + " file \"" __FILE__ "\", line %" LINE_Tf, \ + STRINGIFY(what), (line_t) __LINE__), \ (void) 0)) #else # define Perl_assert(what) ((void) 0) From 791874e267455872707960ec55e43dde151b093e Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Wed, 6 Aug 2025 06:07:08 -0600 Subject: [PATCH 5/8] perl.h Move macro definition to earlier This makes the next commits smaller. --- perl.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/perl.h b/perl.h index c5fcefa5c33a..ca2a84d05cd9 100644 --- a/perl.h +++ b/perl.h @@ -5113,6 +5113,10 @@ Gid_t getegid (void); /* Keep the old croak based assert for those who want it, and as a fallback if the platform is so heretically non-ANSI that it can't assert. */ +#ifndef assert +# define assert(what) Perl_assert(what) +#endif + #ifdef DEBUGGING # define Perl_assert(what) \ ((what) \ @@ -5125,9 +5129,6 @@ Gid_t getegid (void); # define Perl_assert(what) ((void) 0) #endif -#ifndef assert -# define assert(what) Perl_assert(what) -#endif #ifdef DEBUGGING # define assert_(what) assert(what), #else From 0a745c4dcffa1f7a5c31f64c8064a1f4e7d40d4d Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Wed, 6 Aug 2025 06:12:58 -0600 Subject: [PATCH 6/8] perl.h: Combine two preprocessor blocks They have the same conditional, and the next commit will change that conditional and want it to apply to both. --- perl.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/perl.h b/perl.h index ca2a84d05cd9..507de3a3e59c 100644 --- a/perl.h +++ b/perl.h @@ -5125,13 +5125,9 @@ Gid_t getegid (void); " file \"" __FILE__ "\", line %" LINE_Tf, \ STRINGIFY(what), (line_t) __LINE__), \ (void) 0)) +# define assert_(what) assert(what), #else # define Perl_assert(what) ((void) 0) -#endif - -#ifdef DEBUGGING -# define assert_(what) assert(what), -#else # define assert_(what) #endif From 28cffa9a4d09323ff3eaec5277c7372488731f16 Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Wed, 6 Aug 2025 06:14:54 -0600 Subject: [PATCH 7/8] Perl_assert() expands to noop if Coverity, etc, Some assertions have caused Coverity to complain in the past, or overflowed for some platforms, so the definition of __ASSERT_ in handy.h expands to a no-op if under Coverity or the system doesn't have a normal sized macro buffer. Bring that definition here to also be the same for Perl_assert(). --- perl.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/perl.h b/perl.h index 507de3a3e59c..4842193296e5 100644 --- a/perl.h +++ b/perl.h @@ -5117,7 +5117,9 @@ Gid_t getegid (void); # define assert(what) Perl_assert(what) #endif -#ifdef DEBUGGING +#if defined DEBUGGING \ + && ! defined(__COVERITY__) \ + && ! defined(PERL_SMALL_MACRO_BUFFER) # define Perl_assert(what) \ ((what) \ ? ((void) 0) \ From 9a53e6b583c5a01c4ec1f9b96c6ddb65a5781039 Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Wed, 6 Aug 2025 06:16:45 -0600 Subject: [PATCH 8/8] Move __ASSERT_() definition adjacent to assert_() And fix up the documentation, adding a caution that their use can easily lead to differing behavior in DEBUGGING vs non-DEBUGGING builds. These two macros are synonymous. This documents assert_() for the first time and clarifies their usage. Thanks to Tony Cook for clarifying this for me. --- handy.h | 22 ---------------------- perl.h | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/handy.h b/handy.h index 8fc061997b7a..a4e32c4e4e95 100644 --- a/handy.h +++ b/handy.h @@ -348,28 +348,6 @@ don't, so that you can portably take advantage of this C99 feature. /* The largest unsigned number that will fit into n bits */ #define nBIT_UMAX(n) nBIT_MASK(n) -/* -=for apidoc_section $directives -=for apidoc Am||__ASSERT_|bool expr - -This is a helper macro to avoid preprocessor issues, replaced by nothing -unless under DEBUGGING, where it expands to an assert of its argument, -followed by a comma (hence the comma operator). If we just used a straight -assert(), we would get a comma with nothing before it when not DEBUGGING. - -=cut - -We also use empty definition under Coverity since the __ASSERT_ -checks often check for things that Really Cannot Happen, and Coverity -detects that and gets all excited. */ - -#if defined(DEBUGGING) && !defined(__COVERITY__) \ - && ! defined(PERL_SMALL_MACRO_BUFFER) -# define __ASSERT_(statement) assert(statement), -#else -# define __ASSERT_(statement) -#endif - /* =for apidoc_section $SV diff --git a/perl.h b/perl.h index 4842193296e5..844f03fe141b 100644 --- a/perl.h +++ b/perl.h @@ -5109,6 +5109,45 @@ Gid_t getegid (void); Perl_deb(aTHX_ "%s scope %ld (savestack=%ld) at %s:%d\n", \ where, (long)PL_scopestack_ix, (long)PL_savestack_ix, \ __FILE__, __LINE__)); +/* +=for apidoc_section $directives +=for apidoc Am|void|assert_|bool expr +=for apidoc_item | |__ASSERT_ + +These are synonymous, used to wrap the libc C call in comma +expressions in macro expansions, but you probably don't want to use them nor +plain C; read on. + +In DEBUGGING builds, each expands to an assert of its argument, followed by +a comma. (That is what the trailing underscore signifies.) + +In non-DEBUGGING builds, each expands to nothing. + +They thus can be used to string together a bunch of asserts in a comma +expression that is syntactically valid in either type of build. + +NOTE, however, use of these (and plain C) is discouraged in a macro. +This is because their usual use is to validate some of the arguments to that +macro. That will likely lead to the evaluation of those arguments more than +once during the macro expansion. If such an argument is an expression with +side effects, the behavior of the macro will differ between DEBUGGING and +non-DEBUGGING builds. + +And, they are necessary only on platforms where the libc C expands to +nothing when not in a DEBUGGING build. There should be no such platforms now +in existence, as the C89 standard forbids that, and Perl requires at least C99. +So, you can just use plain C, and say S> +and everything will compile (and will work if none of the arguments to the +asserts is an expression with side effects). + +These macros are retained for backward compatibility. + +Do NOT use C<__ASSERT_>. A name with two leading underscores followed by a +capital letter is reserved for the use of the compiler and libc in some +contexts in C, and in all contexts in C++. + +=cut +*/ /* Keep the old croak based assert for those who want it, and as a fallback if the platform is so heretically non-ANSI that it can't assert. */ @@ -5128,9 +5167,11 @@ Gid_t getegid (void); STRINGIFY(what), (line_t) __LINE__), \ (void) 0)) # define assert_(what) assert(what), +# define __ASSERT_(statement) assert(statement), #else # define Perl_assert(what) ((void) 0) # define assert_(what) +# define __ASSERT_(statement) #endif struct ufuncs {