madler / zlib

A massively spiffy yet delicately unobtrusive compression library.
http://zlib.net/
Other
5.55k stars 2.42k forks source link

snprintf warning with ubuntu + c89 + clang + cmake #927

Closed pmqs closed 6 months ago

pmqs commented 6 months ago

This is taken from https://github.com/madler/zlib/pull/926#issuecomment-1929291276

Seeing the warnings below with c89 (and iso9899:199409) + clang + cmake on Ubuntu. The equivalent Mac build is fine. Also there is no issue when built with configure, so the issue must lie with zconf.h and/or the clang commandline.

Adding -DNO_vsnprintf to CFLAGS sorts this issue. Fix needed is to get CMakesList.txt to do the equivalent test that configure does for vsnprintf.

The cmake function check_c_source_compiles looks like a candidate for this change.

$ rm -fr build ; CFLAGS=" -std=c89" cmake  -S . -B build  -D CMAKE_BUILD_TYPE=Release -D CMAKE_C_COMPILER=clang -D ZLIB_BUILD_EXAMPLES=off 
-- The C compiler identification is Clang 16.0.6
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of off64_t
-- Check size of off64_t - done
-- Looking for fseeko
-- Looking for fseeko - found
-- Looking for unistd.h
-- Looking for unistd.h - found
-- Looking for stdarg.h
-- Looking for stdarg.h - found
-- Configuring done (2.1s)
-- Generating done (0.0s)
-- Build files have been written to: /home/paul/git/zlib/build

$ cmake --build build
[  3%] Building C object CMakeFiles/zlib.dir/adler32.c.o
[  6%] Building C object CMakeFiles/zlib.dir/compress.c.o
[  9%] Building C object CMakeFiles/zlib.dir/crc32.c.o
[ 12%] Building C object CMakeFiles/zlib.dir/deflate.c.o
[ 15%] Building C object CMakeFiles/zlib.dir/gzclose.c.o
[ 18%] Building C object CMakeFiles/zlib.dir/gzlib.c.o
/home/paul/git/zlib/gzlib.c:204:15: warning: implicitly declaring library function 'snprintf' with type 'int (char *, unsigned long, const char *, ...)' [-Wimplicit-function-declaration]
        (void)snprintf(state->path, len + 1, "%s", (const char *)path);
              ^
/home/paul/git/zlib/gzlib.c:204:15: note: include the header <stdio.h> or explicitly provide a declaration for 'snprintf'
1 warning generated.
[ 21%] Building C object CMakeFiles/zlib.dir/gzread.c.o
[ 25%] Building C object CMakeFiles/zlib.dir/gzwrite.c.o
/home/paul/git/zlib/gzwrite.c:407:11: warning: implicitly declaring library function 'vsnprintf' with type 'int (char *, unsigned long, const char *, struct __va_list_tag *)' [-Wimplicit-function-declaration]
    len = vsnprintf(next, state->size, format, va);
          ^
/home/paul/git/zlib/gzwrite.c:407:11: note: include the header <stdio.h> or explicitly provide a declaration for 'vsnprintf'
1 warning generated.
[ 28%] Building C object CMakeFiles/zlib.dir/inflate.c.o
[ 31%] Building C object CMakeFiles/zlib.dir/infback.c.o
[ 34%] Building C object CMakeFiles/zlib.dir/inftrees.c.o
[ 37%] Building C object CMakeFiles/zlib.dir/inffast.c.o
[ 40%] Building C object CMakeFiles/zlib.dir/trees.c.o
[ 43%] Building C object CMakeFiles/zlib.dir/uncompr.c.o
[ 46%] Building C object CMakeFiles/zlib.dir/zutil.c.o
[ 50%] Linking C shared library libz.so
[ 50%] Built target zlib
[ 53%] Building C object CMakeFiles/zlibstatic.dir/adler32.c.o
[ 56%] Building C object CMakeFiles/zlibstatic.dir/compress.c.o
[ 59%] Building C object CMakeFiles/zlibstatic.dir/crc32.c.o
[ 62%] Building C object CMakeFiles/zlibstatic.dir/deflate.c.o
[ 65%] Building C object CMakeFiles/zlibstatic.dir/gzclose.c.o
[ 68%] Building C object CMakeFiles/zlibstatic.dir/gzlib.c.o
/home/paul/git/zlib/gzlib.c:204:15: warning: implicitly declaring library function 'snprintf' with type 'int (char *, unsigned long, const char *, ...)' [-Wimplicit-function-declaration]
        (void)snprintf(state->path, len + 1, "%s", (const char *)path);
              ^
