* undefined behaviour findings
@ 2019-03-09 19:33 Bruno Haible
2019-03-09 19:37 ` undefined behaviour findings in bitset Bruno Haible
2019-03-09 21:22 ` undefined behaviour findings Bruno Haible
0 siblings, 2 replies; 17+ messages in thread
From: Bruno Haible @ 2019-03-09 19:33 UTC (permalink / raw)
To: bug-gnulib; +Cc: Jeffrey Walton
Following Jeffrey Walton's example, I built and tested a gnulib
testdir with CC="gcc -fsanitize=undefined". Here are the findings.
Of course, since this is based on runtime tests, not gcc warnings, it does not
produce findings for modules without unit tests.
lib/bitrotate.h:98:14: runtime error: left shift of 43981 by 16 places cannot be represented in type 'int'
lib/bitrotate.h:109:25: runtime error: left shift of 43981 by 16 places cannot be represented in type 'int'
lib/bitset/table.c:784:54: runtime error: shift exponent 87 is too large for 64-bit type 'long unsigned int'
lib/des.c:552:3: runtime error: left shift of 255 by 24 places cannot be represented in type 'int'
lib/des.c:437:3: runtime error: left shift of 242 by 24 places cannot be represented in type 'int'
lib/des.c:625:3: runtime error: left shift of 254 by 24 places cannot be represented in type 'int'
lib/xmemdup0.c:41:3: runtime error: null pointer passed as argument 2, which is declared to never be null
tests/test-c-stack.c:66:13: runtime error: load of null pointer of type 'char'
tests/test-canonicalize.c:74:15: runtime error: null pointer passed as argument 1, which is declared to never be null
tests/test-count-leading-zeros.c:56:3: runtime error: left shift of 1804289383 by 31 places cannot be represented in type 'int'
tests/test-count-leading-zeros.c:56:3: runtime error: left shift of negative value -2147483648
tests/test-count-one-bits.c:55:3: runtime error: left shift of 1804289383 by 31 places cannot be represented in type 'int'
tests/test-count-one-bits.c:55:3: runtime error: left shift of negative value -2147483648
tests/test-count-trailing-zeros.c:56:3: runtime error: left shift of 1804289383 by 31 places cannot be represented in type 'int'
tests/test-count-trailing-zeros.c:56:3: runtime error: left shift of negative value -2147483648
tests/test-memmem.c:84:26: runtime error: null pointer passed as argument 3, which is declared to never be null
Let me fix some of them here.
2019-03-09 Bruno Haible <bruno@clisp.org>
Fix undefined behaviour.
* lib/bitrotate.h (rotl16, rotr16, rotl8, rotr8): Case x to
'unsigned int', to avoid shift operations on 'int'.
* lib/xmemdup0.c (xmemdup0): Don't invoke memcpy with a zero size.
* tests/test-count-leading-zeros.c (main): Use a random number that has
as many bits as TYPE, not only 2*15 or 2*31 bits.
* tests/test-count-trailing-zeros.c (main): Likewise.
* tests/test-count-one-bits.c (main): Likewise.
* tests/test-memmem.c: Don't include "null-ptr.h".
(main): Use zerosize_ptr() instead of null_ptr().
* modules/memmem-tests (Files): Remove tests/null-ptr.h.
diff --git a/lib/bitrotate.h b/lib/bitrotate.h
index 862331e..04b9083 100644
--- a/lib/bitrotate.h
+++ b/lib/bitrotate.h
@@ -95,7 +95,8 @@ rotr_sz (size_t x, int n)
BITROTATE_INLINE uint16_t
rotl16 (uint16_t x, int n)
{
- return ((x << n) | (x >> (16 - n))) & UINT16_MAX;
+ return (((unsigned int) x << n) | ((unsigned int) x >> (16 - n)))
+ & UINT16_MAX;
}
/* Given an unsigned 16-bit argument X, return the value corresponding
@@ -106,7 +107,8 @@ rotl16 (uint16_t x, int n)
BITROTATE_INLINE uint16_t
rotr16 (uint16_t x, int n)
{
- return ((x >> n) | (x << (16 - n))) & UINT16_MAX;
+ return (((unsigned int) x >> n) | ((unsigned int) x << (16 - n)))
+ & UINT16_MAX;
}
/* Given an unsigned 8-bit argument X, return the value corresponding
@@ -117,7 +119,7 @@ rotr16 (uint16_t x, int n)
BITROTATE_INLINE uint8_t
rotl8 (uint8_t x, int n)
{
- return ((x << n) | (x >> (8 - n))) & UINT8_MAX;
+ return (((unsigned int) x << n) | ((unsigned int) x >> (8 - n))) & UINT8_MAX;
}
/* Given an unsigned 8-bit argument X, return the value corresponding
@@ -128,7 +130,7 @@ rotl8 (uint8_t x, int n)
BITROTATE_INLINE uint8_t
rotr8 (uint8_t x, int n)
{
- return ((x >> n) | (x << (8 - n))) & UINT8_MAX;
+ return (((unsigned int) x >> n) | ((unsigned int) x << (8 - n))) & UINT8_MAX;
}
_GL_INLINE_HEADER_END
diff --git a/lib/xmemdup0.c b/lib/xmemdup0.c
index 4f491be..57c1b59 100644
--- a/lib/xmemdup0.c
+++ b/lib/xmemdup0.c
@@ -38,7 +38,8 @@ char *
xmemdup0 (void const *p, size_t s)
{
char *result = xcharalloc (s + 1);
- memcpy (result, p, s);
+ if (s > 0)
+ memcpy (result, p, s);
result[s] = 0;
return result;
}
diff --git a/tests/test-count-leading-zeros.c b/tests/test-count-leading-zeros.c
index 3caae7f..e94e37e 100644
--- a/tests/test-count-leading-zeros.c
+++ b/tests/test-count-leading-zeros.c
@@ -34,23 +34,34 @@ main (int argc, char *argv[])
{
int i, j;
-#define TEST_COUNT_LEADING_ZEROS(FUNC, TYPE, BITS, MAX, ONE) \
- ASSERT (FUNC (0) == BITS); \
- for (i = 0; i < BITS; i++) \
- { \
- ASSERT (FUNC (ONE << i) == BITS - i - 1); \
- for (j = 0; j < i; j++) \
- ASSERT (FUNC ((ONE << i) | (ONE << j)) == BITS - i - 1);\
- } \
- for (i = 0; i < 1000; i++) \
- { \
- TYPE value = rand () ^ (rand () << 31 << 1); \
- int count = 0; \
- for (j = 0; j < BITS; j++) \
- if (value & (ONE << j)) \
- count = BITS - j - 1; \
- ASSERT (count == FUNC (value)); \
- } \
+#define TEST_COUNT_LEADING_ZEROS(FUNC, TYPE, BITS, MAX, ONE) \
+ ASSERT (FUNC (0) == BITS); \
+ for (i = 0; i < BITS; i++) \
+ { \
+ ASSERT (FUNC (ONE << i) == BITS - i - 1); \
+ for (j = 0; j < i; j++) \
+ ASSERT (FUNC ((ONE << i) | (ONE << j)) == BITS - i - 1); \
+ } \
+ for (i = 0; i < 1000; i++) \
+ { \
+ /* RAND_MAX is most often 0x7fff or 0x7fffffff. */ \
+ TYPE value = \
+ (RAND_MAX <= 0xffff \
+ ? ((TYPE) rand () >> 3) \
+ ^ (((TYPE) rand () >> 3) << 12) \
+ ^ (((TYPE) rand () >> 3) << 24) \
+ ^ (((TYPE) rand () >> 3) << 30 << 6) \
+ ^ (((TYPE) rand () >> 3) << 30 << 18) \
+ ^ (((TYPE) rand () >> 3) << 30 << 30) \
+ : ((TYPE) rand () >> 3) \
+ ^ (((TYPE) rand () >> 3) << 22) \
+ ^ (((TYPE) rand () >> 3) << 22 << 22)); \
+ int count = 0; \
+ for (j = 0; j < BITS; j++) \
+ if (value & (ONE << j)) \
+ count = BITS - j - 1; \
+ ASSERT (count == FUNC (value)); \
+ } \
ASSERT (FUNC (MAX) == 0);
TEST_COUNT_LEADING_ZEROS (count_leading_zeros, unsigned int,
diff --git a/tests/test-count-one-bits.c b/tests/test-count-one-bits.c
index 109f3ee..852e1d6 100644
--- a/tests/test-count-one-bits.c
+++ b/tests/test-count-one-bits.c
@@ -34,22 +34,33 @@ main (int argc, char *argv[])
{
int i, j;
-#define TEST_COUNT_ONE_BITS(FUNC, TYPE, BITS, MAX, ONE) \
- ASSERT (FUNC (0) == 0); \
- for (i = 0; i < BITS; i++) \
- { \
- ASSERT (FUNC (ONE << i) == 1); \
- for (j = i + 1; j < BITS; j++) \
- ASSERT (FUNC ((ONE << i) | (ONE << j)) == 2); \
- } \
- for (i = 0; i < 1000; i++) \
- { \
- TYPE value = rand () ^ (rand () << 31 << 1); \
- int count = 0; \
- for (j = 0; j < BITS; j++) \
- count += (value & (ONE << j)) != 0; \
- ASSERT (count == FUNC (value)); \
- } \
+#define TEST_COUNT_ONE_BITS(FUNC, TYPE, BITS, MAX, ONE) \
+ ASSERT (FUNC (0) == 0); \
+ for (i = 0; i < BITS; i++) \
+ { \
+ ASSERT (FUNC (ONE << i) == 1); \
+ for (j = i + 1; j < BITS; j++) \
+ ASSERT (FUNC ((ONE << i) | (ONE << j)) == 2); \
+ } \
+ for (i = 0; i < 1000; i++) \
+ { \
+ /* RAND_MAX is most often 0x7fff or 0x7fffffff. */ \
+ TYPE value = \
+ (RAND_MAX <= 0xffff \
+ ? ((TYPE) rand () >> 3) \
+ ^ (((TYPE) rand () >> 3) << 12) \
+ ^ (((TYPE) rand () >> 3) << 24) \
+ ^ (((TYPE) rand () >> 3) << 30 << 6) \
+ ^ (((TYPE) rand () >> 3) << 30 << 18) \
+ ^ (((TYPE) rand () >> 3) << 30 << 30) \
+ : ((TYPE) rand () >> 3) \
+ ^ (((TYPE) rand () >> 3) << 22) \
+ ^ (((TYPE) rand () >> 3) << 22 << 22)); \
+ int count = 0; \
+ for (j = 0; j < BITS; j++) \
+ count += (value & (ONE << j)) != 0; \
+ ASSERT (count == FUNC (value)); \
+ } \
ASSERT (FUNC (MAX) == BITS);
TEST_COUNT_ONE_BITS (count_one_bits, unsigned int, UINT_BIT, UINT_MAX, 1U);
diff --git a/tests/test-count-trailing-zeros.c b/tests/test-count-trailing-zeros.c
index 5a18599..04d9ddc 100644
--- a/tests/test-count-trailing-zeros.c
+++ b/tests/test-count-trailing-zeros.c
@@ -34,23 +34,34 @@ main (int argc, char *argv[])
{
int i, j;
-#define TEST_COUNT_TRAILING_ZEROS(FUNC, TYPE, BITS, MAX, ONE) \
- ASSERT (FUNC (0) == BITS); \
- for (i = 0; i < BITS; i++) \
- { \
- ASSERT (FUNC (ONE << i) == i); \
- for (j = 0; j < i; j++) \
- ASSERT (FUNC ((ONE << i) | (ONE << j)) == j); \
- } \
- for (i = 0; i < 1000; i++) \
- { \
- TYPE value = rand () ^ (rand () << 31 << 1); \
- int count = 0; \
- for (j = BITS - 1; 0 <= j; j--) \
- if (value & (ONE << j)) \
- count = j; \
- ASSERT (count == FUNC (value)); \
- } \
+#define TEST_COUNT_TRAILING_ZEROS(FUNC, TYPE, BITS, MAX, ONE) \
+ ASSERT (FUNC (0) == BITS); \
+ for (i = 0; i < BITS; i++) \
+ { \
+ ASSERT (FUNC (ONE << i) == i); \
+ for (j = 0; j < i; j++) \
+ ASSERT (FUNC ((ONE << i) | (ONE << j)) == j); \
+ } \
+ for (i = 0; i < 1000; i++) \
+ { \
+ /* RAND_MAX is most often 0x7fff or 0x7fffffff. */ \
+ TYPE value = \
+ (RAND_MAX <= 0xffff \
+ ? ((TYPE) rand () >> 3) \
+ ^ (((TYPE) rand () >> 3) << 12) \
+ ^ (((TYPE) rand () >> 3) << 24) \
+ ^ (((TYPE) rand () >> 3) << 30 << 6) \
+ ^ (((TYPE) rand () >> 3) << 30 << 18) \
+ ^ (((TYPE) rand () >> 3) << 30 << 30) \
+ : ((TYPE) rand () >> 3) \
+ ^ (((TYPE) rand () >> 3) << 22) \
+ ^ (((TYPE) rand () >> 3) << 22 << 22)); \
+ int count = 0; \
+ for (j = BITS - 1; 0 <= j; j--) \
+ if (value & (ONE << j)) \
+ count = j; \
+ ASSERT (count == FUNC (value)); \
+ } \
ASSERT (FUNC (MAX) == 0);
TEST_COUNT_TRAILING_ZEROS (count_trailing_zeros, unsigned int,
diff --git a/tests/test-memmem.c b/tests/test-memmem.c
index ed327e6..17e2e41 100644
--- a/tests/test-memmem.c
+++ b/tests/test-memmem.c
@@ -26,7 +26,6 @@ SIGNATURE_CHECK (memmem, void *, (void const *, size_t, void const *, size_t));
#include <stdlib.h>
#include <unistd.h>
-#include "null-ptr.h"
#include "zerosize-ptr.h"
#include "macros.h"
@@ -81,7 +80,7 @@ main (int argc, char *argv[])
{
const char input[] = "foo";
- const char *result = memmem (input, strlen (input), null_ptr (), 0);
+ const char *result = memmem (input, strlen (input), zerosize_ptr (), 0);
ASSERT (result == input);
}
diff --git a/modules/memmem-tests b/modules/memmem-tests
index 28c0091..250ccbf 100644
--- a/modules/memmem-tests
+++ b/modules/memmem-tests
@@ -1,7 +1,6 @@
Files:
tests/test-memmem.c
tests/signature.h
-tests/null-ptr.h
tests/zerosize-ptr.h
tests/macros.h
m4/mmap-anon.m4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-09 19:33 undefined behaviour findings Bruno Haible
@ 2019-03-09 19:37 ` Bruno Haible
2019-03-16 16:38 ` Akim Demaille
2019-03-09 21:22 ` undefined behaviour findings Bruno Haible
1 sibling, 1 reply; 17+ messages in thread
From: Bruno Haible @ 2019-03-09 19:37 UTC (permalink / raw)
To: Akim Demaille; +Cc: bug-gnulib
Hi Akim,
This one I have not fixed:
lib/bitset/table.c:784:54: runtime error: shift exponent 87 is too large for 64-bit type 'long unsigned int'
To reproduce: Use gcc 8.2.0 and CC="gcc -fsanitize=undefined".
Bruno
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings
2019-03-09 19:33 undefined behaviour findings Bruno Haible
2019-03-09 19:37 ` undefined behaviour findings in bitset Bruno Haible
@ 2019-03-09 21:22 ` Bruno Haible
1 sibling, 0 replies; 17+ messages in thread
From: Bruno Haible @ 2019-03-09 21:22 UTC (permalink / raw)
To: bug-gnulib; +Cc: Jeffrey Walton
> lib/des.c:552:3: runtime error: left shift of 255 by 24 places cannot be represented in type 'int'
> lib/des.c:437:3: runtime error: left shift of 242 by 24 places cannot be represented in type 'int'
> lib/des.c:625:3: runtime error: left shift of 254 by 24 places cannot be represented in type 'int'
This one is fixed by this commit:
2019-03-09 Bruno Haible <bruno@clisp.org>
crypto/des: Fix undefined behaviour.
* lib/des.c (READ_64BIT_DATA): Cast bytes to 'unsigned int', to avoid
shift operations on 'int'.
diff --git a/lib/des.c b/lib/des.c
index f357192..ba174f7 100644
--- a/lib/des.c
+++ b/lib/des.c
@@ -407,11 +407,17 @@ gl_des_is_weak_key (const char * key)
* Macros to convert 8 bytes from/to 32bit words.
*/
#define READ_64BIT_DATA(data, left, right) \
- left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \
- right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
+ left = ((uint32_t) data[0] << 24) \
+ | ((uint32_t) data[1] << 16) \
+ | ((uint32_t) data[2] << 8) \
+ | (uint32_t) data[3]; \
+ right = ((uint32_t) data[4] << 24) \
+ | ((uint32_t) data[5] << 16) \
+ | ((uint32_t) data[6] << 8) \
+ | (uint32_t) data[7];
#define WRITE_64BIT_DATA(data, left, right) \
- data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \
+ data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \
data[2] = (left >> 8) &0xff; data[3] = left &0xff; \
data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \
data[6] = (right >> 8) &0xff; data[7] = right &0xff;
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-09 19:37 ` undefined behaviour findings in bitset Bruno Haible
@ 2019-03-16 16:38 ` Akim Demaille
2019-03-16 16:42 ` Akim Demaille
2019-03-16 19:53 ` Bruno Haible
0 siblings, 2 replies; 17+ messages in thread
From: Akim Demaille @ 2019-03-16 16:38 UTC (permalink / raw)
To: Bruno Haible; +Cc: bug-gnulib
Hi Bruno,
> Le 9 mars 2019 à 20:37, Bruno Haible <bruno@clisp.org> a écrit :
>
> Hi Akim,
>
> This one I have not fixed:
>
> lib/bitset/table.c:784:54: runtime error: shift exponent 87 is too large for 64-bit type 'long unsigned int'
>
> To reproduce: Use gcc 8.2.0 and CC="gcc -fsanitize=undefined".
Thanks for the report! Here is my proposal, in three patches.
commit 6f8b57537eb47418a432b672cbb240713f005a6a
Author: Akim Demaille <akim.demaille@gmail.com>
Date: Thu Mar 14 08:31:54 2019 +0100
bitset: style changes
* lib/bitset/table.c: Use NULL, not 0, for pointers.
Formatting changes.
(tbitset_list): Reduce scopes.
diff --git a/ChangeLog b/ChangeLog
index 544d69d4b..2352520a5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2019-03-14 Akim Demaille <akim@lrde.epita.fr>
+
+ bitset: style changes.
+ * lib/bitset/table.c: Use NULL, not 0, for pointers.
+ Formatting changes.
+ (tbitset_list): Reduce scopes.
+
2019-03-14 Bruno Haible <bruno@clisp.org>
isatty: Make it return true in Cygwin consoles on native Windows.
diff --git a/lib/bitset/table.c b/lib/bitset/table.c
index 8351cf784..a129c8712 100644
--- a/lib/bitset/table.c
+++ b/lib/bitset/table.c
@@ -300,7 +300,7 @@ tbitset_elt_find (bitset bset, bitset_bindex bindex,
abort ();
case EBITSET_FIND:
- return 0;
+ return NULL;
case EBITSET_CREATE:
if (eindex >= size)
@@ -588,8 +588,8 @@ tbitset_list_reverse (bitset bset, bitset_bindex *list,
/* Find list of up to NUM bits set in BSET starting from and including
- *NEXT and store in array LIST. Return with actual number of bits
- found and with *NEXT indicating where search stopped. */
+ *NEXT and store in array LIST. Return with actual number of bits
+ found and with *NEXT indicating where search stopped. */
static bitset_bindex
tbitset_list (bitset bset, bitset_bindex *list,
bitset_bindex num, bitset_bindex *next)
@@ -607,17 +607,14 @@ tbitset_list (bitset bset, bitset_bindex *list,
if (bitno % EBITSET_ELT_BITS)
{
/* We need to start within an element. This is not very common. */
-
tbitset_elt *elt = elts[eindex];
if (elt)
{
- bitset_windex woffset;
bitset_word *srcp = EBITSET_WORDS (elt);
+ bitset_windex woffset = eindex * EBITSET_ELT_WORDS;
- bitset_windex windex = bitno / BITSET_WORD_BITS;
- woffset = eindex * EBITSET_ELT_WORDS;
-
- for (; (windex - woffset) < EBITSET_ELT_WORDS; windex++)
+ for (bitset_windex windex = bitno / BITSET_WORD_BITS;
+ (windex - woffset) < EBITSET_ELT_WORDS; windex++)
{
bitset_word word = srcp[windex - woffset] >> (bitno % BITSET_WORD_BITS);
commit f4a85b4ffa59650c36227fc94e4c5973e6449d48
Author: Akim Demaille <akim.demaille@gmail.com>
Date: Sat Mar 16 17:16:48 2019 +0100
bitset: fix bitset overflows
Reported by Bruno Haible.
https://lists.gnu.org/archive/html/bug-gnulib/2019-03/msg00017.html
* lib/bitset/table.c (tbitset_test): last_bit is the position of
the bit in the array of bitset_word, so be sure to take its modulo
number-of-bits-in-bitset-word (i.e., EBITSET_ELT_WORDS).
* lib/bitset/list.c (lbitset_unused_clear): Likewise.
diff --git a/ChangeLog b/ChangeLog
index 2352520a5..0e7a74a10 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2019-03-16 Akim Demaille <akim@lrde.epita.fr>
+
+ bitset: fix bitset overflows.
+ Reported by Bruno Haible.
+ https://lists.gnu.org/archive/html/bug-gnulib/2019-03/msg00017.html
+ * lib/bitset/table.c (tbitset_test): last_bit is the position of
+ the bit in the array of bitset_word, so be sure to take its modulo
+ number-of-bits-in-bitset-word (i.e., EBITSET_ELT_WORDS).
+ * lib/bitset/list.c (lbitset_unused_clear): Likewise.
+
2019-03-14 Akim Demaille <akim@lrde.epita.fr>
bitset: style changes.
diff --git a/lib/bitset/list.c b/lib/bitset/list.c
index f42edb8ea..fe1b52869 100644
--- a/lib/bitset/list.c
+++ b/lib/bitset/list.c
@@ -859,7 +859,8 @@ lbitset_unused_clear (bitset dst)
bitset_word *srcp = elt->words;
bitset_windex windex = n_bits / BITSET_WORD_BITS;
- srcp[windex - elt->index] &= ((bitset_word) 1 << last_bit) - 1;
+ srcp[windex - elt->index]
+ &= ((bitset_word) 1 << (last_bit % BITSET_WORD_BITS)) - 1;
windex++;
for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++)
diff --git a/lib/bitset/table.c b/lib/bitset/table.c
index a129c8712..9cac96469 100644
--- a/lib/bitset/table.c
+++ b/lib/bitset/table.c
@@ -778,7 +778,8 @@ tbitset_unused_clear (bitset dst)
bitset_windex windex = n_bits / BITSET_WORD_BITS;
bitset_windex woffset = eindex * EBITSET_ELT_WORDS;
- srcp[windex - woffset] &= ((bitset_word) 1 << last_bit) - 1;
+ srcp[windex - woffset]
+ &= ((bitset_word) 1 << (last_bit % BITSET_WORD_BITS)) - 1;
windex++;
for (; (windex - woffset) < EBITSET_ELT_WORDS; windex++)
srcp[windex - woffset] = 0;
commit 4c8a35ed125e1b87a11d6aecd0b7b216384552bb
Author: Akim Demaille <akim.demaille@gmail.com>
Date: Sat Mar 16 17:36:22 2019 +0100
bitset: a bit (...) more tests
* tests/test-bitset.c (check_attributes): Check zero and ones.
diff --git a/ChangeLog b/ChangeLog
index 0e7a74a10..db23ee898 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2019-03-16 Akim Demaille <akim@lrde.epita.fr>
+
+ bitset: a bit (...) more tests
+ * tests/test-bitset.c (check_attributes): Check zero and ones.
+
2019-03-16 Akim Demaille <akim@lrde.epita.fr>
bitset: fix bitset overflows.
diff --git a/tests/test-bitset.c b/tests/test-bitset.c
index 032865095..f4502d1d6 100644
--- a/tests/test-bitset.c
+++ b/tests/test-bitset.c
@@ -32,12 +32,18 @@ void assert_bitset_equal (bitset bs1, bitset bs2)
ASSERT (bitset_test (bs1, i) == bitset_test (bs2, i));
}
+static
void bitset_random (bitset bs)
{
for (bitset_bindex i = 0; i < bitset_size (bs); ++i)
bitset_set (bs, RANDOM (2));
}
+
+/* Check various operations on random bitsets with two different
+ implementations. */
+
+static
void compare (enum bitset_attr a, enum bitset_attr b)
{
const int nbits = RANDOM (256);
@@ -62,10 +68,17 @@ void compare (enum bitset_attr a, enum bitset_attr b)
bitset_copy (bsrc3, asrc3);
bitset bdst = bitset_create (nbits, b);
+ /* not */
+ bitset_not (adst, asrc0);
+ bitset_not (bdst, bsrc0);
+ assert_bitset_equal (adst, bdst);
+
+ /* not */
bitset_not (adst, asrc0);
bitset_not (bdst, bsrc0);
assert_bitset_equal (adst, bdst);
+ /* and */
bitset_and (adst, asrc0, asrc1);
bitset_and (bdst, bsrc0, bsrc1);
assert_bitset_equal (adst, bdst);
@@ -73,6 +86,7 @@ void compare (enum bitset_attr a, enum bitset_attr b)
== bitset_and_cmp (bdst, bsrc0, bsrc1));
assert_bitset_equal (adst, bdst);
+ /* andn */
bitset_andn (adst, asrc0, asrc1);
bitset_andn (bdst, bsrc0, bsrc1);
assert_bitset_equal (adst, bdst);
@@ -80,6 +94,7 @@ void compare (enum bitset_attr a, enum bitset_attr b)
== bitset_andn_cmp (bdst, bsrc0, bsrc1));
assert_bitset_equal (adst, bdst);
+ /* or */
bitset_or (adst, asrc0, asrc1);
bitset_or (bdst, bsrc0, bsrc1);
assert_bitset_equal (adst, bdst);
@@ -87,6 +102,7 @@ void compare (enum bitset_attr a, enum bitset_attr b)
== bitset_or_cmp (bdst, bsrc0, bsrc1));
assert_bitset_equal (adst, bdst);
+ /* xor */
bitset_xor (adst, asrc0, asrc1);
bitset_xor (bdst, bsrc0, bsrc1);
assert_bitset_equal (adst, bdst);
@@ -94,6 +110,7 @@ void compare (enum bitset_attr a, enum bitset_attr b)
== bitset_xor_cmp (bdst, bsrc0, bsrc1));
assert_bitset_equal (adst, bdst);
+ /* and_or */
bitset_and_or (adst, asrc0, asrc1, asrc2);
bitset_and_or (bdst, bsrc0, bsrc1, bsrc2);
assert_bitset_equal (adst, bdst);
@@ -101,6 +118,7 @@ void compare (enum bitset_attr a, enum bitset_attr b)
== bitset_and_or_cmp (bdst, bsrc0, bsrc1, bsrc2));
assert_bitset_equal (adst, bdst);
+ /* andn_or */
bitset_andn_or (adst, asrc0, asrc1, asrc2);
bitset_andn_or (bdst, bsrc0, bsrc1, bsrc2);
assert_bitset_equal (adst, bdst);
@@ -108,6 +126,7 @@ void compare (enum bitset_attr a, enum bitset_attr b)
== bitset_andn_or_cmp (bdst, bsrc0, bsrc1, bsrc2));
assert_bitset_equal (adst, bdst);
+ /* or_and */
bitset_or_and (adst, asrc0, asrc1, asrc2);
bitset_or_and (bdst, bsrc0, bsrc1, bsrc2);
assert_bitset_equal (adst, bdst);
@@ -115,6 +134,16 @@ void compare (enum bitset_attr a, enum bitset_attr b)
== bitset_or_and_cmp (bdst, bsrc0, bsrc1, bsrc2));
assert_bitset_equal (adst, bdst);
+ /* ones */
+ bitset_ones (adst);
+ bitset_ones (bdst);
+ assert_bitset_equal (adst, bdst);
+
+ /* zero */
+ bitset_zero (adst);
+ bitset_zero (bdst);
+ assert_bitset_equal (adst, bdst);
+
bitset_free (bdst);
bitset_free (bsrc3);
bitset_free (bsrc2);
@@ -127,6 +156,11 @@ void compare (enum bitset_attr a, enum bitset_attr b)
bitset_free (asrc0);
}
+
+/* Check various operations against expected values for a bitset
+ having attributes ATTR. */
+
+static
void check_attributes (enum bitset_attr attr)
{
enum { nbits = 32 };
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-16 16:38 ` Akim Demaille
@ 2019-03-16 16:42 ` Akim Demaille
2019-03-16 19:53 ` Bruno Haible
1 sibling, 0 replies; 17+ messages in thread
From: Akim Demaille @ 2019-03-16 16:42 UTC (permalink / raw)
To: Bruno Haible; +Cc: bug-gnulib
> commit 4c8a35ed125e1b87a11d6aecd0b7b216384552bb
> Author: Akim Demaille <akim.demaille@gmail.com>
> Date: Sat Mar 16 17:36:22 2019 +0100
>
> bitset: a bit (...) more tests
>
> * tests/test-bitset.c (check_attributes): Check zero and ones.
>
> diff --git a/tests/test-bitset.c b/tests/test-bitset.c
> index 032865095..f4502d1d6 100644
> --- a/tests/test-bitset.c
> +++ b/tests/test-bitset.c
> @@ -62,10 +68,17 @@ void compare (enum bitset_attr a, enum bitset_attr b)
> bitset_copy (bsrc3, asrc3);
> bitset bdst = bitset_create (nbits, b);
>
> + /* not */
> + bitset_not (adst, asrc0);
> + bitset_not (bdst, bsrc0);
> + assert_bitset_equal (adst, bdst);
> +
> + /* not */
> bitset_not (adst, asrc0);
> bitset_not (bdst, bsrc0);
> assert_bitset_equal (adst, bdst);
I have removed that spurious duplicate.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-16 16:38 ` Akim Demaille
2019-03-16 16:42 ` Akim Demaille
@ 2019-03-16 19:53 ` Bruno Haible
2019-03-17 7:39 ` Akim Demaille
1 sibling, 1 reply; 17+ messages in thread
From: Bruno Haible @ 2019-03-16 19:53 UTC (permalink / raw)
To: Akim Demaille; +Cc: bug-gnulib
Hi Akim,
In the first patch:
> + for (bitset_windex windex = bitno / BITSET_WORD_BITS;
> + (windex - woffset) < EBITSET_ELT_WORDS; windex++)
This is C99 syntax. If you don't add 'c99' as a dependency of your
module, the module will not compile with GCC versions < 5.1.0 with
their default settings.
Bruno
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-16 19:53 ` Bruno Haible
@ 2019-03-17 7:39 ` Akim Demaille
2019-03-17 18:36 ` Akim Demaille
0 siblings, 1 reply; 17+ messages in thread
From: Akim Demaille @ 2019-03-17 7:39 UTC (permalink / raw)
To: Bruno Haible; +Cc: bug-gnulib
> Le 16 mars 2019 à 20:53, Bruno Haible <bruno@clisp.org> a écrit :
>
> Hi Akim,
>
> In the first patch:
>> + for (bitset_windex windex = bitno / BITSET_WORD_BITS;
>> + (windex - woffset) < EBITSET_ELT_WORDS; windex++)
>
> This is C99 syntax. If you don't add 'c99' as a dependency of your
> module, the module will not compile with GCC versions < 5.1.0 with
> their default settings.
hi Bruno,
bitset is already implemented in C99, it's not a new requirement.
I was unaware of the c99 module. I installed the following commit
in addition to the ones I submitted.
Cheers!
commit 4d9813bf6bbf6489c1de4ad9d48943b961976bce
Author: Akim Demaille <akim.demaille@gmail.com>
Date: Sun Mar 17 08:34:22 2019 +0100
bitset, timevar: Depend on c99
Reported by Bruno Haible.
* modules/bitset, modules/timevar (Depends-on): Add c99.
diff --git a/ChangeLog b/ChangeLog
index 97b20b909..9ce4bf24c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2019-03-17 Akim Demaille <akim@lrde.epita.fr>
+
+ bitset, timevar: Depend on c99.
+ Reported by Bruno Haible.
+ * modules/bitset, modules/timevar (Depends-on): Add c99.
+
2019-03-16 Akim Demaille <akim@lrde.epita.fr>
bitset: a bit (...) more tests
diff --git a/modules/bitset b/modules/bitset
index 76d1a2cac..81b71c0c7 100644
--- a/modules/bitset
+++ b/modules/bitset
@@ -17,6 +17,7 @@ lib/bitset/vector.c
lib/bitset/vector.h
Depends-on:
+c99
gettext-h
obstack
xalloc
diff --git a/modules/timevar b/modules/timevar
index 3e1eb48f7..ef86fedb2 100644
--- a/modules/timevar
+++ b/modules/timevar
@@ -6,6 +6,7 @@ lib/timevar.h
lib/timevar.c
Depends-on:
+c99
gethrxtime
getrusage
gettext-h
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-17 7:39 ` Akim Demaille
@ 2019-03-17 18:36 ` Akim Demaille
2019-03-17 18:56 ` Paul Eggert
2019-03-17 19:27 ` Bruno Haible
0 siblings, 2 replies; 17+ messages in thread
From: Akim Demaille @ 2019-03-17 18:36 UTC (permalink / raw)
To: Bruno Haible; +Cc: bug-gnulib
Le 17 mars 2019 à 08:39, Akim Demaille <akim@lrde.epita.fr> a écrit :
>
> commit 4d9813bf6bbf6489c1de4ad9d48943b961976bce
> Author: Akim Demaille <akim.demaille@gmail.com>
> Date: Sun Mar 17 08:34:22 2019 +0100
>
> bitset, timevar: Depend on c99
>
> Reported by Bruno Haible.
> * modules/bitset, modules/timevar (Depends-on): Add c99.
Since that change, Bison's CI fails on GCC 4.7. That's because the c99 module also plays tricks with the C++ compiler, which is now set to use -std=gnu++11 if supported. But GCC 4.7 does not support [[noreturn]] yet, even in gnu++11 mode.
I need something like the following changes.
Wouldn't it be useful to have a file that defines macros such as GL_GCC_VERSION (that is defined on GCC only, not clang, nor icc), GL_ICC_VERSION, etc.? Defined as integer versions easy to compare (say major * 1e6 + minor * 1e3 + patchlevel, or just major&minor if deemed sufficient).
commit 896548de03f6490b57e9aca1f3d4ac8efba0f085
Author: Akim Demaille <akim.demaille@gmail.com>
Date: Sun Mar 17 19:27:20 2019 +0100
_Noreturn: GCC 4.7 does not support [[noreturn]] in C++11 mode
* lib/_Noreturn.h, m4/gnulib-common.m4: Don't use [[noreturn]] before
GCC 4.8.
diff --git a/ChangeLog b/ChangeLog
index 9ce4bf24c..4735bf65b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2019-03-17 Akim Demaille <akim@lrde.epita.fr>
+
+ _Noreturn: GCC 4.7 does not support [[noreturn]] in C++11 mode
+ * lib/_Noreturn.h, m4/gnulib-common.m4: Don't use [[noreturn]] before
+ GCC 4.8.
+
2019-03-17 Akim Demaille <akim@lrde.epita.fr>
bitset, timevar: Depend on c99.
diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h
index 94fdfaf02..ed8f6dbbf 100644
--- a/lib/_Noreturn.h
+++ b/lib/_Noreturn.h
@@ -1,5 +1,6 @@
#ifndef _Noreturn
-# if 201103 <= (defined __cplusplus ? __cplusplus : 0)
+# if (201103 <= (defined __cplusplus ? __cplusplus : 0) \
+ && 4 < __GNUC__ + (8 <= __GNUC_MINOR__))
# define _Noreturn [[noreturn]]
# elif (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
|| 4 < __GNUC__ + (7 <= __GNUC_MINOR__))
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index 7c0e3e8fa..378470a36 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -1,4 +1,4 @@
-# gnulib-common.m4 serial 41
+# gnulib-common.m4 serial 42
dnl Copyright (C) 2007-2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -17,7 +17,8 @@ AC_DEFUN([gl_COMMON_BODY], [
AH_VERBATIM([_Noreturn],
[/* The _Noreturn keyword of C11. */
#ifndef _Noreturn
-# if 201103 <= (defined __cplusplus ? __cplusplus : 0)
+# if (201103 <= (defined __cplusplus ? __cplusplus : 0) \
+ && 4 < __GNUC__ + (8 <= __GNUC_MINOR__))
# define _Noreturn [[noreturn]]
# elif (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
|| 4 < __GNUC__ + (7 <= __GNUC_MINOR__))
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-17 18:36 ` Akim Demaille
@ 2019-03-17 18:56 ` Paul Eggert
2019-03-17 19:27 ` Bruno Haible
1 sibling, 0 replies; 17+ messages in thread
From: Paul Eggert @ 2019-03-17 18:56 UTC (permalink / raw)
To: Akim Demaille, Bruno Haible; +Cc: bug-gnulib
Akim Demaille wrote:
> Wouldn't it be useful to have a file that defines macros such as GL_GCC_VERSION
libc-config.h defines __GNUC_PREREQ, which is the most common spelling for such
a macro. It's in the libc-config module. This was originally designed for code
shared with glibc but can be used elsewhere.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-17 18:36 ` Akim Demaille
2019-03-17 18:56 ` Paul Eggert
@ 2019-03-17 19:27 ` Bruno Haible
2019-03-18 8:16 ` Akim Demaille
1 sibling, 1 reply; 17+ messages in thread
From: Bruno Haible @ 2019-03-17 19:27 UTC (permalink / raw)
To: Akim Demaille; +Cc: bug-gnulib
Hi Akim,
> But GCC 4.7 does not support [[noreturn]] yet, even in gnu++11 mode.
>
> I need something like the following changes.
> -# if 201103 <= (defined __cplusplus ? __cplusplus : 0)
> +# if (201103 <= (defined __cplusplus ? __cplusplus : 0) \
> + && 4 < __GNUC__ + (8 <= __GNUC_MINOR__))
Something like this is OK. But this change drops support for [[noreturn]]
in compilers other than GCC and clang. Shouldn't it be like this:
# if (201103 <= (defined __cplusplus ? __cplusplus : 0) \
&& (!defined __GNUC__ || 4 < __GNUC__ + (8 <= __GNUC_MINOR__)))
> Wouldn't it be useful to have a file that defines macros such as
> GL_GCC_VERSION (that is defined on GCC only, not clang, nor icc),
> GL_ICC_VERSION, etc.?
The effort to distribute (in a module) and include this file may well
be larger than the gain, no?
Also, in this case the code duplication is between a file in m4/ and
a file in lib/. However, we don't have a good way to share code between
m4/ and lib/, because an include statement in a .m4 file
#include "$srcdir/lib/foo.h"
would need to reference the gnulib-tool --source-base value instead of 'lib'.
Bruno
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-17 19:27 ` Bruno Haible
@ 2019-03-18 8:16 ` Akim Demaille
2019-03-18 21:03 ` Bruno Haible
2019-03-20 3:39 ` Bruno Haible
0 siblings, 2 replies; 17+ messages in thread
From: Akim Demaille @ 2019-03-18 8:16 UTC (permalink / raw)
To: Bruno Haible; +Cc: bug-gnulib
[-- Attachment #1: Type: text/html, Size: 3131 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-18 8:16 ` Akim Demaille
@ 2019-03-18 21:03 ` Bruno Haible
2019-03-19 6:07 ` Akim Demaille
2019-03-20 3:39 ` Bruno Haible
1 sibling, 1 reply; 17+ messages in thread
From: Bruno Haible @ 2019-03-18 21:03 UTC (permalink / raw)
To: Akim Demaille; +Cc: bug-gnulib
Hi Akim,
> Also, the relationship with noreturn.h is not completely clear for
> me either.
There are a couple of comment in noreturn.h lines 33..41. But I agree,
some text in the documentation would be better.
> Clang 7 pretends to be GCC 4.2 (__GNUC__ __GNUC_MINOR__).
> For instance I see it already has the above fix for
> GCC 4.7, but in a different way.
>
> /* Use ISO C++11 syntax when the compiler supports it. */
> # if (__cplusplus >= 201103 && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
> || (_MSC_VER >= 1900)
> # define _GL_NORETURN_FUNC [[noreturn]]
Right, this snippet gets clang++ and MSVC++ support right. How about this
patch?
2019-03-18 Bruno Haible <bruno@clisp.org>
_Noreturn: clang and MSVC do support [[noreturn]] in C++11 mode.
* lib/_Noreturn.h: Use [[noreturn]] if __GNUC__ and __GNUC_MINOR__
indicate clang, or if _MSC_VER indicates MSVC++ 14.0 or newer.
diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h
index 19597e0..1629cef 100644
--- a/lib/_Noreturn.h
+++ b/lib/_Noreturn.h
@@ -1,6 +1,7 @@
#ifndef _Noreturn
-# if (201103 <= (defined __cplusplus ? __cplusplus : 0) \
- && (!defined __GNUC__ || 4 < __GNUC__ + (8 <= __GNUC_MINOR__)))
+# if (defined __cplusplus \
+ && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
+ || (defined _MSC_VER && 1900 <= _MSC_VER)))
# define _Noreturn [[noreturn]]
# elif (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
|| 4 < __GNUC__ + (7 <= __GNUC_MINOR__))
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index 688a1e5..20666a5 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -1,4 +1,4 @@
-# gnulib-common.m4 serial 42
+# gnulib-common.m4 serial 43
dnl Copyright (C) 2007-2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -17,8 +17,9 @@ AC_DEFUN([gl_COMMON_BODY], [
AH_VERBATIM([_Noreturn],
[/* The _Noreturn keyword of C11. */
#ifndef _Noreturn
-# if (201103 <= (defined __cplusplus ? __cplusplus : 0) \
- && (!defined __GNUC__ || 4 < __GNUC__ + (8 <= __GNUC_MINOR__)))
+# if (defined __cplusplus \
+ && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
+ || (defined _MSC_VER && 1900 <= _MSC_VER)))
# define _Noreturn [[noreturn]]
# elif (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
|| 4 < __GNUC__ + (7 <= __GNUC_MINOR__))
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-18 21:03 ` Bruno Haible
@ 2019-03-19 6:07 ` Akim Demaille
2019-03-22 16:00 ` Akim Demaille
0 siblings, 1 reply; 17+ messages in thread
From: Akim Demaille @ 2019-03-19 6:07 UTC (permalink / raw)
To: Bruno Haible; +Cc: bug-gnulib
Hi Bruno,
> Le 18 mars 2019 à 22:03, Bruno Haible <bruno@clisp.org> a écrit :
>
> Hi Akim,
>
>> Also, the relationship with noreturn.h is not completely clear for
>> me either.
>
> There are a couple of comment in noreturn.h lines 33..41. But I agree,
> some text in the documentation would be better.
>
>> Clang 7 pretends to be GCC 4.2 (__GNUC__ __GNUC_MINOR__).
>
>> For instance I see it already has the above fix for
>> GCC 4.7, but in a different way.
>>
>> /* Use ISO C++11 syntax when the compiler supports it. */
>> # if (__cplusplus >= 201103 && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
>> || (_MSC_VER >= 1900)
>> # define _GL_NORETURN_FUNC [[noreturn]]
>
> Right, this snippet gets clang++ and MSVC++ support right. How about this
> patch?
Yes, I agree this is the best option so far, thanks!
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-18 8:16 ` Akim Demaille
2019-03-18 21:03 ` Bruno Haible
@ 2019-03-20 3:39 ` Bruno Haible
2019-03-20 17:04 ` Akim Demaille
1 sibling, 1 reply; 17+ messages in thread
From: Bruno Haible @ 2019-03-20 3:39 UTC (permalink / raw)
To: Akim Demaille; +Cc: bug-gnulib
Akim Demaille wrote:
> Also, the relationship with noreturn.h is not completely clear for
> me either.
I'm adding this documentation:
2019-03-19 Bruno Haible <bruno@clisp.org>
doc: Document the 'stdnoreturn' and 'noreturn' modules.
Reported by Akim Demaille.
* doc/noreturn.texi: New file.
* doc/gnulib.texi: Include it.
diff --git a/doc/gnulib.texi b/doc/gnulib.texi
index ac3d570..838895c 100644
--- a/doc/gnulib.texi
+++ b/doc/gnulib.texi
@@ -6372,6 +6372,7 @@ to POSIX that it can be treated like any other Unix-like platform.
* alloca-opt::
* Safe Allocation Macros::
* Compile-time Assertions::
+* Non-returning Functions::
* Integer Properties::
* static inline::
* extern inline::
@@ -6402,6 +6403,8 @@ to POSIX that it can be treated like any other Unix-like platform.
@include verify.texi
+@include noreturn.texi
+
@include intprops.texi
@include static-inline.texi
diff --git a/doc/noreturn.texi b/doc/noreturn.texi
new file mode 100644
index 0000000..862a409
--- /dev/null
+++ b/doc/noreturn.texi
@@ -0,0 +1,60 @@
+@c GNU noreturn, stdnoreturn modules documentation
+
+@c Copyright (C) 2019 Free Software Foundation, Inc.
+
+@c Permission is granted to copy, distribute and/or modify this document
+@c under the terms of the GNU Free Documentation License, Version 1.3
+@c or any later version published by the Free Software Foundation;
+@c with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+@c Texts. A copy of the license is included in the ``GNU Free
+@c Documentation License'' file as part of this distribution.
+
+@node Non-returning Functions
+@section Non-returning Functions
+
+@cindex @code{_Noreturn}
+@cindex @code{noreturn}
+@cindex @code{stdnoreturn}
+A "non-returning" function is a function which cannot return normally.
+It can transfer control only through @code{longjmp()}, @code{throw}
+(in C++), or similar mechanisms. The most prominent function of this
+class is the @code{abort} function. Non-returning functions are
+declared with a @code{void} return type.
+
+It helps the compiler's ability to emit sensible warnings, following
+data-flow analysis, to declare which functions are non-returning.
+
+Gnulib has two modules that support such a declaration:
+
+@itemize @bullet
+@item
+The @samp{stdnoreturn} module. It provides a way to put this
+declaration at function declarations and function definitions, but not
+in function pointer types. The identifier to use is @code{_Noreturn}
+or @code{noreturn}; @code{_Noreturn} is to be preferred because
+@code{noreturn} is a no-op on some platforms. The include file is
+@code{<stdnoreturn.h>}.
+
+@item
+The @samp{noreturn} module. It provides a way to put this declaration
+at function declarations, at function definitions, and in function
+pointer types. The identifiers to use are:
+@itemize -
+@item
+@code{_GL_NORETURN_FUNC} for use in function declarations and function
+definitions.
+@item
+@code{_GL_NORETURN_FUNCPTR} for use on function pointers.
+@end itemize
+@noindent
+The include file is @code{<noreturn.h>}.
+@end itemize
+
+Which of the two modules to use? If the non-returning functions you
+have to declare are unlikely to be accessed through function pointers,
+you should use module @code{stdnoreturn}; otherwise the module
+@code{noreturn} provides for better data-flow analysis and thus for
+better warnings.
+
+For a detailed description of the @code{stdnoreturn} module, see
+@ref{stdnoreturn.h}.
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-20 3:39 ` Bruno Haible
@ 2019-03-20 17:04 ` Akim Demaille
0 siblings, 0 replies; 17+ messages in thread
From: Akim Demaille @ 2019-03-20 17:04 UTC (permalink / raw)
To: Bruno Haible; +Cc: bug-gnulib
Hi Bruno,
> Le 20 mars 2019 à 04:39, Bruno Haible <bruno@clisp.org> a écrit :
>
> Akim Demaille wrote:
>> Also, the relationship with noreturn.h is not completely clear for
>> me either.
>
> I'm adding this documentation:
>
> 2019-03-19 Bruno Haible <bruno@clisp.org>
>
> doc: Document the 'stdnoreturn' and 'noreturn' modules.
> Reported by Akim Demaille.
> * doc/noreturn.texi: New file.
> * doc/gnulib.texi: Include it.
Thanks!
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-19 6:07 ` Akim Demaille
@ 2019-03-22 16:00 ` Akim Demaille
2019-03-23 18:54 ` Bruno Haible
0 siblings, 1 reply; 17+ messages in thread
From: Akim Demaille @ 2019-03-22 16:00 UTC (permalink / raw)
To: Bruno Haible; +Cc: bug-gnulib
Hi Bruno,
> Le 19 mars 2019 à 07:07, Akim Demaille <akim@lrde.epita.fr> a écrit :
>
> Hi Bruno,
>
>> Le 18 mars 2019 à 22:03, Bruno Haible <bruno@clisp.org> a écrit :
>>
>> Hi Akim,
>>
>>> Also, the relationship with noreturn.h is not completely clear for
>>> me either.
>>
>> There are a couple of comment in noreturn.h lines 33..41. But I agree,
>> some text in the documentation would be better.
>>
>>> Clang 7 pretends to be GCC 4.2 (__GNUC__ __GNUC_MINOR__).
>>
>>> For instance I see it already has the above fix for
>>> GCC 4.7, but in a different way.
>>>
>>> /* Use ISO C++11 syntax when the compiler supports it. */
>>> # if (__cplusplus >= 201103 && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
>>> || (_MSC_VER >= 1900)
>>> # define _GL_NORETURN_FUNC [[noreturn]]
>>
>> Right, this snippet gets clang++ and MSVC++ support right. How about this
>> patch?
>
> Yes, I agree this is the best option so far, thanks!
Well, it does not work with G++ in C++98 mode: _Noreturn is not supported there.
This works with Bison's CI:
commit b2a7dec46c0b702b5f7618994641e7381c8ff86f
Author: Akim Demaille <akim.demaille@gmail.com>
Date: Fri Mar 22 08:25:53 2019 +0100
_Noreturn: beware of C's _Noreturn in C++ pre C++11
* lib/_Noreturn.h, m4/gnulib-common.m4: Using C's _Noreturn in
C++98 appears to be supported by Clang, but not by GCC nor ICC.
diff --git a/ChangeLog b/ChangeLog
index 62c522e65..b694c3512 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2019-03-22 Akim Demaille <akim@lrde.epita.fr>
+
+ _Noreturn: beware of C's _Noreturn in C++ pre C++11.
+ * lib/_Noreturn.h, m4/gnulib-common.m4: Using C's _Noreturn in
+ C++98 appears to be supported by Clang, but not by GCC nor ICC.
+
2019-03-19 Akim Demaille <akim@lrde.epita.fr>
bitset: fix memory leaks
diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h
index 1629cef39..7594e4b0c 100644
--- a/lib/_Noreturn.h
+++ b/lib/_Noreturn.h
@@ -3,8 +3,9 @@
&& ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
|| (defined _MSC_VER && 1900 <= _MSC_VER)))
# define _Noreturn [[noreturn]]
-# elif (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
- || 4 < __GNUC__ + (7 <= __GNUC_MINOR__))
+# elif ((!defined __cplusplus || defined __clang__) \
+ && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
+ || 4 < __GNUC__ + (7 <= __GNUC_MINOR__)))
/* _Noreturn works as-is. */
# elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C
# define _Noreturn __attribute__ ((__noreturn__))
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index 8ad963e35..57b94ed53 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -21,8 +21,9 @@ AC_DEFUN([gl_COMMON_BODY], [
&& ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
|| (defined _MSC_VER && 1900 <= _MSC_VER)))
# define _Noreturn [[noreturn]]
-# elif (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
- || 4 < __GNUC__ + (7 <= __GNUC_MINOR__))
+# elif ((!defined __cplusplus || defined __clang__) \
+ && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
+ || 4 < __GNUC__ + (7 <= __GNUC_MINOR__)))
/* _Noreturn works as-is. */
# elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C
# define _Noreturn __attribute__ ((__noreturn__))
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: undefined behaviour findings in bitset
2019-03-22 16:00 ` Akim Demaille
@ 2019-03-23 18:54 ` Bruno Haible
0 siblings, 0 replies; 17+ messages in thread
From: Bruno Haible @ 2019-03-23 18:54 UTC (permalink / raw)
To: Akim Demaille; +Cc: bug-gnulib
Hi Akim,
> it does not work with G++ in C++98 mode: _Noreturn is not supported there.
I confirm: No g++ version I tested supported _Noreturn, neither with
-std=c++98 nor with -std=c++11.
Your patch looks good.
> Using C's _Noreturn in C++98 appears to be supported by Clang
Good point! Let me adjust the 'noreturn' module accordingly:
2019-03-23 Bruno Haible <bruno@clisp.org>
noreturn: In C++ mode with clang, use _Noreturn as fallback.
Reported by Akim Demaille.
* lib/noreturn.h (_GL_NORETURN_FUNC): In C++ mode with clang, when
[[noreturn]] would not work, use _Noreturn instead.
diff --git a/lib/noreturn.h b/lib/noreturn.h
index 3ceeaf5..57e9a88 100644
--- a/lib/noreturn.h
+++ b/lib/noreturn.h
@@ -74,6 +74,9 @@
# if (__cplusplus >= 201103 && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
|| (_MSC_VER >= 1900)
# define _GL_NORETURN_FUNC [[noreturn]]
+ /* clang++ supports the _Noreturn keyword, but g++ doesn't. */
+# elif defined __clang__
+# define _GL_NORETURN_FUNC _Noreturn
# else
# define _GL_NORETURN_FUNC /* empty */
# endif
^ permalink raw reply related [flat|nested] 17+ messages in thread
end of thread, other threads:[~2019-03-23 18:54 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-09 19:33 undefined behaviour findings Bruno Haible
2019-03-09 19:37 ` undefined behaviour findings in bitset Bruno Haible
2019-03-16 16:38 ` Akim Demaille
2019-03-16 16:42 ` Akim Demaille
2019-03-16 19:53 ` Bruno Haible
2019-03-17 7:39 ` Akim Demaille
2019-03-17 18:36 ` Akim Demaille
2019-03-17 18:56 ` Paul Eggert
2019-03-17 19:27 ` Bruno Haible
2019-03-18 8:16 ` Akim Demaille
2019-03-18 21:03 ` Bruno Haible
2019-03-19 6:07 ` Akim Demaille
2019-03-22 16:00 ` Akim Demaille
2019-03-23 18:54 ` Bruno Haible
2019-03-20 3:39 ` Bruno Haible
2019-03-20 17:04 ` Akim Demaille
2019-03-09 21:22 ` undefined behaviour findings Bruno Haible
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).