On 2020-05-23 I wrote: > As you can see: > > 1) clang has eliminated the calloc() and free() calls from the program. > Apparently it "knows" how to optimize matching calloc - free pairs. > > 2) It has estimated that the second call would return a non-NULL pointer, > although the address space does not allow this. > Reported at <https://bugs.llvm.org/show_bug.cgi?id=37304>. But some > people claim it is not a bug. Paul, can you please help with ISO C > citations? > > This patch provides a workaround. > > > 2020-05-23 Bruno Haible <br...@clisp.org> > > calloc-gnu: Avoid wrong configure results with clang. > * m4/calloc.m4 (_AC_FUNC_CALLOC_IF): Mark the pointer variable as > 'volatile', to defeat compiler optimizations.
The same problem occurs also in the test suite. The continuous integration [1] detected it. [1] https://gitlab.com/gnulib/gnulib-ci/-/pipelines/153500376 2020-06-06 Bruno Haible <br...@clisp.org> calloc-gnu tests: Avoid a test failure with clang. * tests/test-calloc-gnu.c (main): Mark the pointer variable as 'volatile', to defeat compiler optimizations. diff --git a/tests/test-calloc-gnu.c b/tests/test-calloc-gnu.c index c13ba47..2ae3925 100644 --- a/tests/test-calloc-gnu.c +++ b/tests/test-calloc-gnu.c @@ -36,20 +36,26 @@ int main () { /* Check that calloc (0, 0) is not a NULL pointer. */ - void *p = calloc (0, 0); - if (p == NULL) - return 1; - free (p); + { + void * volatile p = calloc (0, 0); + if (p == NULL) + return 1; + free (p); + } /* Check that calloc fails when requested to allocate a block of memory larger than SIZE_MAX bytes. - We use eight (), not 8, to avoid a compiler warning from GCC 7. */ - p = calloc ((size_t) -1 / 8 + 1, eight ()); - if (p != NULL) - { - free (p); - return 1; - } + We use eight (), not 8, to avoid a compiler warning from GCC 7. + 'volatile' is needed to defeat an incorrect optimization by clang 10, + see <https://bugs.llvm.org/show_bug.cgi?id=46055>. */ + { + void * volatile p = calloc ((size_t) -1 / 8 + 1, eight ()); + if (p != NULL) + { + free (p); + return 2; + } + } return 0; }