/home/paul/git/zlib/gzlib.c:204:15: note: include the header <stdio.h> or explicitly provide a declaration for 'snprintf'
1 warning generated.
[ 71%] Building C object CMakeFiles/zlibstatic.dir/gzread.c.o
[ 75%] Building C object CMakeFiles/zlibstatic.dir/gzwrite.c.o
/home/paul/git/zlib/gzwrite.c:407:11: warning: implicitly declaring library function 'vsnprintf' with type 'int (char *, unsigned long, const char *, struct __va_list_tag *)' [-Wimplicit-function-declaration]
    len = vsnprintf(next, state->size, format, va);
          ^
/home/paul/git/zlib/gzwrite.c:407:11: note: include the header <stdio.h> or explicitly provide a declaration for 'vsnprintf'
1 warning generated.
[ 78%] Building C object CMakeFiles/zlibstatic.dir/inflate.c.o
[ 81%] Building C object CMakeFiles/zlibstatic.dir/infback.c.o
[ 84%] Building C object CMakeFiles/zlibstatic.dir/inftrees.c.o
[ 87%] Building C object CMakeFiles/zlibstatic.dir/inffast.c.o
[ 90%] Building C object CMakeFiles/zlibstatic.dir/trees.c.o
[ 93%] Building C object CMakeFiles/zlibstatic.dir/uncompr.c.o
[ 96%] Building C object CMakeFiles/zlibstatic.dir/zutil.c.o
[100%] Linking C static library libz.a
[100%] Built target zlibstatic
madler commented 6 months ago

The Ubuntu clang complaint makes sense, since C89/C90 doesn't have snprintf() or vsnprintf(). They were introduced in C99.

pmqs commented 6 months ago

The Ubuntu clang complaint makes sense, since C89/C90 doesn't have snprintf() or vsnprintf(). They were introduced in C99.

Then the clang C89/90 behaviour with configure is (at least) inconsistent as it builds without warning.

As does gcc with C89.

Admittedly, this is an edge condition -- goodness knows if anyone has a valid use case that needs C89 these days.

I'm sure the cmake code can be made to do make everything consistent if needed. I just don't know it well enough to hack it.

Either that or set a minimum C spec that the code needs to conform to.

madler commented 6 months ago

Until very recently (VS 2022), Microsoft Visual C only supported C89/90. However it does have, and has had, snprintf() and vsnprintf(). Recently it claims to support C11 and C17, but only if you request it with the respective compiler options.

I am thinking of checking __STDC__, __STDC_VERSION__, and _WIN32 to deduce whether those functions are missing or not, in addition to the configure checks.

madler commented 6 months ago

Then the clang C89/90 behaviour with configure is (at least) inconsistent as it builds without warning.

configure checks directly for those functions, and doesn't use them if they're not there.

pmqs commented 6 months ago

Until very recently (VS 2022), Microsoft Visual C only supported C89/90. However it does have, and has had, snprintf() and vsnprintf(). Recently it claims to support C11 and C17, but only if you request it with the respective compiler options.

Crikey! C89 is not an edge condition at all then.

I am thinking of checking __STDC__, __STDC_VERSION__, and _WIN32 to deduce whether those functions are missing or not, in addition to the configure checks.

I think that should be enough to catch the clang use-case I highlighted.

Hopefully no need to add cmake code to mirror the check-by-compilation test that configure does for vsnprintf

madler commented 6 months ago

I have pushed some commits on the develop branch. Let me know how that works for you.

pmqs commented 6 months ago

I have pushed some commits on the develop branch. Let me know how that works for you.

Thanks, that silences the warnings