Skip to content

Document assert_(), combine with __ASSERT_; fixup Perl_assert() #23543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: blead
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions handy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
67 changes: 55 additions & 12 deletions perl.h
Original file line number Diff line number Diff line change
Expand Up @@ -5092,25 +5092,68 @@ 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<assert()> call in comma
expressions in macro expansions, but you probably don't want to use them nor
plain C<assert>; 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<assert()>) 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<assert()> 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 us plain C<assert>, and say S<C<assert(...), assert(...),>>
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. */

#define Perl_assert(what) PERL_DEB2( \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit Cleanup Perl_assert definition

I would slightly alter the commit message and add something like:

For reference: PERL_DEB2 is defined as:

#ifdef DEBUGGING
#  define PERL_DEB2(a,b)               a
#else /* ! DEBUGGING below */
#  define PERL_DEB2(a,b)               b
#endif /* DEBUGGING */

(I had no clue what PERL_DEB2 did so had to look it up before I could review the change)

((what) ? ((void) 0) : \
(Perl_croak_nocontext("Assertion %s failed: file \"" __FILE__ \
"\", line %d", STRINGIFY(what), __LINE__), \
(void) 0)), ((void)0))

/* assert() gets defined if DEBUGGING.
* If no DEBUGGING, the <assert.h> has not been included. */
#ifndef assert
# define assert(what) Perl_assert(what)
#endif
#ifdef DEBUGGING
# define assert_(what) assert(what),
# define assert(what) Perl_assert(what)
#endif

#if defined DEBUGGING \
&& ! defined(__COVERITY__) \
&& ! defined(PERL_SMALL_MACRO_BUFFER)
# define Perl_assert(what) \
((what) \
? ((void) 0) \
: Perl_croak_nocontext("Assertion %s failed:" \
" file \"" __FILE__ "\", line %" LINE_Tf, \
STRINGIFY(what), (line_t) __LINE__))
# 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 {
Expand Down
Loading