From 0954feae6411cc0de5f5cb6c7e007b972388139f Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 5 Jun 2014 10:42:05 -0700 Subject: [PATCH] assert.h: allow gcc to detect assert(a = 1) errors * assert/assert.h (assert): Rewrite assert's definition so that a s/==/=/ typo, e.g., assert(errno = ENOENT) is not hidden from gcc's -Wparentheses by assert-added parentheses. The new definition uses "if (expr) /* empty */; else __assert_fail...", so gcc -Wall will now detect that type of error in an assert, too. The __STRICT_ANSI__ disjunct is to avoid the warning that -Wpedantic would otherwise issue for the use of ({...}). I would have preferred to use __extension__ to mark that, but doing so would mistakenly suppress warnings about any extension in the user-supplied "expr". E.g., "assert ( ({1;}) )" must continue to evoke a warning. --- ChangeLog | 15 +++++++++++++++ assert/assert.h | 21 +++++++++++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index e19db5d..a0181e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2016-11-25 Jim Meyering + + Let gcc detect assert(a = 1) errors. + * assert/assert.h (assert): Rewrite assert's definition so that a + s/==/=/ typo, e.g., assert(errno = ENOENT) is not hidden from + gcc's -Wparentheses by assert-added parentheses. The new + definition uses "if (expr) /* empty */; else __assert_fail...", + so gcc -Wall will now detect that type of error in an assert, too. + The __STRICT_ANSI__ disjunct is to avoid the warning that -Wpedantic + would otherwise issue for the use of ({...}). I would have preferred + to use __extension__ to mark that, but doing so would mistakenly + suppress warnings about any extension in the user-supplied "expr". + E.g., "assert ( ({1;}) )" must continue to evoke a warning. + https://bugzilla.redhat.com/1105335 + 2016-12-08 Joseph Myers * Rules [$(run-built-tests) != no] (tests-expected): Add diff --git a/assert/assert.h b/assert/assert.h index 729edeb..0f25131 100644 --- a/assert/assert.h +++ b/assert/assert.h @@ -82,10 +82,23 @@ extern void __assert (const char *__assertion, const char *__file, int __line) __END_DECLS -# define assert(expr) \ - ((expr) \ - ? __ASSERT_VOID_CAST (0) \ - : __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION)) +/* When possible, define assert so that it does not add extra + parentheses around EXPR. Otherwise, those added parentheses would + suppress warnings we'd expect to be detected by gcc's -Wparentheses. */ +# if !defined __GNUC__ || defined __STRICT_ANSI__ +# define assert(expr) \ + ((expr) \ + ? __ASSERT_VOID_CAST (0) \ + : __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION)) +# else +# define assert(expr) \ + ({ \ + if (expr) \ + ; /* empty */ \ + else \ + __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION); \ + }) +# endif # ifdef __USE_GNU # define assert_perror(errnum) \ -- 2.9.3