cgccmacrospreprocessorvariadic-macros

'ISO C99 requires at least one argument for the "..." in a variadic macro' When specifically using c11 and -Wno-variadic-macros


I have a simple: #define log(text, ...) fprintf(stderr, "stuff before" text "stuff after", ## __VA_ARGS__); which is triggering: error: ISO C99 requires at least one argument for the "..." in a variadic macro [-Werror]

Should using -std=c11 and -Wno-variadic-macros not fix this error / warning?

Throwing #pragma GCC system_header in the header file before the define of log fixes this issue (haven't necessarily tested if the outputted binary works...) but this seems sort of hacky and I'm not entirely sure the ramifications of this.

Here's an example of expected behaviour: https://stackoverflow.com/a/31327708/5698848

From GNU

-Wvariadic-macros

    Warn if variadic macros are used in ISO C90 mode, or if the GNU alternate syntax is used in ISO C99 mode.
    This is enabled by either -Wpedantic or -Wtraditional.
    To inhibit the warning messages, use -Wno-variadic-macros.

Any idea on an elegant solution to stop this warning / error from legal GNU GCC C code? Why does it say I'm using C99 and why doesn't the flag to disable the warning for C99 work? Line looks like:

gcc -c src/file.c -Wall -Werror -Wextra -pedantic -Wfloat-equal -Wwrite-strings -Wcast-qual -Wunreachable-code -Wcast-align -Wstrict-prototypes -Wundef -Wshadow -Wstrict-aliasing -Wstrict-overflow -Wno-variadic-macros -g3 -std=c11 -O2 -flto -Iinclude/ -MMD -MF depend/file.d -o bin/file.o

Note that -pedantic is indeed the culprit.


MCVE

c.c

#include <stdio.h>
#include <stdlib.h>

#define log(text, ...) fprintf(stderr, "stuff before" text "stuff after", ## __VA_ARGS__);

int main(void)
{

    log("should work, but doesn't");
    log("works fine: %s", "yep");

    return EXIT_SUCCESS;
}

Makefile

all:
    gcc c.c -Wall -Werror -Wextra -pedantic -Wfloat-equal -Wwrite-strings -Wcast-qual -Wunreachable-code -Wcast-align -Wstrict-prototypes -Wundef -Wshadow -Wstrict-aliasing -Wstrict-overflow -Wno-variadic-macros -g3 -std=c11 -O2

Note: Removing pedantic compiles fine - gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609


Solution

  • In ISO C99 and C11, when you define a macro like:

    #define log(text, ...)   something
    

    then any invocation of the macro must take at least 2 arguments. Your code is ill-formed in ISO C (all versions).

    The GCC flag -pedantic, according to the documentation, means:

    Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used.

    The GCC developers decided to include code using this extension under "some other programs that do not follow ISO C". If you want to use this non-standard extension in your code, then you should not use the -pedantic flag.

    The GCC developers also did not bother to modify the text of the error message to say "ISO C11 forbids..." if you requested C11 conformance. If this concerns you then perhaps you could submit a patch.


    Regarding -Wno-variadic-macros, the documentation is:

    Warn if variadic macros are used in ISO C90 mode, or if the GNU alternate syntax is used in ISO C99 mode.

    By "GNU alternate syntax", it appears that they mean the GNU syntax for enabling variadic macros in the first place prior to C99, as described in the GCC documentation (and not the extension to provide fewer arguments than the minimum):

    GCC has long supported variadic macros, and used a different syntax that allowed you to give a name to the variable arguments just like any other argument. Here is an example:

    #define debug(format, args...) fprintf (stderr, format, args)